This commit is contained in:
Mark
2024-12-19 18:52:56 +01:00
parent 85c79a21e1
commit d3a1facba0
20 changed files with 544 additions and 231 deletions

View File

@@ -12,7 +12,7 @@ directories = "5.0.1"
regex = "1.9.3"
speedy2d = { version = "1.12.0", optional = true }
toml = "0.7.6"
musicdb-mers = { version = "0.1.0", path = "../musicdb-mers", optional = true }
# musicdb-mers = { version = "0.1.0", path = "../musicdb-mers", optional = true }
uianimator = "0.1.1"
[features]
@@ -26,8 +26,8 @@ default = ["gui", "default-playback"]
# playback:
# enables syncplayer modes, where the client mirrors the server's playback
gui = ["speedy2d"]
merscfg = ["mers", "gui"]
mers = ["musicdb-mers"]
# merscfg = ["mers", "gui"]
# mers = ["musicdb-mers"]
playback = []
default-playback = ["playback", "musicdb-lib/default-playback"]
playback-via-playback-rs = ["playback", "musicdb-lib/playback-via-playback-rs"]

View File

@@ -1,6 +1,13 @@
# [build]
# pre-build = [
# "dpkg --add-architecture $CROSS_DEB_ARCH",
# "apt-get update && apt-get --assume-yes install libasound2-dev libasound2-dev:$CROSS_DEB_ARCH"
# ]
# default-target = "aarch64-unknown-linux-gnu"
[build]
pre-build = [
"dpkg --add-architecture $CROSS_DEB_ARCH",
"apt-get update && apt-get --assume-yes install libasound2-dev libasound2-dev:$CROSS_DEB_ARCH"
"apt-get update && apt-get --assume-yes install libasound2-dev"
]
default-target = "aarch64-unknown-linux-gnu"
default-target = "x86_64-unknown-linux-musl"

View File

@@ -362,90 +362,124 @@ impl Gui {
}
Ok(Ok(Ok(()))) => eprintln!("Info: using merscfg"),
}
database.lock().unwrap().update_endpoints.push(
musicdb_lib::data::database::UpdateEndpoint::Custom(Box::new(move |cmd| {
match &cmd.action {
Action::Resume
| Action::Pause
| Action::Stop
| Action::Save
| Action::InitComplete => {}
Action::NextSong
| Action::QueueUpdate(..)
| Action::QueueAdd(..)
| Action::QueueInsert(..)
| Action::QueueRemove(..)
| Action::QueueMove(..)
| Action::QueueMoveInto(..)
| Action::QueueGoto(..)
| Action::QueueShuffle(..)
| Action::QueueSetShuffle(..)
| Action::QueueUnshuffle(..) => {
if let Some(s) = &*event_sender_arc.lock().unwrap() {
_ = s.send_event(GuiEvent::UpdatedQueue);
{
let mut db = database.lock().unwrap();
let udepid = db.update_endpoints_id;
db.update_endpoints_id += 1;
db.update_endpoints.push((
udepid,
musicdb_lib::data::database::UpdateEndpoint::Custom(Box::new(
move |cmd| match &cmd.action {
Action::Resume
| Action::Pause
| Action::Stop
| Action::Save
| Action::InitComplete => {}
Action::NextSong
| Action::QueueUpdate(..)
| Action::QueueAdd(..)
| Action::QueueInsert(..)
| Action::QueueRemove(..)
| Action::QueueMove(..)
| Action::QueueMoveInto(..)
| Action::QueueGoto(..)
| Action::QueueShuffle(..)
| Action::QueueSetShuffle(..)
| Action::QueueUnshuffle(..) => {
if let Some(s) = &*event_sender_arc.lock().unwrap() {
_ = s.send_event(GuiEvent::UpdatedQueue);
}
}
}
Action::SyncDatabase(..)
| Action::AddSong(_)
| Action::AddAlbum(_)
| Action::AddArtist(_)
| Action::AddCover(_)
| Action::ModifySong(_)
| Action::ModifyAlbum(_)
| Action::ModifyArtist(_)
| Action::RemoveSong(_)
| Action::RemoveAlbum(_)
| Action::RemoveArtist(_)
| Action::TagSongFlagSet(..)
| Action::TagSongFlagUnset(..)
| Action::TagAlbumFlagSet(..)
| Action::TagAlbumFlagUnset(..)
| Action::TagArtistFlagSet(..)
| Action::TagArtistFlagUnset(..)
| Action::TagSongPropertySet(..)
| Action::TagSongPropertyUnset(..)
| Action::TagAlbumPropertySet(..)
| Action::TagAlbumPropertyUnset(..)
| Action::TagArtistPropertySet(..)
| Action::TagArtistPropertyUnset(..)
| Action::SetSongDuration(..) => {
if let Some(s) = &*event_sender_arc.lock().unwrap() {
_ = s.send_event(GuiEvent::UpdatedLibrary);
Action::SyncDatabase(..)
| Action::AddSong(_, _)
| Action::AddAlbum(_, _)
| Action::AddArtist(_, _)
| Action::AddCover(_, _)
| Action::ModifySong(_, _)
| Action::ModifyAlbum(_, _)
| Action::ModifyArtist(_, _)
| Action::RemoveSong(_)
| Action::RemoveAlbum(_)
| Action::RemoveArtist(_)
| Action::TagSongFlagSet(..)
| Action::TagSongFlagUnset(..)
| Action::TagAlbumFlagSet(..)
| Action::TagAlbumFlagUnset(..)
| Action::TagArtistFlagSet(..)
| Action::TagArtistFlagUnset(..)
| Action::TagSongPropertySet(..)
| Action::TagSongPropertyUnset(..)
| Action::TagAlbumPropertySet(..)
| Action::TagAlbumPropertyUnset(..)
| Action::TagArtistPropertySet(..)
| Action::TagArtistPropertyUnset(..)
| Action::SetSongDuration(..) => {
if let Some(s) = &*event_sender_arc.lock().unwrap() {
_ = s.send_event(GuiEvent::UpdatedLibrary);
}
}
}
Action::ErrorInfo(t, d) => {
let (t, d) = (t.clone(), d.clone());
notif_sender_two
.send(Box::new(move |_| {
(
Box::new(Panel::with_background(
GuiElemCfg::default(),
[Label::new(
Action::ErrorInfo(t, d) => {
let (t, d) = (t.clone(), d.clone());
notif_sender_two
.send(Box::new(move |_| {
(
Box::new(Panel::with_background(
GuiElemCfg::default(),
if t.is_empty() {
format!("Server message\n{d}")
} else {
format!("Server error ({t})\n{d}")
},
Color::WHITE,
None,
Vec2::new(0.5, 0.5),
)],
Color::from_rgba(0.0, 0.0, 0.0, 0.8),
)),
if t.is_empty() {
NotifInfo::new(Duration::from_secs(2))
} else {
NotifInfo::new(Duration::from_secs(5))
.with_highlight(Color::RED)
},
)
}))
.unwrap();
}
}
})),
);
[Label::new(
GuiElemCfg::default(),
if t.is_empty() {
format!("Server message\n{d}")
} else {
format!("Server error ({t})\n{d}")
},
Color::WHITE,
None,
Vec2::new(0.5, 0.5),
)],
Color::from_rgba(0.0, 0.0, 0.0, 0.8),
)),
if t.is_empty() {
NotifInfo::new(Duration::from_secs(2))
} else {
NotifInfo::new(Duration::from_secs(5))
.with_highlight(Color::RED)
},
)
}))
.unwrap();
}
Action::Denied(req) => {
let req = *req;
notif_sender_two
.send(Box::new(move |_| {
(
Box::new(Panel::with_background(
GuiElemCfg::default(),
[Label::new(
GuiElemCfg::default(),
format!(
"server denied {}",
if req.is_some() {
"request, maybe desynced"
} else {
"action, likely desynced"
},
),
Color::WHITE,
None,
Vec2::new(0.5, 0.5),
)],
Color::from_rgba(0.0, 0.0, 0.0, 0.8),
)),
NotifInfo::new(Duration::from_secs(1)),
)
}))
.unwrap();
}
},
)),
));
}
let no_animations = false;
Gui {
event_sender,
@@ -1307,16 +1341,10 @@ impl Gui {
}
}
GuiAction::SendToServer(action) => {
let command = self.database.lock().unwrap().seq.pack(action);
#[cfg(debug_assertions)]
eprintln!("[DEBUG] Sending command to server: {action:?}");
if let Err(e) = self
.database
.lock()
.unwrap()
.seq
.pack(action)
.to_bytes(&mut self.connection)
{
eprintln!("[DEBUG] Sending command to server: {command:?}");
if let Err(e) = command.to_bytes(&mut self.connection) {
eprintln!("Error sending command to server: {e}");
}
}

View File

@@ -2,7 +2,7 @@ use std::time::Instant;
use musicdb_lib::{
data::{song::Song, ArtistId},
server::Action,
server::{Action, Req},
};
use speedy2d::{color::Color, dimen::Vec2, shape::Rectangle};
@@ -189,7 +189,10 @@ impl GuiElem for EditorForSongs {
song.album = None;
}
info.actions
.push(GuiAction::SendToServer(Action::ModifySong(song)));
.push(GuiAction::SendToServer(Action::ModifySong(
song,
Req::none(),
)));
}
}
Event::SetArtist(name, id) => {

View File

@@ -5,7 +5,7 @@ use musicdb_lib::{
song::Song,
AlbumId, ArtistId,
},
server::Action,
server::{Action, Req},
};
use speedy2d::{
color::Color,
@@ -404,7 +404,7 @@ impl GuiElem for QueueEmptySpaceDragHandler {
dragged_add_to_queue(
dragged,
(),
|_, q| Action::QueueAdd(vec![], q),
|_, q| Action::QueueAdd(vec![], q, Req::none()),
|_, q| Action::QueueMoveInto(q, vec![]),
)
}
@@ -631,9 +631,9 @@ impl GuiElem for QueueSong {
self.path.clone(),
move |mut p: Vec<usize>, q| {
if let Some(j) = p.pop() {
Action::QueueInsert(p, if insert_below { j + 1 } else { j }, q)
Action::QueueInsert(p, if insert_below { j + 1 } else { j }, q, Req::none())
} else {
Action::QueueAdd(p, q)
Action::QueueAdd(p, q, Req::none())
}
},
move |mut p, q| {
@@ -826,7 +826,7 @@ impl GuiElem for QueueFolder {
dragged_add_to_queue(
dragged,
self.path.clone(),
|p, q| Action::QueueAdd(p, q),
|p, q| Action::QueueAdd(p, q, Req::none()),
|p, q| Action::QueueMoveInto(q, p),
)
} else {
@@ -835,7 +835,7 @@ impl GuiElem for QueueFolder {
self.path.clone(),
|mut p, q| {
let j = p.pop().unwrap_or(0);
Action::QueueInsert(p, j, q)
Action::QueueInsert(p, j, q, Req::none())
},
|p, q| Action::QueueMove(q, p),
)
@@ -903,7 +903,7 @@ impl GuiElem for QueueIndentEnd {
dragged_add_to_queue(
dragged,
self.path_insert.clone(),
|(p, j), q| Action::QueueInsert(p, j, q),
|(p, j), q| Action::QueueInsert(p, j, q, Req::none()),
|(mut p, j), q| {
p.push(j);
Action::QueueMove(q, p)
@@ -1066,7 +1066,7 @@ impl GuiElem for QueueLoop {
dragged_add_to_queue(
dragged,
p,
|p, q| Action::QueueAdd(p, q),
|p, q| Action::QueueAdd(p, q, Req::none()),
|p, q| Action::QueueMoveInto(q, p),
)
} else {

View File

@@ -2,7 +2,7 @@ use std::time::Instant;
use musicdb_lib::{
data::queue::{QueueContent, QueueFolder},
server::Action,
server::{Action, Req},
};
use speedy2d::{color::Color, dimen::Vec2, shape::Rectangle, window::VirtualKeyCode, Graphics2D};
use uianimator::{default_animator_f64_quadratic::DefaultAnimatorF64Quadratic, Animator};
@@ -126,6 +126,7 @@ impl GuiScreen {
musicdb_lib::data::queue::QueueFolder::default(),
)
.into(),
Req::none(),
))]
},
[Label::new(

View File

@@ -203,7 +203,7 @@ fn main() {
action(action);
break 'feature_if;
}
db.apply_action_unchecked_seq(action);
db.apply_action_unchecked_seq(action, None);
}
#[cfg(feature = "playback")]
if let Some(player) = &mut player {