fix(playback): add thread::sleep(Duration::from_millis(10))

work in progress
This commit is contained in:
Tsiry Sandratraina
2022-12-03 22:00:04 +03:00
parent 69571f9627
commit df81fe1328
10 changed files with 546 additions and 5 deletions

6
Cargo.lock generated
View File

@@ -1735,9 +1735,9 @@ dependencies = [
[[package]]
name = "ctor"
version = "0.1.23"
version = "0.1.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cdffe87e1d521a10f9696f833fe502293ea446d7f256c06128293a4119bdf4cb"
checksum = "6d2301688392eb071b0bf1a37be05c469d3cc4dbbd95df672fe28ab021e6a096"
dependencies = [
"quote",
"syn",
@@ -3790,11 +3790,13 @@ dependencies = [
"async-graphql",
"async-graphql-tide",
"chrono",
"ctor",
"cuid",
"futures-channel",
"futures-util",
"md5",
"music-player-entity",
"music-player-migration",
"music-player-playback",
"music-player-scanner",
"music-player-settings",

View File

@@ -39,6 +39,13 @@ version = "0.1.5"
path = "../types"
version = "0.1.1"
[dev-dependencies.music-player-migration]
path = "../migration"
version = "0.1.4"
[dev-dependencies]
ctor = "0.1.26"
[dependencies]
async-graphql = "4.0.15"
tide = "0.16.0"

View File

@@ -1,3 +1,6 @@
#[cfg(test)]
mod tests;
use async_graphql::Schema;
use schema::{Mutation, Query, Subscription};

View File

View File

@@ -0,0 +1,103 @@
use async_graphql::*;
use music_player_playback::player::Player;
use std::sync::Arc;
use super::setup_schema;
#[tokio::test]
async fn tracks() {
let (schema, cmd_tx, cmd_rx, tracklist, backend, audio_format) = setup_schema().await;
let (_, _) = Player::new(
move || backend(None, audio_format),
|_| {},
Arc::clone(&cmd_tx),
Arc::clone(&cmd_rx),
Arc::clone(&tracklist),
);
}
#[tokio::test]
async fn artists() {
let (schema, cmd_tx, cmd_rx, tracklist, backend, audio_format) = setup_schema().await;
let (_, _) = Player::new(
move || backend(None, audio_format),
|_| {},
Arc::clone(&cmd_tx),
Arc::clone(&cmd_rx),
Arc::clone(&tracklist),
);
let resp = schema
.execute(
r#"
query Artists {
artists {
id
name
}
}
"#,
)
.await;
eprintln!("{:?}", resp);
assert_eq!(resp.errors.len(), 0);
}
#[tokio::test]
async fn albums() {
let (schema, cmd_tx, cmd_rx, tracklist, backend, audio_format) = setup_schema().await;
let (_, _) = Player::new(
move || backend(None, audio_format),
|_| {},
Arc::clone(&cmd_tx),
Arc::clone(&cmd_rx),
Arc::clone(&tracklist),
);
}
#[tokio::test]
async fn track() {
let (schema, cmd_tx, cmd_rx, tracklist, backend, audio_format) = setup_schema().await;
let (_, _) = Player::new(
move || backend(None, audio_format),
|_| {},
Arc::clone(&cmd_tx),
Arc::clone(&cmd_rx),
Arc::clone(&tracklist),
);
}
#[tokio::test]
async fn artist() {
let (schema, cmd_tx, cmd_rx, tracklist, backend, audio_format) = setup_schema().await;
let (_, _) = Player::new(
move || backend(None, audio_format),
|_| {},
Arc::clone(&cmd_tx),
Arc::clone(&cmd_rx),
Arc::clone(&tracklist),
);
}
#[tokio::test]
async fn album() {
let (schema, cmd_tx, cmd_rx, tracklist, backend, audio_format) = setup_schema().await;
let (_, _) = Player::new(
move || backend(None, audio_format),
|_| {},
Arc::clone(&cmd_tx),
Arc::clone(&cmd_rx),
Arc::clone(&tracklist),
);
}
#[tokio::test]
async fn search() {
let (schema, cmd_tx, cmd_rx, tracklist, backend, audio_format) = setup_schema().await;
let (_, _) = Player::new(
move || backend(None, audio_format),
|_| {},
Arc::clone(&cmd_tx),
Arc::clone(&cmd_rx),
Arc::clone(&tracklist),
);
}

115
graphql/src/tests/mod.rs Normal file
View File

@@ -0,0 +1,115 @@
use std::{env, sync::Arc};
use async_graphql::Schema;
use futures_util::FutureExt;
use music_player_entity::{album, artist, artist_tracks, track};
use music_player_playback::{
audio_backend::{self, rodio::RodioSink, Sink},
config::AudioFormat,
player::PlayerCommand,
};
use music_player_scanner::scan_directory;
use music_player_storage::Database;
use music_player_tracklist::Tracklist;
use sea_orm::ActiveModelTrait;
use tokio::sync::{
mpsc::{UnboundedReceiver, UnboundedSender},
Mutex,
};
use crate::{
schema::{Mutation, Query, Subscription},
MusicPlayerSchema,
};
pub mod library;
pub mod playback;
pub mod playlist;
pub mod tracklist;
#[cfg(test)]
#[ctor::ctor]
fn initialize() {
let runtime = tokio::runtime::Builder::new_multi_thread()
.enable_all()
.build()
.unwrap();
runtime.block_on(setup_database());
}
pub async fn setup_schema() -> (
MusicPlayerSchema,
Arc<std::sync::Mutex<UnboundedSender<PlayerCommand>>>,
Arc<std::sync::Mutex<UnboundedReceiver<PlayerCommand>>>,
Arc<std::sync::Mutex<Tracklist>>,
fn(Option<String>, AudioFormat) -> Box<dyn Sink>,
AudioFormat,
) {
let audio_format = AudioFormat::default();
let backend = audio_backend::find(Some(RodioSink::NAME.to_string())).unwrap();
let (cmd_tx, cmd_rx) = tokio::sync::mpsc::unbounded_channel();
let cmd_tx = Arc::new(std::sync::Mutex::new(cmd_tx));
let cmd_rx = Arc::new(std::sync::Mutex::new(cmd_rx));
let tracklist = Arc::new(std::sync::Mutex::new(Tracklist::new_empty()));
let db = Arc::new(Mutex::new(Database::new().await));
(
Schema::build(
Query::default(),
Mutation::default(),
Subscription::default(),
)
.data(db)
.data(Arc::clone(&cmd_tx))
.data(Arc::clone(&tracklist))
.finish(),
Arc::clone(&cmd_tx),
Arc::clone(&cmd_rx),
Arc::clone(&tracklist),
backend,
audio_format,
)
}
async fn setup_database() {
env::set_var("MUSIC_PLAYER_APPLICATION_DIRECTORY", "/tmp");
env::set_var("MUSIC_PLAYER_MUSIC_DIRECTORY", "/tmp/audio");
env::set_var(
"MUSIC_PLAYER_DATABASE_URL",
"sqlite:///tmp/music-player.sqlite3",
);
env::set_var("DATABASE_URL", "sqlite:///tmp/music-player.sqlite3");
migration::run().await;
scan_directory(move |song, db| {
async move {
let item: artist::ActiveModel = song.try_into().unwrap();
match item.insert(db.get_connection()).await {
Ok(_) => (),
Err(_) => (),
}
let item: album::ActiveModel = song.try_into().unwrap();
match item.insert(db.get_connection()).await {
Ok(_) => (),
Err(_) => (),
}
let item: track::ActiveModel = song.try_into().unwrap();
match item.insert(db.get_connection()).await {
Ok(_) => (),
Err(_) => (),
}
let item: artist_tracks::ActiveModel = song.try_into().unwrap();
match item.insert(db.get_connection()).await {
Ok(_) => (),
Err(_) => (),
}
}
.boxed()
})
.await
.unwrap_or_default();
}

View File

@@ -0,0 +1,54 @@
use super::setup_schema;
use music_player_playback::player::Player;
use std::sync::Arc;
#[tokio::test]
async fn currently_playing_song() {
setup_schema().await;
}
#[tokio::test]
async fn next() {
setup_schema().await;
}
#[tokio::test]
async fn previous() {
setup_schema().await;
}
#[tokio::test]
async fn play() {
let (schema, cmd_tx, cmd_rx, tracklist, backend, audio_format) = setup_schema().await;
let (_, _) = Player::new(
move || backend(None, audio_format),
|_| {},
Arc::clone(&cmd_tx),
Arc::clone(&cmd_rx),
Arc::clone(&tracklist),
);
}
#[tokio::test]
async fn pause() {
let (schema, cmd_tx, cmd_rx, tracklist, backend, audio_format) = setup_schema().await;
let (_, _) = Player::new(
move || backend(None, audio_format),
|_| {},
Arc::clone(&cmd_tx),
Arc::clone(&cmd_rx),
Arc::clone(&tracklist),
);
}
#[tokio::test]
async fn stop() {
let (schema, cmd_tx, cmd_rx, tracklist, backend, audio_format) = setup_schema().await;
let (_, _) = Player::new(
move || backend(None, audio_format),
|_| {},
Arc::clone(&cmd_tx),
Arc::clone(&cmd_rx),
Arc::clone(&tracklist),
);
}

View File

@@ -0,0 +1,172 @@
use music_player_playback::player::Player;
use super::setup_schema;
use std::sync::Arc;
#[tokio::test]
async fn playlist() {
let (schema, cmd_tx, cmd_rx, tracklist, backend, audio_format) = setup_schema().await;
let (_, _) = Player::new(
move || backend(None, audio_format),
|_| {},
Arc::clone(&cmd_tx),
Arc::clone(&cmd_rx),
Arc::clone(&tracklist),
);
}
#[tokio::test]
async fn playlists() {
let (schema, cmd_tx, cmd_rx, tracklist, backend, audio_format) = setup_schema().await;
let (_, _) = Player::new(
move || backend(None, audio_format),
|_| {},
Arc::clone(&cmd_tx),
Arc::clone(&cmd_rx),
Arc::clone(&tracklist),
);
}
#[tokio::test]
async fn folder() {
let (schema, cmd_tx, cmd_rx, tracklist, backend, audio_format) = setup_schema().await;
let (_, _) = Player::new(
move || backend(None, audio_format),
|_| {},
Arc::clone(&cmd_tx),
Arc::clone(&cmd_rx),
Arc::clone(&tracklist),
);
}
#[tokio::test]
async fn folders() {
let (schema, cmd_tx, cmd_rx, tracklist, backend, audio_format) = setup_schema().await;
let (_, _) = Player::new(
move || backend(None, audio_format),
|_| {},
Arc::clone(&cmd_tx),
Arc::clone(&cmd_rx),
Arc::clone(&tracklist),
);
}
#[tokio::test]
async fn create_playlist() {
let (schema, cmd_tx, cmd_rx, tracklist, backend, audio_format) = setup_schema().await;
let (_, _) = Player::new(
move || backend(None, audio_format),
|_| {},
Arc::clone(&cmd_tx),
Arc::clone(&cmd_rx),
Arc::clone(&tracklist),
);
}
#[tokio::test]
async fn delete_playlist() {
let (schema, cmd_tx, cmd_rx, tracklist, backend, audio_format) = setup_schema().await;
let (_, _) = Player::new(
move || backend(None, audio_format),
|_| {},
Arc::clone(&cmd_tx),
Arc::clone(&cmd_rx),
Arc::clone(&tracklist),
);
}
#[tokio::test]
async fn add_track_to_playlist() {
let (schema, cmd_tx, cmd_rx, tracklist, backend, audio_format) = setup_schema().await;
let (_, _) = Player::new(
move || backend(None, audio_format),
|_| {},
Arc::clone(&cmd_tx),
Arc::clone(&cmd_rx),
Arc::clone(&tracklist),
);
}
#[tokio::test]
async fn remove_track_from_playlist() {
let (schema, cmd_tx, cmd_rx, tracklist, backend, audio_format) = setup_schema().await;
let (_, _) = Player::new(
move || backend(None, audio_format),
|_| {},
Arc::clone(&cmd_tx),
Arc::clone(&cmd_rx),
Arc::clone(&tracklist),
);
}
#[tokio::test]
async fn rename_playlist() {
let (schema, cmd_tx, cmd_rx, tracklist, backend, audio_format) = setup_schema().await;
let (_, _) = Player::new(
move || backend(None, audio_format),
|_| {},
Arc::clone(&cmd_tx),
Arc::clone(&cmd_rx),
Arc::clone(&tracklist),
);
}
#[tokio::test]
async fn create_folder() {
let (schema, cmd_tx, cmd_rx, tracklist, backend, audio_format) = setup_schema().await;
let (_, _) = Player::new(
move || backend(None, audio_format),
|_| {},
Arc::clone(&cmd_tx),
Arc::clone(&cmd_rx),
Arc::clone(&tracklist),
);
}
#[tokio::test]
async fn delete_folder() {
let (schema, cmd_tx, cmd_rx, tracklist, backend, audio_format) = setup_schema().await;
let (_, _) = Player::new(
move || backend(None, audio_format),
|_| {},
Arc::clone(&cmd_tx),
Arc::clone(&cmd_rx),
Arc::clone(&tracklist),
);
}
#[tokio::test]
async fn rename_folder() {
let (schema, cmd_tx, cmd_rx, tracklist, backend, audio_format) = setup_schema().await;
let (_, _) = Player::new(
move || backend(None, audio_format),
|_| {},
Arc::clone(&cmd_tx),
Arc::clone(&cmd_rx),
Arc::clone(&tracklist),
);
}
#[tokio::test]
async fn move_playlist_to_folder() {
let (schema, cmd_tx, cmd_rx, tracklist, backend, audio_format) = setup_schema().await;
let (_, _) = Player::new(
move || backend(None, audio_format),
|_| {},
Arc::clone(&cmd_tx),
Arc::clone(&cmd_rx),
Arc::clone(&tracklist),
);
}
#[tokio::test]
async fn move_playlists_to_folder() {
let (schema, cmd_tx, cmd_rx, tracklist, backend, audio_format) = setup_schema().await;
let (_, _) = Player::new(
move || backend(None, audio_format),
|_| {},
Arc::clone(&cmd_tx),
Arc::clone(&cmd_rx),
Arc::clone(&tracklist),
);
}

View File

@@ -0,0 +1,88 @@
use music_player_playback::player::Player;
use std::sync::Arc;
use super::setup_schema;
#[tokio::test]
async fn tracklist_tracks() {
let (schema, cmd_tx, cmd_rx, tracklist, backend, audio_format) = setup_schema().await;
let (_, _) = Player::new(
move || backend(None, audio_format),
|_| {},
Arc::clone(&cmd_tx),
Arc::clone(&cmd_rx),
Arc::clone(&tracklist),
);
}
#[tokio::test]
async fn add_track() {
let (schema, cmd_tx, cmd_rx, tracklist, backend, audio_format) = setup_schema().await;
let (_, _) = Player::new(
move || backend(None, audio_format),
|_| {},
Arc::clone(&cmd_tx),
Arc::clone(&cmd_rx),
Arc::clone(&tracklist),
);
}
#[tokio::test]
async fn add_tracks() {
let (schema, cmd_tx, cmd_rx, tracklist, backend, audio_format) = setup_schema().await;
let (_, _) = Player::new(
move || backend(None, audio_format),
|_| {},
Arc::clone(&cmd_tx),
Arc::clone(&cmd_rx),
Arc::clone(&tracklist),
);
}
#[tokio::test]
async fn clear_tracklist() {
let (schema, cmd_tx, cmd_rx, tracklist, backend, audio_format) = setup_schema().await;
let (_, _) = Player::new(
move || backend(None, audio_format),
|_| {},
Arc::clone(&cmd_tx),
Arc::clone(&cmd_rx),
Arc::clone(&tracklist),
);
}
#[tokio::test]
async fn remove_track() {
let (schema, cmd_tx, cmd_rx, tracklist, backend, audio_format) = setup_schema().await;
let (_, _) = Player::new(
move || backend(None, audio_format),
|_| {},
Arc::clone(&cmd_tx),
Arc::clone(&cmd_rx),
Arc::clone(&tracklist),
);
}
#[tokio::test]
async fn remove_tracks() {
let (schema, cmd_tx, cmd_rx, tracklist, backend, audio_format) = setup_schema().await;
let (_, _) = Player::new(
move || backend(None, audio_format),
|_| {},
Arc::clone(&cmd_tx),
Arc::clone(&cmd_rx),
Arc::clone(&tracklist),
);
}
#[tokio::test]
async fn play_track_at() {
let (schema, cmd_tx, cmd_rx, tracklist, backend, audio_format) = setup_schema().await;
let (_, _) = Player::new(
move || backend(None, audio_format),
|_| {},
Arc::clone(&cmd_tx),
Arc::clone(&cmd_rx),
Arc::clone(&tracklist),
);
}

View File

@@ -1,6 +1,3 @@
use super::searcher::album::AlbumSearcher;
use super::searcher::artist::ArtistSearcher;
use super::searcher::track::TrackSearcher;
use super::*;
use music_player_types::types::{Album, Artist, Song};
use sea_orm::{ConnectionTrait, DbBackend};