Skip to content
Extraits de code Groupes Projets
Vérifiée Valider e04c02b7 rédigé par Kubat's avatar Kubat
Parcourir les fichiers

RUST: Create the safe rust types for the queue and the uri

parent b4ad51b3
Aucune branche associée trouvée
Aucune étiquette associée trouvée
Aucune requête de fusion associée trouvée
...@@ -9,8 +9,8 @@ pub type LktUriPtr = *mut c_void; ...@@ -9,8 +9,8 @@ pub type LktUriPtr = *mut c_void;
#[repr(C)] #[repr(C)]
pub struct LktEvent { pub struct LktEvent {
ty: c_uint, pub ty: c_uint,
attr: *const c_void, pub attr: *const c_void,
} }
#[repr(C)] #[repr(C)]
...@@ -32,6 +32,7 @@ pub enum LktUriValueType { ...@@ -32,6 +32,7 @@ pub enum LktUriValueType {
Integer = 2, Integer = 2,
} }
#[derive(Debug)]
#[repr(C)] #[repr(C)]
pub enum LktPlaybackEvent { pub enum LktPlaybackEvent {
Stop = 0, Stop = 0,
...@@ -40,12 +41,14 @@ pub enum LktPlaybackEvent { ...@@ -40,12 +41,14 @@ pub enum LktPlaybackEvent {
Toggle = 3, Toggle = 3,
} }
#[derive(Debug)]
#[repr(C)] #[repr(C)]
pub enum LktDbUpdateEvent { pub enum LktDbUpdateEvent {
Finished = 0, Finished = 0,
Progress = 1, Progress = 1,
} }
#[derive(Debug, PartialEq, Eq)]
#[repr(C)] #[repr(C)]
pub enum LktEventType { pub enum LktEventType {
Null = 0, Null = 0,
...@@ -64,6 +67,59 @@ pub enum LktEventType { ...@@ -64,6 +67,59 @@ pub enum LktEventType {
TouchKara = (1 << 13), TouchKara = (1 << 13),
} }
impl TryFrom<usize> for LktEventType {
type Error = ();
fn try_from(value: usize) -> Result<Self, Self::Error> {
use LktEventType::*;
match value {
0 => Ok(Null),
x if x == (1 << 1) => Ok(PlayPos),
x if x == (1 << 2) => Ok(PlayFile),
x if x == (1 << 3) => Ok(PlayNext),
x if x == (1 << 4) => Ok(PlayPrev),
x if x == (1 << 5) => Ok(PlayToggle),
x if x == (1 << 6) => Ok(PropVol),
x if x == (1 << 7) => Ok(PropDur),
x if x == (1 << 8) => Ok(PropTime),
x if x == (1 << 9) => Ok(SkipCurrent),
x if x == (1 << 10) => Ok(DbUpdating),
x if x == (1 << 11) => Ok(DbUpdateTotal),
x if x == (1 << 12) => Ok(DbUpdateTick),
x if x == (1 << 13) => Ok(TouchKara),
_ => Err(()),
}
}
}
impl TryFrom<usize> for LktDbUpdateEvent {
type Error = ();
fn try_from(value: usize) -> Result<Self, Self::Error> {
use LktDbUpdateEvent::*;
match value {
0 => Ok(Finished),
1 => Ok(Progress),
_ => Err(()),
}
}
}
impl TryFrom<usize> for LktPlaybackEvent {
type Error = ();
fn try_from(value: usize) -> Result<Self, Self::Error> {
use LktPlaybackEvent::*;
match value {
0 => Ok(Stop),
1 => Ok(Play),
2 => Ok(Pause),
3 => Ok(Toggle),
_ => Err(()),
}
}
}
impl std::ops::BitOr<u32> for LktEventType { impl std::ops::BitOr<u32> for LktEventType {
type Output = u32; type Output = u32;
fn bitor(self, rhs: u32) -> Self::Output { fn bitor(self, rhs: u32) -> Self::Output {
...@@ -89,9 +145,9 @@ impl std::ops::BitOr<LktEventType> for LktEventType { ...@@ -89,9 +145,9 @@ impl std::ops::BitOr<LktEventType> for LktEventType {
pub mod LktMacroEvent { pub mod LktMacroEvent {
use super::LktEventType::*; use super::LktEventType::*;
lazy_static::lazy_static! { lazy_static::lazy_static! {
pub static ref EVENT_PLAY: u32 = PlayPos | PlayFile | PlayNext | PlayPrev | PlayToggle | SkipCurrent; pub static ref PLAY: u32 = PlayPos | PlayFile | PlayNext | PlayPrev | PlayToggle | SkipCurrent;
pub static ref EVENT_PROP: u32 = PropVol | PropDur | PropTime; pub static ref PROP: u32 = PropVol | PropDur | PropTime;
pub static ref LKT_MACRO_EVENT_UPDATE: u32 = DbUpdating | DbUpdateTick | DbUpdateTotal | TouchKara; pub static ref UPDATE: u32 = DbUpdating | DbUpdateTick | DbUpdateTotal | TouchKara;
} }
} }
...@@ -107,7 +163,7 @@ extern "C" { ...@@ -107,7 +163,7 @@ extern "C" {
pub(crate) fn lkt_queue_has_event(_: LktQueuePtr, _: LktEventType) -> bool; pub(crate) fn lkt_queue_has_event(_: LktQueuePtr, _: LktEventType) -> bool;
pub(crate) fn lkt_queue_send(_: LktQueuePtr, _: LktEventType, _: *const c_void); pub(crate) fn lkt_queue_send(_: LktQueuePtr, _: LktEventType, _: *const c_void);
pub(crate) fn lkt_queue_handle(_: LktQueuePtr) -> LktEvent; pub(crate) fn lkt_queue_handle(_: LktQueuePtr) -> LktEvent;
pub(crate) fn lkt_queue_make_available(_: LktQueuePtr, _: LktEventType); pub(crate) fn lkt_queue_make_available(_: LktQueuePtr, _: c_int);
} }
unsafe fn str_len(str: *const c_char) -> usize { unsafe fn str_len(str: *const c_char) -> usize {
......
mod queue;
mod uri;
pub use self::{queue::*, uri::*};
pub(self) use crate::c_types::*;
use super::*;
// Re-export some types, here enums because they are re-used in the safe part of
// the implementation.
pub use crate::c_types::{LktDbUpdateEvent, LktEventType, LktPlaybackEvent};
/// The safe wrapper around the lektord's queue implemented in the C part of the
/// code-base.
pub struct LktCQueue {
ptr: LktQueuePtr,
}
#[derive(Debug)]
pub enum LktEventValue {
/// No event / null event.
Null,
/// Action to play a kara by its position in the queue.
PlayPos(usize),
/// Action to play next kara.
PlayNext,
/// Action to play previous kara.
PlayPrev,
/// Playback state changed.
PlayToggle(LktPlaybackEvent),
/// The volume changed. This is buggy because MPV don't always notify us
/// when the volume is changed externally.
PropVol(usize),
/// The total playtime of the current file changed, only when changing the
/// playing file.
PropDur(usize),
/// Got the playback time of the currently played file.
PropTime(usize),
/// Shall skip the current kara.
SkipCurrent,
/// The status of the update process may have changed.
DbUpdating(LktDbUpdateEvent),
/// Add a specified quantity to the update total.
DbUpdateTotal(usize),
/// Mark a specified quantity as updated.
DbUpdateTick(usize),
/// The specified kara was present during the update, don't delete it.
TouchKara(u64),
}
impl LktEventValue {
pub fn get_type(&self) -> LktEventType {
match self {
LktEventValue::Null => LktEventType::Null,
LktEventValue::PlayPos(_) => LktEventType::PlayPos,
LktEventValue::PlayNext => LktEventType::PlayNext,
LktEventValue::PlayPrev => LktEventType::PlayPrev,
LktEventValue::PlayToggle(_) => LktEventType::PlayToggle,
LktEventValue::PropVol(_) => LktEventType::PropVol,
LktEventValue::PropDur(_) => LktEventType::PropDur,
LktEventValue::PropTime(_) => LktEventType::PropTime,
LktEventValue::SkipCurrent => LktEventType::SkipCurrent,
LktEventValue::DbUpdating(_) => LktEventType::DbUpdating,
LktEventValue::DbUpdateTotal(_) => LktEventType::DbUpdateTotal,
LktEventValue::DbUpdateTick(_) => LktEventType::DbUpdateTick,
LktEventValue::TouchKara(_) => LktEventType::TouchKara,
}
}
}
impl From<LktQueuePtr> for LktCQueue {
fn from(ptr: LktQueuePtr) -> Self {
Self { ptr }
}
}
impl LktCQueue {
pub fn has_event(&self, ty: LktEventType) -> bool {
unsafe { lkt_queue_has_event(self.ptr, ty) }
}
pub fn send(&self, val: LktEventValue) {
use LktEventValue::*;
let ty = val.get_type();
if ty == LktEventType::Null {
return;
}
let val = match val {
PlayNext | PlayPrev | SkipCurrent | Null => std::ptr::null(),
PlayToggle(x) => (x as usize) as *const _,
DbUpdating(x) => (x as usize) as *const _,
PlayPos(x) | PropVol(x) | PropDur(x) | PropTime(x) | DbUpdateTotal(x)
| DbUpdateTick(x) => x as *const _,
TouchKara(x) => (x as usize) as *const _,
};
unsafe { lkt_queue_send(self.ptr, ty, val) }
}
pub fn handle(&mut self) -> Option<LktEventValue> {
use LktEventValue::*;
let LktEvent { ty, attr } = unsafe { lkt_queue_handle(self.ptr) };
Some(match LktEventType::try_from(ty as usize).ok()? {
LktEventType::PlayToggle => PlayToggle(LktPlaybackEvent::try_from(attr as usize).ok()?),
LktEventType::DbUpdating => DbUpdating(LktDbUpdateEvent::try_from(attr as usize).ok()?),
LktEventType::TouchKara => TouchKara(u64::try_from(attr as usize).ok()?),
LktEventType::PlayPos => PlayPos(attr as usize),
LktEventType::PropVol => PropVol(attr as usize),
LktEventType::PropDur => PropDur(attr as usize),
LktEventType::PropTime => PropTime(attr as usize),
LktEventType::DbUpdateTotal => DbUpdateTotal(attr as usize),
LktEventType::DbUpdateTick => DbUpdateTick(attr as usize),
LktEventType::PlayNext => PlayNext,
LktEventType::PlayPrev => PlayPrev,
LktEventType::SkipCurrent => SkipCurrent,
LktEventType::Null | LktEventType::PlayFile => return None,
})
}
/// Make an event available.
pub fn make_available(&mut self, ty: LktEventType) {
use crate::c_int;
unsafe { lkt_queue_make_available(self.ptr, (ty as usize) as c_int) }
}
/// Make play event available.
pub fn make_available_playback_events(&mut self) {
use crate::{c_int, c_types::LktMacroEvent::PLAY};
unsafe { lkt_queue_make_available(self.ptr, (*PLAY) as c_int) }
}
/// Make properties event available.
pub fn make_available_property_events(&mut self) {
use crate::{c_int, c_types::LktMacroEvent::PROP};
unsafe { lkt_queue_make_available(self.ptr, (*PROP) as c_int) }
}
/// Make update event available.
pub fn make_available_update_events(&mut self) {
use crate::{c_int, c_types::LktMacroEvent::UPDATE};
unsafe { lkt_queue_make_available(self.ptr, (*UPDATE) as c_int) }
}
}
use crate::c_types::*; use super::*;
pub struct LktCQueue { /// The safe wrapper around the lektord's URI implemented in the C part of the
ptr: LktQueuePtr, /// code-base.
pub struct LktCUri {
ptr: LktUriPtr,
} }
pub enum LktEventValue<'a> { pub enum LktUriField {
Null, /// The id of the kara must match the URI.
Integer(usize), Id,
String(&'a str),
}
pub struct LktCUri { /// One of the kara makers must match the value of the URI.
ptr: LktUriPtr, KaraMaker,
/// The origin of the kara must match the URI.
Origin,
/// The title of the kara must match the query.
Title,
/// The source of the kara must match the query.
Source,
/// The type of the kara must match the query.
Type,
/// The language of the kara must match the value in the URI.
Language,
/// Do a fuzzy search with the value if the URI. This is the default action
/// for an URI.
FuzzySearch,
} }
impl From<LktQueuePtr> for LktCQueue { impl Default for LktUriField {
fn from(ptr: LktQueuePtr) -> Self { fn default() -> Self {
Self { ptr } LktUriField::FuzzySearch
} }
} }
...@@ -35,7 +54,11 @@ impl LktCUri { ...@@ -35,7 +54,11 @@ impl LktCUri {
unsafe { lkt_uri_get_value_type(self.ptr) } unsafe { lkt_uri_get_value_type(self.ptr) }
} }
pub fn get_value_as_str(&self) -> Option<&str> { /// Get the URI as a string slice, if the contained thing is not a string
/// slice, get None. Note that if the string is not valid using this
/// function may crash the system. If everything is alright in the C part of
/// the code, there should not be any issue.
fn get_value_as_str(&self) -> Option<&str> {
use LktUriValueType::*; use LktUriValueType::*;
match self.get_value_type() { match self.get_value_type() {
Null | Integer => None, Null | Integer => None,
...@@ -43,7 +66,9 @@ impl LktCUri { ...@@ -43,7 +66,9 @@ impl LktCUri {
} }
} }
pub fn get_value_as_int(&self) -> Option<i32> { /// Get the URI value as an int. If the contained thing is not an integer
/// returns None.
fn get_value_as_int(&self) -> Option<i32> {
use LktUriValueType::*; use LktUriValueType::*;
match self.get_value_type() { match self.get_value_type() {
Null | String => None, Null | String => None,
...@@ -51,8 +76,22 @@ impl LktCUri { ...@@ -51,8 +76,22 @@ impl LktCUri {
} }
} }
fn get_column_name(&self) -> &str { /// Get the field that query the uri. See the `inc/lektor/common.h`,
unsafe { ptr_to_str(lkt_uri_get_column_name(self.ptr)) } /// `LKT_DB_*` defines. If those defines change, the implementation of this
/// function must also change.
pub fn get_query_field(&self) -> Option<LktUriField> {
use LktUriField::*;
match unsafe { ptr_to_str(lkt_uri_get_column_name(self.ptr)) } {
"id" => Some(Id),
"source_name" => Some(Source),
"song_title" => Some(Title),
"category" => Some(Origin),
"song_type" => Some(Type),
"author_name" => Some(KaraMaker),
"language" => Some(Language),
"string" => Some(FuzzySearch),
_ => None,
}
} }
} }
...@@ -65,28 +104,3 @@ impl From<LktCUri> for String { ...@@ -65,28 +104,3 @@ impl From<LktCUri> for String {
} }
} }
} }
impl LktCQueue {
pub fn has_event(&self, ty: LktEventType) -> bool {
unsafe { lkt_queue_has_event(self.ptr, ty) }
}
pub fn send(&self, ty: LktEventType, val: LktEventValue) {
use LktEventValue::*;
let val = match val {
Null => std::ptr::null(),
Integer(x) => x as *const _,
String(str) => str.as_ptr() as *const _,
};
unsafe { lkt_queue_send(self.ptr, ty, val) }
todo!("verify validity of (ty, val)")
}
pub fn handle(&mut self) -> Option<(LktEventType, LktEventValue)> {
todo!("verify validity of (ty, val)")
}
pub fn make_available(&mut self, ty: LktEventType) {
unsafe { lkt_queue_make_available(self.ptr, ty) }
}
}
0% Chargement en cours ou .
You are about to add 0 people to the discussion. Proceed with caution.
Terminez d'abord l'édition de ce message.
Veuillez vous inscrire ou vous pour commenter