update deps for async support

parent 790c0e33
Pipeline #87206 failed with stages
in 5 minutes and 16 seconds
This diff is collapsed.
......@@ -6,18 +6,18 @@ build = "build.rs"
edition = "2018"
[dependencies]
gtk = { version="0.6.0", features=["v3_22"] }
libhandy = { version="0.3.0", features=["v0_0_7"] }
glib = { version="0.7.0", features=["subclassing"] }
gio = { version="0.6.0", features=["v2_46"] }
gdk = "0.10.0"
gstreamer = "0.13.0"
gstreamer-pbutils = "0.13.0"
libhandy = { git = "https://gitlab.gnome.org/haecker-felix/libhandy-rs", features=["v0_0_9"] }
gtk = { git="https://github.com/gtk-rs/gtk", features=["v3_24"] }
glib = { git="https://github.com/gtk-rs/glib", features=["subclassing", "futures"] }
gio = { git="https://github.com/gtk-rs/gio", features=["v2_46", "futures"] }
gdk = { git="https://github.com/gtk-rs/gdk" }
gstreamer = { git="https://github.com/sdroege/gstreamer-rs" }
gstreamer-pbutils = { git="https://github.com/sdroege/gstreamer-rs" }
rustio = "0.0.2"
mpris-player = "0.3.0"
mpris-player = { git="https://gitlab.gnome.org/World/Rust/mpris-player/", branch="latest_glib" }
log = "0.4"
pretty_env_logger = "0.3.0"
rusqlite = "0.13"
rusqlite = "0.18"
quick-error = "1.2.2"
restson = "0.4"
uuid = { version = "0.7", features = ["v4"] }
......@@ -29,4 +29,4 @@ serde_json = "1.0.39"
serde_derive = "1.0.89"
lazy_static = "1.3.0"
matches = "0.1.8"
open = "1.2.2"
open = "1.2.2"
\ No newline at end of file
**Note**: This branch requires a nightly version of Rust. It cannot be compiled using Flatpak. It's using unstable Rust features like async.
# Shortwave
Find and listen to internet radio stations
......@@ -44,27 +46,12 @@ That's why we decided to call the project 'Shortwave', because internet radio st
## Development builds
#### Flatpak (officially supported)
#### Flatpak
This Flatpak bundle gets automatically generated with every Git commit.
[Download the latest bundle](https://gitlab.gnome.org/World/Shortwave/-/jobs/artifacts/master/download?job=flatpak)
You can install it with GNOME Software, or just run `flatpak install shortwave-dev.flatpak -y`.
### Third party builds
**These packages are not created and maintained by me. If issues with a package occur, please report them directly to the package maintainer, and NOT to me.**
#### Ubuntu PPA (Requires 19.04+)
You can add the [this PPA](https://code.launchpad.net/~shortwave-developers/+archive/ubuntu/shortwave-nightly). It gets automatically rebuild every day.
```
sudo add-apt-repository ppa:shortwave-developers/shortwave-nightly
sudo apt update
sudo apt install shortwave
```
#### Arch AUR
You can get `shortwave-git` from [the AUR](https://aur.archlinux.org/packages/shortwave-git/).
## Building
Shortwave can be built and run with [Gnome Builder](https://wiki.gnome.org/Apps/Builder) >= 3.28.
Just clone the repo and hit the run button!
......
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.22.0 -->
<interface>
<requires lib="gtk+" version="3.20"/>
<object class="GtkBox" id="resultview_box">
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkOverlay" id="overlay_box">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkImage">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stock">gtk-missing-image</property>
</object>
<packing>
<property name="index">-1</property>
</packing>
</child>
<child type="overlay">
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkSeparator">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkScrolledWindow">
<property name="visible">True</property>
<property name="can_focus">True</property>
<child>
<object class="GtkViewport">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="shadow_type">none</property>
<child>
<placeholder/>
</child>
</object>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
</object>
</interface>
......@@ -10,26 +10,25 @@
<property name="vexpand">True</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkBox" id="search_box">
<object class="GtkScrolledWindow">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<property name="can_focus">True</property>
<child>
<object class="GtkBox">
<object class="GtkViewport">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<property name="shadow_type">none</property>
<child>
<object class="GtkScrolledWindow">
<object class="GtkStack">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkViewport">
<object class="GtkBox" id="overview_box">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="shadow_type">none</property>
<property name="orientation">vertical</property>
<child>
<object class="HdyColumn">
<object class="HdyColumn" id="overview">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="maximum_width">1600</property>
......@@ -37,12 +36,28 @@
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_left">12</property>
<property name="margin_right">12</property>
<property name="margin_top">12</property>
<property name="margin_bottom">12</property>
<property name="orientation">vertical</property>
<property name="spacing">6</property>
<child>
<object class="GtkLabel" id="headline">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
<property name="label" translatable="yes">Discover something new...</property>
<property name="wrap">True</property>
<property name="wrap_mode">word-char</property>
<attributes>
<attribute name="font-desc" value="Cantarell Ultra-Bold 20"/>
</attributes>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="tags_header">
<property name="visible">True</property>
......@@ -56,7 +71,7 @@
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
<property name="position">1</property>
</packing>
</child>
<child>
......@@ -69,7 +84,7 @@
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
<property name="position">2</property>
</packing>
</child>
<child>
......@@ -86,7 +101,7 @@
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
<property name="position">3</property>
</packing>
</child>
<child>
......@@ -111,7 +126,7 @@
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">3</property>
<property name="position">4</property>
</packing>
</child>
<child>
......@@ -126,34 +141,46 @@
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">4</property>
<property name="position">5</property>
</packing>
</child>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
</object>
<packing>
<property name="name">overview</property>
</packing>
</child>
<child>
<object class="GtkBox" id="result_box">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child>
<placeholder/>
</child>
</object>
<packing>
<property name="name">results</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
<property name="position">1</property>
</packing>
</child>
</object>
......
......@@ -14,6 +14,7 @@
<file compressed="true" preprocess="xml-stripblanks">gtk/gtk_controller.ui</file>
<file compressed="true" preprocess="xml-stripblanks">gtk/station_dialog.ui</file>
<file compressed="true" preprocess="xml-stripblanks">gtk/tile_button.ui</file>
<file compressed="true" preprocess="xml-stripblanks">gtk/resultview_box.ui</file>
<file compressed="true">gtk/style.css</file>
......
......@@ -45,12 +45,16 @@ pub struct App {
impl App {
pub fn new() -> Rc<Self> {
let c = glib::MainContext::default();
let future = Self::test();
c.spawn_local(future);
// Set custom style
let p = gtk::CssProvider::new();
gtk::CssProvider::load_from_resource(&p, "/de/haeckerfelix/Shortwave/gtk/style.css");
gtk::StyleContext::add_provider_for_screen(&gdk::Screen::get_default().unwrap(), &p, 500);
let gtk_app = gtk::Application::new(config::APP_ID, gio::ApplicationFlags::FLAGS_NONE).unwrap();
let gtk_app = gtk::Application::new(Some(config::APP_ID), gio::ApplicationFlags::FLAGS_NONE).unwrap();
let (sender, r) = glib::MainContext::channel(glib::PRIORITY_DEFAULT);
let receiver = RefCell::new(Some(r));
......@@ -134,11 +138,11 @@ impl App {
// Sort / Order menu
let sort_variant = "name".to_variant();
let sorting_action = gio::SimpleAction::new_stateful("sorting", sort_variant.type_(), &sort_variant);
let sorting_action = gio::SimpleAction::new_stateful("sorting", Some(sort_variant.type_()), &sort_variant);
self.gtk_app.add_action(&sorting_action);
let order_variant = "ascending".to_variant();
let order_action = gio::SimpleAction::new_stateful("order", order_variant.type_(), &order_variant);
let order_action = gio::SimpleAction::new_stateful("order", Some(order_variant.type_()), &order_variant);
self.gtk_app.add_action(&order_action);
let sa = sorting_action.clone();
......@@ -181,7 +185,7 @@ impl App {
fn add_gaction<F>(&self, name: &str, action: F)
where
for<'r, 's> F: Fn(&'r gio::SimpleAction, &'s Option<glib::Variant>) + 'static,
for<'r, 's> F: Fn(&'r gio::SimpleAction, Option<&'s glib::Variant>) + 'static,
{
let simple_action = gio::SimpleAction::new(name, None);
simple_action.connect_activate(action);
......@@ -221,12 +225,12 @@ impl App {
fn show_about_dialog(window: gtk::ApplicationWindow) {
let dialog = gtk::AboutDialog::new();
dialog.set_program_name(config::NAME);
dialog.set_logo_icon_name(config::APP_ID);
dialog.set_comments("A web radio client");
dialog.set_copyright("© 2019 Felix Häcker");
dialog.set_logo_icon_name(Some(config::APP_ID));
dialog.set_comments(Some("A web radio client"));
dialog.set_copyright(Some("© 2019 Felix Häcker"));
dialog.set_license_type(gtk::License::Gpl30);
dialog.set_version(format!("{}{}", config::VERSION, config::NAME_SUFFIX).as_str());
dialog.set_transient_for(&window);
dialog.set_version(Some(format!("{}{}", config::VERSION, config::NAME_SUFFIX).as_str()));
dialog.set_transient_for(Some(&window));
dialog.set_modal(true);
dialog.set_authors(&["Felix Häcker"]);
......@@ -237,7 +241,13 @@ impl App {
}
fn import_stations(&self) {
let import_dialog = gtk::FileChooserNative::new("Select database to import", &self.window.widget, gtk::FileChooserAction::Open, "Import", "Cancel");
let import_dialog = gtk::FileChooserNative::new(
Some("Select database to import"),
Some(&self.window.widget),
gtk::FileChooserAction::Open,
Some("Import"),
Some("Cancel"),
);
let filter = gtk::FileFilter::new();
import_dialog.set_filter(&filter);
filter.add_mime_type("application/json"); // Shortwave library format
......@@ -263,7 +273,7 @@ impl App {
}
fn export_stations(&self) {
let export_dialog = gtk::FileChooserNative::new("Export database", &self.window.widget, gtk::FileChooserAction::Save, "Export", "Cancel");
let export_dialog = gtk::FileChooserNative::new(Some("Export database"), Some(&self.window.widget), gtk::FileChooserAction::Save, Some("Export"), Some("Cancel"));
export_dialog.set_current_name("library.json");
if gtk::ResponseType::from(export_dialog.run()) == gtk::ResponseType::Accept {
let path = export_dialog.get_file().unwrap().get_path().unwrap();
......@@ -283,4 +293,8 @@ impl App {
}
export_dialog.destroy();
}
async fn test() {
println!("hello from async");
}
}
......@@ -59,16 +59,16 @@ pub struct GstreamerBackend {
impl GstreamerBackend {
pub fn new(sender: Sender<GstreamerMessage>) -> Self {
// create gstreamer pipeline
let pipeline = Pipeline::new("recorder_pipeline");
let pipeline = Pipeline::new(Some("recorder_pipeline"));
// create pipeline elements
let uridecodebin = ElementFactory::make("uridecodebin", "uridecodebin").unwrap();
let audioconvert = ElementFactory::make("audioconvert", "audioconvert").unwrap();
let tee = ElementFactory::make("tee", "tee").unwrap();
let audio_queue = ElementFactory::make("queue", "audio_queue").unwrap();
let volume = ElementFactory::make("volume", "volume").unwrap();
let autoaudiosink = ElementFactory::make("autoaudiosink", "autoaudiosink").unwrap();
let file_queue = ElementFactory::make("queue", "file_queue").unwrap();
let uridecodebin = ElementFactory::make("uridecodebin", Some("uridecodebin")).unwrap();
let audioconvert = ElementFactory::make("audioconvert", Some("audioconvert")).unwrap();
let tee = ElementFactory::make("tee", Some("tee")).unwrap();
let audio_queue = ElementFactory::make("queue", Some("audio_queue")).unwrap();
let volume = ElementFactory::make("volume", Some("volume")).unwrap();
let autoaudiosink = ElementFactory::make("autoaudiosink", Some("autoaudiosink")).unwrap();
let file_queue = ElementFactory::make("queue", Some("file_queue")).unwrap();
let file_srcpad = file_queue.get_static_pad("src").unwrap();
// link pipeline elements
......@@ -313,13 +313,13 @@ struct RecorderBin {
impl RecorderBin {
pub fn new(song_title: String, song_path: PathBuf, pipeline: Pipeline, srcpad: &Pad) -> Self {
// Create elements
let vorbisenc = ElementFactory::make("vorbisenc", "vorbisenc").unwrap();
let oggmux = ElementFactory::make("oggmux", "oggmux").unwrap();
let filesink = ElementFactory::make("filesink", "filesink").unwrap();
let vorbisenc = ElementFactory::make("vorbisenc", Some("vorbisenc")).unwrap();
let oggmux = ElementFactory::make("oggmux", Some("oggmux")).unwrap();
let filesink = ElementFactory::make("filesink", Some("filesink")).unwrap();
filesink.set_property("location", &song_path.to_str().unwrap()).unwrap();
// Create bin itself
let bin = Bin::new("bin");
let bin = Bin::new(Some("bin"));
bin.set_property("message-forward", &true).unwrap();
// Add elements to bin and link them
......@@ -333,7 +333,7 @@ impl RecorderBin {
// Link file_srcpad with vorbisenc sinkpad using a ghostpad
let vorbisenc_sinkpad = vorbisenc.get_static_pad("sink").unwrap();
let ghostpad = gstreamer::GhostPad::new("sink", &vorbisenc_sinkpad).unwrap();
let ghostpad = gstreamer::GhostPad::new(Some("sink"), &vorbisenc_sinkpad).unwrap();
bin.add_pad(&ghostpad).unwrap();
bin.sync_state_with_parent().unwrap();
srcpad.link(&ghostpad).expect("Queue src pad cannot linked to vorbisenc sinkpad");
......
......@@ -41,7 +41,7 @@ use crate::widgets::SongListBox;
pub struct Player {
pub widget: gtk::Box,
controller: Rc<Vec<Box<Controller>>>,
controller: Rc<Vec<Box<dyn Controller>>>,
backend: Arc<Mutex<GstreamerBackend>>,
song_model: Rc<RefCell<SongModel>>,
......@@ -61,7 +61,7 @@ impl Player {
let (gst_sender, gst_receiver) = glib::MainContext::channel(glib::PRIORITY_DEFAULT);
let backend = Arc::new(Mutex::new(GstreamerBackend::new(gst_sender)));
let mut controller: Vec<Box<Controller>> = Vec::new();
let mut controller: Vec<Box<dyn Controller>> = Vec::new();
// Gtk Controller
let gtk_controller = GtkController::new(sender.clone());
......@@ -73,7 +73,7 @@ impl Player {
let mpris_controller = MprisController::new(sender.clone());
controller.push(Box::new(mpris_controller));
let controller: Rc<Vec<Box<Controller>>> = Rc::new(controller);
let controller: Rc<Vec<Box<dyn Controller>>> = Rc::new(controller);
let player = Self {
widget,
......@@ -139,7 +139,7 @@ impl Player {
});
}
fn process_gst_message(message: GstreamerMessage, controller: Rc<Vec<Box<Controller>>>, song_model: Rc<RefCell<SongModel>>, backend: Arc<Mutex<GstreamerBackend>>) -> glib::Continue {
fn process_gst_message(message: GstreamerMessage, controller: Rc<Vec<Box<dyn Controller>>>, song_model: Rc<RefCell<SongModel>>, backend: Arc<Mutex<GstreamerBackend>>) -> glib::Continue {
match message {
GstreamerMessage::SongTitleChanged(title) => {
debug!("Song title has changed: \"{}\"", title);
......
......@@ -151,11 +151,10 @@ impl Library {
let mut client = Client::new("http://www.radio-browser.info");
let connection = Connection::open(path.clone())?;
let mut stmt = connection.prepare("SELECT station_id FROM library;")?;
let mut rows = stmt.query(&[])?;
let mut rows = stmt.query(rusqlite::NO_PARAMS)?;
while let Some(result_row) = rows.next() {
let row = result_row.unwrap();
let station_id: u32 = row.get(0);
while let Ok(Some(row)) = rows.next() {
let station_id: u32 = row.get(0).unwrap();
match client.get_station_by_id(station_id)? {
Some(station) => {
......
#![feature(async_await)]
#[macro_use]
extern crate log;
extern crate pretty_env_logger;
......
......@@ -25,7 +25,7 @@ impl SongListBox {
pub fn bind_model(&self, model: &SongModel) {
let sender = self.sender.clone();
self.listbox.bind_model(&model.model, move |song| {
self.listbox.bind_model(Some(&model.model), move |song| {
let row = SongRow::new(sender.clone(), song.downcast_ref::<ObjectWrapper>().unwrap().deserialize());
row.widget.upcast::<gtk::Widget>()
});
......
......@@ -30,14 +30,14 @@ impl SongRow {
let save_button = gtk::Button::new();
save_button.set_relief(gtk::ReliefStyle::None);
save_button.set_valign(gtk::Align::Center);
let save_image = gtk::Image::new_from_icon_name("document-save-symbolic", gtk::IconSize::__Unknown(4));
let save_image = gtk::Image::new_from_icon_name(Some("document-save-symbolic"), gtk::IconSize::__Unknown(4));
save_button.add(&save_image);
button_stack.add_named(&save_button, "save");
let open_button = gtk::Button::new();
open_button.set_relief(gtk::ReliefStyle::None);
open_button.set_valign(gtk::Align::Center);
let open_image = gtk::Image::new_from_icon_name("media-playback-start-symbolic", gtk::IconSize::__Unknown(4));
let open_image = gtk::Image::new_from_icon_name(Some("media-playback-start-symbolic"), gtk::IconSize::__Unknown(4));
open_button.add(&open_image);
button_stack.add_named(&open_button, "open");
......
......@@ -41,7 +41,7 @@ impl StationDialog {
library_action_stack.set_visible_child_name("library-add");
}
widget.set_transient_for(window);
widget.set_transient_for(Some(window));
let dialog = Self {
widget,
......
......@@ -38,7 +38,7 @@ impl StationFlowBox {
pub fn bind_model(&self, model: &StationModel) {
let sender = self.sender.clone();
self.widget.bind_model(&model.model, move |station| {
self.widget.bind_model(Some(&model.model), move |station| {
let row = StationRow::new(sender.clone(), station.downcast_ref::<ObjectWrapper>().unwrap().deserialize());
row.widget.upcast::<gtk::Widget>()
});
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment