Started wrapper
This commit is contained in:
parent
b5c9401d01
commit
96ac035bc9
61
Cargo.lock
generated
61
Cargo.lock
generated
@ -369,6 +369,30 @@ version = "0.25.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9ffe3a660c3a1b10e96f304a9413d673b2118d62e4520f7ddf4a4faccfe8b9b9"
|
checksum = "9ffe3a660c3a1b10e96f304a9413d673b2118d62e4520f7ddf4a4faccfe8b9b9"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "flume"
|
||||||
|
version = "0.11.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "55ac459de2512911e4b674ce33cf20befaba382d05b62b008afc1c8b57cbf181"
|
||||||
|
dependencies = [
|
||||||
|
"futures-core",
|
||||||
|
"futures-sink",
|
||||||
|
"nanorand",
|
||||||
|
"spin",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-core"
|
||||||
|
version = "0.3.30"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-sink"
|
||||||
|
version = "0.3.30"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "generic-array"
|
name = "generic-array"
|
||||||
version = "0.14.7"
|
version = "0.14.7"
|
||||||
@ -386,8 +410,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
|
checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
|
"js-sys",
|
||||||
"libc",
|
"libc",
|
||||||
"wasi",
|
"wasi",
|
||||||
|
"wasm-bindgen",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -550,6 +576,16 @@ dependencies = [
|
|||||||
"windows-targets 0.52.6",
|
"windows-targets 0.52.6",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lock_api"
|
||||||
|
version = "0.4.12"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"scopeguard",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "log"
|
name = "log"
|
||||||
version = "0.4.22"
|
version = "0.4.22"
|
||||||
@ -597,6 +633,15 @@ version = "0.2.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
|
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "nanorand"
|
||||||
|
version = "0.7.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6a51313c5820b0b02bd422f4b44776fbf47961755c74ce64afc73bfad10226c3"
|
||||||
|
dependencies = [
|
||||||
|
"getrandom",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ndk"
|
name = "ndk"
|
||||||
version = "0.8.0"
|
version = "0.8.0"
|
||||||
@ -924,6 +969,12 @@ dependencies = [
|
|||||||
"winapi-util",
|
"winapi-util",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "scopeguard"
|
||||||
|
version = "1.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.206"
|
version = "1.0.206"
|
||||||
@ -999,6 +1050,15 @@ version = "1.3.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "spin"
|
||||||
|
version = "0.9.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
|
||||||
|
dependencies = [
|
||||||
|
"lock_api",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "strsim"
|
name = "strsim"
|
||||||
version = "0.8.0"
|
version = "0.8.0"
|
||||||
@ -1010,6 +1070,7 @@ name = "sweetmusic"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"file-format",
|
"file-format",
|
||||||
|
"flume",
|
||||||
"metadata",
|
"metadata",
|
||||||
"rand",
|
"rand",
|
||||||
"regex",
|
"regex",
|
||||||
|
@ -5,6 +5,7 @@ edition = "2021"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
file-format = "0.25.0"
|
file-format = "0.25.0"
|
||||||
|
flume = "0.11.0"
|
||||||
metadata = "0.1.9"
|
metadata = "0.1.9"
|
||||||
rand = "0.8.5"
|
rand = "0.8.5"
|
||||||
regex = "1.10.6"
|
regex = "1.10.6"
|
||||||
|
@ -43,6 +43,7 @@ pub mod audioplayer {
|
|||||||
///If true, the player will loop back to the beginning of the playlist when it's done
|
///If true, the player will loop back to the beginning of the playlist when it's done
|
||||||
pub repeating: bool,
|
pub repeating: bool,
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------Enums
|
//-----------------------------------Enums
|
||||||
|
125
src/audiowrapper.rs
Normal file
125
src/audiowrapper.rs
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
pub mod audiowrapper {
|
||||||
|
|
||||||
|
use std::thread::*;
|
||||||
|
use std::error::Error;
|
||||||
|
use std::time::Duration;
|
||||||
|
use std::io::BufReader;
|
||||||
|
use std::fs::File;
|
||||||
|
use std::any::Any;
|
||||||
|
|
||||||
|
use flume::{Receiver, Sender};
|
||||||
|
use rodio::{Decoder, OutputStream, Sink, Source};
|
||||||
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
|
use crate::playlist::playlist::*;
|
||||||
|
use crate::songmeta::songmeta::*;
|
||||||
|
|
||||||
|
|
||||||
|
//A wrapper around a rodio sink that allows for better controls.
|
||||||
|
//Can't use sink queues so I implement myself...
|
||||||
|
//Reads songs in threads, one at a time so we can stop, play, pause, insert songs in playlist, etc.
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct AudioWrapper {
|
||||||
|
tx: Sender<ThreadCom>,
|
||||||
|
rx: Receiver<ThreadCom>,
|
||||||
|
pub playlist: Playlist,
|
||||||
|
handle: Option<JoinHandle<()>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
//Used for handling communication with the thread
|
||||||
|
enum ThreadCom {
|
||||||
|
Stop,
|
||||||
|
Pause,
|
||||||
|
Unpause,
|
||||||
|
SendPos,
|
||||||
|
Pos(Duration),
|
||||||
|
SetVol(f32),
|
||||||
|
GetVol,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AudioWrapper {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
let (tx, rx) = flume::unbounded();
|
||||||
|
Self {
|
||||||
|
tx: tx,
|
||||||
|
rx: rx,
|
||||||
|
playlist: Playlist::new(),
|
||||||
|
handle: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Inner function used in a thread to read music
|
||||||
|
fn sub_sink(path: String, tx: Sender<ThreadCom>, rx: Receiver<ThreadCom>) {
|
||||||
|
let path = Path::new(&path);
|
||||||
|
let (stream, stream_handle) = OutputStream::try_default().unwrap();
|
||||||
|
let sink = Sink::try_new(&stream_handle).unwrap();
|
||||||
|
let file = BufReader::new(File::open(&path).unwrap());
|
||||||
|
let source = Decoder::new(file).unwrap();
|
||||||
|
sink.append(source);
|
||||||
|
|
||||||
|
loop {
|
||||||
|
|
||||||
|
let recv = rx.try_recv();
|
||||||
|
|
||||||
|
match recv {
|
||||||
|
Ok(v) => {
|
||||||
|
match v {
|
||||||
|
ThreadCom::Stop => {
|
||||||
|
sink.stop();
|
||||||
|
break;
|
||||||
|
},
|
||||||
|
ThreadCom::Pause => {
|
||||||
|
sink.pause();
|
||||||
|
},
|
||||||
|
ThreadCom::Unpause => {
|
||||||
|
sink.play();
|
||||||
|
},
|
||||||
|
ThreadCom::SendPos => {
|
||||||
|
tx.try_send(ThreadCom::Pos(sink.get_pos()));
|
||||||
|
},
|
||||||
|
ThreadCom::SetVol(w) => {
|
||||||
|
sink.set_volume(w);
|
||||||
|
},
|
||||||
|
ThreadCom::GetVol => {
|
||||||
|
tx.try_send(ThreadCom::SetVol(sink.volume()));
|
||||||
|
},
|
||||||
|
ThreadCom::Pos(w) => {
|
||||||
|
let _ = sink.try_seek(w);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
},
|
||||||
|
Err(_) => (),
|
||||||
|
};
|
||||||
|
|
||||||
|
//Finished
|
||||||
|
if sink.len() < 1 {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///Reads ONE song by starting a sink in a new thread.
|
||||||
|
///Stop any previous song playing.
|
||||||
|
pub fn play_at(&mut self, index: usize){
|
||||||
|
self.playlist.check_index(index.clone()).unwrap();
|
||||||
|
self.stop();
|
||||||
|
let path = self.playlist.songs[index].path.clone();
|
||||||
|
let tx2 = self.tx.clone();
|
||||||
|
let rx2 = self.rx.clone();
|
||||||
|
let handle = spawn(|| {
|
||||||
|
AudioWrapper::sub_sink(path, tx2, rx2);
|
||||||
|
});
|
||||||
|
self.handle = Some(handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn stop(&mut self) {
|
||||||
|
match &self.handle {
|
||||||
|
Some(h) => {
|
||||||
|
self.tx.try_send(ThreadCom::Stop).unwrap();
|
||||||
|
self.handle.take().expect("Called stop on non-running thread").join().expect("Could not join");
|
||||||
|
},
|
||||||
|
None => (),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
50
src/main.rs
50
src/main.rs
@ -7,48 +7,22 @@ use crate::playlist::playlist::*;
|
|||||||
pub mod audioplayer;
|
pub mod audioplayer;
|
||||||
use crate::audioplayer::audioplayer::*;
|
use crate::audioplayer::audioplayer::*;
|
||||||
|
|
||||||
|
pub mod audiowrapper;
|
||||||
|
use crate::audiowrapper::audiowrapper::*;
|
||||||
|
|
||||||
use std::thread::sleep;
|
use std::thread::sleep;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let mysong = SongMeta::frompath(&String::from("/home/justine/Music/one.mp3")).unwrap();
|
let mut wrap = AudioWrapper::new();
|
||||||
let mysong2 = SongMeta::frompath(&String::from("/home/justine/Music/two.mp3")).unwrap();
|
let mut pl = Playlist::new();
|
||||||
let mysong3 = SongMeta::frompath(&String::from("/home/justine/Music/three.mp3")).unwrap();
|
pl.add_song_from_path(&String::from("/home/justine/Music/1.mp3")).unwrap();
|
||||||
|
wrap.playlist = pl;
|
||||||
|
wrap.play_at(0);
|
||||||
let mut playlist = Playlist::new();
|
sleep(Duration::from_secs(5));
|
||||||
playlist.songs.push(mysong);
|
wrap.stop();
|
||||||
playlist.songs.push(mysong2);
|
sleep(Duration::from_secs(5));
|
||||||
playlist.songs.push(mysong3);
|
dbg!(wrap);
|
||||||
|
|
||||||
let mut player = AudioPlayer::new().unwrap();
|
|
||||||
|
|
||||||
|
|
||||||
player.playlist = playlist;
|
|
||||||
player.play_at(0);
|
|
||||||
dbg!(player.get_state());
|
|
||||||
sleep(Duration::from_secs(3));
|
|
||||||
|
|
||||||
dbg!("SKIPPING FORW TWICE");
|
|
||||||
player.skip_forward();
|
|
||||||
player.skip_forward();
|
|
||||||
sleep(Duration::from_secs(3));
|
|
||||||
|
|
||||||
dbg!("BACKW 5");
|
|
||||||
player.skip_backwards();
|
|
||||||
player.skip_backwards();
|
|
||||||
player.skip_backwards();
|
|
||||||
player.skip_backwards();
|
|
||||||
player.skip_backwards();
|
|
||||||
|
|
||||||
player.unpause();
|
|
||||||
player.set_vol(0.9);
|
|
||||||
|
|
||||||
loop {
|
|
||||||
println!("{:?} - {:?}", player.get_state(), player.get_vol());
|
|
||||||
sleep(Duration::from_secs(1));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user