Testaware

SCAL DLL v2.01

Nov 2nd, 2020
106
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. ; -------------------------------------------------------------------------------------
  2. ; SCAL v2.01 x86-64 DLL - Play-Library for multiple formats [1060 (x86) / 424 (x64)]
  3. ; -------------------------------------------------------------------------------------
  4. ; Peace/TST - 01.11.2020 / Purebasic 5.70
  5. ; https://testaware.wordpress.com
  6. ; -------------------------------------------------------------------------------------
  7. ; Note:  - x64: Doesn't support #C2D_MUSIC_[AMP,BAS,BMF,FCP,MED,S68,SID,TSR,V2M,YMP]
  8. ;        - x86: Install the AmpMaster_x86.dll to playback +626 exotic formats
  9. ; -------------------------------------------------------------------------------------
  10.  
  11. EnableExplicit
  12.  
  13. #SCAL_VERSION  =  201   ; * 0.01 -> 2.01
  14.  
  15. XIncludeFile   "Include\i_scal.pbi"
  16.  
  17. Global   RS_SCAL.RS_SCAL
  18.  
  19. ;************************
  20. ;{ *** LIB-INCLUDES *** }
  21.  
  22. IncludePath "Include\"
  23. XIncludeFile   "minizip_include.pbi"
  24.  
  25. IncludePath "Include\MusicLibs\"
  26.  
  27. CompilerIf  #PB_Compiler_Processor  =  #PB_Processor_x86
  28.    ;Import  "winmm_x86.lib"   :  EndImport   ; not needed coz #C2D_MUSIC_MOD
  29.    Import   "dsound_x86.lib"  :  EndImport
  30.    CompilerIf  #IsSID
  31.       Import   "masm32_x86.lib"  :  EndImport
  32.    CompilerEndIf
  33. ;CompilerElse
  34.    ;Import  "winmm.lib" :  EndImport   ; not needed coz #C2D_MUSIC_MOD
  35. CompilerEndIf
  36.  
  37. UseOGGSoundDecoder()
  38. UseFLACSoundDecoder()
  39.  
  40. ;{ #C2D_MUSIC_MOD * Native PureBasic ModPlug Library * }
  41. ; *.669;*.ABC;*.AMF;*.AMS;*.DBM;*.DMF;*.FAR;*.IT;*.J2B;*.MDL;*.MED;*.MID;*.MOD;*.MT2;*.MTM;*.OKT;*.PAT;*.PSM;*.PTM;*.S3M;*.STM;*.ULT;*.UMX;*.WAV;*.XM;*.MMCMP;*.PP
  42. ;InitSound()
  43. ;}
  44. ;{ #C2D_MUSIC_MOV * Native PureBasic Movie Library * }
  45. ; *.MP3;*.WAV;*.WMA...
  46. ;InitMovie()
  47. ;}
  48. ;{ #C2D_MUSIC_FT2 * Thanx to Olav "8bitbubsy" for the opensource FT2PLAY v1.04 * }
  49. ; Copyright (c) 2016-2020, Olav "8bitbubsy" Sørensen
  50. ; https://16-bits.org
  51. ; https://pastebin.com/0TLkMm0A
  52. ; *.FT;*.MOD;*.STK;*.XM
  53. ;Import  "winmm.lib" :  EndImport
  54. CompilerIf  #PB_Compiler_Processor  =  #PB_Processor_x64
  55.    Import   "playFT2_x64.lib"
  56.       ft2play_Close()
  57.       ft2play_GetAmp()        ; 1..32
  58.       ft2play_GetMasterVol()  ; 0..256
  59.       ft2play_GetMixerTicks() ; returns the amount of milliseconds of mixed audio (not realtime)
  60.       ft2play_GetSongName()   ; max 20 chars (21 with '\0'), string is in code page 437
  61.       ft2play_PauseSong(flag)
  62.       ft2play_PlaySong(*moduleData, length, interpolation, volumeramping, freq)  ; returns 1 = playing or 0 = error
  63.       ft2play_SetAmp(factor)           ; 1..32
  64.       ft2play_SetInterpolation(flag)   ; true/false
  65.       ft2play_SetMasterVol(vol)        ; 0..256
  66.       ft2play_SetVolumeRamping(flag)   ; true/false
  67.       ft2play_TogglePause()
  68.    EndImport
  69. CompilerElse
  70.    ImportC  "playFT2_x86.lib"
  71.       ft2play_Close()                  As "_ft2play_Close"
  72.       ft2play_GetAmp()                 As "_ft2play_GetAmp"
  73.       ft2play_GetMasterVol()           As "_ft2play_GetMasterVol"
  74.       ft2play_GetMixerTicks()          As "_ft2play_GetMixerTicks"
  75.       ft2play_GetSongName()            As "_ft2play_GetSongName"
  76.       ft2play_PauseSong(flag)          As "_ft2play_PauseSong"
  77.       ft2play_PlaySong(*moduleData, length, interpolation, volumeramping, freq)  As "_ft2play_PlaySong"
  78.       ft2play_SetAmp(factor)           As "_ft2play_SetAmp"
  79.       ft2play_SetInterpolation(flag)   As "_ft2play_SetInterpolation"
  80.       ft2play_SetMasterVol(vol)        As "_ft2play_SetMasterVol"
  81.       ft2play_SetVolumeRamping(flag)   As "_ft2play_SetVolumeRamping"
  82.       ft2play_TogglePause()            As "_ft2play_TogglePause"
  83.    EndImport
  84. CompilerEndIf
  85. ;}
  86. ;{ #C2D_MUSIC_PT2 * Thanx to Olav "8bitbubsy" for the opensource PT2PLAY v1.60 * }
  87. ; https://16-bits.org
  88. ; https://pastebin.com/pg95YduC
  89. ; *.MOD
  90. #CIA_TEMPO_MODE      =  0
  91. #VBLANK_TEMPO_MODE   =  1
  92. ;Import  "winmm.lib" :  EndImport
  93. CompilerIf  #PB_Compiler_Processor  =  #PB_Processor_x64
  94.    Import   "playPT2_x64.lib"
  95.       pt2play_Close()
  96.       pt2play_GetMasterVol()  ; 0..256
  97.       pt2play_GetMixerTicks() ; returns the amount of milliseconds of mixed audio (not realtime)
  98.       pt2play_GetSongName()   ; max 20 chars (21 with '\0'), string is in code page 437
  99.       pt2play_PauseSong(flag) ; true/false
  100.       pt2play_PlaySong(*moduleData, length, tempoMode, freq)   ; returns 1 = playing or 0 = error
  101.       pt2play_SetMasterVol(vol)     ; 0..256
  102.       pt2play_SetStereoSep(percent) ; 0..100
  103.       pt2play_TogglePause()
  104.    EndImport
  105. CompilerElse
  106.    ImportC  "playPT2_x86.lib"
  107.       pt2play_Close()               As "_pt2play_Close"
  108.       pt2play_GetMasterVol()        As "_pt2play_GetMasterVol"
  109.       pt2play_GetMixerTicks()       As "_pt2play_GetMixerTicks"
  110.       pt2play_GetSongName()         As "_pt2play_GetSongName"
  111.       pt2play_PauseSong(flag)       As "_pt2play_PauseSong"
  112.       pt2play_PlaySong(*moduleData, length, tempoMode, freq)   As "_pt2play_PlaySong"
  113.       pt2play_SetMasterVol(vol)     As "_pt2play_SetMasterVol"
  114.       pt2play_SetStereoSep(percent) As "_pt2play_SetStereoSep"
  115.       pt2play_TogglePause()         As "_pt2play_TogglePause"
  116.    EndImport
  117. CompilerEndIf
  118. ;}
  119. ;{ #C2D_MUSIC_FC4 * Thanx to Olav "8bitbubsy" for the opensource FC14PLAY v1.29 * }
  120. ; https://16-bits.org
  121. ; https://pastebin.com/VHxZ58UC
  122. ; *.FC;*.FC13;*.FC14;*.FC3;*.FC4;*.FCM;*.SMOD
  123. ;Import  "winmm.lib" :  EndImport
  124. CompilerIf  #PB_Compiler_Processor  =  #PB_Processor_x64
  125.    Import   "playFC4_x64.lib"
  126.       fc14play_Close()
  127.       fc14play_GetMasterVol()
  128.       fc14play_GetMixerTicks()   ; returns the amount of milliseconds of mixed audio (not realtime)
  129.       fc14play_PauseSong(flag)   ; true/false
  130.       fc14play_PlaySong(*moduleData, length, freq) ; returns 1 = playing or 0 = error
  131.       fc14play_SetMasterVol(vol)       ; 0..256
  132.       fc14play_SetStereoSep(percent)   ; 0..100
  133.       fc14play_TogglePause()
  134.    EndImport
  135. CompilerElse
  136.    ImportC  "playFC4_x86.lib"
  137.       fc14play_Close()                 As "_fc14play_Close"
  138.       fc14play_GetMasterVol()          As "_fc14play_GetMasterVol"
  139.       fc14play_GetMixerTicks()         As "_fc14play_GetMixerTicks"
  140.       fc14play_PauseSong(flag)         As "_fc14play_PauseSong"
  141.       fc14play_PlaySong(*moduleData, length, freq) As "_fc14play_PlaySong"
  142.       fc14play_SetMasterVol(vol)       As "_fc14play_SetMasterVol"
  143.       fc14play_SetStereoSep(percent)   As "_fc14play_SetStereoSep"
  144.       fc14play_TogglePause()           As "_fc14play_TogglePause"
  145.    EndImport
  146. CompilerEndIf
  147. ;}
  148. ;{ #C2D_MUSIC_AHX * Thanx to Olav "8bitbubsy" for the opensource AHX1PLAY v0.27 * }
  149. ; https://16-bits.org
  150. ; https://pastebin.com/fqwadbj7
  151. ; *.AHX;*.THX
  152. ;Import  "winmm.lib" :  EndImport
  153. CompilerIf  #PB_Compiler_Processor  =  #PB_Processor_x64
  154.    Import   "playAHX_x64.lib"
  155.       ahx1play_PlaySong(*moduleData, length, subsong, freq) ; returns 1 = playing or 0 = error
  156.       ahx1play_GetSongName()                                ; max 64 chars (65 with '\0'), string is in latin1
  157.       ahx1play_Close()
  158.       ahx1play_PauseSong(flag)         ; true/false
  159.       ahx1play_TogglePause()
  160.       ahx1play_GetMixerTicks()         ; returns the amount of milliseconds of mixed audio (not realtime)
  161.       ahx1play_SetStereoSep(percent)   ; 0..100
  162.    EndImport
  163. CompilerElse
  164.    ImportC  "playAHX_x86.lib"
  165.       ahx1play_PlaySong(*moduleData, length, subsong, freq) As "_ahx1play_PlaySong"
  166.       ahx1play_GetSongName()           As "_ahx1play_GetSongName"
  167.       ahx1play_Close()                 As "_ahx1play_Close"
  168.       ahx1play_PauseSong(flag)         As "_ahx1play_PauseSong"
  169.       ahx1play_TogglePause()           As "_ahx1play_TogglePause"
  170.       ahx1play_GetMixerTicks()         As "_ahx1play_GetMixerTicks"
  171.       ahx1play_SetStereoSep(percent)   As "_ahx1play_SetStereoSep"
  172.    EndImport
  173. CompilerEndIf
  174. ;}
  175. ;{ #C2D_MUSIC_STM * Thanx to Olav "8bitbubsy" for the opensource STMPLAY v0.33 * }
  176. ; https://16-bits.org
  177. ; https://pastebin.com/ifXSCZ71
  178. ; *.STM
  179. ;Import  "winmm.lib" :  EndImport
  180. CompilerIf  #PB_Compiler_Processor  =  #PB_Processor_x64
  181.    Import   "playST2_x64.lib"
  182.       st23play_Close()
  183.       st23play_GetMasterVol()    ; 0..256
  184.       st23play_GetMixerTicks()   ; returns the amount of milliseconds of mixed audio (not realtime)
  185.       st23play_GetSongName()     ; max 20 chars (21 with '\0'), string is in code page 437
  186.       st23play_PauseSong(flag)   ; true/false
  187.       st23play_PlaySong(*moduleData, dataLength, useInterpolationFlag, audioFreq)   ; returns 1 = playing or 0 = error
  188.       st23play_SetInterpolation(flag)  ; true/false
  189.       st23play_SetMasterVol(vol)       ; 0..256
  190.       st23play_TogglePause()
  191.    EndImport
  192. CompilerElse
  193.    ImportC  "playST2_x86.lib"
  194.       st23play_Close()                 As "_st23play_Close"
  195.       st23play_GetMasterVol()          As "_st23play_GetMasterVol"
  196.       st23play_GetMixerTicks()         As "_st23play_GetMixerTicks"
  197.       st23play_GetSongName()           As "_st23play_GetSongName"
  198.       st23play_PauseSong(flag)         As "_st23play_PauseSong"
  199.       st23play_PlaySong(*moduleData, dataLength, useInterpolationFlag, audioFreq)   As "_st23play_PlaySong"
  200.       st23play_SetInterpolation(flag)  As "_st23play_SetInterpolation"
  201.       st23play_SetMasterVol(vol)       As "_st23play_SetMasterVol"
  202.       st23play_TogglePause()           As "_st23play_TogglePause"
  203.    EndImport
  204. CompilerEndIf
  205. ;}
  206. ;{ #C2D_MUSIC_S3M * Thanx to Olav "8bitbubsy" for the opensource ST3PLAY v0.91+ (x86) / v0.99 (x64) * }
  207. ; https://16-bits.org
  208. ; https://pastebin.com/AwRXZAw7
  209. ; *.S3M
  210. #SOUNDCARD_GUS    =  0  ;/* Default */
  211. #SOUNDCARD_SBPRO  =  1
  212. ;Import  "winmm.lib" :  EndImport
  213. CompilerIf  #PB_Compiler_Processor  =  #PB_Processor_x64
  214.    Import   "playST3_x64.lib"
  215.       st3play_Close()
  216.       st3play_GetMasterVol()  ; 0..256
  217.       st3play_GetMixerTicks() ; returns the amount of milliseconds of mixed audio (not realtime)
  218.       st3play_GetSongName()
  219.       st3play_PauseSong(flag) ; true/false
  220.       st3play_PlaySong(*moduleData, length, flag, type, freq)  ; returns 1 = playing or 0 = error
  221.       st3play_SetInterpolation(flag)   ; true/false
  222.       st3play_SetMasterVol(vol)        ; 0..256
  223.       st3play_TogglePause()
  224.    EndImport
  225. CompilerElse
  226.    ImportC  "playST3_x86.lib" ; ST3PLAY v0.91 last working for x86
  227.       st3play_Close()                  As "_st3play_Close"
  228.       st3play_GetMixerTicks()          As "_st3play_GetMixerTicks"
  229.       st3play_GetSongName()            As "_st3play_GetSongName"
  230.       st3play_PauseSong(flag)          As "_st3play_PauseSong"
  231.       st3play_PlaySong(*moduleData, length, flag, type, freq)  As "_st3play_PlaySong"
  232.       st3play_SetInterpolation(flag)   As "_st3play_SetInterpolation"
  233.       st3play_SetMasterVol(vol)        As "_st3play_SetMasterVol"
  234.       st3play_TogglePause()            As "_st3play_TogglePause"
  235.    EndImport
  236. CompilerEndIf
  237. ;}
  238. ;{ #C2D_MUSIC_V1M * Thanx to kb^farbrausch for the static libv2.lib v1.0 / Error * }
  239. ; *.V2M 1.0
  240. CompilerIf  #IsV1M
  241.    ;Import  "winmm.lib"    :  EndImport
  242.    ;Import  "dsound.lib"   :  EndImport
  243.    Import   "libv2_x86.lib"
  244.       ssClose()               As "_ssClose@0"
  245.       ssDoTick()              As "_ssDoTick@0"
  246.       ssFadeOut(milliseconds) As "_ssFadeOut@4"
  247.       ssGetTime()             As "_ssGetTime@0"
  248.       ssInit(*module, *hWnd)  As "_ssInit@8"
  249.       ssPlay()                As "_ssPlay@0"
  250.       ssStop()                As "_ssStop@0"
  251.    EndImport
  252. CompilerEndIf
  253. ;}
  254. ;{ #C2D_MUSIC_V2M * Thanx to kb^farbrausch for the static libv2simple.lib v1.5 * }
  255. ; *.V2M 1.5
  256. CompilerIf  #IsV2M
  257.    Prototype   DSIOCALLBACK(*param, *buf.FLOAT, length.l)
  258.    Prototype   PERCENTCALLBACK(percent.f)
  259.    ;Import  "dsound.lib"   :  EndImport
  260.    Import   "libv2simple_x86.lib"
  261.       V2MClose()                                As "_V2MClose@0"
  262.       V2MGetChannelVU(channel, *left, *right)   As "_V2MGetChannelVU@12"
  263.       V2MGetCurrentTime()                       As "_V2MGetCurrentTime@0"
  264.       V2MGetTotalTime()                         As "_V2MGetTotalTime@0"
  265.       V2MInit(*tune, samplerate, *hWnd)         As "_V2MInit@12"
  266.       V2MIsPlaying()                            As "_V2MIsPlaying@0"
  267.       V2MPlay(start=0)                          As "_V2MPlay@4"
  268.       V2MSaveAsWave(a.s, *b.PERCENTCALLBACK)    As "_V2MSaveAsWave@8"
  269.       V2MSetRepeat(status.b)                    As "_V2MSetRepeat@4"
  270.       V2MSetVUMode(mode)                        As "_V2MSetVUMode@4"
  271.       V2MStop(fade=0)                           As "_V2MStop@4"
  272.       ;initializes DirectSound output.
  273.       ;callback: your render callback function
  274.       ;parm: a pointer that'll be supplied to the function on every call
  275.       ;hWnd: window handle of your application (GetForegroundWindow() works quite well :)
  276.       dsInit(*callback.DSIOCALLBACK, *parm, *hWnd) As "_dsInit@12"
  277.       dsClose()               As "_dsClose@0"      ;shuts down DirectSound output
  278.       dsGetCurSmp()           As "_dsGetCurSmp@0"  ;gets sample-exact and latency compensated current play position
  279.       dsSetVolume(vol.f=1.0)  As "_dsSetVolume@4"  ;sets player volume (Default is 1.0)
  280.       ;forces rendering thread to update. On single-core CPUs it's a good idea to
  281.       ;call this once per frame (improves A/V sync And reduces any stuttering),
  282.       ;with more than one CPU it's pretty much useless.
  283.       dsTick() As "_dsTick@0"
  284.       ;lock And unlock the sound thread's thread sync lock. If you want to modify
  285.       ;any of your sound variables outside the render thread, encapsulate that part
  286.       ;of code in between these two functions.
  287.       dsLock()    As "_dsLock@0"
  288.       dsUnlock()  As "_dsUnlock@0"
  289.    EndImport
  290. CompilerEndIf
  291. ;}
  292. ;{ #C2D_MUSIC_XM2 * Thanx to Quantum for the FastTracker2 uFMOD static lib * }
  293. ; *.XM
  294. CompilerIf  #IsXM2
  295.    #XM_RESOURCE         =  0
  296.    #XM_MEMORY           =  1
  297.    #XM_FILE             =  2
  298.    #XM_NOLOOP           =  8
  299.    #XM_SUSPENDED        =  16
  300.    #uFMOD_MIN_VOL       =  0
  301.    #uFMOD_MAX_VOL       =  25
  302.    #uFMOD_DEFAULT_VOL   =  25
  303.    ;Import  "winmm.lib" :  EndImport
  304.    Import   "ufmod_x86.lib"
  305.       uFMOD_GetRowOrder()                       As "_uFMOD_GetRowOrder@0"  ;Returns the current order in hi-order word and row in low-order word
  306.       uFMOD_GetStats()                          As "_uFMOD_GetStats@0"     ;Returns the L RMS volume in hi-order word and R RMS in low-order word
  307.       uFMOD_GetTime()                           As "_uFMOD_GetTime@0"      ;Returns the time in milliseconds since the song was started
  308.       uFMOD_GetTitle()                          As "_uFMOD_GetTitle@0"     ;Returns the track's title
  309.       uFMOD_Jump2Pattern(pat)                   As "_uFMOD_Jump2Pattern@4" ;Jumps to the specified zero based pattern index
  310.       uFMOD_Pause()                             As "_uFMOD_Pause@0"        ;Pauses the currently playing song, if any
  311.       uFMOD_PlaySong(*lpXM, param=0, fdwSong=0) As "_uFMOD_PlaySong@12"    ;Starts playing an XM song, *lpXM -> 0 = Stopp song
  312.       uFMOD_Resume()                            As "_uFMOD_Resume@0"       ;Resumes the currently paused song, if any
  313.       uFMOD_SetVolume(vol)                      As "_uFMOD_SetVolume@4"    ;Sets global volume: 0 - 25
  314.    EndImport
  315. CompilerEndIf
  316. ;}
  317. ;{ #C2D_MUSIC_SID * Thanx to statmat for the titchysid_extras.lib * }
  318. ; *.SID
  319. CompilerIf  #IsSID
  320.    #SID_RESOURCE     =  0  ;Load SID file from a resource
  321.    #SID_MEMORY       =  1  ;Load SID file from provided memory
  322.    ;Options used in SIDOpen()
  323.    #SID_DEFAULT      =  1  ;Play Default subsong, as found in the PSID header
  324.    #SID_NON_DEFAULT  =  2  ;Play specified subsong
  325.    ;Import  "winmm.lib"    :  EndImport   ; Not really needed!
  326.    ;Import  "masm32_x86.lib"  :  EndImport
  327.    Import   "titchysid_extras_x86.lib"
  328.       SIDOpen(*mem, len, mode, options, subsong)   As "_SIDOpen@20"     ;Returns non-zero on success
  329.       SIDClose()                                   As "_SIDClose@0"     ;Close the SID library
  330.       SIDChangeSong(song)                          As "_SIDChangeSong@4";Change to another sub song in the currently playing SID file
  331.       SIDPause()                                   As "_SIDPause@0"     ;Pause the currently playing SID song
  332.       SIDPlay()                                    As "_SIDPlay@0"      ;Start the SID playback
  333.       SIDResume()                                  As "_SIDResume@0"    ;Resume playing the SID song after a pause
  334.       SIDStop()                                    As "_SIDStop@0"      ;Stop the SID playback
  335.    EndImport
  336. ;  Import   "titchysid_x86.lib"
  337. ;     SIDOpen(*mem, len, mode, options, subsong)   As "_SIDOpen@20"     ;Returns non-zero on success
  338. ;     SIDClose()                                   As "_SIDClose@0"     ;Close the SID library
  339. ;  EndImport
  340. CompilerEndIf
  341. ;}
  342. ;{ #C2D_MUSIC_TPT * Not official TINY PT2PLAY v1.60 * }
  343. CompilerIf  #PB_Compiler_Processor  =  #PB_Processor_x64
  344.    Import   "tinyPT2_x64.lib"
  345.       tinypt2play_Close()  As "pt2play_Close"
  346.       tinypt2play_PlaySong(*moduleData, length) As "pt2play_PlaySong"; returns 1 = playing or 0 = error
  347.    EndImport
  348. CompilerElse
  349.    ImportC  "tinyPT2_x86.lib"
  350.       tinypt2play_Close()  As "_pt2play_Close"
  351.       tinypt2play_PlaySong(*moduleData, length) As "_pt2play_PlaySong"
  352.    EndImport
  353. CompilerEndIf
  354. ;}
  355. ;{ #C2D_MUSIC_TFC * Not official TINY FC14PLAY v1.29 * }
  356.  
  357. ; https://16-bits.org
  358. ; https://pastebin.com/VHxZ58UC
  359.  
  360. ; *.FC;*.FC13;*.FC14;*.FC3;*.FC4;*.FCM;*.SMOD
  361.  
  362. ;Import  "winmm.lib" :  EndImport
  363.  
  364. CompilerIf  #PB_Compiler_Processor  =  #PB_Processor_x64
  365.    Import   "tinyFC4_x64.lib"
  366.       tinyfc14play_Close() As "fc14play_Close"
  367.       tinyfc14play_PlaySong(*moduleData, length)   As "fc14play_PlaySong"  ; returns 1 = playing or 0 = error
  368.    EndImport
  369. CompilerElse
  370.    ImportC  "tinyFC4_x86.lib"
  371.       tinyfc14play_Close() As "_fc14play_Close"
  372.       tinyfc14play_PlaySong(*moduleData, length)   As "_fc14play_PlaySong"
  373.    EndImport
  374. CompilerEndIf
  375. ;}
  376. ;{ #C2D_MUSIC_THX * Not official TINY AHX1PLAY v0.27 * }
  377.  
  378. ; https://16-bits.org
  379. ; https://pastebin.com/fqwadbj7
  380.  
  381. ; *.AHX;*.THX
  382.  
  383. ;Import  "winmm.lib" :  EndImport
  384.  
  385. CompilerIf  #PB_Compiler_Processor  =  #PB_Processor_x64
  386.    Import   "tinyAHX_x64.lib"
  387.       tinyahx1play_PlaySong(*moduleData, length, subsong)   As "ahx1play_PlaySong"  ; returns 1 = playing or 0 = error
  388.       tinyahx1play_Close() As "ahx1play_Close"
  389.    EndImport
  390. CompilerElse
  391.    ImportC  "tinyAHX_x86.lib"
  392.       tinyahx1play_PlaySong(*moduleData, length, subsong)   As "_ahx1play_PlaySong"
  393.       tinyahx1play_Close() As "_ahx1play_Close"
  394.    EndImport
  395. CompilerEndIf
  396.  
  397. ;}
  398. ;{ #C2D_MUSIC_TSR * Thanx to unknown? for the tsidreplay.lib * }
  399. ; *.SID
  400. CompilerIf  #IsTSR
  401.    ImportC  "tsidreplay_x86.lib"
  402.       sid_sound_server_replay_init(*mem, len, subsong)   As "_sid_sound_server_replay_init"
  403.       sid_sound_server_replay_play()                     As "_sid_sound_server_replay_play"
  404.       sid_sound_server_replay_stop()                     As "_sid_sound_server_replay_stop"
  405.    EndImport
  406. CompilerEndIf
  407. ;}
  408. ;{ #C2D_MUSIC_FCP * Thanx to SiRioKD for the tFCLIB.lib (FutureComposer 1.4) * }
  409. ; *.FC;*.FC4;*.FC14
  410. CompilerIf  #IsFCP
  411.    ;Import  "winmm.lib"    :  EndImport   ; Not really needed?
  412.    ;Import  "dsound.lib"   :  EndImport
  413.    Import   "tFCLIB_x86.lib"
  414.       FCp_Open(*hWnd)      As "_FCp_Open@4"
  415.       FCp_InitModule(*Ptr) As "_FCp_InitModule@4"
  416.       FCp_Start()          As "_FCp_Start@0"
  417.       FCp_Close()          As "_FCp_Close@0"
  418.    EndImport
  419. CompilerEndIf
  420. ;}
  421. ;{ #C2D_MUSIC_BAS * Thanx to Ghandi for the ripped bassmod.lib * }
  422. ; *.XM;*.IT;*.S3M;*.MOD;*.MTM;*.UMX
  423. CompilerIf  #IsBAS
  424.    #BASS_OK                 = 0   ; all is OK
  425.    #BASS_ERROR_MEM          = 1   ; memory error
  426.    #BASS_ERROR_FILEOPEN     = 2   ; can't open the file
  427.    #BASS_ERROR_DRIVER       = 3   ; can't find a free/valid driver
  428.    #BASS_ERROR_HANDLE       = 5   ; invalid handle
  429.    #BASS_ERROR_FORMAT       = 6   ; unsupported format
  430.    #BASS_ERROR_POSITION     = 7   ; invalid playback position
  431.    #BASS_ERROR_INIT         = 8   ; BASS_Init has not been successfully called
  432.    #BASS_ERROR_ALREADY      = 14  ; already initialized/loaded
  433.    #BASS_ERROR_ILLTYPE      = 19  ; an illegal type was specified
  434.    #BASS_ERROR_ILLPARAM     = 20  ; an illegal parameter was specified
  435.    #BASS_ERROR_DEVICE       = 23  ; illegal device number
  436.    #BASS_ERROR_NOPLAY       = 24  ; not playing
  437.    #BASS_ERROR_NOMUSIC      = 28  ; no MOD music has been loaded
  438.    #BASS_ERROR_NOSYNC       = 30  ; synchronizers have been disabled
  439.    #BASS_ERROR_NOTAVAIL     = 37  ; requested data is not available
  440.    #BASS_ERROR_DECODE       = 38  ; the channel is a "decoding channel"
  441.    #BASS_ERROR_FILEFORM     = 41  ; unsupported file format
  442.    #BASS_ERROR_UNKNOWN      = -1  ; some other mystery error
  443.  
  444.    ; Device setup flags
  445.    #BASS_DEVICE_8BITS       = 1   ; use 8 bit resolution, else 16 bit
  446.    #BASS_DEVICE_MONO        = 2   ; use mono, else stereo
  447.    #BASS_DEVICE_NOSYNC      = 16  ; disable synchronizers
  448.  
  449.    #BASS_MUSIC_RAMP         =       1  ; normal ramping
  450.    #BASS_MUSIC_RAMPS        =       2  ; sensitive ramping
  451.    #BASS_MUSIC_LOOP         =       4  ; loop music
  452.    #BASS_MUSIC_FT2MOD       =      16  ; play .MOD as FastTracker 2 does
  453.    #BASS_MUSIC_PT1MOD       =      32  ; play .MOD as ProTracker 1 does
  454.    #BASS_MUSIC_POSRESET     =     256  ; stop all notes when moving position
  455.    #BASS_MUSIC_SURROUND     =     512  ; surround sound
  456.    #BASS_MUSIC_SURROUND2    =    1024  ; surround sound (mode 2)
  457.    #BASS_MUSIC_STOPBACK     =    2048  ; stop the music on a backwards jump effect
  458.    #BASS_MUSIC_CALCLEN      =    8192  ; calculate playback length
  459.    #BASS_MUSIC_NONINTER     =   16384  ; non-interpolated mixing
  460.    #BASS_MUSIC_NOSAMPLE     = $400000  ; don't load the samples
  461.  
  462.    #BASS_UNICODE            = $80000000
  463.  
  464.    #BASS_SYNC_MUSICPOS      = 0
  465.    #BASS_SYNC_POS           = 0
  466.    #BASS_SYNC_MUSICINST     = 1
  467.    #BASS_SYNC_END           = 2
  468.    #BASS_SYNC_MUSICFX       = 3
  469.    #BASS_SYNC_ONETIME       = $80000000   ; FLAG: sync only once, else continuously
  470.  
  471.    ; BASSMOD_ChannelIsActive return values
  472.    #BASS_ACTIVE_STOPPED     = 0
  473.    #BASS_ACTIVE_PLAYING     = 1
  474.    #BASS_ACTIVE_PAUSED      = 3
  475.  
  476.    ;Import  "winmm.lib"    :  EndImport
  477.    Import   "bassmod_x86.lib"
  478.       BASSMOD_DllMain(*hInstance, fdwReason, lpvReserved)
  479.       BASSMOD_Free()
  480.       BASSMOD_GetVolume()
  481.       BASSMOD_Init(device=-1, freq=44100, flags=0)
  482.       BASSMOD_MusicFree()
  483.       BASSMOD_MusicGetLength(playlen)
  484.       BASSMOD_MusicGetName()
  485.       BASSMOD_MusicLoad(mem, *file, offset=#Null, length=#Null, flags=#BASS_MUSIC_LOOP|#BASS_MUSIC_POSRESET|#BASS_MUSIC_NONINTER|#BASS_MUSIC_CALCLEN) ;mem=#true -> Load from *memory
  486.       BASSMOD_MusicPause()
  487.       BASSMOD_MusicPlay()
  488.       BASSMOD_MusicSetPosition(pos) ; $FFFF0000 | Seconds (max. $0000FFFF)
  489.       BASSMOD_MusicSetVolume(chanins, volume)
  490.       BASSMOD_MusicStop()
  491.       BASSMOD_SetVolume(volume)
  492.    EndImport
  493. CompilerEndIf
  494. ;}
  495. ;{ #C2D_MUSIC_S68 * Thanx to benjihan for the MC68000 Amiga/Atari SC68 libsc68replay.lib * }
  496. ; http://sc68.atari.org/index.html
  497. ; *.SC68
  498. CompilerIf  #IsS68
  499.    #SC68Replay_MEMORY   =  0
  500.    #SC68Replay_FILE     =  1
  501.    ;Import  "winmm.lib" :  EndImport
  502.    ImportC  "libsc68replay_x86.lib"
  503.       sc68replay_Init(*Ptr, Size, Mode)   As "_sc68replay_Init"
  504.       sc68replay_Play()                   As "_sc68replay_Play"
  505.       sc68replay_Stop()                   As "_sc68replay_Stop"
  506.    EndImport
  507. CompilerEndIf
  508. ;}
  509. ;{ #C2D_MUSIC_BMF * Thanx to BeRo^farbraush for the BR404 Software Synthesizer libbr404.lib * }
  510. ; *.BRO
  511. CompilerIf  #IsBMF
  512.    Import   "libbr404_x86.lib"
  513.       SynthCreate(SampleRate, BufferSize, ThreadPlay, SoundOutput)   As "_SynthCreate@16" ; = int Track
  514.       SynthReadBMFSampleRate(*Ptr, Size)                             As "_SynthReadBMFSampleRate@8"
  515.       SynthReadBMF(Track, *Ptr, Size)                                As "_SynthReadBMF@12"
  516.       SynthPlay(Track)                                               As "_SynthPlay@4"
  517.       SynthSetLooping(Track, Looping)                                As "_SynthSetLooping@8"
  518.       SynthEnter(Track)                                              As "_SynthEnter@4"
  519.       SynthStop(Track)                                               As "_SynthStop@4"
  520.       SynthLeave(Track)                                              As "_SynthLeave@4"
  521.       SynthDestroy(Track)                                            As "_SynthDestroy@4"
  522.    EndImport
  523. CompilerEndIf
  524. ;}
  525. ;{ #C2D_MUSIC_MED * MEDPDLL static lib ripped by Peace^TST * }
  526. ; *.MED;*.MMD0;*.MMD1;*.MMD2;*.MMD3 (PP20)
  527. ;Import  "winmm.lib" :  EndImport
  528. ;Import  "dsound.lib":  EndImport
  529. CompilerIf  #IsMED
  530.    Import   "medpdll_x86.lib"
  531.       MEDPDLL_DllMain(*hinstDLL, fdwReason, lpvReserved) As "_MEDPDLL_DllMain@12"
  532.       MEDP_Initialize(*instance, *mainwindow)            As "__MEDP_Initialize@8"
  533.       MEDP_ChangeOption(option, newvalue)                As "__MEDP_ChangeOption@8"
  534.       MEDP_Load(*filename)                               As "__MEDP_Load@4"
  535.       MEDP_IsLoaded()                                    As "__MEDP_IsLoaded@0"
  536.       MEDP_Play()                                        As "__MEDP_Play@0"
  537.       MEDP_Stop()                                        As "__MEDP_Stop@0"
  538.       MEDP_Unload()                                      As "__MEDP_Unload@0"
  539.       MEDP_ModuleLength()                                As "__MEDP_ModuleLength@0"
  540.       MEDP_ModuleTime()                                  As "__MEDP_ModuleTime@0"
  541.       MEDP_PlayPosition()                                As "__MEDP_PlayPosition@0"
  542.       MEDP_SetPlayPosition(pos)                          As "__MEDP_SetPlayPosition@4"
  543.       MEDP_IsPlaying()                                   As "__MEDP_IsPlaying@0"
  544.       MEDP_ModuleName(*buffer, max)                      As "__MEDP_ModuleName@8"
  545.       MEDP_Release()                                     As "__MEDP_Release@0"
  546.    EndImport
  547. CompilerEndIf
  548. ;}
  549. ;{ #C2D_MUSIC_YMP * YmPluginDLL static lib ripped by Peace^TST * }
  550. ; *.YM
  551. CompilerIf  #IsYMP
  552.    Structure RS_ymMusicInfo_t
  553.       *pSongName
  554.       *pSongAuthor
  555.       *pSongComment
  556.       *pSongType
  557.       *pSongPlayer
  558.       musicTimeInSec.l
  559.       musicTimeInMs.l
  560.    EndStructure
  561.    ;Import  "winmm.lib" :  EndImport
  562.    Import   "YmPlugin_x86.lib"
  563.       YMPLUGIN_DllMain(*hinstDLL, fdwReason, lpvReserved)   As "_YMPLUGIN_DllMain@12"
  564.       YM_Close()                    As "__YM_Close@0"
  565.       YM_FFT()                      As "__YM_FFT@0"
  566.       YM_Get_Info(struct)           As "__YM_Get_Info@4"    ; RS_ymMusicInfo_t
  567.       YM_Init()                     As "__YM_Init@0"
  568.       YM_Open(*file, *memory, size) As "__YM_Open@12"       ; file (size=0) or memory (size <>0)
  569.       YM_Pause()                    As "__YM_Pause@0"
  570.       YM_Play()                     As "__YM_Play@0"
  571.       YM_Seek(seconds)              As "__YM_Seek@4"
  572.       YM_SetVolume(vol)             As "__YM_SetVolume@4"   ; 0..255
  573.       YM_Stop()                     As "__YM_Stop@0"
  574.    EndImport
  575. CompilerEndIf
  576. ;}
  577.  
  578. ;#C2D_MUSIC_WAV ; *.WAV
  579. ;#C2D_MUSIC_API ; *.WAV
  580. ;#C2D_MUSIC_OGG ; *.OGG
  581. ;#C2D_MUSIC_FLA ; *.FLAC
  582. ;#C2D_MUSIC_MCI ; *.MID;*.MP3;*.OGG;*.WMA...
  583.  
  584. ;}
  585. ;************************
  586.  
  587. Procedure   StrSize(Value.q, Flags=1)
  588.  
  589.    Protected   nSize.d
  590.  
  591.    Static   t$ ; return param MUST! global or static in dll
  592.  
  593.    If       Value >= 1099511627776
  594.       nSize =  Value /  1099511627776  :  t$ =  "TB"  ;Pow(1024,4)
  595.    ElseIf   Value >= 1073741824
  596.       nSize =  Value /  1073741824     :  t$ =  "GB"  ;Pow(1024,3)
  597.    ElseIf   Value >= 1048576
  598.       nSize =  Value /  1048576        :  t$ =  "MB"  ;Pow(1024,2)
  599.    ElseIf   Value >= 1024
  600.       nSize =  Value /  1024           :  t$ =  "KB"
  601.    Else  ; also negative size / no NbDecimals
  602.       t$ =  FormatNumber(Value, 0) + " Bytes"
  603.       ProcedureReturn   @t$
  604.    EndIf
  605.  
  606.    t$ =  FormatNumber(nSize, 2) + " " + t$
  607.  
  608.    If Flags
  609.       t$ +  " ("  +  FormatNumber(Value, 0)  +  " Bytes)"
  610.    EndIf
  611.  
  612.    ProcedureReturn   @t$
  613.  
  614.    ; *** Not working in PB x86 ***
  615.    ;  Static   *Memory
  616.    ;  If *Memory  =  #Null :  *Memory  =  AllocateMemory(128)  :  EndIf
  617.    ;  StrFormatByteSize_(Value, *Memory, 128)
  618.    ;  ProcedureReturn   PeekS(*Memory)
  619.  
  620. EndProcedure
  621. Procedure   StrAsc(*Memory)
  622.  
  623.    ; correct ascii or unicode strings
  624.  
  625.    Static   *Buffer
  626.  
  627.    If *Buffer
  628.       FreeMemory(*Buffer)
  629.       *Buffer  =  #Null
  630.    EndIf
  631.  
  632.    If *Memory
  633.       If RS_SCAL\StrFormat =  #PB_Ascii
  634.          ProcedureReturn   *Memory
  635.       Else
  636.          *Buffer  =  Ascii(PeekS(*Memory, -1, RS_SCAL\StrFormat))
  637.       EndIf
  638.    EndIf
  639.  
  640.    ProcedureReturn   *Buffer
  641.  
  642. EndProcedure
  643. Procedure$  StrTime(Time)
  644.  
  645.    ; Milliseconds to String: HH:MM:SS,TTT
  646.    ; Flags <> 0 => show rest ms
  647.  
  648.    Static   t$
  649.  
  650.    t$ =  RSet(StrU(Time  / 3600000),      2, "0")  +  ":"   +  ; HH:
  651.          RSet(StrU((Time / 60000) % 60),  2, "0")  +  ":"   +  ; MM:
  652.          RSet(StrU((Time / 1000)  % 60),  2, "0")              ; SS
  653.  
  654.    t$ +  ","   +  LSet(StrU(Time % 1000), 3, "0")  ; ,TTT
  655.  
  656.    ProcedureReturn   t$
  657.  
  658. ;  Protected   t$=Space(64)
  659. ;  StrFromTimeInterval_(@t$, 64, Time, 1000)
  660. ;  ProcedureReturn   t$
  661.  
  662. EndProcedure
  663.  
  664. ;*******************************
  665. ;- *** NetWork ? ***************
  666. CompilerIf  Defined(HTTP_QUERY_CONTENT_LENGTH,     #PB_Constant)  =  0
  667.    #HTTP_QUERY_CONTENT_LENGTH    =  $5
  668. CompilerEndIf
  669. CompilerIf  Defined(INTERNET_FLAG_RELOAD,          #PB_Constant)  =  0
  670.    #INTERNET_FLAG_RELOAD         =  $80000000
  671. CompilerEndIf
  672. CompilerIf  Defined(INTERNET_FLAG_NO_CACHE_WRITE,  #PB_Constant)  =  0
  673.    #INTERNET_FLAG_NO_CACHE_WRITE =  $4000000
  674. CompilerEndIf
  675.  
  676. Structure   RS_NetWork
  677.    *CallBack   ; @Procedure(Param)
  678.    *hInternet  ; iNetConnection
  679.    *hURL       ; iNetURL
  680.    BytesRead.i ; Buffered bytes
  681.    BytesSkip.i ; Skip bytes of "header"!
  682.    Length.i    ; Bytesize of url
  683. EndStructure
  684. Global   RS_NetWork.RS_NetWork
  685.  
  686. Procedure   NetWorkCallBack(*CallBack=0)
  687.    ; *CallBack = @Procedure(Param)
  688.    RS_NetWork\CallBack  =  *CallBack
  689. EndProcedure
  690. Procedure   NetWorkFree()     ; private
  691.  
  692.    With  RS_NetWork
  693.  
  694.       If \hInternet
  695.          InternetCloseHandle_(\hInternet)
  696.       EndIf
  697.  
  698.       ClearStructure(@RS_NetWork, RS_NetWork)
  699.  
  700.    EndWith
  701.  
  702. EndProcedure
  703. Procedure$  NetWorkUrl(Url$)  ; private
  704.  
  705.    ; Encode unsave characters (canonicalize)
  706.    ; https://www.ietf.org/rfc/rfc1738.txt
  707.  
  708.    Protected   *Memory.Character=@Url$, i
  709.  
  710.    Static   t$
  711.  
  712.    t$ =  #Null$
  713.  
  714.    While *Memory\c
  715.       Select   *Memory\c
  716.          Case  ',',' ','!','"','#','$','&','+',';','<','=','>','@','[','\',']','^','_','`','{','|','}','~',$27 ; not '-','%'
  717.            t$ +  "%"   +  Hex(*Memory\c)
  718.         Default
  719.            If *Memory\c   <> '\'   ; no "\/"
  720.               t$ +  Chr(*Memory\c)
  721.            EndIf
  722.      EndSelect
  723.      *Memory  +  SizeOf(Character)
  724.   Wend
  725.  
  726.   ; Canonicalize filename - else error when char + % (s. "war at 33%.psid", "100%.mod"...)
  727.   If StrStrI_(@t$, @"%")
  728.      For   i  =  $20   To $FF
  729.         Select   i
  730.            Case  $20 To $2F, $40 To $FF  ; no numbers
  731.               t$ =  ReplaceString(t$, "%" + Chr(i), "%25" + Chr(i), #PB_String_CaseSensitive)
  732.         EndSelect
  733.      Next
  734.   EndIf
  735.  
  736.   ProcedureReturn   t$
  737.  
  738. EndProcedure
  739. Procedure   NetWorkBytes(Length=4096)
  740.   ; Length (BytesToRead) = Number of bytes preloaded from Url$
  741.   If Length   >  #Null
  742.      RS_NetWork\BytesRead =  Length
  743.   EndIf
  744. EndProcedure
  745. Procedure   NetWorkInit(Url$) ; private
  746.  
  747.   ; Return:  Filesize(Url$) or #NULL -> Error
  748.  
  749.   If StrStrI_(@Url$, @"://") =  #Null :  ProcedureReturn   #Null :  EndIf
  750.  
  751.   Protected   *Memory, Length
  752.  
  753.   With  RS_NetWork
  754.  
  755.      NetWorkCallBack(RS_SCAL\CallBack)   ; always set callback!
  756.  
  757.      If \hInternet  <= #Null
  758.         \hInternet  =  InternetOpen_(@"SCAL/1.0", #INTERNET_OPEN_TYPE_PRECONFIG, 0, 0, 0)
  759.      EndIf
  760.  
  761.      \Length  =  #Null
  762.  
  763.      If \hInternet
  764.  
  765.         If \BytesRead  <= #Null
  766.            NetWorkBytes()
  767.         EndIf
  768.  
  769.         ; Encode unsave URL-Characters (canonicalize)
  770.         Url$     =  NetWorkUrl(Url$)
  771.         Length   =  1024  +  Len(Url$)   +  \BytesSkip  ; + space for query content
  772.         *Memory  =  AllocateMemory(Length * SizeOf(Character))
  773.         PokeS(*Memory, Url$)
  774.  
  775.         \hURL =  InternetOpenUrl_(\hInternet, *Memory, 0, 0, #INTERNET_FLAG_RELOAD|#INTERNET_FLAG_NO_CACHE_WRITE|#INTERNET_FLAG_NO_COOKIES, 0)
  776.  
  777.         If \hURL
  778.            If HttpQueryInfo_(\hURL, #HTTP_QUERY_STATUS_CODE, *Memory, @Length, 0)
  779.               If StrToInt_(*Memory)   =  200
  780.  
  781.                  Length   =  MemorySize(*Memory)
  782.  
  783.                  If HttpQueryInfo_(\hURL, #HTTP_QUERY_CONTENT_LENGTH, *Memory, @Length, 0)
  784.  
  785.                     \Length  =  StrToInt_(*Memory)
  786.  
  787.                     If GetLastError_()   Or \Length  <= 0  ; Error?
  788.                        \Length  =  #Null
  789.                     ElseIf   \BytesSkip  ; <- skip pseudoheader for deceive hoster?
  790.                        InternetReadFile_(\hURL, *Memory, \BytesSkip, @Length)
  791.                        \Length  -  Length
  792.                     EndIf
  793.  
  794.                  EndIf
  795.  
  796.               EndIf
  797.            EndIf
  798.         EndIf
  799.  
  800.         FreeMemory(*Memory)
  801.  
  802.      EndIf
  803.  
  804.      RS_SCAL\NetLength =  \Length  ; global length for SCAL_Struct()
  805.  
  806.      ProcedureReturn   \Length
  807.  
  808.   EndWith
  809.  
  810. EndProcedure
  811. Procedure   NetWorkLoad(Url$)
  812.  
  813.   ; Download Netfile to *Memory
  814.  
  815.   ; Return: Ptr to *Memory
  816.  
  817.   Protected   *Buffer, Length
  818.   Static   *Memory
  819.  
  820.   *Memory  =  #Null
  821.  
  822.   If NetWorkInit(Url$)
  823.  
  824.      With  RS_NetWork
  825.  
  826.         If \Length  >  #Null
  827.  
  828.            *Memory  =  AllocateMemory(\Length)
  829.            *Buffer  =  *Memory
  830.  
  831.            While InternetReadFile_(\hURL, *Buffer, \BytesRead, @Length)
  832.  
  833.               *Buffer  +  Length
  834.  
  835.               ;// If   *CallBack   And   CallFunctionFast(*CallBack, Percent)   :  Break :  EndIf
  836.               If \CallBack
  837.                  If CallFunctionFast(\CallBack, (100.0 / \Length) * (*Buffer - *Memory)) ; Abort?
  838.                     FreeMemory(*Memory)
  839.                     *Memory  =  #Null
  840.                     Break
  841.                  EndIf
  842.               Else
  843.                  Delay(1)
  844.               EndIf
  845.  
  846.               If (Length  <= #Null)   Or (*Buffer >= *Memory  +  \Length)
  847.                  Break
  848.               EndIf
  849.  
  850.            Wend
  851.  
  852.         EndIf
  853.  
  854.         InternetCloseHandle_(\hURL)
  855.  
  856.      EndWith
  857.  
  858.   EndIf
  859.  
  860.   If RS_NetWork\CallBack
  861.      CallFunctionFast(RS_NetWork\CallBack, 100)
  862.   EndIf
  863.  
  864.   ProcedureReturn   *Memory
  865.  
  866. EndProcedure
  867. Procedure   NetWorkSize(Url$)
  868.  
  869.   ; = size of url$
  870.  
  871.   If NetWorkInit(Url$)
  872.      InternetCloseHandle_(RS_NetWork\hURL)
  873.      ProcedureReturn   RS_NetWork\Length
  874.   EndIf
  875.  
  876. EndProcedure
  877. Procedure   NetWorkSkip(Length=0)
  878.   ; Length (skip bytes) of decive header chars
  879.   If Length   >= #Null
  880.      RS_NetWork\BytesSkip =  Length
  881.   EndIf
  882. EndProcedure
  883. Procedure   NetWorkDownload(Url$, File$)
  884.  
  885.   ; Return: Size of saved file, Error = #NULL
  886.  
  887.   If NetWorkInit(Url$) =  #Null :  ProcedureReturn   #Null :  EndIf
  888.  
  889.   Protected   *Memory, Length, hF
  890.   Protected   nSizeLoad, IsAbort
  891.  
  892.   Static   nSizeSave
  893.  
  894.   nSizeSave   =  #Null
  895.  
  896.   With  RS_NetWork
  897.  
  898.      If \Length  >  #Null
  899.  
  900.         *Memory  =  AllocateMemory(\BytesRead)
  901.  
  902.         hF =  CreateFile(#PB_Any, File$)
  903.  
  904.         If hF
  905.  
  906.            While InternetReadFile_(\hURL, *Memory, \BytesRead, @nSizeLoad)
  907.  
  908.               Length      =  WriteData(hF, *Memory, nSizeLoad)
  909.               nSizeSave   +  Length
  910.  
  911.               ;// If   *CallBack   And   CallFunctionFast(*CallBack, Percent)   :  Break :  EndIf
  912.               If \CallBack
  913.                  If CallFunctionFast(\CallBack, (100.0 / \Length) * nSizeSave)  ; %Percent (Abort?)
  914.                     IsAbort  =  #True
  915.                     Break
  916.                  EndIf
  917.               Else
  918.                  Delay(1)
  919.               EndIf
  920.  
  921.               If nSizeSave   >= \Length  Or Length   <  nSizeLoad   ; Length -> WriteError?
  922.                  Break
  923.               EndIf
  924.  
  925.            Wend
  926.  
  927.            FlushFileBuffers(hF)
  928.            CloseFile(hF)
  929.  
  930.         EndIf
  931.  
  932.         FreeMemory(*Memory)
  933.  
  934.      EndIf
  935.  
  936.      InternetCloseHandle_(\hURL)
  937.  
  938.   EndWith
  939.  
  940.   If IsAbort  ; aborted?
  941.      nSizeSave   =  #Null
  942.      DeleteFile_(@File$)
  943.   EndIf
  944.  
  945.   If RS_NetWork\CallBack
  946.      CallFunctionFast(RS_NetWork\CallBack, 100)
  947.   EndIf
  948.  
  949.   ProcedureReturn   nSizeSave
  950.  
  951. EndProcedure
  952. ;*******************************
  953.  
  954. Declare  SCAL_IsFormat(Mode, *Memory.Long, Length)
  955. Declare  SCAL_SetVolume(Percent)
  956.  
  957. Procedure   scal_Init()
  958.  
  959.   Static   IsInit
  960.  
  961.   If IsInit   :  ProcedureReturn   :  EndIf
  962.  
  963.   IsInit   =  1
  964.  
  965.   InitSound()
  966.  
  967.   CompilerIf  #IsMOV
  968.      InitMovie()
  969.   CompilerEndIf
  970.  
  971. EndProcedure
  972. Procedure   scal_Temp(Name$)
  973.  
  974.   ; Creates %TEMP%\Name$
  975.  
  976.   Protected   t$, Path$, i
  977.   Static   IsError
  978.  
  979.   If RS_SCAL\Temp$  :  ProcedureReturn   #True :  EndIf
  980.  
  981.   Path$    =  GetTemporaryDirectory()
  982.   IsError  =  #Null
  983.  
  984.   Repeat
  985.  
  986.      i  +  1
  987.  
  988.      t$ =  Trim(StringField(Name$, i, #PS$))
  989.  
  990.      If Len(t$)
  991.  
  992.         Path$ +  t$ +  #PS$
  993.  
  994.         If FileSize(Path$)   =  -1
  995.            If CreateDirectory(Path$)  =  #Null
  996.               IsError  =  1  :  Break ; ERROR - Can't create directory
  997.            EndIf
  998.         EndIf
  999.  
  1000.      EndIf
  1001.  
  1002.   Until Len(t$)  =  0
  1003.  
  1004.   If IsError
  1005.      RS_SCAL\Temp$  =  GetTemporaryDirectory()
  1006.   Else
  1007.      RS_SCAL\Temp$  =  Path$
  1008.   EndIf
  1009.  
  1010.   IsError  !  1
  1011.  
  1012.   ProcedureReturn   IsError  ; true if ok
  1013.  
  1014. EndProcedure
  1015. Procedure   scal_Size(File$)
  1016.  
  1017.   Static   Length
  1018.  
  1019.   If StrStrI_(@File$, @"://")   ; Netfile?
  1020.      Length   =  NetWorkSize(File$)
  1021.      If Length   <  #Null :  Length   =  #Null :  EndIf
  1022.      ProcedureReturn   Length
  1023.   EndIf
  1024.  
  1025.   Length   =  FileSize(File$)
  1026.  
  1027.   If Length   <  #Null :  Length   =  #Null :  EndIf
  1028.  
  1029.   ProcedureReturn   Length
  1030.  
  1031. EndProcedure
  1032. Procedure$  scal_Case(a$, b$)
  1033.  
  1034.   ; canonicalize a$ like b$
  1035.  
  1036.   ; some server allows real upper/lower chars only.
  1037.   ; so we have to adapt the upper/lower chars!
  1038.  
  1039.   ; use it align char-cases of "MDAT.?" / "SMPL.?" files
  1040.  
  1041.   ; e.g.: scal_Case("smpl.Song", "MDAT.song") =  "SMPL.Song"
  1042.  
  1043.   Protected   *a.Character   =  @a$
  1044.   Protected   *b.Character   =  @b$
  1045.  
  1046.   While *a\c  And   *b\c
  1047.      If *b\c  &  %0100000
  1048.         *a\c  |  %0100000
  1049.      Else
  1050.         *a\c  &  %1011111
  1051.      EndIf
  1052.      *a +  SizeOf(Character)
  1053.      *b +  SizeOf(Character)
  1054.   Wend
  1055.  
  1056.   ProcedureReturn   a$
  1057.  
  1058. EndProcedure
  1059. Procedure   scal_Copy(File$, Save$)
  1060.  
  1061.   ; Return:   #True = OK, #False = Error
  1062.  
  1063.   Static   IsError
  1064.  
  1065.   If StrStrI_(@File$, @"://")   ; Netfile?
  1066.      IsError  =  NetWorkDownload(File$, Save$)
  1067.      ProcedureReturn   IsError
  1068.   EndIf
  1069.  
  1070.   IsError  =  CopyFile_(@File$, @Save$, #False)
  1071.  
  1072.   ProcedureReturn   IsError
  1073.  
  1074. EndProcedure
  1075. Procedure   scal_Sufx(*Memory, Flags)
  1076.  
  1077.   ; Checks filename first for "*.mod" & second for "mod.*"
  1078.  
  1079.   ; Do NOT check with GetExtensionPart()
  1080.   ; Extension doesn't accept spaces, that's why we must use the stringfield-trick!
  1081.  
  1082.   ; Return:   ptr to semi-quoted extension ";MOD;" etc.
  1083.  
  1084.    Static   t$
  1085.  
  1086.    Protected   File$ =  GetFilePart(PeekS(*Memory, -1, RS_SCAL\StrFormat))
  1087.  
  1088.    If Flags ; MOD.* (like MDAT.*)
  1089.       t$ =  StringField(File$, 1, ".")
  1090.    Else     ; *.MOD (default)
  1091.       t$ =  Trim(PeekS(PathFindExtension_(@File$), -1), ".")   ;StringField(File$, CountString(File$, ".") + 1, ".")
  1092.    EndIf
  1093.  
  1094.    If Len(t$)  =  #Null Or Len(t$)  >  16 Or StrStrI_(@t$, @" ")  ; spaces in extension are NOT allowed!
  1095.       ProcedureReturn   #Null
  1096.    EndIf
  1097.  
  1098.    CharUpper_(@t$)
  1099.  
  1100.    t$ =  ";"   +  t$ +  ";"
  1101.  
  1102.    ProcedureReturn   @t$
  1103.  
  1104. EndProcedure
  1105. Procedure   scal_Down(URL$)
  1106.  
  1107.    ;- Download file + sfx-libs to temporary path
  1108.    ; Return:   <> 0 = OK
  1109.  
  1110.    Protected   File$, t$, i
  1111.  
  1112.    If StrStrI_(@URL$, @"://") =  #Null :  ProcedureReturn   #Null :  EndIf
  1113.  
  1114.    scal_Temp(#SCAL_TempPath$)
  1115.  
  1116.    File$ =  GetFilePart(URL$)
  1117.    For   i  =  $20   To $FF
  1118.       If StrStrI_(@File$, @"%")  =  #Null :  Break :  EndIf
  1119.       File$ =  ReplaceString(File$, "%" + Hex(i), Chr(i), #PB_String_NoCase)
  1120.    Next
  1121.    File$ =  RS_SCAL\Temp$  +  File$
  1122.  
  1123.    RS_SCAL\File$  =  File$
  1124.  
  1125.    ; *** Already downloaded?
  1126.    If scal_Size(URL$)   =  scal_Size(File$)
  1127.       ProcedureReturn   #True
  1128.    EndIf
  1129.  
  1130.    ; *** Download file to #SCAL_TempPath$
  1131.    If scal_Copy(URL$, File$)  =  0
  1132.       ProcedureReturn   #Null
  1133.    EndIf
  1134.  
  1135.    ; =======================================================
  1136.    ;{ *** Check for needed sfx-lib files on server (x86) ***
  1137.    CompilerIf  #IsAMP
  1138.    If StrStrI_(@File$, @"MDAT.")
  1139.  
  1140.       ; MDAT.* =  Amiga TFMX?          -  Needs the SMPL.* sfx-file! Download always with adapted chars
  1141.  
  1142.       t$ =  GetFilePart(URL$, #PB_FileSystem_NoExtension)
  1143.       t$ =  scal_Case("SMPL", t$)   ; adapt upper / lower chars
  1144.  
  1145.       PokeS(StrStrI_(@URL$, @"MDAT."), t$, -1, #PB_String_NoZero)
  1146.       PokeS(StrStrI_(@File$,@"MDAT."), t$, -1, #PB_String_NoZero)
  1147.       scal_Copy(URL$, File$)
  1148.  
  1149.    ElseIf   StrStrI_(PathFindExtension_(@File$), @".TFX")
  1150.  
  1151.       ; *.TFX  =  Amiga TFMX Clone?    -  Needs the *.SAM sfx-file!  Download always with adapted chars
  1152.  
  1153.       t$ =  GetExtensionPart(URL$)
  1154.       t$ =  "."   +  scal_Case("SAM", t$)
  1155.  
  1156.       PathRenameExtension_(@URL$,   @t$)
  1157.       PathRenameExtension_(@File$,  @t$)
  1158.       scal_Copy(URL$, File$)
  1159.  
  1160.    ElseIf   StrStrI_(PathFindExtension_(@File$), @".KDM")
  1161.  
  1162.       ; *.KDM  =  Ken's Digital Music? -  Needs the waves.kwv sfx-file!
  1163.  
  1164.       URL$  =  GetPathPart(URL$) +  "waves.kwv"
  1165.       File$ =  RS_SCAL\Temp$     +  "waves.kwv"
  1166.       If scal_Size(URL$)   <> scal_Size(File$)
  1167.          scal_Copy(URL$, File$)
  1168.       EndIf
  1169.  
  1170.    ElseIf   StrStrI_(@File$, @".MINI2SF")    Or ; =   Nintendo DS Sound?      -  Needs a tagged *.lib sfx-file
  1171.             StrStrI_(@File$, @".MINIDSF")    Or ; =   Dreamcast Sound?        -  Needs a tagged *.lib sfx-file
  1172.             StrStrI_(@File$, @".MINIGSF")    Or ; =   Gameboy Sound?          -  Needs a tagged *.lib sfx-file
  1173.             StrStrI_(@File$, @".MINIPSF")    Or ; =   Playstation Sound?      -  Needs almost a couple of tagged *.lib sfx-files
  1174.             StrStrI_(@File$, @".PSF")        Or ; =   Playstation Sound?      -  Courious yes/no tagged *.lib sfx-files
  1175.             StrStrI_(@File$, @".MINIPSF2")   Or ; =   Playstation2 Sound?     -  Needs a tagged *.lib sfx-file
  1176.             StrStrI_(@File$, @".MINIQSF")    Or ; =   Capcom Q-Sound?         -  Needs a tagged *.lib sfx-file
  1177.             StrStrI_(@File$, @".MINISNSF")   Or ; =   Super Nintendo Sound?   -  Needs a tagged *.lib sfx-file
  1178.             StrStrI_(@File$, @".MINISSF")    Or ; =   Saturn Sound?           -  Needs almost a couple of tagged *.lib sfx-files
  1179.             StrStrI_(@File$, @".SSF")        Or ; =   Saturn Sound?           -  Courious yes/no tagged *.lib sfx-files
  1180.             StrStrI_(@File$, @".MINIUSF")       ; =   Ultra64 Sound?          -  Needs a tagged *.lib sfx-file
  1181.  
  1182.       ; *** Hardcoded [TAG] check for all needed *.lib sfx-files ***
  1183.       ; (too bad, unfortunately there are occasionally incorrect named *.lib's on modland server)
  1184.       If ReadFile(0, File$)
  1185.          While Eof(0)   =  0
  1186.             t$ =  ReadString(0, #PB_Ascii)
  1187.             If StrStrI_(@t$, @"_lib")  And   StrStrI_(@t$, @"=")                 ; [Tag] & _lib=, _lib1=, _lib2=..
  1188.                t$ =  PeekS(CharLower_(StrStrI_(@t$, @"=") + SizeOf(Character)))  ; LCase(StringField(t$, 2, "="))
  1189.                If scal_Size(GetPathPart(URL$) + t$)   <> scal_Size(RS_SCAL\Temp$ + t$) ; Bad solution, but works for now
  1190.                   scal_Copy(GetPathPart(URL$) + t$, RS_SCAL\Temp$ + t$)
  1191.                EndIf
  1192.             EndIf
  1193.          Wend
  1194.          CloseFile(0)
  1195.       EndIf
  1196.  
  1197.    EndIf
  1198.    CompilerEndIf  ;}
  1199.    ; =======================================================
  1200.  
  1201.    ProcedureReturn   #True
  1202.  
  1203. EndProcedure
  1204.  
  1205. CompilerIf  #IsAMP   ; C:\Users\Public\Documents\AmpMaster\
  1206. PrototypeC  pAmp_Close()
  1207. PrototypeC  pAmp_CountAmpFormatsAll()
  1208. PrototypeC  pAmp_CountAmpPlayersAll()
  1209. PrototypeC  pAmp_CountSubSongs(*File.p-Ascii)
  1210. PrototypeC  pAmp_Free()
  1211. PrototypeC  pAmp_GetAmpFormatsStrAll()
  1212. PrototypeC  pAmp_GetAmpInDllsStrAll(*File.p-Ascii)
  1213. PrototypeC  pAmp_GetAmpInDllStr(*File.p-Ascii)
  1214. PrototypeC  pAmp_GetAmpInFormatStr(*InLib.p-Ascii)
  1215. PrototypeC  pAmp_GetError()
  1216. PrototypeC  pAmp_GetErrorStr(Error.i)
  1217. PrototypeC  pAmp_GetFileInfo(*File.p-Ascii, *Title, *Length)
  1218. PrototypeC  pAmp_GetInFlags(*InLib.p-Ascii)
  1219. PrototypeC  pAmp_GetInFormatStr()
  1220. PrototypeC  pAmp_GetInInfoStr()
  1221. PrototypeC  pAmp_GetOutInfoStr()
  1222. PrototypeC  pAmp_GetPercent()
  1223. PrototypeC  pAmp_GetPlayTime()
  1224. PrototypeC  pAmp_GetStopTime()
  1225. PrototypeC  pAmp_GetSubSong(*File.p-Ascii)
  1226. PrototypeC  pAmp_InAbout()
  1227. PrototypeC  pAmp_InConfig()
  1228. PrototypeC  pAmp_InfoBox(*File.p-Ascii)
  1229. PrototypeC  pAmp_Init()
  1230. PrototypeC  pAmp_MusicBox(*File.p-Ascii, Flags.i=1)
  1231. PrototypeC  pAmp_MusicGetLength(Flags.i=0)
  1232. PrototypeC  pAmp_MusicGetOutPosition()
  1233. PrototypeC  pAmp_MusicGetPosition()
  1234. PrototypeC  pAmp_MusicGetTitleStr()
  1235. PrototypeC  pAmp_MusicIsPlaying()
  1236. PrototypeC  pAmp_MusicIsSeekable()
  1237. PrototypeC  pAmp_MusicPause(Pause.i)
  1238. PrototypeC  pAmp_MusicPlay(*File.p-Ascii)
  1239. PrototypeC  pAmp_MusicSetPan(Pan.i)
  1240. PrototypeC  pAmp_MusicSetPosition(Milliseconds.i)
  1241. PrototypeC  pAmp_MusicSetVolume(Volume.i)
  1242. PrototypeC  pAmp_MusicStop()
  1243. PrototypeC  pAmp_Open()
  1244. PrototypeC  pAmp_OutAbout()
  1245. PrototypeC  pAmp_OutConfig()
  1246. PrototypeC  pAmp_Play(*File.p-Ascii, Volume.i=255)
  1247. PrototypeC  pAmp_QuickPlay(*File.p-Ascii, *Path.p-Ascii)
  1248. PrototypeC  pAmp_SetAmpPath(*Path.p-Ascii)
  1249. PrototypeC  pAmp_SetDefaultLength(Milliseconds.i=0)
  1250. PrototypeC  pAmp_SetInDll(*InLib.p-Ascii)
  1251. PrototypeC  pAmp_SetInPath(*Path.p-Ascii)
  1252. PrototypeC  pAmp_SetLength(Milliseconds.i)
  1253. PrototypeC  pAmp_SetOutDll(*OutLib.p-Ascii)
  1254. PrototypeC  pAmp_SetOutPath(*Path.p-Ascii)
  1255. PrototypeC  pAmp_SetSubSong(*File.p-Ascii, SubSong.i)
  1256. PrototypeC  pAmp_SetWindow(*Window)
  1257. PrototypeC  pAmp_VersionStr(Flags.i=0)
  1258.  
  1259. Structure   RS_Amp
  1260.    DLL.i
  1261.    IsPlay.i
  1262.    TimeLength.i
  1263.    TimeLoop.i
  1264.    File$
  1265.    CountSubSongs     .pAmp_CountSubSongs
  1266.    Play              .pAmp_Play
  1267.    Free              .pAmp_Free
  1268.    GetPlayTime       .pAmp_GetPlayTime
  1269.    GetInInfoStr      .pAmp_GetInInfoStr
  1270.    GetSubSong        .pAmp_GetSubSong
  1271.    MusicGetLength    .pAmp_MusicGetLength
  1272.    MusicGetTitle     .pAmp_MusicGetTitleStr
  1273.    MusicIsSeekable   .pAmp_MusicIsSeekable
  1274.    MusicPause        .pAmp_MusicPause
  1275.    MusicSetPosition  .pAmp_MusicSetPosition
  1276.    MusicSetVolume    .pAmp_MusicSetVolume
  1277.    SetAmpPath        .pAmp_SetAmpPath
  1278.    SetSubSong        .pAmp_SetSubSong
  1279. EndStructure
  1280. Global   RS_Amp.RS_Amp
  1281.  
  1282. ProcedureC  AmpMusicFree()
  1283.    With  RS_Amp
  1284.       If \DLL
  1285.          \Free()
  1286.          FreeLibrary_(\DLL)
  1287.          \DLL     =  #Null
  1288.          \IsPlay  =  #Null
  1289.       EndIf
  1290.    EndWith
  1291. EndProcedure
  1292. ProcedureC  AmpMusicInit(Path$=#Null$)
  1293.  
  1294.    ; Default path to AmpMaster -> "C:\Users\Public\Documents\AmpMaster\"
  1295.  
  1296.    If RS_Amp\DLL  :  ProcedureReturn   RS_Amp\DLL  :  EndIf
  1297.  
  1298.    Protected   t${#MAX_PATH}
  1299.  
  1300.    With  RS_Amp
  1301.  
  1302.       If Path$
  1303.  
  1304.          t$ =  Path$
  1305.  
  1306.       Else  ; C:\Users\Public\Documents\ + "AmpMaster\"
  1307.  
  1308.          SHGetFolderPath_(#Null, #CSIDL_COMMON_DOCUMENTS, #Null, #Null, @t$)
  1309.          PathAddBackslash_(@t$)
  1310.  
  1311.          t$ +  "AmpMaster\"
  1312.  
  1313.       EndIf
  1314.  
  1315.       t$ +  "AmpMaster_x86.dll"
  1316.  
  1317.       \DLL  =  LoadLibrary_(@t$)
  1318.  
  1319.       If \DLL
  1320.  
  1321.          \CountSubSongs    =  GetProcAddress_(\DLL, StrAsc(@"Amp_CountSubSongs"))
  1322.          \Play             =  GetProcAddress_(\DLL, StrAsc(@"Amp_Play"))
  1323.          \Free             =  GetProcAddress_(\DLL, StrAsc(@"Amp_Free"))
  1324.          \MusicGetLength   =  GetProcAddress_(\DLL, StrAsc(@"Amp_MusicGetLength"))
  1325.          \MusicGetTitle    =  GetProcAddress_(\DLL, StrAsc(@"Amp_MusicGetTitleStr"))
  1326.          \MusicPause       =  GetProcAddress_(\DLL, StrAsc(@"Amp_MusicPause"))
  1327.          \MusicIsSeekable  =  GetProcAddress_(\DLL, StrAsc(@"Amp_MusicIsSeekable"))
  1328.          \MusicSetPosition =  GetProcAddress_(\DLL, StrAsc(@"Amp_MusicSetPosition"))
  1329.          \MusicSetVolume   =  GetProcAddress_(\DLL, StrAsc(@"Amp_MusicSetVolume"))
  1330.          \GetPlayTime      =  GetProcAddress_(\DLL, StrAsc(@"Amp_GetPlayTime"))
  1331.          \GetInInfoStr     =  GetProcAddress_(\DLL, StrAsc(@"Amp_GetInInfoStr"))
  1332.          \GetSubSong       =  GetProcAddress_(\DLL, StrAsc(@"Amp_GetSubSong"))
  1333.          \SetAmpPath       =  GetProcAddress_(\DLL, StrAsc(@"Amp_SetAmpPath"))
  1334.          \SetSubSong       =  GetProcAddress_(\DLL, StrAsc(@"Amp_SetSubSong"))
  1335.  
  1336.          If Path$
  1337.             Path$ +  "AmpLibs\"  :  \SetAmpPath(StrAsc(@Path$))   ; set path of amplibs
  1338.          EndIf
  1339.  
  1340.       EndIf
  1341.  
  1342.       ProcedureReturn   \DLL
  1343.  
  1344.    EndWith
  1345.  
  1346. EndProcedure
  1347. ProcedureC  AmpMusicPlay(*Memory, SubSong=0)
  1348.  
  1349.    ; *Memory   =  Ptr to @Filename$ only!
  1350.    ; SubSong   =  Number of subsong to play (eg. SID)
  1351.  
  1352.    ; Return: #True = Music is playing or #False = Error!
  1353.  
  1354.    With  RS_Amp
  1355.  
  1356.       \IsPlay     =  #False
  1357.       \TimeLength =  #Null
  1358.       \TimeLoop   =  #Null
  1359.       \File$      =  PeekS(*Memory, -1, RS_SCAL\StrFormat)
  1360.  
  1361.       If AmpMusicInit()
  1362.  
  1363.          \Free()
  1364.  
  1365.          If SubSong  >  0
  1366.             \SetSubSong(StrAsc(@\File$), SubSong)
  1367.          EndIf
  1368.  
  1369.          If \Play(StrAsc(@\File$))  =  0
  1370.             \TimeLength =  \MusicGetLength()
  1371.             If \TimeLength <= 100   Or StrStrI_(@\File$, @".SID") Or StrStrI_(@\File$, @".PSID")   Or StrStrI_(@\File$, @".RSID")
  1372.                \TimeLength =  600000
  1373.             EndIf
  1374.             \TimeLoop   =  \TimeLength +  ElapsedMilliseconds()   +  50 ; <- Time to reset
  1375.             \IsPlay     =  #True
  1376.          EndIf
  1377.  
  1378.          ProcedureReturn   \IsPlay
  1379.  
  1380.       EndIf
  1381.  
  1382.    EndWith
  1383.  
  1384. EndProcedure
  1385. ProcedureC  AmpMusicStop()
  1386.    RS_Amp\Free()  :  RS_Amp\IsPlay  =  #False
  1387. EndProcedure
  1388. ProcedureC  AmpMusicLoop()
  1389.    If RS_Amp\IsPlay  And   ElapsedMilliseconds()   >  RS_Amp\TimeLoop
  1390.       ProcedureReturn   AmpMusicPlay(@RS_Amp\File$)
  1391.    EndIf
  1392. EndProcedure
  1393. ProcedureC  AmpMusicPosition()
  1394.    If RS_Amp\IsPlay
  1395.       ProcedureReturn   RS_Amp\GetPlayTime()
  1396.    EndIf
  1397. EndProcedure
  1398. ProcedureC  AmpMusicVolume(Volume)
  1399.    If RS_Amp\IsPlay
  1400.       ProcedureReturn   RS_Amp\MusicSetVolume(Volume)
  1401.    EndIf
  1402. EndProcedure
  1403. ProcedureC  AmpMusicTitle()
  1404.    If RS_Amp\IsPlay
  1405.       ProcedureReturn   RS_Amp\MusicGetTitle()
  1406.    EndIf
  1407. EndProcedure
  1408. ProcedureC  AmpCountSubSongs(*Memory)
  1409.    ProcedureReturn   RS_Amp\CountSubSongs(StrAsc(*Memory))
  1410. EndProcedure
  1411. ProcedureC  AmpMusicInfo()
  1412.    If RS_Amp\IsPlay
  1413.       ProcedureReturn   RS_Amp\GetInInfoStr()
  1414.    EndIf
  1415. EndProcedure
  1416. ProcedureC  AmpMusicLength()
  1417.    ProcedureReturn   RS_Amp\TimeLength
  1418. EndProcedure
  1419. ProcedureC  AmpMusicPause(Flags)
  1420.    If RS_Amp\IsPlay
  1421.       ProcedureReturn   RS_Amp\MusicPause(Flags)
  1422.    EndIf
  1423. EndProcedure
  1424. ProcedureC  AmpMusicIsSeekable()
  1425.    With  RS_Amp
  1426.       ProcedureReturn   \MusicIsSeekable()
  1427.    EndWith
  1428. EndProcedure
  1429. ProcedureC  AmpMusicSetPosition(Milliseconds)
  1430.    With  RS_Amp
  1431.       If \IsPlay  And   AmpMusicIsSeekable() And   ; no PSID/SID/RSID
  1432.          StrStrI_(@\File$, @".SID")    =  0  And
  1433.          StrStrI_(@\File$, @".PSID")   =  0  And
  1434.          StrStrI_(@\File$, @".RSID")   =  0
  1435.          ProcedureReturn   \MusicSetPosition(Milliseconds)
  1436.       EndIf
  1437.    EndWith
  1438. EndProcedure
  1439. CompilerEndIf
  1440.  
  1441. CompilerIf  #IsS68
  1442. ProcedureC  sc68_Play(*Memory, Length)
  1443.    With  RS_SCAL
  1444.  
  1445.       If Length
  1446.          \ID      =  sc68replay_Init(*Memory, Length, #SC68Replay_MEMORY)
  1447.          \Title$  =  PeekS(*Memory + $48, -1, #PB_Ascii)
  1448.       Else
  1449.          \ID   =  sc68replay_Init(StrAsc(*Memory), #Null, #SC68Replay_FILE)
  1450.       EndIf
  1451.  
  1452.       If \ID
  1453.          sc68replay_Play()
  1454.       EndIf
  1455.  
  1456.       ProcedureReturn   \ID
  1457.  
  1458.    EndWith
  1459. EndProcedure
  1460. ProcedureC  sc68_Free()
  1461.    If RS_SCAL\ID
  1462.       sc68replay_Stop()
  1463.    EndIf
  1464. EndProcedure
  1465. CompilerEndIf
  1466.  
  1467. Procedure   IsAmpMaster()
  1468.  
  1469.    CompilerIf  #IsAMP
  1470.  
  1471.       Static   t${#MAX_PATH}
  1472.  
  1473.       If Len(t$)  =  #Null
  1474.          SHGetFolderPath_(#Null, #CSIDL_COMMON_DOCUMENTS, #Null, #Null, @t$)
  1475.          PathAddBackslash_(@t$)
  1476.          t$ +  "AmpMaster"
  1477.       EndIf
  1478.  
  1479.       ProcedureReturn   Bool(FileSize(t$) =  -2)
  1480.  
  1481.    CompilerElse
  1482.  
  1483.       ProcedureReturn   #False
  1484.  
  1485.    CompilerEndIf
  1486.  
  1487. EndProcedure
  1488. Procedure   Default_Mode(*Memory.Long, Length)
  1489.  
  1490.    ; Autodetect #C2D_MUSIC_[mode]
  1491.  
  1492.    ; *Memory = Pointer to @Filename if Length = 0
  1493.    ; Checks file.extension ?.* and *.?
  1494.  
  1495.    ; Return: Default playback-mode or 0 = Error!
  1496.  
  1497.    Static   Mode
  1498.  
  1499.    Mode  =  #Null
  1500.  
  1501.    If Length   >  #Null ; *** Check memory for default mode (not to be confused with supported mode!) ***
  1502.  
  1503.       If       SCAL_IsFormat(#C2D_MUSIC_FT2, *Memory, Length)  :  Mode  =  #C2D_MUSIC_FT2 ; stabile Sound/Pro/Mod/FastTracker-Replay
  1504.       ElseIf   SCAL_IsFormat(#C2D_MUSIC_PT2, *Memory, Length)  :  Mode  =  #C2D_MUSIC_PT2 ; only Protracker 2.3d
  1505.       ElseIf   SCAL_IsFormat(#C2D_MUSIC_AHX, *Memory, Length)  :  Mode  =  #C2D_MUSIC_AHX
  1506.       ElseIf   SCAL_IsFormat(#C2D_MUSIC_FC4, *Memory, Length)  :  Mode  =  #C2D_MUSIC_FC4
  1507.       ElseIf   SCAL_IsFormat(#C2D_MUSIC_S3M, *Memory, Length)  :  Mode  =  #C2D_MUSIC_S3M
  1508.       ElseIf   SCAL_IsFormat(#C2D_MUSIC_STM, *Memory, Length)  :  Mode  =  #C2D_MUSIC_STM
  1509.       ElseIf   SCAL_IsFormat(#C2D_MUSIC_OGG, *Memory, Length)  :  Mode  =  #C2D_MUSIC_OGG
  1510.       ElseIf   SCAL_IsFormat(#C2D_MUSIC_FLA, *Memory, Length)  :  Mode  =  #C2D_MUSIC_FLA
  1511.       ElseIf   SCAL_IsFormat(#C2D_MUSIC_WAV, *Memory, Length)  :  Mode  =  #C2D_MUSIC_WAV
  1512.  
  1513.       CompilerIf  (#IsSID  +  #IsTSR)
  1514.       ElseIf   SCAL_IsFormat(#C2D_MUSIC_SID, *Memory, Length)  :  Mode  =  #C2D_MUSIC_SID
  1515.       CompilerEndIf
  1516.       CompilerIf  #IsYMP
  1517.       ElseIf   SCAL_IsFormat(#C2D_MUSIC_YMP, *Memory, Length)  :  Mode  =  #C2D_MUSIC_YMP
  1518.       CompilerEndIf
  1519.       CompilerIf  #IsBAS
  1520.       ElseIf   SCAL_IsFormat(#C2D_MUSIC_BAS, *Memory, Length)  :  Mode  =  #C2D_MUSIC_BAS
  1521.       CompilerEndIf
  1522.       CompilerIf  #IsBMF
  1523.       ElseIf   SCAL_IsFormat(#C2D_MUSIC_BMF, *Memory, Length)  :  Mode  =  #C2D_MUSIC_BMF
  1524.       CompilerEndIf
  1525.       CompilerIf  #IsS68
  1526.       ElseIf   SCAL_IsFormat(#C2D_MUSIC_S68, *Memory, Length)  :  Mode  =  #C2D_MUSIC_S68
  1527.       CompilerEndIf
  1528.       CompilerIf  (#IsV2M  +  #IsV1M)
  1529.       ElseIf   SCAL_IsFormat(#C2D_MUSIC_V2M, *Memory, Length)  :  Mode  =  #C2D_MUSIC_V2M
  1530.       CompilerEndIf
  1531.  
  1532.       Else  ; default memory mode
  1533.  
  1534.          Mode  =  #C2D_MUSIC_MOD
  1535.  
  1536.       EndIf
  1537.  
  1538.    Else  ; *** Checks file.extension ?.* and *.? ***
  1539.  
  1540.       Protected   *x, i
  1541.  
  1542.       For   i  =  0  To 1
  1543.  
  1544.          *x =  scal_Sufx(*Memory, i)   :  If *x =  #Null :  Continue :  EndIf
  1545.  
  1546.          If       StrStrI_(?l_FT2, *x) :  Mode  =  #C2D_MUSIC_FT2
  1547.          ElseIf   StrStrI_(?l_PT2, *x) :  Mode  =  #C2D_MUSIC_PT2
  1548.          ElseIf   StrStrI_(?l_S3M, *x) :  Mode  =  #C2D_MUSIC_S3M
  1549.          ElseIf   StrStrI_(?l_STM, *x) :  Mode  =  #C2D_MUSIC_STM
  1550.          ElseIf   StrStrI_(?l_AHX, *x) :  Mode  =  #C2D_MUSIC_AHX
  1551.          ElseIf   StrStrI_(?l_FC4, *x) :  Mode  =  #C2D_MUSIC_FC4
  1552.          ElseIf   StrStrI_(?l_WAV, *x) :  Mode  =  #C2D_MUSIC_WAV
  1553.          ElseIf   StrStrI_(?l_OGG, *x) :  Mode  =  #C2D_MUSIC_OGG
  1554.          ElseIf   StrStrI_(?l_FLA, *x) :  Mode  =  #C2D_MUSIC_FLA
  1555.  
  1556.          CompilerIf  #IsBAS
  1557.          ElseIf   StrStrI_(?l_BAS, *x) :  Mode  =  #C2D_MUSIC_BAS
  1558.          CompilerEndIf
  1559.          CompilerIf  #IsMED
  1560.          ElseIf   StrStrI_(?l_MED, *x) :  Mode  =  #C2D_MUSIC_MED
  1561.          CompilerEndIf
  1562.          CompilerIf  #IsSID
  1563.          ElseIf   StrStrI_(?l_SID, *x) :  Mode  =  #C2D_MUSIC_SID
  1564.          CompilerEndIf
  1565.          CompilerIf  #IsTSR
  1566.          ElseIf   StrStrI_(?l_SID, *x) :  Mode  =  #C2D_MUSIC_TSR
  1567.          CompilerEndIf
  1568.          CompilerIf  #IsYMP
  1569.          ElseIf   StrStrI_(?l_YMP, *x) :  Mode  =  #C2D_MUSIC_YMP
  1570.          CompilerEndIf
  1571.          CompilerIf  #IsS68
  1572.          ElseIf   StrStrI_(?l_SC68, *x):  Mode  =  #C2D_MUSIC_S68
  1573.          CompilerEndIf
  1574.          CompilerIf  #IsV2M
  1575.          ElseIf   StrStrI_(?l_V2M, *x)
  1576.             If IsAmpMaster()
  1577.                Mode  =  #C2D_MUSIC_AMP ; stabile v1.0/1.5 playback
  1578.             Else
  1579.                Mode  =  #C2D_MUSIC_V2M
  1580.             EndIf
  1581.          CompilerEndIf
  1582.          CompilerIf  #IsBMF
  1583.          ElseIf   StrStrI_(?l_BMF, *x) :  Mode  =  #C2D_MUSIC_BMF
  1584.          CompilerEndIf
  1585.  
  1586.          ElseIf   StrStrI_(?l_MCI, *x) :  Mode  =  #C2D_MUSIC_MCI
  1587.          ElseIf   StrStrI_(?l_MOD, *x) :  Mode  =  #C2D_MUSIC_MOD
  1588.  
  1589.          CompilerIf  #IsAMP   ; check at last, coz we don't know if ampmaster is installed?
  1590.          ElseIf   StrStrI_(?l_AMP, *x) :  Mode  =  #C2D_MUSIC_AMP
  1591.          CompilerEndIf
  1592.  
  1593.          EndIf
  1594.  
  1595.          If Mode  :  Break :  EndIf
  1596.  
  1597.          ;Mode =  #C2D_MUSIC_MCI ; pre-set as default
  1598.  
  1599.       Next
  1600.  
  1601.    EndIf
  1602.  
  1603.    ProcedureReturn   Mode
  1604.  
  1605. EndProcedure
  1606.  
  1607. ;- *** Functions ***************
  1608. ProcedureDLL   SCAL_AmpInstall(*URL)
  1609.  
  1610.    ; Only for Windows x86!
  1611.  
  1612.    ; *** ZIP ***
  1613.    ; https://testaware.files.wordpress.com/2020/08/ampmaster200824
  1614.  
  1615.    CompilerIf  #IsAMP
  1616.  
  1617.       scal_Temp(#SCAL_TempPath$) ; create temporary directory for all files
  1618.  
  1619.       Static   IsError
  1620.       Protected   URL$, File$, i, Count
  1621.  
  1622.       ; 2.5KB smaller than -> Install_Path$  =  GetUserDirectory(#PB_Directory_Public)
  1623.       Protected   Install_Path${#MAX_PATH}
  1624.       SHGetFolderPath_(#Null, #CSIDL_COMMON_DOCUMENTS, #Null, #Null, @Install_Path$)
  1625.       PathAddBackslash_(@Install_Path$)
  1626.  
  1627.       If *URL
  1628.          URL$  =  PeekS(*URL, -1, RS_SCAL\StrFormat)
  1629.       Else
  1630.          URL$  =  #SCAL_AmpMaster$  +  ".gif"
  1631.       EndIf
  1632.  
  1633.       If StrStrI_(@URL$, @"://")
  1634.  
  1635.          File$ =  RS_SCAL\Temp$ + GetFilePart(URL$, #PB_FileSystem_NoExtension) + ".zip"
  1636.  
  1637.          If StrStrI_(@URL$, @".GIF")
  1638.             NetWorkSkip(6) ; "GIF89a" -> ; skip to real Arc-Header (6 bytes)
  1639.          Else
  1640.             NetWorkSkip(#Null)
  1641.          EndIf
  1642.  
  1643.          IsError  =  Bool(NetWorkDownload(URL$, File$)=0)
  1644.  
  1645.       Else  ; unpack file-archive
  1646.  
  1647.          File$    =  URL$
  1648.          IsError  =  Bool(FileSize(File$)<=0)   ; file error?
  1649.  
  1650.       EndIf
  1651.  
  1652.       If IsError  =  0
  1653.  
  1654.          Count =  ZIP_GetFilesCount(File$)
  1655.  
  1656.          If Count
  1657.             For   i  =  1  To Count
  1658.                If ZIP_ExtractFile(File$, i, Install_Path$)
  1659.                   If RS_SCAL\CallBack  ; user proc?
  1660.                      If CallFunctionFast(RS_SCAL\CallBack, (100.0 / Count) * (i + 1))  ; 126 Files + 3 Folders
  1661.                         IsError  =  #True
  1662.                         Break
  1663.                      EndIf
  1664.                   EndIf
  1665.                Else
  1666.                   IsError  =  #True
  1667.                   Break
  1668.                EndIf
  1669.             Next
  1670.          Else
  1671.             IsError  =  #True
  1672.          EndIf
  1673.  
  1674.       Else
  1675.  
  1676.          IsError  =  #True
  1677.  
  1678.       EndIf
  1679.  
  1680.       If RS_SCAL\CallBack  :  CallFunctionFast(RS_SCAL\CallBack, 100)   :  EndIf ; user proc?
  1681.  
  1682.       ; *** #True = ALL correct unpacked, #False = ERROR!
  1683.       ProcedureReturn   Bool(IsError=0)
  1684.  
  1685.    CompilerElse
  1686.  
  1687.       If RS_SCAL\CallBack  :  CallFunctionFast(RS_SCAL\CallBack, 100)   :  EndIf ; user proc?
  1688.  
  1689.       ProcedureReturn   #False
  1690.  
  1691.    CompilerEndIf
  1692.  
  1693. EndProcedure
  1694. ProcedureDLL   SCAL_CallBack(*Proc)
  1695.    ; *proc = @Procedurename(Param)
  1696.    ; Param -> downloadstatus 0-100%
  1697.    RS_SCAL\CallBack  =  *Proc ; NetWorkCallBack()
  1698. EndProcedure
  1699. ProcedureDLL   SCAL_Download(*URL, *File, Skip, Flags)
  1700.  
  1701.    ; Return:   Bytesize of download or number of unpacked files
  1702.  
  1703.    Static   Count
  1704.    Protected   i, File$, Path$, URL$
  1705.  
  1706.    If *URL  =  #Null :  ProcedureReturn   #Null :  EndIf
  1707.  
  1708.    URL$  =  PeekS(*URL, -1, RS_SCAL\StrFormat)
  1709.    If StrStrI_(@URL$, @"://") =  #Null :  ProcedureReturn   #Null :  EndIf
  1710.  
  1711.    If *File =  #Null
  1712.       scal_Temp(#SCAL_TempPath$)
  1713.       File$ =  RS_SCAL\Temp$ + GetFilePart(URL$)
  1714.    Else
  1715.       File$ =  PeekS(*File, -1, RS_SCAL\StrFormat)
  1716.    EndIf
  1717.  
  1718.    ; *** already downloaded?
  1719.    Count =  scal_Size(File$)
  1720.    If scal_Size(URL$)   =  Count
  1721.       ProcedureReturn   Count
  1722.    EndIf
  1723.  
  1724.    NetWorkSkip(Skip)
  1725.  
  1726.    i  =  NetWorkDownload(URL$, File$)
  1727.  
  1728.    ; *** Unzip archive?
  1729.    If Flags And   i  >  #Null
  1730.  
  1731.       Count =  ZIP_GetFilesCount(File$)
  1732.  
  1733.       If Count
  1734.  
  1735.          Path$ =  GetPathPart(File$)
  1736.  
  1737.          For   i  =  1  To Count
  1738.             If ZIP_ExtractFile(File$, i, Path$)
  1739.                If RS_SCAL\CallBack  ; user proc?
  1740.                   If CallFunctionFast(RS_SCAL\CallBack, (100.0 / Count) * (i + 1))
  1741.                      Count =  i
  1742.                      Break
  1743.                   EndIf
  1744.                EndIf
  1745.             Else
  1746.                Count =  i
  1747.                Break
  1748.             EndIf
  1749.          Next
  1750.  
  1751.       Else
  1752.  
  1753.          Count =  i  ; bytesize if not packed
  1754.  
  1755.       EndIf
  1756.  
  1757.    Else
  1758.  
  1759.       Count =  i  ; bytesize
  1760.  
  1761.    EndIf
  1762.  
  1763.    If RS_SCAL\CallBack  :  CallFunctionFast(RS_SCAL\CallBack, 100)   :  EndIf ; user proc?
  1764.  
  1765.    ProcedureReturn   Count
  1766.  
  1767. EndProcedure
  1768. ProcedureDLL   SCAL_DownMemory(*URL, *Length.Integer)
  1769.  
  1770.    Static   *Memory
  1771.  
  1772.    If *Memory  >  #Null
  1773.       FreeMemory(*Memory)
  1774.       *Memory  =  #Null
  1775.    EndIf
  1776.  
  1777.    If *URL  <= #Null Or *Length  <= #Null :  ProcedureReturn   #Null :  EndIf
  1778.  
  1779.    *Memory  =  NetWorkLoad(PeekS(*URL, -1, RS_SCAL\StrFormat))
  1780.  
  1781.    If *Memory
  1782.       *Length\i   =  RS_NetWork\Length
  1783.    Else
  1784.       *Length\i   =  #Null
  1785.    EndIf
  1786.  
  1787.    ProcedureReturn   *Memory
  1788.  
  1789. EndProcedure
  1790. ProcedureDLL   SCAL_Formats(Mode, Flags)
  1791.  
  1792.    ; Mode:  #C2D_MUSIC_[MODE] =  Get info of supported formats by Mode
  1793.    ;        < min or > max    =  Get info of all supported formats by SCAL
  1794.  
  1795.    ; Flags: 0  =  Get number of supported formats
  1796.    ;        1  =  Get ptr to unicode formatstrings "AHX;MOD;MP3..."
  1797.  
  1798.    Static   Count
  1799.    Static   TotalMode$, TotalCount
  1800.  
  1801.    Protected   t$, *Memory.Character
  1802.  
  1803.    Select   Mode
  1804.       Case  #SCAL_MIN   To #SCAL_MAX
  1805.  
  1806.          ;{ Mode = #C2D_MUSIC_[MODE] - Calculate supported formats by Engine }
  1807.  
  1808.          Select   Mode
  1809.  
  1810.             Case  #C2D_MUSIC_AHX :  *Memory  =  ?l_AHX
  1811.  
  1812.             CompilerIf  #IsAMP
  1813.             Case  #C2D_MUSIC_AMP :  *Memory  =  ?l_AMP
  1814.             CompilerEndIf
  1815.  
  1816.             Case  #C2D_MUSIC_API :  *Memory  =  ?l_WAV
  1817.  
  1818.             CompilerIf  #IsBAS
  1819.             Case  #C2D_MUSIC_BAS :  *Memory  =  ?l_BAS
  1820.             CompilerEndIf
  1821.  
  1822.             CompilerIf  #IsBMF
  1823.             Case  #C2D_MUSIC_BMF :  *Memory  =  ?l_BMF
  1824.             CompilerEndIf
  1825.  
  1826.             Case  #C2D_MUSIC_FC4 :  *Memory  =  ?l_FC4
  1827.  
  1828.             CompilerIf  #IsFCP
  1829.             Case  #C2D_MUSIC_FCP :  *Memory  =  ?l_FCP
  1830.             CompilerEndIf
  1831.  
  1832.             Case  #C2D_MUSIC_FLA :  *Memory  =  ?l_FLA
  1833.  
  1834.             Case  #C2D_MUSIC_FT2 :  *Memory  =  ?l_FT2
  1835.  
  1836.             Case  #C2D_MUSIC_MCI :  *Memory  =  ?l_MCI
  1837.  
  1838.             CompilerIf  #IsMED
  1839.             Case  #C2D_MUSIC_MED :  *Memory  =  ?l_MED
  1840.             CompilerEndIf
  1841.  
  1842.             Case  #C2D_MUSIC_MOD :  *Memory  =  ?l_MOD
  1843.  
  1844.             CompilerIf  #IsMOV
  1845.             Case  #C2D_MUSIC_MOV :  *Memory  =  ?l_MCI
  1846.             CompilerEndIf
  1847.  
  1848.             Case  #C2D_MUSIC_OGG :  *Memory  =  ?l_OGG
  1849.  
  1850.             Case  #C2D_MUSIC_PT2 :  *Memory  =  ?l_PT2
  1851.  
  1852.             CompilerIf  #IsS68
  1853.             Case  #C2D_MUSIC_S68 :  *Memory  =  ?l_SC68
  1854.             CompilerEndIf
  1855.  
  1856.             CompilerIf  #IsSID
  1857.             Case  #C2D_MUSIC_SID :  *Memory  =  ?l_SID
  1858.             CompilerEndIf
  1859.  
  1860.             Case  #C2D_MUSIC_STM :  *Memory  =  ?l_STM
  1861.  
  1862.             Case  #C2D_MUSIC_S3M :  *Memory  =  ?l_S3M
  1863.  
  1864.             Case  #C2D_MUSIC_TFC :  *Memory  =  ?l_FC4
  1865.  
  1866.             Case  #C2D_MUSIC_THX :  *Memory  =  ?l_AHX
  1867.  
  1868.             Case  #C2D_MUSIC_TPT :  *Memory  =  ?l_PT2
  1869.  
  1870.             CompilerIf  #IsTSR
  1871.             Case  #C2D_MUSIC_TSR :  *Memory  =  ?l_SID
  1872.             CompilerEndIf
  1873.  
  1874.             CompilerIf  #IsV1M
  1875.             Case  #C2D_MUSIC_V1M :  *Memory  =  ?l_V2M
  1876.             CompilerEndIf
  1877.  
  1878.             CompilerIf  #IsV2M
  1879.             Case  #C2D_MUSIC_V2M :  *Memory  =  ?l_V2M
  1880.             CompilerEndIf
  1881.  
  1882.             Case  #C2D_MUSIC_WAV :  *Memory  =  ?l_WAV
  1883.  
  1884.             CompilerIf  #IsXM2
  1885.             Case  #C2D_MUSIC_XM2 :  *Memory  =  ?l_XM2
  1886.             CompilerEndIf
  1887.  
  1888.             CompilerIf  #IsYMP
  1889.             Case  #C2D_MUSIC_YMP :  *Memory  =  ?l_YMP
  1890.             CompilerEndIf
  1891.  
  1892.          EndSelect
  1893.  
  1894.          If Flags And   *Memory
  1895.             ProcedureReturn   *Memory  ; ptr to ;MOD;...
  1896.          EndIf
  1897.  
  1898.          If *Memory  ; count extensions?
  1899.             Count =  -2 ; first ";" + last ";" + #null
  1900.             While *Memory  >  SizeOf(Character)
  1901.                *Memory  =  StrStrI_(*Memory, @";") +  SizeOf(Character)
  1902.                Count +  1
  1903.             Wend
  1904.          Else
  1905.             Count =  #Null
  1906.          EndIf
  1907.  
  1908.          ProcedureReturn   Count
  1909.          ;}
  1910.  
  1911.       Default  ; -1
  1912.  
  1913.          ;{ Mode <= #Null - Calculate ALL supported formats once }
  1914.  
  1915.          If TotalCount
  1916.             If Flags ; String?
  1917.                ProcedureReturn   @TotalMode$
  1918.             EndIf
  1919.             ProcedureReturn   TotalCount
  1920.          EndIf
  1921.  
  1922.          Protected   NewMap   ExtMap.s()
  1923.          Protected   NewList  ExtList.s()
  1924.  
  1925.          *Memory  =  ?l_Start
  1926.          While *Memory  <  ?l_Finish
  1927.             If *Memory\c
  1928.                t$ =  PeekS(*Memory)
  1929.                TotalMode$  +  Trim(t$, ";")  +  ";"   :  *Memory  +  Len(t$)  *  SizeOf(Character)
  1930.             EndIf
  1931.             *Memory  +  SizeOf(Character) ; Null$
  1932.          Wend
  1933.  
  1934.          Repeat
  1935.             TotalCount  +  1  :  t$ =  StringField(TotalMode$, TotalCount, ";")  :  ExtMap(t$)
  1936.          Until Len(t$)  =  #Null
  1937.  
  1938.          ForEach  ExtMap()
  1939.             If MapKey(ExtMap())
  1940.                AddElement(ExtList())   :  ExtList()   =  MapKey(ExtMap())
  1941.             EndIf
  1942.          Next
  1943.  
  1944.          SortList(ExtList(), #PB_Sort_Ascending)
  1945.  
  1946.          TotalCount  =  ListSize(ExtList())
  1947.          TotalMode$  =  ";"   ; ";Format;"
  1948.          ForEach  ExtList()
  1949.             TotalMode$  +  ExtList()   +  ";"
  1950.          Next
  1951.  
  1952.          FreeMap(ExtMap())
  1953.          FreeList(ExtList())
  1954.  
  1955.          If Flags
  1956.             ProcedureReturn   @TotalMode$
  1957.          EndIf
  1958.  
  1959.          ProcedureReturn   TotalCount
  1960.          ;}
  1961.  
  1962.    EndSelect
  1963.  
  1964. EndProcedure
  1965. ProcedureDLL   SCAL_Free()
  1966.  
  1967.    Protected   StrFormat, Freq, *Proc
  1968.    Static   Volume=-1
  1969.  
  1970.    With  RS_SCAL
  1971.  
  1972.       If \ID   ; Is playing active?
  1973.          Select   \Mode
  1974.  
  1975.             Case  #C2D_MUSIC_AHX :  ahx1play_Close()
  1976.             Case  #C2D_MUSIC_API :  PlaySound_(#Null, #Null, #Null)
  1977.             Case  #C2D_MUSIC_FC4 :  fc14play_Close()
  1978.             Case  #C2D_MUSIC_FLA :  If IsSound(0)  :  FreeSound(0)   :  EndIf
  1979.             Case  #C2D_MUSIC_FT2 :  ft2play_Close()
  1980.             Case  #C2D_MUSIC_MCI :  mciSendString_(@"STOP 0", 0, 0, 0)  :  mciSendString_(@"CLOSE 0", 0, 0, 0)
  1981.             Case  #C2D_MUSIC_MOD :  If IsMusic(0)  :  FreeMusic(0)   :  EndIf
  1982.             Case  #C2D_MUSIC_OGG :  If IsSound(0)  :  FreeSound(0)   :  EndIf
  1983.             Case  #C2D_MUSIC_PT2 :  pt2play_Close()
  1984.             Case  #C2D_MUSIC_S3M :  st3play_Close()
  1985.             Case  #C2D_MUSIC_STM :  st23play_Close()
  1986.             Case  #C2D_MUSIC_TFC :  tinyfc14play_Close()
  1987.             Case  #C2D_MUSIC_THX :  tinyahx1play_Close()
  1988.             Case  #C2D_MUSIC_TPT :  tinypt2play_Close()
  1989.             Case  #C2D_MUSIC_WAV :  If IsSound(0)  :  FreeSound(0)   :  EndIf
  1990.  
  1991.             CompilerIf  #IsAMP
  1992.             Case  #C2D_MUSIC_AMP :  AmpMusicFree()
  1993.             CompilerEndIf
  1994.             CompilerIf  #IsBAS
  1995.             Case  #C2D_MUSIC_BAS
  1996.                BASSMOD_MusicStop()
  1997.                BASSMOD_MusicFree()
  1998.                BASSMOD_SetVolume(100)  ; restore digital volume!
  1999.                BASSMOD_Free()
  2000.             CompilerEndIf
  2001.             CompilerIf  #IsBMF
  2002.             Case  #C2D_MUSIC_BMF
  2003.                SynthEnter(\ID)
  2004.                SynthStop(\ID)
  2005.                SynthLeave(\ID)
  2006.                SynthDestroy(\ID)
  2007.             CompilerEndIf
  2008.             CompilerIf  #IsFCP
  2009.             Case  #C2D_MUSIC_FCP :  FCp_Close()
  2010.             CompilerEndIf
  2011.             CompilerIf  #IsMED
  2012.             Case  #C2D_MUSIC_MED
  2013.                MEDP_Stop()
  2014.                MEDP_Unload()
  2015.                MEDP_Release()
  2016.             CompilerEndIf
  2017.             CompilerIf  #IsMOV
  2018.             Case  #C2D_MUSIC_MOV
  2019.                If IsMovie(0)     :  FreeMovie(0)      :  EndIf
  2020.                If \WinID   And   IsWindow(\WinID)
  2021.                   CloseWindow(\WinID)
  2022.                EndIf
  2023.                \WinID   =  #Null
  2024.             CompilerEndIf
  2025.             CompilerIf  #IsS68
  2026.             Case  #C2D_MUSIC_S68 :  sc68_Free() ;sc68replay_Stop()
  2027.             CompilerEndIf
  2028.             CompilerIf  #IsSID
  2029.             Case  #C2D_MUSIC_SID :  SIDClose()
  2030.             CompilerEndIf
  2031.             CompilerIf  #IsTSR
  2032.             Case  #C2D_MUSIC_TSR :  sid_sound_server_replay_stop()
  2033.             CompilerEndIf
  2034.             CompilerIf  #IsV1M
  2035.             Case  #C2D_MUSIC_V1M
  2036.                ssStop()
  2037.                ssClose()
  2038.             CompilerEndIf
  2039.             CompilerIf  #IsV2M
  2040.             Case  #C2D_MUSIC_V2M
  2041.                If \IsPause =  0  ; remember: custom pause!
  2042.                   V2MStop()
  2043.                   dsClose()
  2044.                EndIf
  2045.             CompilerEndIf
  2046.             CompilerIf  #IsXM2
  2047.             Case  #C2D_MUSIC_XM2 :  uFMOD_PlaySong(#Null)
  2048.             CompilerEndIf
  2049.             CompilerIf  #IsYMP
  2050.             Case  #C2D_MUSIC_YMP
  2051.                YM_Stop()
  2052.                YM_Close()
  2053.             CompilerEndIf
  2054.  
  2055.          EndSelect
  2056.       EndIf
  2057.  
  2058.       ; Netfile downloaded?
  2059.       NetWorkFree()
  2060.  
  2061.       ; Intern temporary *buffer?
  2062.       If \IsAlloc And   \Memory
  2063.          FreeMemory(\Memory)
  2064.       EndIf
  2065.  
  2066.       ; AscII or Unicode?
  2067.       If \StrFormat  <= #Null
  2068.          \StrFormat  =  #PB_Unicode ; Default PeekS-Mode if *Memory = @File
  2069.       EndIf
  2070.  
  2071.       ; Set default frequency
  2072.       If \Freq <= #Null
  2073.          \Freq =  44100
  2074.       EndIf
  2075.  
  2076.       ; Set default volume (used in SCAL_Play)
  2077.       If Volume   <  #Null And   \Volume  <= #Null
  2078.          \Volume  =  100
  2079.       EndIf
  2080.  
  2081.       StrFormat   =  \StrFormat
  2082.       Freq        =  \Freq
  2083.       Volume      =  \Volume
  2084.       *Proc       =  \CallBack
  2085.  
  2086.       ClearStructure(@RS_SCAL, RS_SCAL)
  2087.  
  2088.       \Freq       =  Freq
  2089.       \StrFormat  =  StrFormat
  2090.       \Volume     =  Volume   ; -1
  2091.       \CallBack   =  *Proc
  2092.       \NetLength  =  #Null
  2093.  
  2094.       ; Generate *pointers (avoid *ptr=0 error)
  2095.       \File$      =  #Null$
  2096.       \Path$      =  #Null$
  2097.       \Time$      =  #Null$
  2098.       \Title$     =  #Null$
  2099.       \Tracker$   =  #Null$
  2100.  
  2101.    EndWith
  2102.  
  2103. EndProcedure
  2104. ProcedureDLL   SCAL_GetLength(Flags)
  2105.  
  2106.    ; Flags: 0  =  Get timelength in ms
  2107.    ;        1  =  Get ptr to unicode timestring "hh:mm:ss.ttt"
  2108.  
  2109.    ; RETURN: Time in ms or ptr to timestring - #NULL not playing or time not calcuable
  2110.  
  2111.    With  RS_SCAL
  2112.  
  2113.       If Flags
  2114.          If \Time
  2115.             \Time$   =  StrTime(\Time)
  2116.             \Time$   =  RTrim(\Time$, "0")
  2117.             \Time$   =  RTrim(\Time$, ",")
  2118.          Else
  2119.             \Time$   =  PeekS(?s_unknown) ; "?"
  2120.          EndIf
  2121.          ProcedureReturn   @\Time$
  2122.       EndIf
  2123.  
  2124.       ProcedureReturn   \Time
  2125.  
  2126.    EndWith
  2127.  
  2128. EndProcedure
  2129. ProcedureDLL   SCAL_GetLink(*URL)
  2130.  
  2131.    ; Decode the real url of a hosted mediafile
  2132.  
  2133.    ; Return: Ptr to @filename / #NULL = Error
  2134.  
  2135.    Static   URL$
  2136.  
  2137.    Protected   Link$, t$, ID$, ID, *Start, *Finish
  2138.    Protected   hNET, hURL, Length
  2139.  
  2140.    URL$  =  #Null$
  2141.    Link$ =  PeekS(*URL, -1, RS_SCAL\StrFormat)  ; string to user-format
  2142.  
  2143.    If       StrStrI_(@Link$, @"://www.4shared.com/")        :  ID =  #ID_4SHARED       :  ID$   =  ~"data-cp-preview=\""
  2144.   ElseIf   StrStrI_(@Link$, @"://www.bitchute.com/video/") :  ID =  #ID_BITCHUTE      :  ID$   =  "https://seed"
  2145.   ElseIf   StrStrI_(@Link$, @"://dein.tube/watch/")        :  ID =  #ID_DEINTUBE      :  ID$   =  "/upload/videos/"
  2146.   ElseIf   StrStrI_(@Link$, @"://donnersender.ru/v/")      :  ID =  #ID_DONNERSENDER  :  ID$   =  "https://cdn.donnersender.ru/videos/"
  2147.   ElseIf   StrStrI_(@Link$, @"://www.mediafire.com/file/") :  ID =  #ID_MEDIAFIRE     :  ID$   =  "http://download"
  2148.   Else
  2149.      ProcedureReturn   #Null
  2150.   EndIf
  2151.  
  2152.   ; ---------------------------------
  2153.   ; *** Read full website of host ***
  2154.   ; ---------------------------------
  2155.   hNET = InternetOpen_(@"SCAL/1.0", #INTERNET_OPEN_TYPE_PRECONFIG, #Null, #Null, 0)
  2156.   If hNET  =  #Null :  ProcedureReturn   #Null :  EndIf ; error
  2157.  
  2158.   hURL = InternetOpenUrl_(hNET, @Link$, #Null, 0, #INTERNET_FLAG_PRAGMA_NOCACHE|#INTERNET_FLAG_KEEP_CONNECTION, 0)
  2159.   If hURL  =  #Null :  InternetCloseHandle_(hNET) :  ProcedureReturn   #Null :  EndIf ; error
  2160.  
  2161.   *Start   =  AllocateMemory(#ID_HOSTSIZE)
  2162.   Length   =  0
  2163.  
  2164.   While InternetReadFile_(hURL, *Start, #ID_HOSTSIZE, @Length)
  2165.      If Length   =  0  :  Break :  EndIf
  2166.      t$ +  PeekS(*Start, Length, #PB_Ascii)
  2167.   Wend
  2168.  
  2169.   FreeMemory(*Start)
  2170.  
  2171.   InternetCloseHandle_(hURL)
  2172.   InternetCloseHandle_(hNET)
  2173.  
  2174.   ; ------------------------------------
  2175.   ; *** Search for link ( & decode ) ***
  2176.   ; ------------------------------------
  2177.   *Start   =  @t$
  2178.   *Finish  =  *Start   +  Len(t$)  *  SizeOf(Character)
  2179.  
  2180.   Select   ID
  2181.  
  2182.      Case  #ID_MEDIAFIRE, ; "http://download"
  2183.            #ID_BITCHUTE   ; "https://seed"
  2184.  
  2185.         *URL  =  StrStrI_(*Start, @ID$)
  2186.  
  2187.         If *URL
  2188.            URL$  =  PeekS(*URL, (StrStrI_(*URL, #DQUOTE$) - *URL) / SizeOf(Character))
  2189.         EndIf
  2190.  
  2191.      Case  #ID_DONNERSENDER, ; "https://cdn.donnersender.ru/videos/"
  2192.            #ID_DEINTUBE      ; "/upload/videos/"
  2193.  
  2194.         While *Start   <  *Finish
  2195.  
  2196.            *URL  =  StrStrI_(*Start, @ID$)
  2197.            If *URL  =  #Null :  URL$  =  #Null$   :  Break :  EndIf
  2198.  
  2199.            URL$  =  PeekS(*URL, (StrStrI_(*URL, #DQUOTE$) - *URL) / SizeOf(Character))
  2200.  
  2201.            ; must type/mp4 (no jpg, gif - don't test with extensionpart)
  2202.            If StrStrI_(@URL$, @".MP4")
  2203.  
  2204.               ; remove parameter?
  2205.               If StrStrI_(@URL$, @"?")
  2206.                  URL$  =  PeekS(*URL, (StrStrI_(*URL, @"?") - *URL) / SizeOf(Character))
  2207.               EndIf
  2208.  
  2209.               Select   ID
  2210.                  Case  #ID_DEINTUBE   :  URL$  =  "https://dein.tube"  +  URL$
  2211.               EndSelect
  2212.  
  2213.               Break
  2214.  
  2215.            EndIf
  2216.  
  2217.            *Start   +  MemoryStringLength(@URL$)
  2218.  
  2219.         Wend
  2220.  
  2221.      Case  #ID_4SHARED ; "data-cp-preview="
  2222.  
  2223.         If StrStrI_(@Link$, @"/MP3/") Or StrStrI_(@Link$, @"/music/")
  2224.            ; *** MP3 full preview ***
  2225.  
  2226.            *URL  =  StrStrI_(*Start, @ID$)
  2227.  
  2228.            If *URL
  2229.  
  2230.               *URL  +  Len(ID$) *  SizeOf(Character)
  2231.               URL$  =  PeekS(*URL, (StrStrI_(*URL, #DQUOTE$) - *URL) / SizeOf(Character))
  2232.  
  2233.               *URL  =  AllocateMemory(Len(URL$) * SizeOf(Character) * 2 + 64)
  2234.  
  2235.               ; decode link
  2236.               If Base64Decoder(URL$, *URL, MemorySize(*URL))
  2237.                  URL$  =  PeekS(*URL, -1, #PB_Ascii)
  2238.               Else
  2239.                  URL$  =  #Null$
  2240.               EndIf
  2241.  
  2242.               FreeMemory(*URL)
  2243.  
  2244.            EndIf
  2245.  
  2246.         ElseIf   StrStrI_(@Link$, @"/video/")
  2247.            ; *** MP4 full preview ***
  2248.  
  2249.            *URL  =  StrStrI_(*Start, @"file: 'https://dc")
  2250.  
  2251.            If *URL
  2252.               *URL  =  StrStrI_(*URL, @"h") ; https://
  2253.               URL$  =  PeekS(*URL, (StrStrI_(*URL, @"'") - *URL) / SizeOf(Character))
  2254.            EndIf
  2255.  
  2256.         EndIf
  2257.  
  2258.   EndSelect
  2259.  
  2260.   If Len(URL$)
  2261.      ProcedureReturn   @URL$
  2262.   EndIf
  2263.  
  2264.   ProcedureReturn   #Null
  2265.  
  2266. EndProcedure
  2267. ProcedureDLL   SCAL_GetMode(Flags)
  2268.  
  2269.   ; Flags: 0  =  Get #ID of playengine
  2270.   ;        1  =  Get *ptr to string char[3] of playengine
  2271.  
  2272.   Static   t$
  2273.  
  2274.   With  RS_SCAL
  2275.  
  2276.      If \ID   =  #Null ; do not check with <= 0
  2277.         If Flags
  2278.            ProcedureReturn   ?s_unknown
  2279.         EndIf
  2280.         ProcedureReturn   #Null
  2281.      EndIf
  2282.  
  2283.      If Flags
  2284.         t$ =  PeekS(PeekI(?mode + \Mode * SizeOf(Integer)))
  2285.         t$ =  StringField(t$, 1, "|")
  2286.         ProcedureReturn   @t$
  2287.         ;ProcedureReturn  (?s_Mode +  (\Mode   -  1) *  4  *  SizeOf(Character))   ; 4 = AHX + 0
  2288.      EndIf
  2289.  
  2290.      ProcedureReturn   \Mode
  2291.  
  2292.   EndWith
  2293.  
  2294. EndProcedure
  2295. ProcedureDLL   SCAL_GetPosition(Flags)
  2296.  
  2297.   ; Flags: 0  =  Get current playposition in ms
  2298.   ;        1  =  Get ptr to timestring (hh:mm:ss.ttt) of current playposition
  2299.  
  2300.   ; RETURN:   Playtime in ms or *ptr to timestring
  2301.  
  2302.   ; - remarked engines calculate a timeline not the real pos of mixerticks!
  2303.   ; - call GetPosition() also to loop song on end
  2304.  
  2305.   Static   Time, t${#MAX_PATH}
  2306.  
  2307.   With  RS_SCAL
  2308.  
  2309.      If \ID   =  #Null ; do not check with <= 0
  2310.         If Flags
  2311.            ProcedureReturn   ?s_unknown
  2312.         EndIf
  2313.         ProcedureReturn   #Null
  2314.      EndIf
  2315.  
  2316.      Select   \Mode
  2317.  
  2318.         ;Case #C2D_MUSIC_AHX :  Time  =  ahx1play_GetMixerTicks()
  2319.         ;Case #C2D_MUSIC_FC4 :  Time  =  fc14play_GetMixerTicks()
  2320.         ;Case #C2D_MUSIC_FT2 :  Time  =  ft2play_GetMixerTicks()
  2321.         ;Case #C2D_MUSIC_PT2 :  Time  =  pt2play_GetMixerTicks()
  2322.         ;Case #C2D_MUSIC_STM :  Time  =  st23play_GetMixerTicks()
  2323.         ;Case #C2D_MUSIC_S3M :  Time  =  st3play_GetMixerTicks()
  2324.  
  2325.         Case  #C2D_MUSIC_OGG, #C2D_MUSIC_FLA, #C2D_MUSIC_WAV
  2326.            Time  =  GetSoundPosition(0, #PB_Sound_Millisecond)
  2327.  
  2328.         Case  #C2D_MUSIC_MCI
  2329.            mciSendString_(@"STATUS 0 POSITION", @t$, #MAX_PATH, 0)
  2330.            StrToInt64Ex_(@t$, #Null, @Time)
  2331.  
  2332.         CompilerIf  #IsV2M
  2333.         Case  #C2D_MUSIC_V2M
  2334.            Time  =  V2MGetCurrentTime()
  2335.         CompilerEndIf
  2336.  
  2337.         CompilerIf  #IsXM2
  2338.         Case  #C2D_MUSIC_XM2
  2339.            Time  =  uFMOD_GetTime()
  2340.         CompilerEndIf
  2341.  
  2342.         CompilerIf  #IsAMP
  2343.         Case  #C2D_MUSIC_AMP
  2344.            Time  =  AmpMusicPosition()
  2345.            If Time  >= RS_Amp\TimeLength
  2346.               RS_Amp\TimeLoop   =  #Null
  2347.               AmpMusicLoop() ; reload file
  2348.               AmpMusicVolume(2.55 * RS_SCAL\Volume)
  2349.            EndIf
  2350.         CompilerEndIf
  2351.  
  2352.         Default
  2353.  
  2354.            Time  =  ElapsedMilliseconds()   -  \TimePlay
  2355.  
  2356.            ; reset time-position & loop media?
  2357.            If \Time And   Time  >= \Time
  2358.  
  2359.               Select   \Mode
  2360.                  Case  #C2D_MUSIC_YMP
  2361.                     CompilerIf  #IsYMP
  2362.                        ; time is -200 ms coz no loop on (real) end
  2363.                        ; some songs work, some not...
  2364.                        YM_Seek(0)
  2365.                     CompilerEndIf
  2366.                  Case  #C2D_MUSIC_MOV
  2367.                     CompilerIf  #IsMOV
  2368.                        MovieSeek(0, 0)
  2369.                     CompilerEndIf
  2370.               EndSelect
  2371.  
  2372.               Time        =  #Null
  2373.               \TimePlay   =  ElapsedMilliseconds()
  2374.  
  2375.            EndIf
  2376.  
  2377.      EndSelect
  2378.  
  2379.      If Time  <  #Null :  Time  =  #Null :  EndIf
  2380.  
  2381.      If Flags ; TimeString?
  2382.         \Time$   =  StrTime(Time)
  2383.         ProcedureReturn   @\Time$
  2384.      EndIf
  2385.  
  2386.      ProcedureReturn   Time
  2387.  
  2388.   EndWith
  2389.  
  2390. EndProcedure
  2391. ProcedureDLL   SCAL_GetSize(Flags)
  2392.  
  2393.   ; Flags: 0 = Integer, 1 = *StrSize
  2394.  
  2395.   With  RS_SCAL
  2396.  
  2397.      If \Length  <= #Null
  2398.         \Length  =  FileSize(\File$)
  2399.      EndIf
  2400.  
  2401.      If \Length  <  #Null
  2402.         \Length  =  #Null
  2403.      EndIf
  2404.  
  2405.      If Flags
  2406.         ProcedureReturn   StrSize(\Length)
  2407.      EndIf
  2408.  
  2409.      ProcedureReturn   \Length
  2410.  
  2411.   EndWith
  2412.  
  2413. EndProcedure
  2414. ProcedureDLL   SCAL_GetSubsongs()
  2415.   With  RS_SCAL
  2416.      ProcedureReturn   \Songs
  2417.   EndWith
  2418. EndProcedure
  2419. ProcedureDLL   SCAL_GetTitle()
  2420.   With  RS_SCAL
  2421.      ProcedureReturn   @\Title$
  2422.   EndWith
  2423. EndProcedure
  2424. ProcedureDLL   SCAL_GetTracker()
  2425.   With  RS_SCAL
  2426.      ProcedureReturn   @\Tracker$
  2427.   EndWith
  2428. EndProcedure
  2429. ProcedureDLL   SCAL_Info(Flags)
  2430.  
  2431.   Protected   t$, Title$="SCAL DLL v" + StrF(#SCAL_VERSION * 0.01, 2)
  2432.  
  2433.   CompilerIf  #IsX86
  2434.      Title$   +  " (x86)"
  2435.   CompilerElse
  2436.      Title$   +  " (x64)"
  2437.   CompilerEndIf
  2438.  
  2439.   With  RS_SCAL
  2440.  
  2441.      ; Sound playing?
  2442.      If \ID   <= #Null :  ProcedureReturn   #Null :  EndIf
  2443.  
  2444.      If \Length  <= #Null
  2445.         \Length  =  SCAL_GetSize(0)
  2446.      EndIf
  2447.  
  2448.      If \File$
  2449.         \File$   =  ReplaceString(\File$, "%20", " ")
  2450.         t$ +  "File:"  +  #TAB$ +  GetFilePart(\File$)  +  #LF$
  2451.         t$ +  "Path:"  +  #TAB$ +  GetPathPart(\File$)  +  #LF$
  2452.      EndIf
  2453.  
  2454.      If \Length        :  t$ +  "Size:"  +  #TAB$ +  PeekS(SCAL_GetSize(1))        +  #LF$  :  EndIf
  2455.  
  2456.      If t$ :  t$ +  #LF$  :  EndIf ; kosmetische Freizeile
  2457.  
  2458.      If \Title$        :  t$ +  "Title:" +  #TAB$ +  \Title$                       +  #LF$  :  EndIf ; PeekS(SCAL_GetTitle())
  2459.  
  2460.      If \Time >  #Null :  t$ +  "Time:"  +  #TAB$ +  PeekS(SCAL_GetLength(1))      +  #LF$  :  EndIf
  2461.  
  2462.      If \Songs   >  1
  2463.         t$ +  "Song:"  +  #TAB$ +  Str(\SubSong + \ZipSong) + "/" + Str(\Songs)    +  #LF$  ; Str(SCAL_GetSubsongs())
  2464.      EndIf
  2465.  
  2466.      t$ +  #LF$  ; kosmetische Freizeile
  2467.  
  2468.      If \Tracker$      :  t$ +  "Type:"  +  #TAB$ +  \Tracker$                     +  #LF$  :  EndIf ; PeekS(SCAL_GetTracker())
  2469.  
  2470.      t$ +  #LF$  +  "Mode:"  +  #TAB$ +  "#C2D_MUSIC_"  +  PeekS(SCAL_GetMode(1))  +  #LF$
  2471.  
  2472.      ProcedureReturn   MessageBox_(GetForegroundWindow_(), @t$, @Title$, Flags)
  2473.  
  2474.   EndWith
  2475.  
  2476. EndProcedure
  2477. ProcedureDLL   SCAL_IsFormat(Mode, *Memory.Long, Length)
  2478.  
  2479.   ; Tiny check file.extension ?.* and *.? or *Memoryblock
  2480.  
  2481.   ; *Memory   =  Pointer to @File or *Memory
  2482.   ; Length    =  Size of *Memory or 0 if *Memory = @File
  2483.  
  2484.   ; Return:   Mode or #NULL if not supported
  2485.  
  2486.   Static   Typ
  2487.  
  2488.   Typ   =  #Null
  2489.  
  2490.   If Length   <= #Null
  2491.  
  2492.      ;{ *File? }
  2493.  
  2494.      Protected   *x, i
  2495.  
  2496.      For   i  =  0  To 1
  2497.  
  2498.         *x =  scal_Sufx(*Memory, i)   :  If *x =  #Null :  Continue :  EndIf
  2499.  
  2500.         Select   Mode
  2501.         Case  #C2D_MUSIC_AHX, #C2D_MUSIC_THX   :  Typ   =  StrStrI_(?l_AHX, *x)
  2502.         Case  #C2D_MUSIC_FC4, #C2D_MUSIC_TFC   :  Typ   =  StrStrI_(?l_FC4, *x)
  2503.         Case  #C2D_MUSIC_PT2, #C2D_MUSIC_TPT   :  Typ   =  StrStrI_(?l_PT2, *x)
  2504.         Case  #C2D_MUSIC_API, #C2D_MUSIC_WAV   :  Typ   =  StrStrI_(?l_WAV, *x)
  2505.         Case  #C2D_MUSIC_MCI, #C2D_MUSIC_MOV   :  Typ   =  StrStrI_(?l_MCI, *x)
  2506.         Case  #C2D_MUSIC_FT2 :  Typ   =  StrStrI_(?l_FT2, *x)
  2507.         Case  #C2D_MUSIC_S3M :  Typ   =  StrStrI_(?l_S3M, *x)
  2508.         Case  #C2D_MUSIC_STM :  Typ   =  StrStrI_(?l_STM, *x)
  2509.         Case  #C2D_MUSIC_FLA :  Typ   =  StrStrI_(?l_FLA, *x)
  2510.         Case  #C2D_MUSIC_OGG :  Typ   =  StrStrI_(?l_OGG, *x)
  2511.         Case  #C2D_MUSIC_MOD :  Typ   =  StrStrI_(?l_MOD, *x)
  2512.  
  2513.         CompilerIf  #IsAMP
  2514.         Case  #C2D_MUSIC_AMP
  2515.            Typ   =  StrStrI_(?l_AMP, *x)
  2516.         CompilerEndIf
  2517.         CompilerIf  #IsBAS
  2518.         Case  #C2D_MUSIC_BAS
  2519.               Typ   =  StrStrI_(?l_BAS, *x)
  2520.         CompilerEndIf
  2521.         CompilerIf  #IsBMF
  2522.         Case  #C2D_MUSIC_BMF
  2523.            Typ   =  StrStrI_(?l_BMF, *x)
  2524.         CompilerEndIf
  2525.         CompilerIf  #IsMED
  2526.         Case  #C2D_MUSIC_MED
  2527.            Typ   =  StrStrI_(?l_MED, *x)
  2528.         CompilerEndIf
  2529.         CompilerIf  #IsFCP
  2530.         Case  #C2D_MUSIC_FCP
  2531.            Typ   =  StrStrI_(?l_FCP, *x)
  2532.         CompilerEndIf
  2533.         CompilerIf  #IsS68
  2534.         Case  #C2D_MUSIC_S68
  2535.            Typ   =  StrStrI_(?l_SC68, *x)
  2536.         CompilerEndIf
  2537.         CompilerIf  (#IsSID  +  #IsTSR)
  2538.         Case  #C2D_MUSIC_SID, #C2D_MUSIC_TSR
  2539.            Typ   =  StrStrI_(?l_SID, *x)
  2540.         CompilerEndIf
  2541.         CompilerIf  (#IsV1M  +  #IsV2M)
  2542.         Case  #C2D_MUSIC_V1M, #C2D_MUSIC_V2M
  2543.            Typ   =  StrStrI_(?l_V2M, *x)
  2544.         CompilerEndIf
  2545.         CompilerIf  #IsXM2
  2546.         Case  #C2D_MUSIC_XM2
  2547.            Typ   =  StrStrI_(?l_XM2, *x)
  2548.         CompilerEndIf
  2549.         CompilerIf  #IsYMP
  2550.         Case  #C2D_MUSIC_YMP
  2551.            Typ   =  StrStrI_(?l_YMP, *x)
  2552.         CompilerEndIf
  2553.  
  2554.         Default  ; < Min or > Max  -> search through all extensions (SCAL Mode)
  2555.  
  2556.            Typ   =  StrStrI_(SCAL_Formats(#Null, 1), *x)   ; fastest check on 2. call!
  2557.  
  2558.         EndSelect
  2559.  
  2560.         If Typ   >  0  :  Break :  EndIf
  2561.  
  2562.      Next
  2563.      ;}
  2564.  
  2565.   Else
  2566.  
  2567.      ;{ *Memory? }
  2568.  
  2569.      Protected   *ID_MOD.Long   =  *Memory  +  $438
  2570.      Protected   *ID_STM.Long   =  *Memory  +  $14
  2571.      Protected   *ID_S3M.Long   =  *Memory  +  $2C
  2572.      Protected   *ID_WAV.Long   =  *Memory  +  $8
  2573.      CompilerIf  #IsYMP
  2574.         Protected   *ID_YMP.Long   =  *Memory  +  $2
  2575.      CompilerEndIf
  2576.  
  2577.      Select   Mode
  2578.         Case  #C2D_MUSIC_PT2, #C2D_MUSIC_TPT
  2579.            Typ   =  Bool(*ID_MOD\l =  #ID_M_K_ Or
  2580.                          *ID_MOD\l =  #ID_MIKI Or
  2581.                          *ID_MOD\l =  #ID_MAKI Or
  2582.                          *ID_MOD\l =  #ID_N_T_)
  2583.  
  2584.         Case  #C2D_MUSIC_FT2
  2585.            Typ   =  Bool(*Memory\l =  #ID_XM)  +
  2586.                     Bool(*ID_MOD\l =  #ID_6CHN Or
  2587.                          *ID_MOD\l =  #ID_8CHN Or
  2588.                          *ID_MOD\l =  #ID_FLT4 Or
  2589.                          *ID_MOD\l =  #ID_FLT8 Or
  2590.                          *ID_MOD\l =  #ID_M_K_ Or
  2591.                          *ID_MOD\l =  #ID_MIKI Or
  2592.                          *ID_MOD\l =  #ID_MAKI Or
  2593.                          *ID_MOD\l =  #ID_N_T_)
  2594.  
  2595.         Case  #C2D_MUSIC_AHX, #C2D_MUSIC_THX
  2596.            Typ   =  Bool(*Memory\l =  #ID_AHX  Or
  2597.                          *Memory\l =  #ID_THX)
  2598.  
  2599.         Case  #C2D_MUSIC_FC4, #C2D_MUSIC_TFC
  2600.            Typ   =  Bool(*Memory\l =  #ID_SMOD Or
  2601.                          *Memory\l =  #ID_FC14)
  2602.  
  2603.         Case  #C2D_MUSIC_S3M
  2604.            Typ   =  Bool(*ID_S3M\l =  #ID_S3M)
  2605.  
  2606.         Case  #C2D_MUSIC_STM
  2607.            Typ   =  Bool(*ID_STM\l =  #ID_STM)
  2608.  
  2609.         Case  #C2D_MUSIC_OGG
  2610.            Typ   =  Bool(*Memory\l =  #ID_OGG)
  2611.  
  2612.         Case  #C2D_MUSIC_FLA
  2613.            Typ   =  Bool(*Memory\l =  #ID_FLAC)
  2614.  
  2615.         Case  #C2D_MUSIC_API, #C2D_MUSIC_WAV
  2616.            Typ   =  Bool(*Memory\l =  #ID_RIFF And
  2617.                          *ID_WAV\l =  #ID_WAVE)
  2618.  
  2619.         Case  #C2D_MUSIC_MOD
  2620.            Typ   =  Bool(*ID_MOD\l =  #ID_M_K_ Or
  2621.                          *ID_MOD\l =  #ID_MIKI Or
  2622.                          *ID_MOD\l =  #ID_MAKI Or
  2623.                          *ID_MOD\l =  #ID_N_T_ Or
  2624.                          *ID_MOD\l =  #ID_6CHN Or
  2625.                          *ID_MOD\l =  #ID_8CHN Or
  2626.                          *ID_MOD\l =  #ID_FLT4 Or
  2627.                          *ID_MOD\l =  #ID_FLT8)   +
  2628.                     Bool(*ID_S3M\l =  #ID_S3M)    +
  2629.                     Bool(*ID_STM\l =  #ID_STM)    +
  2630.                     Bool(*Memory\l =  #ID_XM   Or
  2631.                          *Memory\l =  #ID_IT   Or
  2632.                          *Memory\l =  #ID_UMX  Or
  2633.                          *Memory\l =  #ID_MTM  Or
  2634.                          *Memory\l =  #ID_MT20 Or
  2635.                          *Memory\l =  #ID_MMD0 Or
  2636.                          *Memory\l =  #ID_MMD1 Or
  2637.                          *Memory\l =  #ID_MMD2 Or
  2638.                          *Memory\l =  #ID_MMD3 Or
  2639.                          *Memory\l =  #ID_OKTA)   +
  2640.                     Bool(*Memory\l =  #ID_RIFF And
  2641.                          *ID_WAV\l =  #ID_WAVE)
  2642.  
  2643.         CompilerIf  #IsBAS
  2644.         Case  #C2D_MUSIC_BAS
  2645.            Typ   =  Bool(*Memory\l =  #ID_IT   Or
  2646.                          *Memory\l =  #ID_UMX  Or
  2647.                          *Memory\l =  #ID_MTM)    +
  2648.                     Bool(*Memory\l =  #ID_XM   Or
  2649.                          *ID_MOD\l =  #ID_6CHN Or
  2650.                          *ID_MOD\l =  #ID_8CHN Or
  2651.                          *ID_MOD\l =  #ID_FLT4 Or
  2652.                          *ID_MOD\l =  #ID_FLT8)   +
  2653.                     Bool(*ID_MOD\l =  #ID_M_K_ Or
  2654.                          *ID_MOD\l =  #ID_MIKI Or
  2655.                          *ID_MOD\l =  #ID_MAKI Or
  2656.                          *ID_MOD\l =  #ID_N_T_)   +
  2657.                     Bool(*ID_S3M\l =  #ID_S3M)
  2658.         CompilerEndIf
  2659.         CompilerIf  #IsBMF
  2660.         Case  #C2D_MUSIC_BMF
  2661.            Typ   =  Bool(*Memory\l =  #ID_BMF4)
  2662.         CompilerEndIf
  2663.         CompilerIf  #IsFCP
  2664.         Case  #C2D_MUSIC_FCP
  2665.            Typ   =  Bool(*Memory\l =  #ID_FC14)
  2666.         CompilerEndIf
  2667.         CompilerIf  #IsS68
  2668.         Case  #C2D_MUSIC_S68
  2669.            Typ   =  Bool(*Memory\l =  #ID_SC68)
  2670.         CompilerEndIf
  2671.         CompilerIf  (#IsSID  +  #IsTSR)
  2672.         Case  #C2D_MUSIC_SID, #C2D_MUSIC_TSR
  2673.            Typ   =  Bool(*Memory\l =  #ID_SID)
  2674.         CompilerEndIf
  2675.         CompilerIf  (#IsV2M  +  #IsV1M)
  2676.         Case  #C2D_MUSIC_V1M, #C2D_MUSIC_V2M
  2677.            Typ   =  Bool(*Memory\l =  #ID_V2M  Or
  2678.                          *Memory\l =  #ID_V2M6 Or
  2679.                          *Memory\l =  #ID_V2ME)
  2680.            ; Loosy but important v1.5 sanity check or... crash
  2681.            If Mode  =  #C2D_MUSIC_V2M And   PeekL(*Memory + Length - SizeOf(Long)) <> #Null
  2682.               Typ   =  #Null
  2683.            EndIf
  2684.         CompilerEndIf
  2685.         CompilerIf  #IsXM2
  2686.         Case  #C2D_MUSIC_XM2 :  Typ   =  Bool(*Memory\l =  #ID_XM)
  2687.         CompilerEndIf
  2688.         CompilerIf  #IsYMP
  2689.         Case  #C2D_MUSIC_YMP
  2690.            Typ   =  Bool(*ID_YMP\l =  #ID_LH5  Or
  2691.                          *Memory\l =  #ID_YM6I)
  2692.         CompilerEndIf
  2693.  
  2694.      EndSelect
  2695.      ;}
  2696.  
  2697.   EndIf
  2698.  
  2699.   ProcedureReturn   Bool(Typ > #Null)
  2700.  
  2701. EndProcedure
  2702. ProcedureDLL   SCAL_Pause(Flags)
  2703.  
  2704.   ; Flags: 1 = Pause, 0 = Resume
  2705.  
  2706.   ; Return: 1 = paused, 0 = unpaused or no pause possible by engine
  2707.  
  2708.   Static   Time
  2709.  
  2710.   With  RS_SCAL
  2711.  
  2712.      If \ID   =  #Null :  ProcedureReturn   #Null :  EndIf
  2713.  
  2714.      Flags =  Bool(Flags<>0)
  2715.  
  2716.      If \IsPause =  Flags :  ProcedureReturn   \IsPause :  EndIf
  2717.  
  2718.      \IsPause =  Flags
  2719.  
  2720.      Select   \Mode
  2721.  
  2722.         Case  #C2D_MUSIC_AHX
  2723.            ahx1play_PauseSong(\IsPause)
  2724.  
  2725.         CompilerIf  #IsAMP
  2726.         Case  #C2D_MUSIC_AMP
  2727.            AmpMusicPause(\IsPause)
  2728.         CompilerEndIf
  2729.  
  2730.         CompilerIf  #IsBAS
  2731.         Case  #C2D_MUSIC_BAS
  2732.            If \IsPause
  2733.               BASSMOD_MusicPause()
  2734.            Else
  2735.               BASSMOD_MusicPlay()
  2736.            EndIf
  2737.         CompilerEndIf
  2738.  
  2739.         CompilerIf  #IsBMF
  2740.         Case  #C2D_MUSIC_BMF
  2741.            If \IsPause
  2742.               SynthStop(\ID)
  2743.            Else
  2744.               SynthPlay(\ID)
  2745.            EndIf
  2746.         CompilerEndIf
  2747.  
  2748.         Case  #C2D_MUSIC_FC4
  2749.            fc14play_PauseSong(\IsPause)
  2750.  
  2751.         Case  #C2D_MUSIC_FLA, #C2D_MUSIC_OGG, #C2D_MUSIC_WAV
  2752.            If IsSound(0)
  2753.               If \IsPause
  2754.                  PauseSound(0)
  2755.               Else
  2756.                  ResumeSound(0)
  2757.               EndIf
  2758.            EndIf
  2759.  
  2760.         Case  #C2D_MUSIC_FT2
  2761.            ft2play_PauseSong(\IsPause)
  2762.  
  2763.         Case  #C2D_MUSIC_MCI
  2764.            If \IsPause
  2765.               mciSendString_(@"PAUSE 0", 0, 0, 0)
  2766.            Else
  2767.               mciSendString_(@"RESUME 0",   0, 0, 0)
  2768.            EndIf
  2769.  
  2770.         CompilerIf  #IsMED
  2771.         Case  #C2D_MUSIC_MED
  2772.            If \IsPause
  2773.               MEDP_Stop()
  2774.            Else
  2775.               MEDP_Play()
  2776.            EndIf
  2777.         CompilerEndIf
  2778.  
  2779.         Case  #C2D_MUSIC_MOD
  2780.            If \IsPause
  2781.               StopMusic(0)
  2782.            Else
  2783.               PlayMusic(0)
  2784.            EndIf
  2785.  
  2786.         CompilerIf  #IsMOV
  2787.         Case  #C2D_MUSIC_MOV
  2788.            If \IsPause
  2789.               PauseMovie(0)
  2790.            Else
  2791.               ResumeMovie(0)
  2792.            EndIf
  2793.         CompilerEndIf
  2794.  
  2795.         Case  #C2D_MUSIC_PT2
  2796.            pt2play_PauseSong(\IsPause)
  2797.  
  2798.         Case  #C2D_MUSIC_S3M
  2799.            st3play_PauseSong(\IsPause)
  2800.  
  2801.         CompilerIf  #IsSID
  2802.         Case  #C2D_MUSIC_SID
  2803.            If \IsPause
  2804.               SIDPause()
  2805.            Else
  2806.               SIDResume()
  2807.            EndIf
  2808.         CompilerEndIf
  2809.  
  2810.         Case  #C2D_MUSIC_STM
  2811.            st23play_PauseSong(\IsPause)
  2812.  
  2813.         CompilerIf  #IsV2M   ; Custom Pause
  2814.         Case  #C2D_MUSIC_V2M
  2815.            If \IsPause
  2816.               Time  =  V2MGetCurrentTime()
  2817.               V2MStop()
  2818.               dsClose()
  2819.            Else
  2820.               V2MInit(\Memory, \Freq, GetForegroundWindow_())
  2821.               V2MSetRepeat(1)
  2822.               dsSetVolume(0.01  *  \Volume)
  2823.               V2MPlay(Time)
  2824.            EndIf
  2825.         CompilerEndIf
  2826.  
  2827.         CompilerIf  #IsXM2
  2828.         Case  #C2D_MUSIC_XM2
  2829.            If \IsPause
  2830.               uFMOD_Pause()
  2831.            Else
  2832.               uFMOD_Resume()
  2833.            EndIf
  2834.         CompilerEndIf
  2835.  
  2836.         CompilerIf  #IsYMP
  2837.         Case  #C2D_MUSIC_YMP
  2838.            If \IsPause
  2839.               YM_Pause()
  2840.            Else
  2841.               YM_Play()
  2842.            EndIf
  2843.         CompilerEndIf
  2844.  
  2845.      Default
  2846.  
  2847.         ; #C2D_MUSIC_API, #C2D_MUSIC_FCP, #C2D_MUSIC_S68
  2848.         ; #C2D_MUSIC_SCA, #C2D_MUSIC_TFC, #C2D_MUSIC_THX
  2849.         ; #C2D_MUSIC_TPT, #C2D_MUSIC_TSR, #C2D_MUSIC_V1M
  2850.  
  2851.         \IsPause =  #Null
  2852.         ProcedureReturn   #Null
  2853.  
  2854.      EndSelect
  2855.  
  2856.      ; Timecorrection, coz some mixerticks do a simple timeline
  2857.      Select   \Mode
  2858.         Case  #C2D_MUSIC_AHX,
  2859.               #C2D_MUSIC_BAS,
  2860.               #C2D_MUSIC_BMF,
  2861.               #C2D_MUSIC_FC4,
  2862.               #C2D_MUSIC_FT2,
  2863.               #C2D_MUSIC_PT2,
  2864.               #C2D_MUSIC_MED,
  2865.               #C2D_MUSIC_MOD,
  2866.               #C2D_MUSIC_MOV,
  2867.               #C2D_MUSIC_S3M,
  2868.               #C2D_MUSIC_SID,
  2869.               #C2D_MUSIC_STM,
  2870.               #C2D_MUSIC_YMP
  2871.            If \IsPause
  2872.               Time  =  ElapsedMilliseconds()
  2873.            Else
  2874.               \TimePlay   +  ElapsedMilliseconds()   -  Time
  2875.            EndIf
  2876.      EndSelect
  2877.  
  2878.      ProcedureReturn   \IsPause
  2879.  
  2880.   EndWith
  2881.  
  2882. EndProcedure
  2883. ProcedureDLL   SCAL_Play(Mode, *Memory, Length, SubSong)
  2884.  
  2885.   ; Mode      =  -1 (autoset) or #C2D_MUSIC_[Mode]
  2886.   ; *Memory   =  Ptr to data or @Filename$
  2887.   ; Length    =  Size(End) of data or #Null (*Memory = @Filename$)
  2888.   ; SubSong   =  #Subsong to play (#AMP, #SID, #TSR)
  2889.  
  2890.   ; Return: #True = Music is playing or #False = Error!
  2891.  
  2892.   Protected   IsOK, IsAmp, i, t$, Path$, *x, MDAT$, SMPL$
  2893.   Static   File$ ; *Memory = temporary @File$
  2894.  
  2895.   SCAL_Free() ; always stop if playing
  2896.  
  2897.   With  RS_SCAL
  2898.  
  2899.      ; Check for not-supported engines (*)do NOT check with [SCA] here!
  2900.      If Mode  =  #C2D_MUSIC_V1M Or Mode  =  #C2D_MUSIC_S68
  2901.         ProcedureReturn   #Null
  2902.      EndIf
  2903.  
  2904.      ; Check if *Memory is a ptr to a @Filename
  2905.      If Length   <= #Null
  2906.         \File$   =  PeekS(*Memory, -1, \StrFormat)
  2907.      EndIf
  2908.  
  2909.      ; ==========================================================================
  2910.      ;{ Network file? ("http://...") *** also download all needed sfx-libs ***
  2911.      If Length   <= 0  And   StrStrI_(@\File$, @"://")
  2912.         If scal_Down(\File$)
  2913.            *Memory  =  @\File$  ; filename set in scal_down()
  2914.            Length   =  #Null
  2915.         Else
  2916.            SCAL_Free() :  ProcedureReturn   #Null
  2917.         EndIf
  2918.      EndIf
  2919.      ;}
  2920.      ; ==========================================================================
  2921.  
  2922.      ; ==========================================================================
  2923.      ;{ Check for zipped @File (Extension)
  2924.      If Length   <= #Null
  2925.  
  2926.         *x =  scal_Sufx(@\File$, 0)   ; ";ZIP;" etc.
  2927.  
  2928.          If *x And   StrStrI_(?l_ZIP, *x)
  2929.  
  2930.             scal_Temp(#SCAL_TempPath$)
  2931.  
  2932.             \ZipCount   =  ZIP_GetFilesCount(\File$)
  2933.  
  2934.             If \ZipCount   <= 2  ; Single zipped or TFMX (MDAT+SMPL)?
  2935.                i  =  1  ; First file in archive
  2936.             Else
  2937.                \IsZip   =  1  ; Playing subsongs from zip-archive (flag)
  2938.                ;\Songs  =  \ZipCount;
  2939.                \ZipSong =  SubSong  ; SongNumber of archive-file (for Info)
  2940.                i        =  SubSong  ; SongNumber of archive-file to unpack
  2941.                SubSong  =  #Null    ; No individual subsong when zipped archive
  2942.                If i  <= #Null :  i  =  1  :  EndIf
  2943.             EndIf
  2944.  
  2945.             t$ =  GetFilePart(ZIP_GetFileInfo(\File$, i))
  2946.  
  2947.             If Len(t$)  =  #Null :  SCAL_Free() :  ProcedureReturn   #Null :  EndIf
  2948.  
  2949.             CompilerIf  #IsAMP
  2950.                ; UnZIP always TFMX (almost same names for different songs/sample-banks (MDAT.ingame1...)
  2951.  
  2952.                *x =  PathFindExtension_(@t$)
  2953.  
  2954.                If StrStrI_(@t$, @"MDAT.") Or StrStrI_(@t$, @"SMPL.") Or ; TFMX
  2955.                   StrStrI_(*x,  @".TFX")  Or StrStrI_(*x,  @".SAM")  Or ; TFMX Custom
  2956.                   StrStrI_(*x,  @".KDM")  ; Ken's Digital Music (waves.kwv sfx-bank)
  2957.  
  2958.                   IsAMP =  #True
  2959.  
  2960.                   If ZIP_ExtractFile(\File$, i, \Temp$)  =  #False   ; Error?
  2961.                      SCAL_Free() :  ProcedureReturn   #Null
  2962.                   EndIf
  2963.  
  2964.                   If       StrStrI_(@t$, @"MDAT.") =  @t$   :  PokeS(@t$, "SMPL", -1, #PB_String_NoZero)
  2965.                   ElseIf   StrStrI_(@t$, @"SMPL.") =  @t$   :  PokeS(@t$, "MDAT", -1, #PB_String_NoZero)
  2966.                   ElseIf   StrStrI_(*x,  @".SAM")  :  PathRenameExtension_(@t$, @".TFX")  ; need the song.tfx
  2967.                   ElseIf   StrStrI_(*x,  @".TFX")  :  PathRenameExtension_(@t$, @".SAM")  ; need the sfx-file.sam
  2968.                   ElseIf   StrStrI_(*x,  @".KDM")  :  File$ =  t$ :  t$ =  "waves.kwv"    ; need kwv sfx-bank
  2969.                   EndIf
  2970.  
  2971.                   i  =  ZIP_GetFileNumber(\File$, t$)
  2972.  
  2973.                   If i  <= #Null Or ZIP_ExtractFile(\File$, i, \Temp$)  =  #False   ; Error?
  2974.                      SCAL_Free() :  ProcedureReturn   #Null
  2975.                   EndIf
  2976.  
  2977.                   ; Restore songname!
  2978.                   If       StrStrI_(@t$, @"SMPL.") =  @t$               :  PokeS(@t$, "MDAT", -1, #PB_String_NoZero)
  2979.                   ElseIf   StrStrI_(PathFindExtension_(@t$), @".SAM")   :  PathRenameExtension_(@t$, @".TFX")
  2980.                   ElseIf   StrStrI_(PathFindExtension_(@t$), @".KWV")   :  t$ =  File$
  2981.                   EndIf
  2982.  
  2983.                EndIf
  2984.             CompilerEndIf
  2985.  
  2986.             ; No AMP & Do not UnZip if already unzipped
  2987.             If IsAMP =  #Null And   FileSize(\Temp$ + t$)   <= #Null
  2988.                If ZIP_ExtractFile(\File$, i, \Temp$)  =  #False   ; Error?
  2989.                   SCAL_Free() :  ProcedureReturn   #Null
  2990.                EndIf
  2991.             EndIf
  2992.  
  2993.             ; Update to temporary unzipped filename
  2994.             \File$   =  \Temp$   +  t$
  2995.             \Title$  =  t$
  2996.             *Memory  =  @\File$
  2997.  
  2998.          EndIf
  2999.       EndIf
  3000.       ;}
  3001.       ; ==========================================================================
  3002.  
  3003.       ; ==========================================================================
  3004.       ;{ Check mode-flag (when own-call (*) [SCA] - change to default mode
  3005.       If Bool(Mode = #C2D_MUSIC_SCA Or Mode < #SCAL_MIN Or Mode > #SCAL_MAX)  ; (-1,0) .. Clamp(1 upto 29)
  3006.          If Length   >  #Null
  3007.             Mode  =  Default_Mode(*Memory, Length)
  3008.          Else
  3009.             Mode  =  Default_Mode(@\File$, #Null)
  3010.          EndIf
  3011.          If Mode  <= #Null
  3012.             SCAL_Free() :  ProcedureReturn   #Null
  3013.          EndIf
  3014.       EndIf
  3015.       ;}
  3016.       ; ==========================================================================
  3017.  
  3018.       ; ================================================================================
  3019.       ; Play from memory? Check if file-only mode -> reset to its default support-engine
  3020.       ; ================================================================================
  3021.       If Length   >  #Null
  3022.          Select   Mode  ; this can't play from memory
  3023.             Case  #C2D_MUSIC_AMP,
  3024.                   #C2D_MUSIC_MCI,
  3025.                   #C2D_MUSIC_MED,
  3026.                   #C2D_MUSIC_MOV
  3027.                Mode  =  Default_Mode(*Memory, Length)
  3028.          EndSelect
  3029.       EndIf
  3030.  
  3031.       \Mode =  Mode
  3032.  
  3033.       ; *** @File or *Memory?
  3034.       Select   \Mode
  3035.          Case  #C2D_MUSIC_AMP ; *Memory = @File (ascii)
  3036.          Case  #C2D_MUSIC_API ; *Memory & @File (ascii & utf8)
  3037.          Case  #C2D_MUSIC_BAS ; *Memory & @File (ascii)
  3038.          Case  #C2D_MUSIC_FLA ; *Memory & @File (ascii & utf8)
  3039.          Case  #C2D_MUSIC_MCI ; *Memory = @File (ascii & utf8)
  3040.          Case  #C2D_MUSIC_MED ; *Memory = @File (ascii)
  3041.          Case  #C2D_MUSIC_MOD ; *Memory & @File (ascii & utf8)
  3042.          Case  #C2D_MUSIC_MOV ; *Memory = @File (ascii & utf8)
  3043.          Case  #C2D_MUSIC_OGG ; *Memory & @File (ascii & utf8)
  3044.          Case  #C2D_MUSIC_S68 ; *Memory & @File (ascii)
  3045.          Case  #C2D_MUSIC_WAV ; *Memory & @File (ascii & utf8)
  3046.          Case  #C2D_MUSIC_XM2 ; *Memory & @File (ascii)
  3047.          Case  #C2D_MUSIC_YMP ; *Memory & @File (ascii)
  3048.  
  3049.          Default  ;{ Engines who supports *Memory only? }
  3050.  
  3051.             If Length   <= #Null
  3052.  
  3053.                If ReadFile(0, \File$)
  3054.                   Length   =  Lof(0)
  3055.                   If Length   >  0
  3056.                      \Memory  =  AllocateMemory(Length)
  3057.                      \IsAlloc =  Bool(\Memory>0)   ; flag to free temp *memory
  3058.                      If \IsAlloc
  3059.                         Length   =  ReadData(0, \Memory, Length)
  3060.                      Else
  3061.                         Length   =  #Null
  3062.                      EndIf
  3063.                   EndIf
  3064.                   CloseFile(0)
  3065.                EndIf
  3066.  
  3067.                If  Length  <= #Null
  3068.                   SCAL_Free() :  ProcedureReturn   #Null
  3069.                EndIf
  3070.  
  3071.                *Memory  =  \Memory
  3072.  
  3073.             EndIf
  3074.             ;}
  3075.  
  3076.       EndSelect
  3077.  
  3078.       If Length   >  *Memory  :  Length   -  *Memory  :  EndIf
  3079.  
  3080.       ; *** DEFAULTS ***
  3081.       \ID      =  #True ; ok by default
  3082.       \Memory  =  *Memory
  3083.       \Length  =  Length
  3084.       \SubSong =  SubSong
  3085.  
  3086.       ; *** Default name of Tracker- / Decoder ***
  3087.       If \Mode >= #SCAL_MIN   And   Mode <= #SCAL_MAX
  3088.          \Tracker$   =  StringField(PeekS(PeekI(?mode + \Mode * SizeOf(Integer))), 3, "|")
  3089.       EndIf
  3090.  
  3091.       ; =========================================================================
  3092.       ; Playback the music (na endlich...)
  3093.       ; =========================================================================
  3094.       Select   \Mode
  3095.  
  3096.          Case  #C2D_MUSIC_AHX ;{ *** Play AHX/THX (no HVL) (*Memory)
  3097.             ; http://lclevy.free.fr/exotica/ahx/ahxformat.txt
  3098.             \ID   =  ahx1play_PlaySong(\Memory, \Length, \SubSong - 1, \Freq)
  3099.             If \ID
  3100.                \Title$  =  PeekS(ahx1play_GetSongName(), -1, #PB_Ascii)
  3101.                If \Songs   =  #Null ; no zip archive?
  3102.                   \Songs   =  PeekB(\Memory  +  $D)   +  1
  3103.                EndIf
  3104.             EndIf
  3105.             ;}
  3106.  
  3107.          Case  #C2D_MUSIC_API ;{ *** Play API-Wave (*.WAV) (@File / *Memory)
  3108.             If \Length
  3109.                \ID   =  PlaySound_(\Memory, #Null, #SND_MEMORY|#SND_ASYNC|#SND_LOOP|#SND_NODEFAULT)   ; play from *Memory
  3110.             Else
  3111.                \ID   =  PlaySound_(\Memory, #Null, #SND_FILENAME|#SND_ASYNC|#SND_LOOP|#SND_NODEFAULT) ; play from file -> *Memory = @Filename$
  3112.             EndIf
  3113.             ;}
  3114.  
  3115.          Case  #C2D_MUSIC_FC4 ;{ *** Play FutureComposer 1..4 (FC) (*Memory)
  3116.             \ID   =  fc14play_PlaySong(\Memory, \Length, \Freq)
  3117.             If \ID   And   PeekL(\Memory) =  #ID_SMOD
  3118.                \Tracker$   +  " / SMOD"   ; 1.3
  3119.             EndIf
  3120.             ;}
  3121.  
  3122.          Case  #C2D_MUSIC_FLA ;{ *** Play native FLAC-decoder (*.FLAC) (@File / *Memory)
  3123.             scal_Init()
  3124.             If \Length
  3125.                \ID   =  CatchSound(0, \Memory, \Length)
  3126.             Else
  3127.                \ID   =  LoadSound(0, PeekS(\Memory))
  3128.             EndIf
  3129.             If \ID
  3130.                PlaySound(0, #PB_Sound_Loop)
  3131.                \Time =  SoundLength(0, #PB_Sound_Millisecond)
  3132.             EndIf
  3133.             ;}
  3134.  
  3135.          Case  #C2D_MUSIC_FT2 ;{ *** Play FastTracker I/II (FT/XM) & Amiga Tracker (MOD) (*Memory)
  3136.             \ID   =  ft2play_PlaySong(\Memory, \Length, 0, 1, \Freq)
  3137.             If \ID
  3138.                ft2play_SetAmp(18)
  3139.                If PeekL(\Memory) =  #ID_XM
  3140.                   \Title$     =  PeekS(\Memory + $11, 20, #PB_Ascii)
  3141.                Else
  3142.                   \Tracker$   +  " / Amiga Tracker"
  3143.                   \Title$     =  PeekS(\Memory, 20, #PB_Ascii)
  3144.                EndIf
  3145.             EndIf
  3146.             ;}
  3147.  
  3148.          Case  #C2D_MUSIC_MCI ;{ *** Play Systemfile (*.MP3;*.OGG;*.WAV;*.WMA...) (@File)
  3149.             ; https://www.vbarchiv.net/tipps/tipp_856-alles-ueber-das-multimedia-control-interface-mci-api.html
  3150.             t$ =  "OPEN " + #DQUOTE$ + PeekS(\Memory) + #DQUOTE$ + " TYPE MPEGVIDEO ALIAS 0"
  3151.             If mciSendString_(@t$, 0, 0, 0)  =  #S_OK
  3152.                t$ =  Space(#MAX_PATH)
  3153.                mciSendString_(@"SET 0 TIME FORMAT MILLISECONDS", 0, 0, 0)
  3154.                mciSendString_(@"PLAY 0 REPEAT", 0, 0, 0)
  3155.                mciSendString_(@"STATUS 0 LENGTH", @t$, #MAX_PATH, 0)
  3156.                \Time =  Val(t$)
  3157.             Else
  3158.                \ID   =  #False
  3159.             EndIf
  3160.             ;}
  3161.  
  3162.          Case  #C2D_MUSIC_MOD ;{ *** Play native Tracker (*.XM;*.IT;*.S3M;*.MOD;*.MTM;*.UMX;*.OKT;*.MED + PP20) (@File / *Memory)
  3163.             scal_Init()
  3164.             If \Length
  3165.                \ID   =  CatchMusic(0, \Memory, \Length)
  3166.             Else
  3167.                \ID   =  LoadMusic(0, PeekS(\Memory))
  3168.             EndIf
  3169.             If \ID
  3170.                PlayMusic(0)
  3171.             EndIf
  3172.             ;}
  3173.  
  3174.          Case  #C2D_MUSIC_MOV ;{ *** Play native Movie / Audio (same as MCI) (@File)
  3175.          CompilerIf  #IsMOV
  3176.             scal_Init()
  3177.             If LoadMovie(0, \File$)
  3178.                *Memory  =  GetForegroundWindow_()
  3179.                If MovieWidth(0)  >  0  ; 99 if portable
  3180.                   \WinID   =  OpenWindow(#PB_Any, 40, 40, MovieWidth(0), MovieHeight(0), GetFilePart(\File$), #PB_Window_Tool|#PB_Window_NoGadgets)
  3181.                   *Memory  =  WindowID(\WinID)
  3182.                EndIf
  3183.                If PlayMovie(0, *Memory)
  3184.                   \Time =  (MovieLength(0) / (MovieInfo(0, 0) + 1)) * 1000
  3185.                Else
  3186.                   \ID   =  #False
  3187.                EndIf
  3188.             Else
  3189.                \ID   =  #False
  3190.             EndIf
  3191.          CompilerElse
  3192.             \ID   =  #False
  3193.          CompilerEndIf
  3194.          ;}
  3195.  
  3196.          Case  #C2D_MUSIC_OGG ;{ *** Play native ogg-decoder (*.OGG) (@File / *Memory)
  3197.             scal_Init()
  3198.             If \Length
  3199.                \ID   =  CatchSound(0, \Memory, \Length)
  3200.             Else
  3201.                \ID   =  LoadSound(0, PeekS(\Memory))
  3202.             EndIf
  3203.             If \ID
  3204.                PlaySound(0, #PB_Sound_Loop)
  3205.                \Time =  SoundLength(0, #PB_Sound_Millisecond)
  3206.             EndIf
  3207.             ;}
  3208.  
  3209.          Case  #C2D_MUSIC_PT2 ;{ *** Play ProTracker 2.3D (MOD) (*Memory)
  3210.             If SCAL_IsFormat(#C2D_MUSIC_PT2, \Memory, \Length) ; check, coz pt2 crashes if an error;Default_Mode(\Memory, \Length)  =  #C2D_MUSIC_PT2
  3211.                \ID   =  pt2play_PlaySong(\Memory, \Length, #CIA_TEMPO_MODE, \Freq)
  3212.             Else
  3213.                \ID   =  #False
  3214.             EndIf
  3215.             If \ID
  3216.                \Title$  =  PeekS(pt2play_GetSongName(), -1, #PB_Ascii)
  3217.             EndIf
  3218.             ;}
  3219.  
  3220.          Case  #C2D_MUSIC_S3M ;{ *** Play ScreamTracker III (S3M) (*Memory)
  3221.             \ID   =  st3play_PlaySong(\Memory, \Length, 0, #SOUNDCARD_GUS, \Freq)
  3222.             If \ID
  3223.                \Title$  =  PeekS(st3play_GetSongName(), -1, #PB_Ascii)
  3224.             EndIf
  3225.             ;}
  3226.  
  3227.          Case  #C2D_MUSIC_STM ;{ *** Play Scream Tracker 2.3 (STM) (*Memory)
  3228.             \ID   =  st23play_PlaySong(\Memory, \Length, 0, \Freq)
  3229.             If \ID
  3230.                \Title$  =  PeekS(st23play_GetSongName(), -1, #PB_Ascii)
  3231.             EndIf
  3232.             ;}
  3233.  
  3234.          Case  #C2D_MUSIC_TPT ;{ +++ Tiny ProTracker 2.3D (MOD) (*Memory)
  3235.             If SCAL_IsFormat(#C2D_MUSIC_TPT, \Memory, \Length)
  3236.                \ID   =  tinypt2play_PlaySong(\Memory, \Length)
  3237.             EndIf
  3238.             If \ID
  3239.                \Title$  =  PeekS(\Memory, -1, #PB_Ascii)
  3240.             EndIf
  3241.             ;}
  3242.  
  3243.          Case  #C2D_MUSIC_TFC ;{ +++ Tiny FutureComposer 1..4 (FC) (*Memory)
  3244.             \ID   =  tinyfc14play_PlaySong(\Memory, \Length)
  3245.             If \ID   And   PeekL(\Memory) =  #ID_SMOD
  3246.                \Tracker$   +  " / SMOD"   ; 1.3
  3247.             EndIf
  3248.             ;}
  3249.  
  3250.          Case  #C2D_MUSIC_THX ;{ +++ Tiny AHX (no HVL) (*Memory)
  3251.             \ID   =  tinyahx1play_PlaySong(\Memory, \Length, \SubSong)
  3252.             ;}
  3253.  
  3254.          Case  #C2D_MUSIC_WAV ;{ *** Play native Wave-Decoder (*.WAV) (@File / *Memory)
  3255.             scal_Init()
  3256.             If \Length
  3257.                \ID   =  CatchSound(0, \Memory, \Length)
  3258.             Else
  3259.                \ID   =  LoadSound(0, PeekS(\Memory))
  3260.             EndIf
  3261.             If \ID
  3262.                PlaySound(0, #PB_Sound_Loop)
  3263.                \Time =  SoundLength(0, #PB_Sound_Millisecond)
  3264.             EndIf
  3265.          ;}
  3266.  
  3267.          CompilerIf  #IsAMP   ;{ *** x86 - Play AmpMaster Plugin (933+ formats) (@File)
  3268.          Case  #C2D_MUSIC_AMP
  3269.             If AmpMusicInit()
  3270.  
  3271.                ; Clone to temp & set Subsong - coz we will NOT change the original one by AmpMaster!
  3272.  
  3273.                scal_Temp(#SCAL_TempPath$) ; create temporary directory for all files
  3274.  
  3275.                Path$ =  GetPathPart(\File$)
  3276.                File$ =  GetFilePart(\File$)
  3277.  
  3278.                If StrStrI_(@File$, @"MDAT.")    ; *** MDAT.file ***
  3279.  
  3280.                   MDAT$ =  StringField(File$, 1, ".")
  3281.                   SMPL$ =  scal_Case("SMPL", MDAT$)   ; adapt upper/lower case
  3282.  
  3283.                   File$ =  StringField(File$, 2, ".") ; Filename (no extension)
  3284.  
  3285.                   ; path-check coz don't download again to temp if already downloaded
  3286.                   If (Path$   <> \Temp$)  And   scal_Size(\File$) <> scal_Size(\Temp$  + MDAT$ + File$)
  3287.                      scal_Copy(\File$,                      \Temp$ + MDAT$ + "." + File$)
  3288.                      scal_Copy(Path$ + SMPL$ + "." + File$, \Temp$ + SMPL$ + "." + File$)
  3289.                   EndIf
  3290.  
  3291.                   File$    =  \Temp$   +  MDAT$ +  "."   +  File$
  3292.                   \Memory  =  @File$
  3293.  
  3294.                   \Songs   =  AmpCountSubSongs(\Memory)
  3295.  
  3296.                ElseIf   StrStrI_(@File$, @".MDAT") ; *** file.MDAT (rare) ***
  3297.  
  3298.                   MDAT$ =  GetExtensionPart(File$)
  3299.                   SMPL$ =  scal_Case("SMPL", MDAT$)
  3300.  
  3301.                   PathRemoveExtension_(@File$)  ; no extension (MDAT)
  3302.  
  3303.                   If (Path$   <> \Temp$)  And   scal_Size(\File$) <> scal_Size(\Temp$  + MDAT$ + "." + File$)
  3304.                      scal_Copy(\File$,                      \Temp$ + MDAT$ + "." + File$)
  3305.                      scal_Copy(Path$ + File$ + "." + SMPL$, \Temp$ + SMPL$ + "." + File$)
  3306.                   EndIf
  3307.  
  3308.                   File$    =  \Temp$ + MDAT$ + "." + File$
  3309.                   \Memory  =  @File$
  3310.  
  3311.                   \Songs   =  AmpCountSubSongs(\Memory)
  3312.  
  3313.                ElseIf   StrStrI_(@File$, @".TFX")  ; *** file.TFX (MDAT Clone) ***
  3314.  
  3315.                   MDAT$ =  GetExtensionPart(File$)
  3316.                   SMPL$ =  scal_Case("SAM", MDAT$)
  3317.  
  3318.                   PathRemoveExtension_(@File$)  ; no extension (TFX)
  3319.  
  3320.                   If (Path$   <> \Temp$)  And   scal_Size(\File$) <> scal_Size(\Temp$ + File$ + "." + MDAT$)
  3321.                      scal_Copy(\File$,                      \Temp$ + File$ + "." + MDAT$)
  3322.                      scal_Copy(Path$ + File$ + "." + SMPL$, \Temp$ + File$ + "." + SMPL$)
  3323.                   EndIf
  3324.  
  3325.                   File$    =  \Temp$   +  File$ +  "." + MDAT$
  3326.                   \Memory  =  @File$
  3327.  
  3328.                   \Songs   =  AmpCountSubSongs(\Memory)
  3329.  
  3330.                ElseIf   StrStrI_(@File$, @".SID")  Or
  3331.                         StrStrI_(@File$, @".PSID") Or
  3332.                         StrStrI_(@File$, @".RSID") Or
  3333.                         StrStrI_(@File$, @".TFM")  Or
  3334.                         StrStrI_(@File$, @".TFMX") Or
  3335.                         StrStrI_(@File$, @".GBS")  Or
  3336.                         StrStrI_(@File$, @".NSF")  Or
  3337.                         StrStrI_(@File$, @".FRED") Or StrStrI_(@File$, @"FRED.")
  3338.  
  3339.                   File$    =  \Temp$   +  File$
  3340.                   \Memory  =  @File$
  3341.  
  3342.                   If (Path$   <> \Temp$)  And   scal_Size(File$)  <= #Null
  3343.                      scal_Copy(\File$, File$)
  3344.                   EndIf
  3345.  
  3346.                   \Songs   =  AmpCountSubSongs(\Memory)
  3347.  
  3348.                Else
  3349.  
  3350.                   \SubSong =  0
  3351.  
  3352.                EndIf
  3353.  
  3354.                \ID   =  AmpMusicPlay(\Memory, \SubSong)
  3355.  
  3356.                If \ID
  3357.                   \File$      =  PeekS(\Memory, -1, \StrFormat)
  3358.                   \Time       =  AmpMusicLength()
  3359.                   \Title$     =  PeekS(AmpMusicTitle(),  -1, #PB_Ascii)
  3360.                   \Tracker$   =  PeekS(AmpMusicInfo(),   -1, #PB_Ascii)
  3361.                EndIf
  3362.  
  3363.             Else
  3364.  
  3365.                \ID   =  #False   ; Error!
  3366.  
  3367.             EndIf
  3368.  
  3369.          CompilerEndIf
  3370.          ;}
  3371.  
  3372.          CompilerIf  #IsBAS   ;{ *** x86 - Play Modules (*.XM;*.IT;*.S3M;*.MOD;*.MTM;*.UMX) (@File / *Memory)
  3373.          Case  #C2D_MUSIC_BAS
  3374.             ; http://www.users.on.net/~jtlim/ImpulseTracker/
  3375.  
  3376.             BASSMOD_DllMain(GetModuleHandle_(#Null), #DLL_PROCESS_ATTACH, #Null)
  3377.  
  3378.             \ID   =  BASSMOD_Init(-1, \Freq, #Null)
  3379.  
  3380.             If \ID
  3381.  
  3382.                If \Length  ; play from *memory?
  3383.                   IsOK  =  BASSMOD_MusicLoad(#True, \Memory, 0, \Length)
  3384.                   Select   PeekL(\Memory)
  3385.                      Case  #ID_IT
  3386.                         \Tracker$   +  " / Impulse Tracker 2.14"
  3387.                      Case  #ID_UMX
  3388.                         \Tracker$   +  " / UMX Container"
  3389.                      Case  #ID_MTM
  3390.                         \Tracker$   +  " / Multi Tracker"
  3391.                      Case  #ID_XM
  3392.                         \Tracker$   +  " / Fast Tracker II"
  3393.                   EndSelect
  3394.                Else  ; play from file
  3395.                   \File$   =  PeekS(\Memory, -1, \StrFormat)
  3396.                   IsOK     =  BASSMOD_MusicLoad(#False, StrAsc(\Memory))
  3397.                EndIf
  3398.  
  3399.                If IsOK  And   BASSMOD_MusicPlay()
  3400.                   ;\Time      =  BASSMOD_MusicGetLength(1)  /  176.4 ; = 44100
  3401.                   \Time    =  BASSMOD_MusicGetLength(1)  /  (\Freq   /  250.0)   ; / 2 * 125 BPM
  3402.                   *Memory  =  BASSMOD_MusicGetName()
  3403.                   If *Memory
  3404.                      \Title$  =  PeekS(*Memory, -1, #PB_Ascii)
  3405.                   EndIf
  3406.                Else
  3407.                   \ID   =  #Null ; Error!
  3408.                EndIf
  3409.  
  3410.             EndIf
  3411.          CompilerEndIf
  3412.          ;}
  3413.  
  3414.          CompilerIf  #IsBMF   ;{ *** x86 - Play BeroTracker04 (*.BMF) (*Memory)
  3415.          Case  #C2D_MUSIC_BMF
  3416.             \ID   =  SynthCreate(SynthReadBMFSampleRate(\Memory, \Length), 2048, 1, 1)
  3417.             If \ID
  3418.                SynthReadBMF(\ID, \Memory, \Length)
  3419.                SynthPlay(\ID)
  3420.                SynthSetLooping(\ID, 1)
  3421.             EndIf
  3422.          CompilerEndIf
  3423.          ;}
  3424.  
  3425.          CompilerIf  #IsFCP   ;{ *** x86 - Play FutureComposer 1.4 (*.FC;*.FC14;*.FC4) (*Memory)
  3426.          Case  #C2D_MUSIC_FCP
  3427.             FCp_Open(GetForegroundWindow_())
  3428.             FCp_InitModule(\Memory)
  3429.             FCp_Start()
  3430.          CompilerEndIf
  3431.          ;}
  3432.  
  3433.          CompilerIf  #IsMED   ;{ *** x86 - Play OctaMED (*.MED;*.MMD0;*.MMD1;*.MMD2;*.MMD3;*.MOD + PP20) (@File)
  3434.          Case  #C2D_MUSIC_MED
  3435.             MEDPDLL_DllMain(GetModuleHandle_(#Null), #DLL_PROCESS_ATTACH, #Null)
  3436.             MEDP_Initialize(#Null, GetForegroundWindow_())
  3437.             If MEDP_Load(StrAsc(\Memory)) ; *Memory = always @Filename$
  3438.                If MEDP_IsLoaded()
  3439.                   t$ =  Space(100)
  3440.                   MEDP_Play()
  3441.                   MEDP_ModuleName(@t$, 100)
  3442.                   \Title$  =  PeekS(@t$, -1, #PB_Ascii)
  3443.                   \Time    =  Abs(MEDP_ModuleTime())  *  0.001 ; micro- to milliseconds (dear Andreas - it's buggy)
  3444.                Else
  3445.                   \ID   =  #False
  3446.                EndIf
  3447.             Else
  3448.                \ID   =  #False
  3449.             EndIf
  3450.          CompilerEndIf
  3451.          ;}
  3452.  
  3453.          CompilerIf  #IsS68   ;{ *** x86 - Play SC68 MC68000 Amiga/Atari (*.SC68;*.SNDH + GZIP) (@File / *Memory)
  3454.          Case  #C2D_MUSIC_S68
  3455.             \ID   =  sc68_Play(\Memory, \Length)
  3456.          CompilerEndIf
  3457.          ;}
  3458.  
  3459.          CompilerIf  #IsSID   ;{ *** x86 - Play C64 (*.SID) (*Memory) (need masm32.lib)
  3460.          Case  #C2D_MUSIC_SID
  3461.             If \SubSong
  3462.                \ID   =  SIDOpen(\Memory, \Length, #SID_MEMORY, #SID_NON_DEFAULT, \SubSong)
  3463.             Else
  3464.                \ID   =  SIDOpen(\Memory, \Length, #SID_MEMORY, #SID_DEFAULT, #Null)
  3465.             EndIf
  3466.             If \ID
  3467.                \Title$     =  PeekS(\Memory + $16, -1, #PB_Ascii)
  3468.                If \Songs   =  #Null
  3469.                   \Songs   =  PeekW(\Memory + $E)
  3470.                   \Songs   =  UINT16(\Songs)
  3471.                EndIf
  3472.             EndIf
  3473.          CompilerEndIf
  3474.          ;}
  3475.  
  3476.          CompilerIf  #IsTSR   ;{ *** x86 - Play C64 (*.SID) (*Memory) (no masm32.lib)
  3477.          Case  #C2D_MUSIC_TSR
  3478.             \Title$     =  PeekS(\Memory + $16, -1, #PB_Ascii)
  3479.             If \Songs   =  #Null
  3480.                \Songs      =  PeekW(\Memory + $E)
  3481.                \Songs      =  UINT16(\Songs)
  3482.             EndIf
  3483.             sid_sound_server_replay_init(\Memory, \Length, \SubSong)
  3484.             sid_sound_server_replay_play()
  3485.          CompilerEndIf
  3486.          ;}
  3487.  
  3488.          CompilerIf  #IsV1M   ;{ *** x86 - Play LibV2 1.0 (*.V2M) (*Memory)
  3489.          Case  #C2D_MUSIC_V1M
  3490.             \ID   =  ssInit(\Memory, GetForegroundWindow_())
  3491.             If \ID
  3492.                ssPlay()
  3493.                ssDoTick()
  3494.             EndIf
  3495.          CompilerEndIf
  3496.          ;}
  3497.  
  3498.          CompilerIf  #IsV2M   ;{ *** x86 - Play LibV2 1.5 (*.V2M) (*Memory)
  3499.          Case  #C2D_MUSIC_V2M
  3500.             \ID   =  V2MInit(\Memory, \Freq, GetForegroundWindow_())
  3501.             If \ID
  3502.                V2MSetRepeat(1)
  3503.                V2MPlay()
  3504.                \Time =  V2MGetTotalTime()
  3505.             EndIf
  3506.          CompilerEndIf
  3507.          ;}
  3508.  
  3509.          CompilerIf  #IsXM2   ;{ *** x86 - Play FastTracker II (*.XM) (@File / *Memory)
  3510.          Case  #C2D_MUSIC_XM2
  3511.             If \Length
  3512.                uFMOD_PlaySong(\Memory, \Length, #XM_MEMORY)       ; *memory
  3513.             Else
  3514.                uFMOD_PlaySong(StrAsc(\Memory), #Null, #XM_FILE)   ; @file
  3515.             EndIf
  3516.             \Title$     =  PeekS(uFMOD_GetTitle(), -1, #PB_Ascii)
  3517.          CompilerEndIf
  3518.          ;}
  3519.  
  3520.          CompilerIf  #IsYMP   ;{ *** x86 - Play Atari (*.YM) (@File / *Memory)
  3521.          Case  #C2D_MUSIC_YMP
  3522.             Protected   *RS_ymMusicInfo_t.RS_ymMusicInfo_t  =  AllocateStructure(RS_ymMusicInfo_t)
  3523.  
  3524.             YMPLUGIN_DllMain(GetModuleHandle_(#Null), #DLL_PROCESS_ATTACH, #Null)
  3525.             YM_Init()
  3526.  
  3527.             If \Length  >  0
  3528.                YM_Open(#Null, \Memory, \Length)
  3529.             Else
  3530.                YM_Open(StrAsc(@\File$), #Null, #Null)
  3531.             EndIf
  3532.  
  3533.             YM_Play()
  3534.             YM_Get_Info(*RS_ymMusicInfo_t)
  3535.  
  3536.             \Tracker$   +  " / " +  Trim(PeekS(*RS_ymMusicInfo_t\pSongPlayer, -1, #PB_Ascii), ".") +  " ("  +  PeekS(*RS_ymMusicInfo_t\pSongType, -1, #PB_Ascii)  +  ")"
  3537.             \Title$     =  PeekS(*RS_ymMusicInfo_t\pSongName, -1, #PB_Ascii)
  3538.             \Time       =  *RS_ymMusicInfo_t\musicTimeInSec *  1000  -  200   ; -200 ms coz no loop on (real) end
  3539.  
  3540.             FreeStructure(*RS_ymMusicInfo_t)
  3541.  
  3542.          CompilerEndIf
  3543.          ;}
  3544.  
  3545.          Default
  3546.  
  3547.             \ID   =  #False   ; unknown or play x86 on x64?
  3548.  
  3549.       EndSelect
  3550.  
  3551.       If \ID
  3552.  
  3553.          SCAL_SetVolume(\Volume)
  3554.  
  3555.          If \IsZip   ; restore subsongs from zip-archive?
  3556.             \Songs   =  \ZipCount
  3557.             \SubSong =  \ZipSong
  3558.          EndIf
  3559.  
  3560.          \TimePlay   =  ElapsedMilliseconds()
  3561.  
  3562.       Else
  3563.          SCAL_Free()
  3564.       EndIf
  3565.  
  3566.       ProcedureReturn   \ID
  3567.  
  3568.    EndWith
  3569.  
  3570. EndProcedure
  3571. ProcedureDLL   SCAL_Seek(Position, Flags)
  3572.  
  3573.    ; Position = ms or 0-100%
  3574.    ; Flags = 0 -> seek in ms, 1 -> seek in percent
  3575.  
  3576.    ; Remember: \TimePlay   =  ElapsedMilliseconds()   -  Position
  3577.  
  3578.    Protected   t$
  3579.  
  3580.    With  RS_SCAL
  3581.  
  3582.       ; Playing?
  3583.       If \ID   =  #Null :  ProcedureReturn   #Null :  EndIf
  3584.  
  3585.       If Flags ; Percent?
  3586.          If Position <  0  Or Position >  100
  3587.             Position =  #Null
  3588.          EndIf
  3589.       ElseIf   Position <  0  Or Position >  \Time    ; Milliseconds!
  3590.          Position =  #Null
  3591.       EndIf
  3592.  
  3593.       If Flags ; convert % to ms
  3594.          Position =  \Time *  0.01  *  Position
  3595.       EndIf
  3596.  
  3597.       Select   \Mode
  3598.          Case  #C2D_MUSIC_OGG, #C2D_MUSIC_FLA, #C2D_MUSIC_WAV
  3599.             If IsSound(0)
  3600.                SetSoundPosition(0, Position, #PB_Sound_Millisecond)
  3601.             EndIf
  3602.  
  3603.          Case  #C2D_MUSIC_MCI
  3604.             t$ =  "SEEK 0 TO " + Str(Position)
  3605.             mciSendString_(@t$, 0, 0, 0)
  3606.             mciSendString_(@"PLAY 0 REPEAT", 0, 0, 0)
  3607.  
  3608.          CompilerIf  #IsAMP
  3609.          Case  #C2D_MUSIC_AMP
  3610.             AmpMusicSetPosition(Position)
  3611.          CompilerEndIf
  3612.  
  3613.          CompilerIf  #IsBAS
  3614.          Case  #C2D_MUSIC_BAS
  3615.             \TimePlay   =  ElapsedMilliseconds()   -  Position
  3616.             Position =  $FFFF0000   |  (Position   /  1000)
  3617.             BASSMOD_MusicSetPosition(Position)
  3618.          CompilerEndIf
  3619.  
  3620.          CompilerIf  #IsMED   ; Error
  3621. ;        Case  #C2D_MUSIC_MED
  3622. ;           If Flags ; only percent (coz unknown / buggy? ticks)
  3623. ;              \TimePlay   =  ElapsedMilliseconds()   -  Position
  3624. ;              Position    =  Abs(MEDP_ModuleLength())   *  0.01  *  Position
  3625. ;              MEDP_SetPlayPosition(Position)
  3626. ;           EndIf
  3627.          CompilerEndIf
  3628.  
  3629.          CompilerIf  #IsV2M
  3630.          Case  #C2D_MUSIC_V2M
  3631.             V2MStop()
  3632.             dsClose()
  3633.             V2MInit(\Memory, \Freq, GetForegroundWindow_())
  3634.             V2MSetRepeat(1)
  3635.             dsSetVolume(0.01  *  \Volume)
  3636.             V2MPlay(Position)
  3637.          CompilerEndIf
  3638.  
  3639.          CompilerIf  #IsYMP
  3640.          Case  #C2D_MUSIC_YMP
  3641.             \TimePlay   =  ElapsedMilliseconds()   -  Position
  3642.             Position /  1000
  3643.             YM_Seek(Position)
  3644.          CompilerEndIf
  3645.  
  3646.       EndSelect
  3647.  
  3648.    EndWith
  3649.  
  3650. EndProcedure
  3651. ProcedureDLL   SCAL_SetFreq(Freq)
  3652.    If Freq  <= #Null
  3653.       Freq  =  44100
  3654.    EndIf
  3655.    RS_SCAL\Freq   =  Freq
  3656. EndProcedure
  3657. ProcedureDLL   SCAL_SetString(Format)
  3658.  
  3659.    ; Set stringformat to AscII, UTF8, Unicode
  3660.  
  3661.    ; Format:   ASCII =  1 or #PB_Ascii (24)
  3662.    ;           UTF8  =  3
  3663.    ;           UNICODE  =  any other number (default)
  3664.  
  3665.    ; Tipp = SizeOf(Character))
  3666.  
  3667.    With  RS_SCAL
  3668.       Select   Format
  3669.          Case  1, #PB_Ascii
  3670.             \StrFormat  =  #PB_Ascii
  3671.          Case  3; #PB_UTF8
  3672.             \StrFormat  =  #PB_UTF8
  3673.          Default
  3674.             \StrFormat  =  #PB_Unicode
  3675.       EndSelect
  3676.    EndWith
  3677.  
  3678. EndProcedure
  3679. ProcedureDLL   SCAL_SetVolume(Percent)
  3680.  
  3681.    Protected   t$
  3682.  
  3683.    With  RS_SCAL
  3684.  
  3685.       If Percent  <  0
  3686.          Percent  =  0
  3687.       ElseIf   Percent  >  100
  3688.          Percent  =  100
  3689.       EndIf
  3690.  
  3691.       \Volume  =  Percent
  3692.  
  3693.       ; Playing?
  3694.       If \ID   =  #Null :  ProcedureReturn   :  EndIf
  3695.  
  3696.       Select   \Mode
  3697.          Case  #C2D_MUSIC_FT2 :  ft2play_SetMasterVol(2.56  *  \Volume)
  3698.          Case  #C2D_MUSIC_PT2 :  pt2play_SetMasterVol(2.56  *  \Volume)
  3699.          Case  #C2D_MUSIC_FC4 :  fc14play_SetMasterVol(2.56 *  \Volume)
  3700.          Case  #C2D_MUSIC_STM :  st23play_SetMasterVol(2.56 *  \Volume)
  3701.          Case  #C2D_MUSIC_S3M :  st3play_SetMasterVol(2.56  *  \Volume)
  3702.  
  3703.          Case  #C2D_MUSIC_MCI
  3704.             t$ =  "SETAUDIO 0 VOLUME TO " + Str(10 * \Volume)
  3705.             mciSendString_(@t$, 0, 0, 0)  ; 0 - 1000
  3706.  
  3707.          Case  #C2D_MUSIC_MOD :  MusicVolume(0, \Volume)
  3708.          Case  #C2D_MUSIC_MOV :  MovieAudio(0,  \Volume, 0)
  3709.  
  3710.          Case  #C2D_MUSIC_FLA, #C2D_MUSIC_OGG, #C2D_MUSIC_WAV
  3711.             SoundVolume(0, \Volume)
  3712.  
  3713.          CompilerIf  #IsAMP
  3714.          Case  #C2D_MUSIC_AMP
  3715.             AmpMusicVolume(2.55  *  \Volume)
  3716.          CompilerEndIf
  3717.  
  3718.          CompilerIf  #IsBAS
  3719.          Case  #C2D_MUSIC_BAS
  3720.             BASSMOD_SetVolume(\Volume)
  3721.          CompilerEndIf
  3722.  
  3723.          CompilerIf  #IsV2M
  3724.          Case  #C2D_MUSIC_V2M
  3725.             dsSetVolume(0.01  *  \Volume)
  3726.          CompilerEndIf
  3727.  
  3728.          CompilerIf  #IsXM2
  3729.          Case  #C2D_MUSIC_XM2
  3730.             uFMOD_SetVolume(0.25 *  \Volume)
  3731.          CompilerEndIf
  3732.  
  3733.          CompilerIf  #IsYMP
  3734.          Case  #C2D_MUSIC_YMP
  3735.             YM_SetVolume(2.55 *  \Volume)
  3736.          CompilerEndIf
  3737.  
  3738.       EndSelect
  3739.  
  3740.    EndWith
  3741.  
  3742. EndProcedure
  3743. ProcedureDLL   SCAL_Struct()
  3744.  
  3745.    ; creates temporary directory for all files
  3746.    ; define RS_SCAL\Temp$ even if not exist
  3747.  
  3748.    ; Return: private *structure
  3749.  
  3750.    scal_Temp(#SCAL_TempPath$)
  3751.  
  3752.    ProcedureReturn   @RS_SCAL
  3753.  
  3754. EndProcedure
  3755. ProcedureDLL   SCAL_Table(Mode)
  3756.  
  3757.    ; Mode = #C2D_MUSIC_[ID]
  3758.  
  3759.    ; Return:   ptr to infostring or table
  3760.  
  3761.    Static   *Memory.Integer
  3762.  
  3763.    *Memory  =  ?mode
  3764.  
  3765.    If Mode >= #Null  And   Mode <= #SCAL_MAX
  3766.       *Memory  +  Mode  *  SizeOf(Integer)
  3767.       ProcedureReturn   *Memory\i
  3768.    EndIf
  3769.  
  3770.    ProcedureReturn   *Memory
  3771.  
  3772. EndProcedure
  3773. ProcedureDLL   SCAL_Version()
  3774.    ; 100 = 1.00
  3775.    ProcedureReturn   #SCAL_VERSION
  3776. EndProcedure
  3777.  
  3778. DataSection
  3779.  
  3780.    IncludePath "Include\"
  3781.  
  3782.    l_Start: ; Compare extensions
  3783.  
  3784.    l_AHX:   :  IncludeFile "i_AHX.pbi"
  3785.    l_FC4:   :  IncludeFile "i_FC4.pbi"
  3786.    l_FLA:   :  IncludeFile "i_FLA.pbi"
  3787.    l_FT2:   :  IncludeFile "i_FT2.pbi"
  3788.    l_MOD:   :  IncludeFile "i_MOD.pbi"
  3789.    l_OGG:   :  IncludeFile "i_OGG.pbi"
  3790.    l_PT2:   :  IncludeFile "i_PT2.pbi"
  3791.    l_S3M:   :  IncludeFile "i_S3M.pbi"
  3792.    l_STM:   :  IncludeFile "i_STM.pbi"
  3793.    l_API:   ; same as wav
  3794.    l_WAV:   :  IncludeFile "i_WAV.pbi"
  3795.    l_MOV:   ; same as mci
  3796.    l_MCI:   :  IncludeFile "i_MCI.pbi"
  3797.  
  3798.    CompilerIf  #IsAMP
  3799.    l_AMP:   :  IncludeFile "i_AMP.pbi"
  3800.    CompilerEndIf
  3801.    CompilerIf  #IsBAS
  3802.    l_BAS:   :  IncludeFile "i_BAS.pbi"
  3803.    CompilerEndIf
  3804.    CompilerIf  #IsBMF
  3805.    l_BMF:   :  IncludeFile "i_BMF.pbi"
  3806.    CompilerEndIf
  3807.    CompilerIf  #IsFCP
  3808.    l_FCP:   :  IncludeFile "i_FCP.pbi"
  3809.    CompilerEndIf
  3810.    CompilerIf  #IsMED
  3811.    l_MED:   :  IncludeFile "i_MED.pbi"
  3812.    CompilerEndIf
  3813.    CompilerIf  #IsS68
  3814.    l_SC68:  :  IncludeFile "i_S68.pbi"
  3815.    CompilerEndIf
  3816.    CompilerIf  (#IsSID  +  #IsTSR)
  3817.    l_TSR:   ; same as sid
  3818.    l_SID:   :  IncludeFile "i_SID.pbi"
  3819.    CompilerEndIf
  3820.    CompilerIf  (#IsV1M  +  #IsV2M)
  3821.    l_V1M:   ; same as v2m
  3822.    l_V2M:   :  IncludeFile "i_V2M.pbi"
  3823.    CompilerEndIf
  3824.    CompilerIf  #IsXM2
  3825.    l_XM2:   :  IncludeFile "i_XM2.pbi"
  3826.    CompilerEndIf
  3827.    CompilerIf  #IsYMP
  3828.    l_YMP:   :  IncludeFile "i_YMP.pbi"
  3829.    CompilerEndIf
  3830.  
  3831.    l_ZIP:   :  IncludeFile "i_ZIP.pbi"
  3832.  
  3833.    l_Finish:   :  Data.l   #Null ; End of compare extensions
  3834.  
  3835.    ; Playengines: ID | Processor x86-64 | Trackerinfo/name -> never change order (same as #C2D_MUSIC_[ID])!
  3836.    mode: :  Data.i   ?m0,?m1,?m2,?m3,?m4,?m5,?m6,?m7,?m8,?m9,?m10,?m11,?m12,?m13,?m14,?m15,?m16,?m17,?m18,?m19,?m20,?m21,?m22,?m23,?m24,?m25,?m26,?m27,?m28,?m29
  3837.    m0:   :  Data.s   "AUTO|x86-64|Autodetect"
  3838.    m1:   :  Data.s   "AHX|x86-64|Amiga Abyss' Highest eXperience 1.00-1.27"
  3839.    m2:   :  Data.s   "AMP|x86|AmpMaster_x86.dll"
  3840.    m3:   :  Data.s   "API|x86-64|PlaySound Wave API"
  3841.    m4:   :  Data.s   "BAS|x86|BASSMOD 2.0"
  3842.    m5:   :  Data.s   "BMF|x86|BeRo 404 Tracker"
  3843.    m6:   :  Data.s   "FC4|x86-64|Amiga Future Composer 1.0-1.4"
  3844.    m7:   :  Data.s   "FCP|x86|Amiga Future Composer 1.4"
  3845.    m8:   :  Data.s   "FLA|x86-64|Pure Free Lossless Audio Codec"
  3846.    m9:   :  Data.s   "FT2|x86-64|FastTracker I / II"
  3847.    m10:  :  Data.s   "MCI|x86-64|Media Control Interface"
  3848.    m11:  :  Data.s   "MED|x86|Amiga OctaMED / MEDP 1.0"
  3849.    m12:  :  Data.s   "MOD|x86-64|Pure ModPlug Module"
  3850.    m13:  :  Data.s   "MOV|x86-64|Pure Movie Mediadecoder"
  3851.    m14:  :  Data.s   "OGG|x86-64|Pure OGG Vorbis Decoder"
  3852.    m15:  :  Data.s   "PT2|x86-64|Amiga ProTracker 2.3d"
  3853.    m16:  :  Data.s   "S3M|x86-64|ScreamTracker v3.21"
  3854.    m17:  :  Data.s   "S68|x86|SC68 MC68000 Amiga / Atari"
  3855.    m18:  :  Data.s   "SCA|x86-64|SCAL DLL"
  3856.    m19:  :  Data.s   "SID|x86|C64 TitchySid"
  3857.    m20:  :  Data.s   "STM|x86-64|ScreamTracker v2.2-2.3"
  3858.    m21:  :  Data.s   "TFC|x86-64|Tiny Future Composer 1.0-1.4"
  3859.    m22:  :  Data.s   "THX|x86-64|Tiny Abyss' Highest eXperience 1.00-1.27"
  3860.    m23:  :  Data.s   "TPT|x86-64|Tiny ProTracker 2.3d"
  3861.    m24:  :  Data.s   "TSR|x86|C64 Sid SoundServer"
  3862.    m25:  :  Data.s   "V1M|x86|Farbrausch V2 Synthesizer System v1.0"
  3863.    m26:  :  Data.s   "V2M|x86|Farbrausch V2 Synthesizer System v1.5"
  3864.    m27:  :  Data.s   "WAV|x86-64|Pure WAV Sound Decoder"
  3865.    m28:  :  Data.s   "XM2|x86|uFMOD FastTracker II"
  3866.    m29:  :  Data.s   "YMP|x86|Atari ST YM2149 (LZH-h0)"
  3867.  
  3868.    s_unknown:  :  Data.s   "?"
  3869.  
  3870. EndDataSection
RAW Paste Data