@@ -17,11 +17,25 @@ const firstTime = settings.firstTime;
1717const downloadsDatabasePath = settings . downloads_database ;
1818const failedDownloadsDatabasePath = settings . failed_downloads_database
1919
20- function getResourcePath ( filename ) {
21- if ( app . isPackaged ) {
22- return path . join ( process . resourcesPath , 'app.asar.unpacked' , 'src' , filename ) ;
20+ function getPythonCommand ( ) {
21+ switch ( process . platform ) {
22+ case 'win32' :
23+ return 'py' ;
24+ case 'darwin' :
25+ case 'linux' :
26+ // fall back to python if python3 not found
27+ return new Promise ( ( resolve ) => {
28+ exec ( 'python3 --version' , ( error ) => {
29+ if ( error ) {
30+ resolve ( 'python' ) ;
31+ } else {
32+ resolve ( 'python3' ) ;
33+ }
34+ } ) ;
35+ } ) ;
36+ default :
37+ return 'python' ;
2338 }
24- return path . join ( __dirname , filename ) ;
2539}
2640
2741function loadTheSettings ( ) {
@@ -33,6 +47,15 @@ function loadTheSettings() {
3347 return getDefaultSettings ( ) ;
3448 }
3549}
50+
51+ function getResourcePath ( filename ) {
52+ if ( app . isPackaged ) {
53+ return path . join ( process . resourcesPath , 'app.asar.unpacked' , 'src' , filename )
54+ . replace ( / \\ / g, '/' ) ;
55+ }
56+ return path . join ( __dirname , filename ) . replace ( / \\ / g, '/' ) ;
57+ }
58+
3659ipcMain . handle ( 'get-default-settings' , async ( ) => {
3760 return getDefaultSettings ( ) ;
3861} ) ;
@@ -160,34 +183,44 @@ ipcMain.handle('dialog:openFolder', async (event) => {
160183 }
161184} ) ;
162185ipcMain . handle ( 'perform-search' , async ( event , { platform, query, type } ) => {
186+ const pythonCommand = await getPythonCommand ( ) ;
187+
163188 return new Promise ( ( resolve , reject ) => {
164189 let command ;
165-
190+ const scriptPath = getResourcePath ( getPythonScript ( platform ) ) ;
166191 switch ( platform ) {
167192 case 'youtube' :
168- command = `py "${ getResourcePath ( 'ytsearchapi.py' ) } " -q "${ query } " ${ type ? `-t ${ type } ` : '' } ` ;
193+ command = `${ pythonCommand } "${ scriptPath } " -q "${ query } " ${ type ? `-t ${ type } ` : '' } ` ;
169194 break ;
170195 case 'youtubeMusic' :
171- command = `py "${ getResourcePath ( 'ytmusicsearchapi.py' ) } " -q "${ query } " ${ type ? `-t ${ type } ` : 'song' } ` ;
196+ command = `${ pythonCommand } "${ scriptPath } " -q "${ query } " ${ type ? `-t ${ type } ` : 'song' } ` ;
172197 break ;
173198 case 'spotify' :
174- command = `py "${ getResourcePath ( 'spotifyapi.py' ) } " --search-${ type || 'track' } "${ query } "` ;
199+ command = `${ pythonCommand } "${ scriptPath } " --search-${ type || 'track' } "${ query } "` ;
175200 break ;
176201 case 'tidal' :
177- command = `py "${ getResourcePath ( 'tidalapi.py' ) } " --search-${ type || 'track' } "${ query } "` ;
202+ command = `${ pythonCommand } "${ scriptPath } " --search-${ type || 'track' } "${ query } "` ;
178203 break ;
179204 case 'deezer' :
180- command = `py "${ getResourcePath ( 'deezerapi.py' ) } " --search-${ type || 'track' } "${ query } "` ;
205+ command = `${ pythonCommand } "${ scriptPath } " --search-${ type || 'track' } "${ query } "` ;
181206 break ;
182207 case 'qobuz' :
183- command = `py "${ getResourcePath ( 'qobuzapi.py' ) } " --search-${ type || 'track' } "${ query } "` ;
208+ command = `${ pythonCommand } "${ scriptPath } " --search-${ type || 'track' } "${ query } "` ;
184209 break ;
185210 default :
186211 reject ( new Error ( 'Invalid platform' ) ) ;
187212 return ;
188213 }
214+ const options = {
215+ encoding : 'utf8' ,
216+ env : {
217+ ...process . env ,
218+ PYTHONIOENCODING : 'utf-8' ,
219+ PATH : process . env . PATH
220+ }
221+ } ;
189222
190- exec ( command , { encoding : 'utf8' } , ( error , stdout ) => {
223+ exec ( command , options , ( error , stdout ) => {
191224 if ( error ) {
192225 console . error ( 'Search execution error:' , error ) ;
193226 reject ( error ) ;
@@ -206,6 +239,7 @@ ipcMain.handle('perform-search', async (event, { platform, query, type }) => {
206239} ) ;
207240
208241ipcMain . handle ( 'play-media' , async ( event , { url, platform } ) => {
242+ const pythonCommand = await getPythonCommand ( ) ;
209243 return new Promise ( ( resolve , reject ) => {
210244 console . log ( 'Input URL:' , url ) ;
211245 if ( ! url ) {
@@ -215,17 +249,21 @@ ipcMain.handle('play-media', async (event, { url, platform }) => {
215249
216250 const options = {
217251 encoding : 'utf8' ,
218- env : { ...process . env , PYTHONIOENCODING : 'utf-8' }
252+ env : {
253+ ...process . env ,
254+ PYTHONIOENCODING : 'utf-8' ,
255+ PATH : process . env . PATH
256+ }
219257 } ;
220258
221259 let command ;
222-
260+ const scriptPath = getResourcePath ( getPythonStreamScript ( platform ) ) ;
223261 switch ( platform ) {
224262 case 'youtube' :
225- command = `$py "${ getResourcePath ( 'ytvideostream.py' ) } --url "${ url } "` ;
263+ command = `${ pythonCommand } "${ scriptPath } " --url "${ url } "` ;
226264 break ;
227265 case 'youtubeMusic' :
228- command = `py "${ getResourcePath ( 'ytaudiostream.py' ) } --url "${ url } "` ;
266+ command = `${ pythonCommand } "${ scriptPath } " --url "${ url } "` ;
229267 break ;
230268 case 'qobuz' :
231269 command = `custom_rip -q 4 -ndb streamurl "${ url } "` ;
@@ -439,12 +477,13 @@ function createFirstStartWindow() {
439477 } ) ;
440478
441479 ipcMain . on ( 'spawn-tidal-config' , async ( ) => {
442- console . log ( 'wayaw' ) ;
480+ const customRipCommand = process . platform === 'win32' ? 'custom_rip' : './custom_rip' ;
443481
444- const authProcess = spawn ( 'custom_rip' , [ "url" , "https://tidal.com/track/1" ] ) ;
445- authProcess . stdout . on ( 'data' , ( data ) => {
446- const output = data . toString ( 'utf-8' ) ;
447- console . log ( output ) ;
482+ const authProcess = spawn ( customRipCommand , [ "url" , "https://tidal.com/track/1" ] , {
483+ env : {
484+ ...process . env ,
485+ PATH : process . env . PATH
486+ }
448487 } ) ;
449488
450489 authProcess . stderr . on ( 'data' , ( data ) => {
@@ -456,9 +495,14 @@ function createFirstStartWindow() {
456495 } ) ;
457496 } ) ;
458497
459- ipcMain . on ( 'install-services' , ( event , services ) => {
460- const pythonProcess = spawn ( 'python' , [ getResourcePath ( 'start.py' ) , ...services ] ) ;
461-
498+ ipcMain . on ( 'install-services' , async ( event , services ) => {
499+ const pythonCommand = await getPythonCommand ( ) ;
500+ const pythonProcess = spawn ( pythonCommand , [ getResourcePath ( 'start.py' ) , ...services ] , {
501+ env : {
502+ ...process . env ,
503+ PATH : process . env . PATH
504+ }
505+ } ) ;
462506 pythonProcess . stdout . on ( 'data' , ( data ) => {
463507 // Send the output back to renderer
464508 event . sender . send ( 'python-output' , {
@@ -524,4 +568,23 @@ app.on('activate', () => {
524568 if ( BrowserWindow . getAllWindows ( ) . length === 0 ) {
525569 createWindow ( ) ;
526570 }
527- } ) ;
571+ } ) ;
572+ function getPythonScript ( platform ) {
573+ const scriptMap = {
574+ youtube : 'ytsearchapi.py' ,
575+ youtubeMusic : 'ytmusicsearchapi.py' ,
576+ spotify : 'spotifyapi.py' ,
577+ tidal : 'tidalapi.py' ,
578+ deezer : 'deezerapi.py' ,
579+ qobuz : 'qobuzapi.py'
580+ } ;
581+ return scriptMap [ platform ] || '' ;
582+ }
583+
584+ function getPythonStreamScript ( platform ) {
585+ const scriptMap = {
586+ youtube : 'ytvideostream.py' ,
587+ youtubeMusic : 'ytaudiostream.py'
588+ } ;
589+ return scriptMap [ platform ] || '' ;
590+ }
0 commit comments