11use std:: ffi:: { CStr , CString } ;
22use std:: os:: raw:: { c_char, c_int, c_ulonglong} ;
33use std:: ptr:: null_mut;
4+ use std:: sync:: Mutex ;
45
56use crate :: player_core:: { PlayerCore , PlayerState } ;
7+ type PlayerHandle = Mutex < PlayerCore > ;
68
79const OK : c_int = 0 ;
810const ERR_NULL : c_int = -1 ;
@@ -23,7 +25,7 @@ pub extern "C" fn liplayer_create(
2325 device_name : * const c_char ,
2426 music_dir : * const c_char ,
2527 index_path : * const c_char ,
26- ) -> * mut PlayerCore {
28+ ) -> * mut PlayerHandle {
2729 let device_name = match cstr_to_string ( device_name) {
2830 Ok ( v) => v,
2931 Err ( _) => return null_mut ( ) ,
@@ -36,15 +38,15 @@ pub extern "C" fn liplayer_create(
3638 Ok ( v) => v,
3739 Err ( _) => return null_mut ( ) ,
3840 } ;
39- Box :: into_raw ( Box :: new ( PlayerCore :: new (
41+ Box :: into_raw ( Box :: new ( Mutex :: new ( PlayerCore :: new (
4042 & device_name,
4143 & music_dir,
4244 & index_path,
43- ) ) )
45+ ) ) ) )
4446}
4547
4648#[ unsafe( no_mangle) ]
47- pub extern "C" fn liplayer_destroy ( handle : * mut PlayerCore ) {
49+ pub extern "C" fn liplayer_destroy ( handle : * mut PlayerHandle ) {
4850 if handle. is_null ( ) {
4951 return ;
5052 }
@@ -56,7 +58,7 @@ pub extern "C" fn liplayer_destroy(handle: *mut PlayerCore) {
5658
5759#[ unsafe( no_mangle) ]
5860pub extern "C" fn liplayer_scan_local_library (
59- handle : * mut PlayerCore ,
61+ handle : * mut PlayerHandle ,
6062 music_dir : * const c_char ,
6163) -> c_int {
6264 if handle. is_null ( ) {
@@ -67,30 +69,37 @@ pub extern "C" fn liplayer_scan_local_library(
6769 Err ( code) => return code,
6870 } ;
6971 // SAFETY: handle is checked for null and points to a valid PlayerCore by API contract.
70- let core = unsafe { & mut * handle } ;
71- core. scan_local_library ( & music_dir) ;
72+ let core = unsafe { & * handle } ;
73+ if let Ok ( core) = core. lock ( ) {
74+ core. scan_local_library ( & music_dir) ;
75+ } else {
76+ return ERR_OP ;
77+ }
7278 OK
7379}
7480
7581#[ unsafe( no_mangle) ]
76- pub extern "C" fn liplayer_track_count ( handle : * mut PlayerCore ) -> usize {
82+ pub extern "C" fn liplayer_track_count ( handle : * mut PlayerHandle ) -> usize {
7783 if handle. is_null ( ) {
7884 return 0 ;
7985 }
8086 // SAFETY: handle is checked for null and points to a valid PlayerCore by API contract.
81- let core = unsafe { & mut * handle } ;
82- core. list_tracks ( ) . len ( )
87+ let core = unsafe { & * handle } ;
88+ core. lock ( ) . map ( |c| c . list_tracks ( ) . len ( ) ) . unwrap_or ( 0 )
8389}
8490
8591#[ unsafe( no_mangle) ]
86- pub extern "C" fn liplayer_list_tracks_json ( handle : * mut PlayerCore ) -> * mut c_char {
92+ pub extern "C" fn liplayer_list_tracks_json ( handle : * mut PlayerHandle ) -> * mut c_char {
8793 if handle. is_null ( ) {
8894 return null_mut ( ) ;
8995 }
9096 // SAFETY: handle is checked for null and points to a valid PlayerCore by API contract.
91- let core = unsafe { & mut * handle } ;
92- let tracks = core. list_tracks ( ) ;
93- let json = match serde_json:: to_string ( & tracks. iter ( ) . map ( |t| & t. path ) . collect :: < Vec < _ > > ( ) ) {
97+ let core = unsafe { & * handle } ;
98+ let tracks = match core. lock ( ) {
99+ Ok ( c) => c. list_tracks ( ) ,
100+ Err ( _) => return null_mut ( ) ,
101+ } ;
102+ let json = match serde_json:: to_string ( & tracks) {
94103 Ok ( v) => v,
95104 Err ( _) => return null_mut ( ) ,
96105 } ;
@@ -112,69 +121,87 @@ pub extern "C" fn liplayer_string_free(s: *mut c_char) {
112121}
113122
114123#[ unsafe( no_mangle) ]
115- pub extern "C" fn liplayer_play_track_at ( handle : * mut PlayerCore , index : usize ) -> c_int {
124+ pub extern "C" fn liplayer_play_track_at ( handle : * mut PlayerHandle , index : usize ) -> c_int {
116125 if handle. is_null ( ) {
117126 return ERR_NULL ;
118127 }
119128 // SAFETY: handle is checked for null and points to a valid PlayerCore by API contract.
120- let core = unsafe { & mut * handle } ;
121- match core. play_track_at ( index ) {
122- Ok ( ( ) ) => OK ,
129+ let core = unsafe { & * handle } ;
130+ match core. lock ( ) {
131+ Ok ( mut c ) => c . play_track_at ( index ) . map ( |_| OK ) . unwrap_or ( ERR_OP ) ,
123132 Err ( _) => ERR_OP ,
124133 }
125134}
126135
127136#[ unsafe( no_mangle) ]
128- pub extern "C" fn liplayer_stop ( handle : * mut PlayerCore ) -> c_int {
137+ pub extern "C" fn liplayer_stop ( handle : * mut PlayerHandle ) -> c_int {
129138 if handle. is_null ( ) {
130139 return ERR_NULL ;
131140 }
132141 // SAFETY: handle is checked for null and points to a valid PlayerCore by API contract.
133- let core = unsafe { & mut * handle } ;
134- core. stop ( ) ;
135- OK
142+ let core = unsafe { & * handle } ;
143+ if let Ok ( mut c) = core. lock ( ) {
144+ c. stop ( ) ;
145+ OK
146+ } else {
147+ ERR_OP
148+ }
136149}
137150
138151#[ unsafe( no_mangle) ]
139- pub extern "C" fn liplayer_pause ( handle : * mut PlayerCore ) -> c_int {
152+ pub extern "C" fn liplayer_pause ( handle : * mut PlayerHandle ) -> c_int {
140153 if handle. is_null ( ) {
141154 return ERR_NULL ;
142155 }
143156 // SAFETY: handle is checked for null and points to a valid PlayerCore by API contract.
144- let core = unsafe { & mut * handle } ;
145- core. pause ( ) ;
146- OK
157+ let core = unsafe { & * handle } ;
158+ if let Ok ( mut c) = core. lock ( ) {
159+ c. pause ( ) ;
160+ OK
161+ } else {
162+ ERR_OP
163+ }
147164}
148165
149166#[ unsafe( no_mangle) ]
150- pub extern "C" fn liplayer_resume ( handle : * mut PlayerCore ) -> c_int {
167+ pub extern "C" fn liplayer_resume ( handle : * mut PlayerHandle ) -> c_int {
151168 if handle. is_null ( ) {
152169 return ERR_NULL ;
153170 }
154171 // SAFETY: handle is checked for null and points to a valid PlayerCore by API contract.
155- let core = unsafe { & mut * handle } ;
156- core. resume ( ) ;
157- OK
172+ let core = unsafe { & * handle } ;
173+ if let Ok ( mut c) = core. lock ( ) {
174+ c. resume ( ) ;
175+ OK
176+ } else {
177+ ERR_OP
178+ }
158179}
159180
160181#[ unsafe( no_mangle) ]
161- pub extern "C" fn liplayer_elapsed_millis ( handle : * mut PlayerCore ) -> c_ulonglong {
182+ pub extern "C" fn liplayer_elapsed_millis ( handle : * mut PlayerHandle ) -> c_ulonglong {
162183 if handle. is_null ( ) {
163184 return 0 ;
164185 }
165186 // SAFETY: handle is checked for null and points to a valid PlayerCore by API contract.
166- let core = unsafe { & mut * handle } ;
167- core. elapsed_millis ( ) as c_ulonglong
187+ let core = unsafe { & * handle } ;
188+ core. lock ( )
189+ . map ( |c| c. elapsed_millis ( ) as c_ulonglong )
190+ . unwrap_or ( 0 )
168191}
169192
170193#[ unsafe( no_mangle) ]
171- pub extern "C" fn liplayer_state ( handle : * mut PlayerCore ) -> c_int {
194+ pub extern "C" fn liplayer_state ( handle : * mut PlayerHandle ) -> c_int {
172195 if handle. is_null ( ) {
173196 return ERR_NULL ;
174197 }
175198 // SAFETY: handle is checked for null and points to a valid PlayerCore by API contract.
176- let core = unsafe { & mut * handle } ;
177- match core. state ( ) {
199+ let core = unsafe { & * handle } ;
200+ let state = match core. lock ( ) {
201+ Ok ( c) => c. state ( ) ,
202+ Err ( _) => return ERR_OP ,
203+ } ;
204+ match state {
178205 PlayerState :: Idle => 0 ,
179206 PlayerState :: Playing => 1 ,
180207 PlayerState :: Paused => 2 ,
0 commit comments