1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
use std::ffi::CString;
use mpdclient_sys::{
mpd_connection_get_error, mpd_run_rescan, mpd_run_update, mpd_send_list_all,
mpd_send_list_all_meta, mpd_send_list_files, mpd_send_list_meta,
};
use crate::{
Error,
entity::EntityReceiver,
error::{MpdError, Result},
};
use super::Connection;
/// Intermediate to bundle database functions with MPD.
pub struct Database<'a> {
connection: &'a Connection,
}
impl<'a> Database<'a> {
pub(super) fn new(connection: &'a Connection) -> Self {
Self { connection }
}
/// Returns a recursive list of all [Entities](crate::entity::Entity) **without** metadata in
/// the MPD database or a specified directory.
///
/// # Errors
///
/// Returns [`Error::Mpd`] if MPD returns an error.
pub fn list_all(&self, path: Option<&str>) -> Result<EntityReceiver<'_>> {
let ret = unsafe {
match path {
Some(p) => {
let cstr = CString::new(p)?;
mpd_send_list_all(self.connection.connection(), cstr.as_ptr())
}
None => mpd_send_list_all(self.connection.connection(), std::ptr::null()),
}
};
self.connection.get_bool_error(|| ret)?;
Ok(EntityReceiver::new(self.connection))
}
/// Returns a recursive list of all [Entities](crate::entity::Entity) **with** metadata in the
/// MPD database or a specified directory.
///
/// # Errors
///
/// Returns [`Error::Mpd`] if MPD returns an error.
pub fn list_all_meta(&self, path: Option<&str>) -> Result<EntityReceiver<'_>> {
let ret = unsafe {
match path {
Some(p) => {
let cstr = CString::new(p)?;
mpd_send_list_all_meta(self.connection.connection(), cstr.as_ptr())
}
None => mpd_send_list_all_meta(self.connection.connection(), std::ptr::null()),
}
};
self.connection.get_bool_error(|| ret)?;
Ok(EntityReceiver::new(self.connection))
}
/// Returns a **non**-recursive list of all [Entities](crate::entity::Entity) with metadata in
/// a specified directory.
///
/// # Errors
///
/// Returns [`Error::Mpd`] if MPD returns an error.
pub fn list_meta(&self, path: Option<&str>) -> Result<EntityReceiver<'_>> {
let ret = unsafe {
match path {
Some(p) => {
let cstr = CString::new(p)?;
mpd_send_list_meta(self.connection.connection(), cstr.as_ptr())
}
None => mpd_send_list_meta(self.connection.connection(), std::ptr::null()),
}
};
self.connection.get_bool_error(|| ret)?;
Ok(EntityReceiver::new(self.connection))
}
/// Returns a **non**-recursive list of all files in a specified directory.
///
/// # Errors
///
/// Returns [`Error::Mpd`] if MPD returns an error.
pub fn list_files(&self, path: Option<&str>) -> Result<EntityReceiver<'_>> {
let ret = unsafe {
match path {
Some(p) => {
let cstr = CString::new(p)?;
mpd_send_list_files(self.connection.connection(), cstr.as_ptr())
}
None => mpd_send_list_files(self.connection.connection(), std::ptr::null()),
}
};
self.connection.get_bool_error(|| ret)?;
Ok(EntityReceiver::new(self.connection))
}
fn get_update_id_error(&self, func: impl Fn() -> u32) -> Result<u32> {
let ret = func();
if ret == 0 {
// unreachable!(), because error is ensured with ret == 0
Err(Error::from_mpd(
MpdError::from_sys(
unsafe { mpd_connection_get_error(self.connection.connection()) },
self.connection.connection(),
)
.unwrap_or_else(|| unreachable!()),
self.connection.connection(),
))
} else {
Ok(ret)
}
}
/// Updates the MPD database. Returns the update id.
///
/// # Errors
///
/// Returns [`Error::Mpd`] if MPD returns an error.
pub fn update(&self, path: Option<&str>) -> Result<u32> {
let ret = unsafe {
match path {
Some(p) => {
let cstr = CString::new(p)?;
mpd_run_update(self.connection.connection(), cstr.as_ptr())
}
None => mpd_run_update(self.connection.connection(), std::ptr::null()),
}
};
self.get_update_id_error(|| ret)
}
/// Rescans the MPD database. Same as update but also scans unmodified files. Returns the
/// update id.
///
/// # Errors
///
/// Returns [`Error::Mpd`] if MPD returns an error.
pub fn rescan(&self, path: Option<&str>) -> Result<u32> {
let ret = unsafe {
match path {
Some(p) => {
let cstr = CString::new(p)?;
mpd_run_rescan(self.connection.connection(), cstr.as_ptr())
}
None => mpd_run_rescan(self.connection.connection(), std::ptr::null()),
}
};
self.get_update_id_error(|| ret)
}
}