Daemonize the musicbrainz thread #217
@ -1,33 +1,18 @@
|
|||||||
use std::{
|
use std::{collections::VecDeque, sync::mpsc::{self, TryRecvError}};
|
||||||
collections::VecDeque,
|
|
||||||
sync::{
|
|
||||||
mpsc::{self, TryRecvError},
|
|
||||||
Arc, Mutex,
|
|
||||||
},
|
|
||||||
thread, time,
|
|
||||||
};
|
|
||||||
|
|
||||||
use musichoard::collection::{
|
use musichoard::collection::{artist::Artist, musicbrainz::IMusicBrainzRef};
|
||||||
album::AlbumMeta,
|
|
||||||
artist::{Artist, ArtistMeta},
|
|
||||||
musicbrainz::{IMusicBrainzRef, Mbid},
|
|
||||||
};
|
|
||||||
|
|
||||||
use crate::tui::{
|
use crate::tui::{
|
||||||
app::{
|
app::{
|
||||||
machine::{match_state::MatchState, App, AppInner, AppMachine},
|
machine::{match_state::MatchState, App, AppInner, AppMachine},
|
||||||
AppPublicState, AppState, IAppEventFetch, IAppInteractFetch, MatchStateInfo,
|
AppPublicState, AppState, IAppEventFetch, IAppInteractFetch, MatchStateInfo,
|
||||||
},
|
},
|
||||||
event::{Event, EventSender},
|
|
||||||
lib::{
|
lib::{
|
||||||
external::musicbrainz::daemon::{
|
external::musicbrainz::daemon::{
|
||||||
ApiParams, Job, JobInstance, JobPriority, ReturnSender, SearchArtistParams,
|
ApiParams, Job, JobInstance, JobPriority, ReturnSender, SearchArtistParams,
|
||||||
SearchParams, SearchReleaseGroupParams,
|
SearchParams, SearchReleaseGroupParams,
|
||||||
},
|
},
|
||||||
interface::musicbrainz::{
|
interface::musicbrainz::api::Error as MbError,
|
||||||
self,
|
|
||||||
api::{Error as MbError, IMusicBrainz},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -43,7 +28,6 @@ impl FetchState {
|
|||||||
|
|
||||||
pub type FetchError = MbError;
|
pub type FetchError = MbError;
|
||||||
pub type FetchResult = Result<MatchStateInfo, FetchError>;
|
pub type FetchResult = Result<MatchStateInfo, FetchError>;
|
||||||
pub type FetchSender = mpsc::Sender<FetchResult>;
|
|
||||||
pub type FetchReceiver = mpsc::Receiver<FetchResult>;
|
pub type FetchReceiver = mpsc::Receiver<FetchResult>;
|
||||||
|
|
||||||
impl AppMachine<FetchState> {
|
impl AppMachine<FetchState> {
|
||||||
@ -115,58 +99,6 @@ impl AppMachine<FetchState> {
|
|||||||
let job = Job::new(JobPriority::Background, JobInstance::new(tx, queue));
|
let job = Job::new(JobPriority::Background, JobInstance::new(tx, queue));
|
||||||
inner.musicbrainz.send(job);
|
inner.musicbrainz.send(job);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fetch_artist(
|
|
||||||
musicbrainz: Arc<Mutex<dyn IMusicBrainz + Send>>,
|
|
||||||
fetch_tx: FetchSender,
|
|
||||||
events: EventSender,
|
|
||||||
artist: ArtistMeta,
|
|
||||||
) {
|
|
||||||
let result = musicbrainz.lock().unwrap().search_artist(&artist);
|
|
||||||
let result = result.map(|list| MatchStateInfo::artist(artist, list));
|
|
||||||
Self::send_fetch_result(&fetch_tx, &events, result).ok();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn fetch_albums(
|
|
||||||
musicbrainz: Arc<Mutex<dyn IMusicBrainz + Send>>,
|
|
||||||
fetch_tx: FetchSender,
|
|
||||||
events: EventSender,
|
|
||||||
arid: Mbid,
|
|
||||||
albums: Vec<AlbumMeta>,
|
|
||||||
) {
|
|
||||||
let mut musicbrainz = musicbrainz.lock().unwrap();
|
|
||||||
let mut album_iter = albums.into_iter().peekable();
|
|
||||||
while let Some(album) = album_iter.next() {
|
|
||||||
if album.musicbrainz.is_some() {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
let result = musicbrainz.search_release_group(&arid, &album);
|
|
||||||
let result = result.map(|list| MatchStateInfo::album(album, list));
|
|
||||||
if Self::send_fetch_result(&fetch_tx, &events, result).is_err() {
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
|
|
||||||
if album_iter.peek().is_some() {
|
|
||||||
thread::sleep(time::Duration::from_secs(1));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn send_fetch_result(
|
|
||||||
fetch_tx: &FetchSender,
|
|
||||||
events: &EventSender,
|
|
||||||
result: Result<MatchStateInfo, musicbrainz::api::Error>,
|
|
||||||
) -> Result<(), ()> {
|
|
||||||
// If receiver disconnects just drop the rest.
|
|
||||||
fetch_tx.send(result).map_err(|_| ())?;
|
|
||||||
|
|
||||||
// If this send fails the event listener is dead. Don't panic as this function runs in a
|
|
||||||
// detached thread so this might be happening during normal shut down.
|
|
||||||
events.send(Event::FetchResultReady).map_err(|_| ())?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<AppMachine<FetchState>> for App {
|
impl From<AppMachine<FetchState>> for App {
|
||||||
|
@ -8,16 +8,14 @@ mod match_state;
|
|||||||
mod reload_state;
|
mod reload_state;
|
||||||
mod search_state;
|
mod search_state;
|
||||||
|
|
||||||
use std::sync::{mpsc, Arc, Mutex};
|
use std::sync::mpsc;
|
||||||
|
|
||||||
use crate::tui::{
|
use crate::tui::{
|
||||||
app::{
|
app::{
|
||||||
selection::Selection, AppMode, AppPublic, AppPublicInner, AppPublicState, AppState, IApp,
|
selection::Selection, AppMode, AppPublic, AppPublicInner, AppPublicState, AppState, IApp,
|
||||||
IAppAccess, IAppBase, IAppState,
|
IAppAccess, IAppBase, IAppState,
|
||||||
},
|
},
|
||||||
event::EventSender,
|
lib::{external::musicbrainz::daemon::Job, IMusicHoard},
|
||||||
lib::{external::musicbrainz::daemon::Job, interface::musicbrainz::api::IMusicBrainz, IMusicHoard},
|
|
||||||
RequestChannel,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use browse_state::BrowseState;
|
use browse_state::BrowseState;
|
||||||
|
15
src/tui/lib/external/musicbrainz/daemon/mod.rs
vendored
15
src/tui/lib/external/musicbrainz/daemon/mod.rs
vendored
@ -163,14 +163,14 @@ impl MusicBrainzDaemon {
|
|||||||
api: MB,
|
api: MB,
|
||||||
request_receiver: mpsc::Receiver<Job>,
|
request_receiver: mpsc::Receiver<Job>,
|
||||||
events: EventSender,
|
events: EventSender,
|
||||||
) {
|
) -> Result<(), Error> {
|
||||||
let daemon = MusicBrainzDaemon {
|
let daemon = MusicBrainzDaemon {
|
||||||
api: Box::new(api),
|
api: Box::new(api),
|
||||||
request_receiver,
|
request_receiver,
|
||||||
job_queue: JobQueue::new(),
|
job_queue: JobQueue::new(),
|
||||||
events,
|
events,
|
||||||
};
|
};
|
||||||
daemon.main();
|
daemon.main()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn wait_for_jobs(&mut self) -> Result<(), Error> {
|
fn wait_for_jobs(&mut self) -> Result<(), Error> {
|
||||||
@ -195,13 +195,12 @@ impl MusicBrainzDaemon {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn execute_next_job(&mut self) -> Option<()> {
|
fn execute_next_job(&mut self) -> Option<()> {
|
||||||
while let Some(instance) = self.job_queue.front_mut() {
|
if let Some(instance) = self.job_queue.front_mut() {
|
||||||
match instance.execute_next(&mut self.api, &mut self.events) {
|
let result = instance.execute_next(&mut self.api, &mut self.events);
|
||||||
Some(()) => return Some(()),
|
if result.is_none() {
|
||||||
None => {
|
self.job_queue.pop_front();
|
||||||
self.job_queue.pop_front();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
return Some(());
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user