From 34ac38765b6e95950cfa42dea6bce3f559b4fb7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hubert=20Figui=C3=A8re?= Date: Fri, 5 Jan 2024 18:44:04 -0500 Subject: [PATCH] glib: channel is deprecated, use async_channel instead MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Hubert Figuière --- src/audio_stack.rs | 17 ++++---- src/instruments/fluidlite_ui.rs | 75 +++++++++++++++++---------------- src/soundbanks/downloader.rs | 36 +++++++++------- src/synth/fluidlite_synth.rs | 15 ++++--- 4 files changed, 76 insertions(+), 67 deletions(-) diff --git a/src/audio_stack.rs b/src/audio_stack.rs index 16b0699..00fdc0c 100644 --- a/src/audio_stack.rs +++ b/src/audio_stack.rs @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -// SPDX-FileCopyrightText: (c) 2020-2023 Hubert Figuière +// SPDX-FileCopyrightText: (c) 2020-2024 Hubert Figuière // use std::cell::RefCell; @@ -43,7 +43,7 @@ pub struct AudioStack { /// sample rate in Hz. sample_rate: u32, /// To send messages to the audio stack. - pub sender: glib::Sender, + pub sender: async_channel::Sender, } impl AudioStack { @@ -51,8 +51,7 @@ impl AudioStack { pub fn new(midi_control: MidiControlSender) -> Arc { let (mixer, mixer_handle) = audio::Mixer::new(); - let (sender, receiver) = - glib::MainContext::channel::(glib::Priority::DEFAULT); + let (sender, receiver) = async_channel::unbounded::(); let engine = audio::Engine::start(Box::new(mixer)).expect("Failed to start audio engine."); let sample_rate = engine.sample_rate(); @@ -65,11 +64,11 @@ impl AudioStack { sender, }); - let stack2 = stack.clone(); - receiver.attach(None, move |msg| { - stack2.messages(msg); - glib::ControlFlow::Continue - }); + glib::spawn_future_local(glib::clone!(@strong stack => async move { + while let Ok(msg) = receiver.recv().await { + stack.messages(msg); + } + })); stack } diff --git a/src/instruments/fluidlite_ui.rs b/src/instruments/fluidlite_ui.rs index 5d97f63..99456d6 100644 --- a/src/instruments/fluidlite_ui.rs +++ b/src/instruments/fluidlite_ui.rs @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -// SPDX-FileCopyrightText: (c) 2020-2023 Hubert Figuière +// SPDX-FileCopyrightText: (c) 2020-2024 Hubert Figuière // //! Implement the UI for the [FluidLite synth][fluidlite_synth::FluidLiteSynth]. @@ -25,7 +25,7 @@ pub struct FluidLiteUi { /// The [`FluidLiteSynth`][fluidlite_synth::FluidLiteSynth] to control. handle: fluidlite_synth::FluidLiteSynthHandle, /// UI messages received. - receiver: Option>, + receiver: Option>, } impl FluidLiteUi { @@ -36,7 +36,7 @@ impl FluidLiteUi { /// `handle` is the handle for the synth, to send commands. pub fn new( _ui: &str, - receiver: glib::Receiver, + receiver: async_channel::Receiver, handle: &fluidlite_synth::FluidLiteSynthHandle, ) -> Self { FluidLiteUi { @@ -108,45 +108,46 @@ impl super::InstrumentUi for FluidLiteUi { }); if let Some(receiver) = self.receiver.take() { - receiver.attach(None, glib::clone!(@weak program_list => @default-return glib::ControlFlow::Break, move |message| { - match message { - Message::Banks(banks) => { - // populate program list - let model = program_list.model().or_else(|| { - // The tree store contain the bank and preset encoded into column 1 - // bank is bits 8-15, preset is 0-8 (actually 7 bits each) - let treestore = gtk4::ListStore::new(&[glib::Type::STRING, glib::Type::U32]); - program_list.set_model(Some(&treestore)); - - program_list.model() - }).map(|m| m.downcast::().unwrap()).unwrap(); - model.clear(); - - let mut preselected: Option = None; - let selected_program = settings::get_uint_value(SETTINGS_PROGRAM_SELECTED); - for bank in banks.banks { - for preset in bank.1 { - let iter = model.append(); - let program: u32 = ((bank.0 as u32) << 8) + preset.0 as u32; - if program == selected_program { - preselected = Some(iter); + glib::spawn_future_local(glib::clone!(@weak program_list => async move { + while let Ok(message) = receiver.recv().await { + match message { + Message::Banks(banks) => { + // populate program list + let model = program_list.model().or_else(|| { + // The tree store contain the bank and preset encoded into column 1 + // bank is bits 8-15, preset is 0-8 (actually 7 bits each) + let treestore = gtk4::ListStore::new(&[glib::Type::STRING, glib::Type::U32]); + program_list.set_model(Some(&treestore)); + + program_list.model() + }).map(|m| m.downcast::().unwrap()).unwrap(); + model.clear(); + + let mut preselected: Option = None; + let selected_program = settings::get_uint_value(SETTINGS_PROGRAM_SELECTED); + for bank in banks.banks { + for preset in bank.1 { + let iter = model.append(); + let program: u32 = ((bank.0 as u32) << 8) + preset.0 as u32; + if program == selected_program { + preselected = Some(iter); + } + let line = format!("{:03}-{:03} {}", bank.0, preset.0, preset.1); + model.set(&iter, &[(0, &line), (1, &program)]); } - let line = format!("{:03}-{:03} {}", bank.0, preset.0, preset.1); - model.set(&iter, &[(0, &line), (1, &program)]); } - } - let col = program_list.column(0).unwrap(); - if preselected.is_none() { - preselected = model.iter_first(); - } - if let Some(path) = preselected.map(|iter| model.path(&iter)) { - program_list.selection().select_path(&path); - program_list.row_activated(&path, Some(&col)); - program_list.scroll_to_cell(Some(&path), Some(&col), false, 0.0, 0.0); + let col = program_list.column(0).unwrap(); + if preselected.is_none() { + preselected = model.iter_first(); + } + if let Some(path) = preselected.map(|iter| model.path(&iter)) { + program_list.selection().select_path(&path); + program_list.row_activated(&path, Some(&col)); + program_list.scroll_to_cell(Some(&path), Some(&col), false, 0.0, 0.0); + } } } } - glib::ControlFlow::Continue })); } } diff --git a/src/soundbanks/downloader.rs b/src/soundbanks/downloader.rs index e880e9a..5a1e668 100644 --- a/src/soundbanks/downloader.rs +++ b/src/soundbanks/downloader.rs @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -// SPDX-FileCopyrightText: (c) 2021-2023 Hubert Figuière +// SPDX-FileCopyrightText: (c) 2021-2024 Hubert Figuière // use async_trait::async_trait; @@ -13,6 +13,7 @@ use super::file::SingleFileDownloader; use super::git::GitDownloader; use super::Soundbank; use crate::config; +use crate::toolkit; /// Downloader error #[derive(Debug, thiserror::Error)] @@ -63,13 +64,13 @@ pub trait Downloader: Send { /// Download manager, that will send back [messages][crate::AudioMessage]. pub struct DownloadManager { - sender: gtk4::glib::Sender, + sender: async_channel::Sender, } impl DownloadManager { /// Create the download manager with `sender` from the /// [`AudioStack`][crate::audio_stack::AudioStack]. - pub fn new(sender: gtk4::glib::Sender) -> Self { + pub fn new(sender: async_channel::Sender) -> Self { DownloadManager { sender } } @@ -95,12 +96,16 @@ impl DownloadManager { pub fn download(&self, soundbank: &Soundbank) -> Result<(), Error> { use super::Type; debug!("downloading {} to {:?}", &soundbank.name, &soundbank.path); + let soundbank_id = soundbank.id.clone(); + if let Some(p) = &soundbank.path { if Self::download_is_valid(p) { - print_on_err!(self.sender.send(crate::AudioMessage::SoundbankAvailable( - soundbank.id.clone(), - p.to_path_buf() - ))); + let sender = self.sender.clone(); + let path = p.to_path_buf(); + toolkit::utils::send_async_any!( + crate::AudioMessage::SoundbankAvailable(soundbank_id, path), + sender + ); debug!("Already downloaded"); return Err(Error::AlreadyDownloaded); } @@ -118,12 +123,13 @@ impl DownloadManager { }; let p = downloader.get_target_directory(); + let sender = self.sender.clone(); if Self::download_is_valid(&p) { debug!("Found target directory"); - print_on_err!(self.sender.send(crate::AudioMessage::SoundbankAvailable( - soundbank.id.clone(), - p - ))); + toolkit::utils::send_async_any!( + crate::AudioMessage::SoundbankAvailable(soundbank_id, p), + sender + ); debug!("Already downloaded"); return Err(Error::AlreadyDownloaded); } else { @@ -140,10 +146,10 @@ impl DownloadManager { let path = rx.recv().unwrap(); crate::ui::display_message_async(i18n("Download finished.")); - print_on_err!(self.sender.send(crate::AudioMessage::SoundbankAvailable( - soundbank.id.clone(), - path - ))); + toolkit::utils::send_async_any!( + crate::AudioMessage::SoundbankAvailable(soundbank_id, path), + sender + ); } Ok(()) } diff --git a/src/synth/fluidlite_synth.rs b/src/synth/fluidlite_synth.rs index 568aeac..5129f6b 100644 --- a/src/synth/fluidlite_synth.rs +++ b/src/synth/fluidlite_synth.rs @@ -1,18 +1,18 @@ // SPDX-License-Identifier: GPL-3.0-or-later -// SPDX-FileCopyrightText: (c) 2020-2022 Hubert Figuière +// SPDX-FileCopyrightText: (c) 2020-2024 Hubert Figuière // use std::path::PathBuf; use crossbeam_channel::{self, Receiver, Sender}; use fluidlite::{IsFont, IsPreset}; -use gtk4::glib; use midi_control as midi; use crate::audio::AudioSource; use crate::config; use crate::instruments; use crate::instruments::fluidlite_ui; +use crate::toolkit; use super::{BoxedHandle, Plugin, SynthHandle}; @@ -125,7 +125,7 @@ pub struct FluidLiteSynth { /// The optional UI handle. /// /// For `FluidLiteSynth`, when used with a preset soundfont, there is no UI. - ui: Option>, + ui: Option>, /// The synth synth: fluidlite::Synth, /// The messages receiver for [`Message`]. @@ -201,7 +201,11 @@ impl AudioSource for FluidLiteSynth { self.load_soundfont(path).map(|fontid| { self.list_banks_and_presets(fontid).map(|banks| { if let Some(sender) = &self.ui { - print_on_err!(sender.send(fluidlite_ui::Message::Banks(banks))); + let sender = sender.clone(); + toolkit::utils::send_async_any!( + fluidlite_ui::Message::Banks(banks), + sender + ); } }) }); @@ -256,8 +260,7 @@ impl FluidLiteSynth { .unwrap_or(0); } // XXX only do that if necessary. - let (sender, receiver) = - glib::MainContext::channel::(glib::Priority::DEFAULT); + let (sender, receiver) = async_channel::unbounded::(); let samples = [0.0f32; SAMPLES_SIZE]; let this = FluidLiteSynth { ui: Some(sender), -- GitLab