SHARE
TWEET

AmpMaster DLL v1.18.8.19 (x86)

Testaware Aug 19th, 2018 164 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. ;************************************************************************************************
  2. ;* AmpMasterLibrary DLL (x86) v1.18.8 - 19.08.2018 10:58 - PB 5.44 LTS - Peace^TST
  3. ;* ----------------------------------------------------------------------------------------------
  4. ;* Unit for WinAmp In/Out Dlls x86 - no unicode!
  5. ;* ----------------------------------------------------------------------------------------------
  6. ;* https://testaware.wordpress.com
  7. ;************************************************************************************************
  8.  
  9. EnableExplicit
  10.  
  11. #AMP_VER =  #PB_Compiler_Date
  12.  
  13. #IsAPI   =  0  ;* Windows API -> 1 = on / 0 = off (always off -> coz buggy API)
  14.  
  15. XIncludeFile   "Includes\i_amp_enumeration.pbi"
  16. XIncludeFile   "Includes\i_amp_structures.pbi"
  17. XIncludeFile   "Includes\i_amp_macros.pbi"
  18. XIncludeFile   "Includes\i_amp_player.pbi"
  19. XIncludeFile   "Includes\i_amp_table.pbi"
  20.  
  21. ; *** IDs for Subsongs: *.sid;*.mdat;*.tfm;*.tfx;*.nsf;*.gbs;*.fred
  22. #ID_FR10 =  ID_MAGIC($4E,$FA,$00,$10)  ; FRED10
  23. #ID_FR12 =  ID_MAGIC($4E,$FA,$00,$12)  ; FRED12
  24. #ID_FR4E =  ID_MAGIC($4E,$FA,$00,$4E)  ; FRED4E
  25. #ID_FR78 =  ID_MAGIC($4E,$FA,$00,$78)  ; FRED78
  26. #ID_FRSS =  $F1D4                      ; FRED SubSong (*.fred Word $6000 = 6 Songs $SN = always 0..6=7)
  27. #MAX_FRED=  %1111                      ; Max. Subsongs ($F/15) (random-crap)
  28.  
  29. #ID_GBS1 =  ID_MAGIC('G','B','S', 1 )  ; GBS1   =  *.gbs
  30. #ID_NESM =  ID_MAGIC('N','E','S','M')  ; NESM   =  *.nsf
  31. #ID_PSID =  ID_MAGIC('P','S','I','D')  ; PSID   =  *.sid
  32.  
  33. #ID_TFMX =  ID_MAGIC('T','F','M','X')  ; TFMX   =  mdat.*, *.tfm
  34. #ID_SONG =  ID_MAGIC('-','S','O','N')  ; TFMX-SON(G)
  35. #ID_TMOD =  ID_MAGIC('-','M','O','D')  ; TFMX-MERGED *.tfm
  36. #ID_2001 =  ID_MAGIC(' ', 0,  0,  1 )  ; TFMX-CUSTOM
  37. #ID_AMP0 =  ID_MAGIC('A','M','P', 0 )  ; TFMX-AMP0 = Private Tag (ReSet-SubSong) V1
  38.  
  39. DeclareCDLL Amp_Free()
  40.  
  41. ProcedureDLL   AttachProcess(Instance)
  42.  
  43.    Global   RS_WINAMP.RS_WINAMP        ; Winamp structure
  44.    Global   RS_AMPMASTER.RS_AMPMASTER  ; AmpMaster structure
  45.    Global   RS_AMPTIME.RS_AMPTIME      ; Intern timehandling structure
  46.  
  47.    Global   *i_n  =  ?i_n  ; s. include i_amp_table.pbi
  48.  
  49.    RS_AMPMASTER\ProgramName$  =  ProgramFilename()
  50.  
  51. EndProcedure
  52. ProcedureDLL   DetachProcess(Instance)
  53.    Amp_Free()
  54. EndProcedure
  55.  
  56. ProcedureC  Amp_Dummy(*pointer=#Null, numsamples=#Null, bps=#Null, nch=#Null);, srate=#Null, temp=#Null)
  57.    ProcedureReturn   numsamples
  58. EndProcedure
  59. ProcedureC  Amp_IsFile(*File)
  60.  
  61.    ;*************************************************************
  62.    ; Let's check for avail file to avoid loosy request by plugins
  63.    ; ------------------------------------------------------------
  64.    ; Return:   1 = file exist / 0 = file not found
  65.    ;*************************************************************
  66.    If *File =  #Null :  ProcedureReturn   #False   :  EndIf
  67.  
  68.    Protected   iStatus
  69.  
  70.    iStatus  =  FileSize(PeekS(*File))
  71.  
  72.    ProcedureReturn   Bool(iStatus > #Null)
  73.  
  74. EndProcedure
  75.  
  76. ProcedureCDLL  Amp_VersionStr(Flags.i)
  77.  
  78.    With  RS_AMPMASTER
  79.  
  80.       Protected   t$
  81.  
  82.       t$ =  StrU(Year(#AMP_VER)%1000)  +  "."   +
  83.             StrU(Month(#AMP_VER))      +  "."   +
  84.             StrU(Day(#AMP_VER))
  85.  
  86.       If Flags
  87.          t$ +  RSet(StrU(Hour(#AMP_VER)),    3)       +  ":"   +
  88.                RSet(StrU(Minute(#AMP_VER)),  2, "0")  +  ":"   +
  89.                RSet(StrU(Second(#AMP_VER)),  2, "0")
  90.       EndIf
  91.  
  92.       \Version$   =  #AMP_NAME$  +  " v1."   +  t$ +  " (x86)"
  93.  
  94.       ProcedureReturn   @\Version$
  95.  
  96.    EndWith
  97.  
  98. EndProcedure
  99.  
  100. ProcedureCDLL  Amp_Close()
  101.  
  102.    With  RS_WINAMP
  103.  
  104.       If \In2_DLL
  105.          If RS_AMPMASTER\IsPause
  106.             If \In2_Head\UnPause :  CallCFunctionFast(\In2_Head\UnPause)   :  EndIf
  107.          EndIf
  108.          If RS_AMPMASTER\IsPlay
  109.             If \In2_Head\Stop    :  CallCFunctionFast(\In2_Head\Stop)      :  EndIf
  110.          EndIf
  111.          If \In2_Head\Quit       :  CallCFunctionFast(\In2_Head\Quit)      :  EndIf
  112.       EndIf
  113.  
  114.       If \Out_DLL
  115.          If \Out_Head\Quit :  CallCFunctionFast(\Out_Head\Quit)   :  EndIf
  116.       EndIf
  117.  
  118.       If \In2_DLL :  MA_LibClose(\In2_DLL)   :  EndIf
  119.       If \Out_DLL :  MA_LibClose(\Out_DLL)   :  EndIf
  120.  
  121.    EndWith
  122.  
  123.    With  RS_AMPMASTER
  124.       \IsOpen  =  #False
  125.       \IsPause =  #False
  126.       \IsPlay  =  #False
  127.    EndWith
  128.  
  129.    ClearStructure(@RS_WINAMP, RS_WINAMP)
  130.    ClearStructure(@RS_AMPTIME,RS_AMPTIME)
  131.  
  132. EndProcedure
  133. ProcedureCDLL  Amp_Free()
  134.  
  135.    Amp_Close()
  136.  
  137.    ClearStructure(@RS_AMPMASTER, RS_AMPMASTER)
  138.  
  139. EndProcedure
  140. ProcedureCDLL  Amp_Init()
  141.  
  142.    Amp_Free()
  143.  
  144.    With  RS_AMPMASTER
  145.       \ProgramName$  =  ProgramFilename()
  146.       \Path$         =  GetPathPart(\ProgramName$) +  #DAMP_PATH$
  147.       \OutPath$      =  #DAMP_PATH$
  148.       \InPath$       =  #DAMP_PATH$
  149.       \InDll$        =  #DAMP_InDll$
  150.       \OutDll$       =  #DAMP_OUTDLL$
  151.       \Volume        =  #DAMP_VOLUME
  152.       \DefaultLength =  #DAMP_LENGTH
  153.    EndWith
  154.  
  155. EndProcedure
  156. ProcedureCDLL  Amp_Open()
  157.  
  158.    Protected   In_Ptr
  159.  
  160.    Amp_Close() ; Already open -> close all and clear RS_WINAMP structure
  161.  
  162.    With  RS_AMPMASTER
  163.  
  164.       ; Is path of AmpLibs -> or default -> "AmpLibs\"
  165.       If Len(\Path$)    =  #Null :  \Path$   =  GetPathPart(\ProgramName$) +  #DAMP_PATH$ :  EndIf
  166.       If Right(\Path$, 1)  <> "\":  \Path$   +  "\"   :  EndIf
  167.  
  168.       ; Set in_dll -> or use default one one -> "in_xmp.dll"
  169.       If Len(\InDll$)   =  #Null :  \InDll$  =  #DAMP_INDLL$   :  EndIf
  170.       If Len(\InPath$)  <  2     :  \InPath$ =  \Path$         :  EndIf
  171.  
  172.       ; Set out_dll -> or use default one -> "out_wave.dll"
  173.       If Len(\OutDll$)  =  #Null :  \OutDll$ =  #DAMP_OUTDLL$  :  EndIf
  174.       If Len(\OutPath$) <  2     :  \OutPath$=  \Path$         :  EndIf
  175.  
  176.       \InDll$  =  \InPath$    +  GetFilePart(\InDll$)
  177.       \OutDll$ =  \OutPath$   +  GetFilePart(\OutDll$)
  178.  
  179.       ; Check if in/out avail
  180.       If Amp_IsFile(@\InDll$) =  #False   :  RETURN_ERR(#EAMP_OPEN_INDLL)  :  EndIf
  181.       ;If   Amp_IsFile(@\OutDll$)=  #False   :  RETURN_ERR(#EAMP_OPEN_OUTDLL) :  EndIf
  182.  
  183.       If \WindowID   =  #Null :  \WindowID   =  GetForegroundWindow_()  :  EndIf
  184.  
  185.    EndWith
  186.  
  187.    ;************************************************
  188.    ; Initialize WinAmp In/Out - Libraries
  189.    ;************************************************
  190.    With  RS_WINAMP
  191.  
  192.       ; Set windowhandle -> or use foreground
  193.       \WindowID   =  RS_AMPMASTER\WindowID
  194.  
  195.       SetCurrentDirectory(RS_AMPMASTER\InPath$) ; Must set for sublibs & ini
  196.  
  197.       ; IN_DLL
  198.       ; -------------------------------------------------
  199.       MA_LibOpen(\In2_DLL, RS_AMPMASTER\InDll$)
  200.  
  201.       If \In2_DLL >  #Null
  202.  
  203.          MA_LibPtr(\In2_DLL, \In2_GeInModule2, "winampGetInModule2")
  204.  
  205.          If \In2_GeInModule2
  206.  
  207.             \In2_Head   =  CallCFunctionFast(\In2_GeInModule2)
  208.  
  209.             If \In2_Head   >  #Null
  210.  
  211.                \In2_Head\Version       =  #IN_VER
  212.                \In2_Head\hMainWindow   =  \WindowID
  213.                \In2_Head\hDllInstance  =  \In2_DLL
  214.  
  215.                CallCFunctionFast(\In2_Head\Init)
  216.  
  217.                ;dummy-routines (not used but needed)
  218.                \In2_Head\SAVSAInit     =  @Amp_Dummy()
  219.                \In2_Head\SAVSADeInit   =  @Amp_Dummy()
  220.                \In2_Head\SAAddPCMData  =  @Amp_Dummy()
  221.                \In2_Head\SAGetMode     =  @Amp_Dummy()
  222.                \In2_Head\SAAdd         =  @Amp_Dummy()
  223.                \In2_Head\VSAAddPCMData =  @Amp_Dummy()
  224.                \In2_Head\VSAGetMode    =  @Amp_Dummy()
  225.                \In2_Head\VSAAdd        =  @Amp_Dummy()
  226.                \In2_Head\VSASetInfo    =  @Amp_Dummy()
  227.                \In2_Head\dsp_isactive  =  @Amp_Dummy()
  228.                \In2_Head\dsp_dosamples =  @Amp_Dummy()
  229.                \In2_Head\EQSet         =  @Amp_Dummy()
  230.                \In2_Head\SetInfo       =  @Amp_Dummy()
  231.  
  232.                RS_AMPMASTER\InInfo$ =  PeekS(\In2_Head\description)
  233.  
  234.             EndIf
  235.          EndIf
  236.       EndIf
  237.  
  238.       If \In2_DLL <= #Null Or \In2_Head   <= #Null ; In-Error?
  239.          Amp_Close() :  RETURN_ERR(#EAMP_OPEN_INDLL)
  240.       EndIf
  241.  
  242.       ; OUT_DLL
  243.       ; -------------------------------------------------
  244.       If \In2_Head\UsesOutputPlug   ; does this plug-in use the output plug-ins?
  245.  
  246.          If Amp_IsFile(@RS_AMPMASTER\OutDll$)=  #False   :  RETURN_ERR(#EAMP_OPEN_OUTDLL) :  EndIf
  247.  
  248.          MA_LibOpen(\Out_DLL, RS_AMPMASTER\OutDll$)
  249.  
  250.          If \Out_DLL >  #Null
  251.  
  252.             MA_LibPtr(\Out_DLL, \Out_GetOutModule, "winampGetOutModule")
  253.  
  254.             \Out_Head   =  CallCFunctionFast(\Out_GetOutModule)
  255.  
  256.             If \Out_Head   >  #Null
  257.                \Out_Head\Version       =  #OUT_VER
  258.                \Out_Head\hMainWindow   =  \WindowID
  259.                \Out_Head\hDllInstance  =  \Out_DLL
  260.                CallCFunctionFast(\Out_Head\Init)
  261.             EndIf
  262.  
  263.          EndIf
  264.  
  265.          If \Out_DLL <= #Null Or \Out_Head   <= #Null ; Out-Error?
  266.             Amp_Close() :  RETURN_ERR(#EAMP_OPEN_OUTDLL)
  267.          EndIf
  268.  
  269.          \In2_Head\outMod        =  \Out_Head
  270.  
  271.          RS_AMPMASTER\OutInfo$   =  PeekS(\Out_Head\description)
  272.  
  273.       Else
  274.  
  275.          RS_AMPMASTER\OutInfo$   =  "No use of output plug-ins"
  276.  
  277.       EndIf
  278.  
  279.    EndWith
  280.  
  281.    RS_AMPMASTER\IsOpen  =  #True
  282.  
  283.    RETURN_ERR(#EAMP_OK)
  284.  
  285. EndProcedure
  286.  
  287. ProcedureCDLL  Amp_GetInFlags(*InLib)
  288.  
  289.    With  RS_AMPMASTER
  290.  
  291.       \InFlags =  #FAMP_DEFAULT
  292.  
  293.       If *InLib
  294.  
  295.          Protected   File$ =  GetFilePart(PeekS(*InLib))
  296.  
  297.          Protected   *i_x.RS_INTABLE   =  *i_n
  298.  
  299.          While *i_x\iFLG
  300.  
  301.             If StrCmpNI_(@*i_x\iLIB\s, @File$, Len(File$))  =  #Null
  302.                \InFlags =  PeekI(*i_x\iFLG)
  303.                Break
  304.             EndIf
  305.  
  306.             *i_x  +  SizeOf(RS_INTABLE)
  307.  
  308.          Wend
  309.  
  310.          If \IsPlay
  311.             If RS_WINAMP\In2_Head\is_seekable   =  #Null ; is this stream not seekable?
  312.                \InFlags|#FAMP_NO_SEEK
  313.             EndIf
  314.             If RS_WINAMP\In2_Head\UsesOutputPlug=  #Null ; doesn't this plug-in use output plug-ins?
  315.                \InFlags|#FAMP_NO_OUTPUT|#FAMP_NO_RECORD
  316.             EndIf
  317.          EndIf
  318.  
  319.       EndIf
  320.  
  321.       ProcedureReturn   \InFlags
  322.  
  323.    EndWith
  324.  
  325. EndProcedure
  326. ProcedureCDLL  Amp_GetAmpInFormatStr(*InLib)
  327.  
  328.    ; Returns all supported formats by given *InLib only as string
  329.  
  330.    With  RS_AMPMASTER
  331.  
  332.       Protected   File$ =  GetFilePart(PeekS(*InLib))
  333.       Protected   *i_x.RS_INTABLE   =  *i_n
  334.  
  335.       \InFormats$ =  #Empty$
  336.  
  337.       While *i_x\iFLG
  338.  
  339.          If StrCmpNI_(@*i_x\iLIB\s, @File$, Len(File$))  =  #Null
  340.             \InFormats$ =  *i_x\iEXT\s
  341.             Break
  342.          EndIf
  343.  
  344.          *i_x  +  SizeOf(RS_INTABLE)   ; Next in Table-Ptr
  345.  
  346.       Wend
  347.  
  348.       CharLower_(@\InFormats$)
  349.  
  350.       ProcedureReturn   @\InFormats$
  351.  
  352.    EndWith
  353.  
  354. EndProcedure
  355.  
  356. ;-
  357. ;- *** Play-Stuff ***
  358. ProcedureCDLL  Amp_MusicPlay(*File)
  359.  
  360.    ; Play musicfile, returns 0 if all ok
  361.  
  362.    With  RS_AMPMASTER
  363.  
  364.       If \IsOpen           =  #False   :  RETURN_ERR(#EAMP_INITIALIZE)  :  EndIf
  365.       If Amp_IsFile(*File) =  #False   :  RETURN_ERR(#EAMP_OPEN_FILE)   :  EndIf
  366.  
  367.       \MusicFile$ =  PeekS(*File)
  368.  
  369.       Amp_GetInFlags(@\InDll$)   ; get flags of in_dll
  370.  
  371.       If \InFlags&#FAMP_EX_SFX
  372.          If GetPathPart(\MusicFile$)
  373.             SetCurrentDirectory(GetPathPart(\MusicFile$))   ; Must set for miniusf, minipsf...
  374.          EndIf
  375.       Else
  376.          If GetCurrentDirectory()   <> \InPath$
  377.             SetCurrentDirectory(\InPath$) ; Must set for sublibs & ini
  378.          EndIf
  379.       EndIf
  380.  
  381.       ; Try to get Tag-Title and real length in ms by played file (*File=0 doesn't work for wma)
  382.       CallCFunctionFast(RS_WINAMP\In2_Head\GetFileInfo, *File, @\Buffer, @\MusicTime)
  383.  
  384.       ; Title of musicfile (eg. *.Mod)
  385.       If \Buffer
  386.          \MusicTitle$   =  \Buffer  ; get title
  387.       Else
  388.          \MusicTitle$   =  GetFilePart(\MusicFile$)   ; use filename
  389.       EndIf
  390.  
  391.       \MusicLength   =  \MusicTime  ; length in ms
  392.  
  393.       If CallCFunctionFast(RS_WINAMP\In2_Head\Play, *File)  <> #EAMP_OK ; Error?
  394.          RETURN_ERR(#EAMP_UNKOWN_FORMAT)
  395.       EndIf
  396.  
  397.       CallCFunctionFast(RS_WINAMP\In2_Head\SetVolume, \Volume) ; s. Amp_Init()
  398.       CallCFunctionFast(RS_WINAMP\In2_Head\SetPan,    \Pan)    ; s. Amp_Init()
  399.  
  400.       If RS_WINAMP\In2_Head\is_seekable   =  #Null
  401.          \InFlags|#FAMP_NO_SEEK
  402.       EndIf
  403.       If RS_WINAMP\In2_Head\UsesOutputPlug=  #Null
  404.          \InFlags|#FAMP_NO_OUTPUT|#FAMP_NO_RECORD
  405.       EndIf
  406.  
  407.       \IsPlay  =  #True
  408.  
  409.       ; No real playlength -> use getlength or length as default in ms (#DAMP_LENGTH)
  410.       If \MusicLength   <= 1000  ; length must > 1000ms
  411.  
  412.          \MusicLength   =  CallCFunctionFast(RS_WINAMP\In2_Head\GetLength) ; get playlength
  413.  
  414.          If \MusicLength   <= 1000  ; use default length?
  415.             \MusicLength   =  \DefaultLength ; s. Amp_SetDefaultLength(ms)
  416.          EndIf
  417.  
  418.       EndIf
  419.  
  420.    EndWith
  421.  
  422.    ; set starttime (EleapsedMilliseconds() equ 0)
  423.    With  RS_AMPTIME
  424.       \msStart =  MA_GetTime()
  425.       ;\msStop =  \msStart +  RS_AMPMASTER\MusicLength
  426.    EndWith
  427.  
  428.    RETURN_ERR(#EAMP_OK)
  429.  
  430. EndProcedure
  431. ProcedureCDLL  Amp_MusicPause(Pause.i)
  432.  
  433.    ; set/return status of pause (1=pause/0=unpause)
  434.    With  RS_AMPMASTER
  435.  
  436.       Pause =  Bool(Pause)
  437.  
  438.       If \IsPause <> Pause
  439.  
  440.          \IsPause =  Pause
  441.  
  442.          If \IsPlay
  443.             If \IsPause
  444.  
  445.                CallCFunctionFast(RS_WINAMP\In2_Head\Pause)
  446.  
  447.                RS_AMPTIME\msSleep   =  MA_GetTime()   ; ms until unpause
  448.  
  449.             Else
  450.  
  451.                CallCFunctionFast(RS_WINAMP\In2_Head\UnPause)
  452.  
  453.                RS_AMPTIME\msStart   +  (MA_GetTime()  -  RS_AMPTIME\msSleep)     ; refresh startime
  454.                ;RS_AMPTIME\msStart  =  MA_GetTime()   -  (RS_AMPTIME\msSleep  -  RS_AMPTIME\msStart)
  455.                ;RS_AMPTIME\msStop      =  RS_AMPTIME\msStart   +  RS_AMPMASTER\MusicLength   ; refresh finish
  456.  
  457.             EndIf
  458.          EndIf
  459.  
  460.       EndIf
  461.  
  462.       ProcedureReturn   \IsPause
  463.  
  464.    EndWith
  465.  
  466. EndProcedure
  467. ProcedureCDLL  Amp_MusicStop()
  468.  
  469.    With  RS_AMPMASTER
  470.       If \IsPlay
  471.          \IsPlay  =  #False
  472.          CallCFunctionFast(RS_WINAMP\In2_Head\Stop)
  473.       EndIf
  474.    EndWith
  475.  
  476. EndProcedure
  477. ProcedureCDLL  Amp_MusicSetVolume(Volume.i)
  478.  
  479.    With  RS_AMPMASTER
  480.  
  481.       If \Volume  <> Volume
  482.  
  483.          If Volume   <  #Null
  484.             Volume   =  0
  485.          ElseIf   Volume   >  255
  486.             Volume   =  255
  487.          EndIf
  488.  
  489.          \Volume  =  Volume
  490.  
  491.          If \IsOpen
  492.             CallCFunctionFast(RS_WINAMP\In2_Head\SetVolume, \Volume)
  493.          EndIf
  494.  
  495.       EndIf
  496.  
  497.       ProcedureReturn   \Volume
  498.  
  499.    EndWith
  500.  
  501. EndProcedure
  502. ProcedureCDLL  Amp_MusicSetPan(Pan.i)
  503.  
  504.    With  RS_AMPMASTER
  505.  
  506.       If \Pan  <> Pan
  507.  
  508.          If Pan   <  -127
  509.             Pan   =  -127
  510.          ElseIf   Pan   >  127
  511.             Pan   =  127
  512.          EndIf
  513.  
  514.          \Pan  =  Pan
  515.  
  516.          If \IsOpen
  517.             CallCFunctionFast(RS_WINAMP\In2_Head\SetPan, \Pan)
  518.          EndIf
  519.  
  520.       EndIf
  521.  
  522.       ProcedureReturn   \Pan
  523.  
  524.    EndWith
  525.  
  526. EndProcedure
  527. ProcedureCDLL  Amp_MusicIsPlaying()
  528.  
  529.    With  RS_AMPMASTER
  530.  
  531.       If \IsOpen  =  #Null
  532.          ProcedureReturn   #Null
  533.       ElseIf   RS_WINAMP\In2_Head\UsesOutputPlug
  534.          \IsPlay  =  CallCFunctionFast(RS_WINAMP\Out_Head\IsPlaying)
  535.       EndIf
  536.  
  537.       ProcedureReturn   \IsPlay
  538.  
  539.    EndWith
  540.  
  541. EndProcedure
  542. ProcedureCDLL  Amp_MusicGetLength(Flags.i)
  543.  
  544.    ;**************************************************************************************
  545.    ; Flags:    0=MusicLength  (eg. DefaultLength)
  546.    ;           1=MusicTime    (original length by in_dll)
  547.    ; -------------------------------------------------------------------------------------
  548.    ; Return: total length of music in ms
  549.    ;**************************************************************************************
  550.  
  551.    If Flags
  552.       ProcedureReturn   RS_AMPMASTER\MusicTime
  553.    EndIf
  554.  
  555.    ProcedureReturn   RS_AMPMASTER\MusicLength   ; Fast & full musiclength in ms -> s. Amp_MusicPlay (real length)
  556.  
  557. EndProcedure
  558. ProcedureCDLL  Amp_MusicGetPosition()
  559.    ;**************************************
  560.    ; Return:   current playposition in ms
  561.    ;**************************************
  562.    With  RS_WINAMP
  563.  
  564.       If RS_AMPMASTER\IsPlay
  565.  
  566.          If \In2_Head\is_seekable   And   RS_AMPMASTER\MusicLength   <> RS_AMPMASTER\DefaultLength
  567.             ProcedureReturn   CallCFunctionFast(\In2_Head\GetOutputTime)
  568.          ElseIf   \In2_Head\UsesOutputPlug
  569.             ProcedureReturn   CallCFunctionFast(\Out_Head\GetOutputTime)
  570.          EndIf
  571.  
  572.       EndIf
  573.  
  574.    EndWith
  575.  
  576.    ProcedureReturn   #Null
  577.  
  578. EndProcedure
  579. ProcedureCDLL  Amp_MusicGetOutPosition()
  580.    ;****************************************************
  581.    ; Important:   use this if in_player is a diskwriter!
  582.    ; Return:      written/saved size in ms
  583.    ;****************************************************
  584.    With  RS_AMPMASTER
  585.       If \IsPlay  And   RS_WINAMP\In2_Head\UsesOutputPlug
  586.          ProcedureReturn   CallCFunctionFast(RS_WINAMP\Out_Head\GetOutputTime)
  587.       EndIf
  588.    EndWith
  589.  
  590.    ProcedureReturn   #Null
  591.  
  592. EndProcedure
  593. ProcedureCDLL  Amp_MusicSetPosition(Milliseconds.i)
  594.    ;****************************************
  595.    ; Milliseconds:   position in ms
  596.    ; Return:         real playposition in ms
  597.    ;****************************************
  598.    With  RS_WINAMP
  599.  
  600.       If RS_AMPMASTER\IsOpen
  601.  
  602.          If \In2_Head\is_seekable
  603.  
  604.             If Milliseconds   <  #Null
  605.                Milliseconds   =  0
  606.             ElseIf   Milliseconds   >  RS_AMPMASTER\MusicLength
  607.                Milliseconds   =  RS_AMPMASTER\MusicLength
  608.             EndIf
  609.  
  610.             If RS_AMPMASTER\IsPlay
  611.  
  612.                CallCFunctionFast(\In2_Head\SetOutputTime, Milliseconds)
  613.  
  614.                If \In2_Head\UsesOutputPlug
  615.                   CallCFunctionFast(\Out_Head\Flush, Milliseconds)
  616.                EndIf
  617.  
  618.             EndIf
  619.  
  620.          Else
  621.  
  622.             Milliseconds   =  Amp_MusicGetPosition()  ;CallCFunctionFast(\Out_Head\GetOutputTime)  ; current position in ms
  623.  
  624.          EndIf
  625.  
  626.          ; Refresh starttime
  627.          RS_AMPTIME\msStart   =  MA_GetTime()   -  Milliseconds
  628.  
  629.          ProcedureReturn   Milliseconds
  630.  
  631.       EndIf
  632.  
  633.    EndWith
  634.  
  635. EndProcedure
  636. ProcedureCDLL  Amp_MusicGetTitleStr()
  637.    ProcedureReturn   @RS_AMPMASTER\MusicTitle$
  638. EndProcedure
  639.  
  640. ProcedureCDLL  Amp_InAbout()
  641.  
  642.    If RS_AMPMASTER\IsOpen  =  #False   :  RETURN_ERR(#EAMP_NO_INDLL) :  EndIf
  643.  
  644.    With  RS_WINAMP
  645.       If \In2_DLL And   \In2_Head\About   :  CallCFunctionFast(\In2_Head\About,  \WindowID)  :  EndIf
  646.    EndWith
  647.  
  648. EndProcedure
  649. ProcedureCDLL  Amp_InConfig()
  650.  
  651.    If RS_AMPMASTER\IsOpen  =  #False   :  RETURN_ERR(#EAMP_NO_INDLL) :  EndIf
  652.  
  653.    With  RS_WINAMP
  654.       If \In2_DLL And   \In2_Head\Config  :  CallCFunctionFast(\In2_Head\Config, \WindowID)  :  EndIf
  655.    EndWith
  656.  
  657. EndProcedure
  658.  
  659. ProcedureCDLL  Amp_OutAbout()
  660.  
  661.    If RS_AMPMASTER\IsOpen  =  #False   :  RETURN_ERR(#EAMP_NO_OUTDLL)   :  EndIf
  662.  
  663.    With  RS_WINAMP
  664.       If \Out_DLL And   \Out_Head\About   :  CallCFunctionFast(\Out_Head\About,  \WindowID)  :  EndIf
  665.    EndWith
  666.  
  667. EndProcedure
  668. ProcedureCDLL  Amp_OutConfig()
  669.  
  670.    If RS_AMPMASTER\IsOpen  =  #False   :  RETURN_ERR(#EAMP_NO_OUTDLL)   :  EndIf
  671.  
  672.    With  RS_WINAMP
  673.       If \Out_DLL And   \Out_Head\Config  :  CallCFunctionFast(\Out_Head\Config, \WindowID)  :  EndIf
  674.    EndWith
  675.  
  676. EndProcedure
  677.  
  678. ProcedureCDLL  Amp_InfoBox(*File)
  679.  
  680.    ; Shows in_dll depended informations
  681.  
  682.    If RS_AMPMASTER\IsOpen  =  #False   :  RETURN_ERR(#EAMP_NO_INDLL)    :  EndIf
  683.    If Amp_IsFile(*File)    =  #False   :  RETURN_ERR(#EAMP_OPEN_FILE)   :  EndIf
  684.  
  685.    With  RS_WINAMP
  686.       If \In2_DLL And   \In2_Head\InfoBox
  687.          ProcedureReturn   CallCFunctionFast(\In2_Head\InfoBox, *File, \WindowID)
  688.       EndIf
  689.    EndWith
  690.  
  691.    ProcedureReturn   #Null
  692.  
  693. EndProcedure
  694. ProcedureCDLL  Amp_GetFileInfo(*File, *Title, *Length)
  695.    ;************************************************
  696.    ; File   =  0 -> current played file
  697.    ; Title  =  Buffer{2048} for real title of module
  698.    ; Length =  Integer for time in ms
  699.    ;************************************************
  700.    If RS_AMPMASTER\IsOpen  =  #False   :  RETURN_ERR(#EAMP_NO_INDLL)    :  EndIf
  701.    If Amp_IsFile(*File)    =  #False   :  RETURN_ERR(#EAMP_OPEN_FILE)   :  EndIf
  702.  
  703.    With  RS_WINAMP
  704.       If \In2_DLL And   \In2_Head\GetFileInfo
  705.          CallCFunctionFast(\In2_Head\GetFileInfo, *File, *Title, *Length)
  706.       EndIf
  707.    EndWith
  708.  
  709. EndProcedure
  710.  
  711. ProcedureCDLL  Amp_SetDefaultLength(Milliseconds.i)
  712.    ;**************************************************************
  713.    ; Set default playlength if no calculated musiclength by in_dll
  714.    ; -------------------------------------------------------------
  715.    ; Milliseconds =  length in ms or default length (300000)
  716.    ;**************************************************************
  717.    With  RS_AMPMASTER
  718.  
  719.       If Milliseconds   <= #Null
  720.          Milliseconds   =  #DAMP_LENGTH
  721.       EndIf
  722.  
  723.       \DefaultLength =  Milliseconds
  724.  
  725.    EndWith
  726.  
  727. EndProcedure
  728. ProcedureCDLL  Amp_GetInFormatStr()
  729.  
  730.    ; Return supported tracker + (*.formats;..) by in_dll only (winamp)
  731.  
  732.    If RS_AMPMASTER\IsOpen  =  #False   :  RETURN_ERR(#EAMP_NO_INDLL) :  EndIf
  733.  
  734.    With  RS_AMPMASTER
  735.  
  736.       Protected   NewList  Srt.s()
  737.  
  738.       Protected   i, e$, i$
  739.       Protected   *Ptr.Character =  RS_WINAMP\In2_Head\FileExtensions
  740.  
  741.       If *Ptr
  742.  
  743.          \Formats$   =  #Null$   ; clear string
  744.  
  745.          While *Ptr\c
  746.  
  747.             e$ =  PeekS(*Ptr) :  *Ptr  +  Len(e$)  +  SizeOf(Character)
  748.             i$ =  PeekS(*Ptr) :  *Ptr  +  Len(i$)  +  SizeOf(Character)
  749.  
  750.             i  =  StrStrI_(i$, "(")
  751.  
  752.             AddElement(Srt())
  753.  
  754.             If i
  755.                CharLower_(i)  :  Srt() =  i$
  756.             Else
  757.                CharLower_(@e$):  Srt() =  i$ +  " ("  +  e$ +  ")"   ; eg. in_tfmx.dll
  758.             EndIf
  759.  
  760.          Wend
  761.  
  762.          SortList(Srt(), #PB_Sort_Ascending)
  763.  
  764.          ForEach  Srt()
  765.             \Formats$   +  Srt() +  #LF$
  766.          Next
  767.  
  768.          \Formats$   =  Trim(\Formats$, #LF$)
  769.  
  770.       Else
  771.  
  772.          \Formats$   =  #Empty$  ; must set empty$ coz error if null$
  773.  
  774.       EndIf
  775.  
  776.       FreeList(Srt())
  777.  
  778.       ProcedureReturn   @\Formats$
  779.  
  780.    EndWith
  781.  
  782. EndProcedure
  783.  
  784. ProcedureCDLL  Amp_SetAmpPath(*Path)
  785.  
  786.    ; Set path for in_/out_dll
  787.  
  788.    With  RS_AMPMASTER
  789.  
  790.       If *Path
  791.          \Path$   =  PeekS(*Path)
  792.       Else
  793.          \Path$   =  GetPathPart(\ProgramName$) +  #DAMP_PATH$
  794.       EndIf
  795.  
  796.       If Right(\Path$, 1)  <> "\"   :  \Path$   +  "\"   :  EndIf
  797.  
  798.       \InPath$    =  \Path$
  799.       \OutPath$   =  \Path$
  800.  
  801.    EndWith
  802.  
  803. EndProcedure
  804.  
  805. ProcedureCDLL  Amp_SetInPath(*Path)
  806.  
  807.    ; Set path for in_dll only
  808.  
  809.    With  RS_AMPMASTER
  810.       If *Path
  811.          \InPath$ =  PeekS(*Path)
  812.       Else
  813.          \InPath$ =  GetPathPart(\ProgramName$) +  #DAMP_PATH$
  814.       EndIf
  815.       If Right(\InPath$, 1)   <> "\"   :  \InPath$ +  "\"   :  EndIf
  816.    EndWith
  817.  
  818. EndProcedure
  819. ProcedureCDLL  Amp_SetInDll(*InLib)
  820.  
  821.    ; Set in_dll for musicfile
  822.  
  823.    With  RS_AMPMASTER
  824.       If *InLib
  825.          \InDll$  =  PeekS(*InLib)  :  If GetPathPart(\InDll$) :  \InPath$ =  GetPathPart(\InDll$) :  EndIf
  826.       EndIf
  827.    EndWith
  828.  
  829. EndProcedure
  830. ProcedureCDLL  Amp_SetOutPath(*Path)
  831.  
  832.    ; Set path to out_dll only
  833.  
  834.    With  RS_AMPMASTER
  835.       If *Path
  836.          \OutPath$   =  PeekS(*Path)
  837.       Else
  838.          \OutPath$   =  GetPathPart(\ProgramName$) +  #DAMP_PATH$
  839.       EndIf
  840.       If Right(\OutPath$, 1)  <> "\"   :  \OutPath$   +  "\"   :  EndIf
  841.    EndWith
  842.  
  843. EndProcedure
  844. ProcedureCDLL  Amp_SetOutDll(*OutLib)
  845.  
  846.    ; Set out_dll for musicplay
  847.  
  848.    With  RS_AMPMASTER
  849.       If *OutLib
  850.          \OutDll$ =  PeekS(*OutLib) :  If GetPathPart(\OutDll$)   :  \OutPath$   =  GetPathPart(\InDll$) :  EndIf
  851.       EndIf
  852.    EndWith
  853.  
  854. EndProcedure
  855. ProcedureCDLL  Amp_SetWindow(*Window)
  856.  
  857.    ; Set Window for callback
  858.  
  859.    With  RS_AMPMASTER
  860.       If *Window
  861.          \WindowID   =  *Window
  862.       Else
  863.          \WindowID   =  GetForegroundWindow_()
  864.       EndIf
  865.       RS_WINAMP\WindowID   =  \WindowID
  866.       ;SetActiveWindow_(\WindowID)
  867.    EndWith
  868.  
  869. EndProcedure
  870.  
  871. ProcedureCDLL  Amp_GetAmpInDllStr(*File)
  872.    ;**************************************************************************************
  873.    ; If no in_dll is given, Amp searchs for predefined in_dll by extension (*.MOD & MOD.*)
  874.    ; -------------------------------------------------------------------------------------
  875.    ; Return:   ptr to string of in_dll
  876.    ;**************************************************************************************
  877.    With  RS_AMPMASTER
  878.  
  879.       \InDll$  =  #Empty$
  880.  
  881.       If *File
  882.  
  883.          Protected   File$ =  GetFilePart(PeekS(*File))  ; No spaces allowed (extension can't use it)
  884.          Protected   i     =  CountString(File$, ".") +  1
  885.  
  886.          If i  >  1
  887.  
  888.             Protected   *i_x.RS_INTABLE   =  *i_n
  889.  
  890.             Protected   a$ =  ";"   +  Trim(StringField(File$, i, ".")) +  ";"   ; 1. try -> *.MOD (standard PC)
  891.             Protected   b$ =  ";"   +  Trim(StringField(File$, 1, ".")) +  ";"   ; 2. try -> MOD.* (classic Amiga)
  892.  
  893.             While *i_x\iFLG
  894.                If StrStrI_(@*i_x\iEXT\s, @a$)   Or StrStrI_(@*i_x\iEXT\s, @b$)
  895.                   \InDll$  =  *i_x\iLIB\s :  Break
  896.                EndIf
  897.                *i_x  +  SizeOf(RS_INTABLE)
  898.             Wend
  899.  
  900.          EndIf
  901.       EndIf
  902.  
  903.       ProcedureReturn   @\InDll$
  904.  
  905.    EndWith
  906.  
  907. EndProcedure
  908.  
  909. ProcedureCDLL  Amp_CountAmpFormatsAll()
  910.    ;*************************************************************
  911.    ; Calculates number of all supported formats (*.MOD) by AmpLib
  912.    ; ------------------------------------------------------------
  913.    ; Return: Number of all supported formats
  914.    ;*************************************************************
  915.    With  RS_AMPMASTER
  916.  
  917.       If \nAmpFormatsAll   :  ProcedureReturn   \nAmpFormatsAll   :  EndIf
  918.  
  919.       Protected   i, t$, e$
  920.       Protected   *i_x.RS_INTABLE   =  *i_n
  921.  
  922.       Protected   NewMap   Extensions.s()
  923.  
  924.       While *i_x\iFLG
  925.  
  926.          i  =  #Null
  927.  
  928.          t$ =  Trim(*i_x\iEXT\s, ";")
  929.  
  930.          Repeat
  931.             i  +  1  :  e$ =  StringField(t$, i, ";") :  Extensions(e$) +  1
  932.          Until Len(e$)  =  0
  933.  
  934.          *i_x  +  SizeOf(RS_INTABLE)   ; Next in Table-Ptr
  935.  
  936.       Wend
  937.  
  938.       \nAmpFormatsAll   =  MapSize(Extensions())   -  1  ; No/empty extension (-1)
  939.  
  940.       FreeMap(Extensions())
  941.  
  942.       ProcedureReturn   \nAmpFormatsAll
  943.  
  944.    EndWith
  945.  
  946. EndProcedure
  947. ProcedureCDLL  Amp_CountAmpPlayersAll()
  948.    ;****************************************************************
  949.    ; Calculates number of all supported players (in_*.dll) by AmpLib
  950.    ; ---------------------------------------------------------------
  951.    ; Return: Number of all supported players (in_dlls)
  952.    ;****************************************************************
  953.    With  RS_AMPMASTER
  954.  
  955.       If \nAmpPlayersAll   :  ProcedureReturn   \nAmpPlayersAll   :  EndIf
  956.  
  957.       Protected   *i_x.RS_INTABLE   =  *i_n
  958.  
  959.       While *i_x\iLIB\s
  960.  
  961.          \nAmpPlayersAll   +  1
  962.  
  963.          *i_x  +  SizeOf(RS_INTABLE)   ; Next in Table-Ptr
  964.  
  965.       Wend
  966.  
  967.       ProcedureReturn   \nAmpPlayersAll
  968.  
  969.    EndWith
  970.  
  971. EndProcedure
  972. ProcedureCDLL  Amp_GetAmpFormatsStrAll()
  973.    ;***********************************************************
  974.    ; Generates sorted string of all supported formats by AmpLib
  975.    ; ----------------------------------------------------------
  976.    ; Return: ptr to (very long) formatstring (*.A;*.B;*.C;...)
  977.    ;***********************************************************
  978.    With  RS_AMPMASTER
  979.  
  980.       If Len(\sAmpFormatsAll$)   :  ProcedureReturn   @\sAmpFormatsAll$ :  EndIf
  981.  
  982.       Protected   i, t$, e$
  983.       Protected   *i_x.RS_INTABLE   =  *i_n
  984.  
  985.       Protected   NewMap   Extensions.s()
  986.       Protected   NewList  Srt.s()
  987.  
  988.       While *i_x\iFLG
  989.  
  990.          i  =  #Null
  991.  
  992.          t$ =  Trim(*i_x\iEXT\s, ";")
  993.  
  994.          Repeat
  995.             i  +  1  :  e$ =  StringField(t$, i, ";") :  Extensions(e$) +  1
  996.          Until Len(e$)  =  0
  997.  
  998.          *i_x  +  SizeOf(RS_INTABLE)   ; Next in Table-Ptr
  999.  
  1000.       Wend
  1001.  
  1002.       ForEach  Extensions()
  1003.          If MapKey(Extensions())
  1004.             AddElement(Srt()) :  Srt() =  MapKey(Extensions())
  1005.          EndIf
  1006.       Next
  1007.  
  1008.       SortList(Srt(), #PB_Sort_Ascending)
  1009.  
  1010.       ForEach  Srt()
  1011.          \sAmpFormatsAll$  +  ";*." +  Srt()
  1012.       Next
  1013.  
  1014.       CharLower_(@\sAmpFormatsAll$)
  1015.  
  1016.       FreeMap(Extensions())
  1017.       FreeList(Srt())
  1018.  
  1019.       ProcedureReturn   @\sAmpFormatsAll$
  1020.  
  1021.    EndWith
  1022. EndProcedure
  1023. ProcedureCDLL  Amp_GetAmpInDllsStrAll(*File)
  1024.    ;**************************************************************************************
  1025.    ; Generates sorted string of all predefined in_dlls used by extension
  1026.    ; -------------------------------------------------------------------------------------
  1027.    ; Return:   ptr to multi-string of in_dlls (in_xamp.dll;in_oldsk00l.dll;in_bass.dll...)
  1028.    ;**************************************************************************************
  1029.    With  RS_AMPMASTER
  1030.  
  1031.       \InDllsAll$ =  #Empty$
  1032.  
  1033.       If *File
  1034.  
  1035.          Protected   File$ =  GetFilePart(PeekS(*File))  ; No spaces allowed in PB (extensions can't use it)
  1036.          Protected   i     =  CountString(File$, ".") +  1
  1037.  
  1038.          If i  >  1
  1039.  
  1040.             Protected   *i_x.RS_INTABLE   =  *i_n
  1041.  
  1042.             Protected   a$ =  ";"   +  Trim(StringField(File$, i, ".")) +  ";"   ; 1. try -> *.MOD (standard PC)
  1043.             Protected   b$ =  ";"   +  Trim(StringField(File$, 1, ".")) +  ";"   ; 2. try -> MOD.* (classic Amiga)
  1044.  
  1045.             While *i_x\iFLG
  1046.                If StrStrI_(@*i_x\iEXT\s, @a$)   Or StrStrI_(@*i_x\iEXT\s, @b$)
  1047.                   \InDllsAll$ +  *i_x\iLIB\s +  ";"
  1048.                EndIf
  1049.                *i_x  +  SizeOf(RS_INTABLE)
  1050.             Wend
  1051.  
  1052.          EndIf
  1053.       EndIf
  1054.  
  1055.       ProcedureReturn   @\InDllsAll$
  1056.  
  1057.    EndWith
  1058.  
  1059. EndProcedure
  1060.  
  1061. ProcedureCDLL  Amp_GetErrorStr(Error.i)
  1062.  
  1063.    With  RS_AMPMASTER
  1064.  
  1065.       Select   Error
  1066.          Case  #EAMP_OK             :  \ErrorStr$  =  #SAMP_OK$
  1067.          Case  #EAMP_NO_INDLL       :  \ErrorStr$  =  #SAMP_NO_INDLL$
  1068.          Case  #EAMP_NO_OUTDLL      :  \ErrorStr$  =  #SAMP_NO_OUTDLL$
  1069.          Case  #EAMP_OPEN_FILE      :  \ErrorStr$  =  #SAMP_OPEN_FILE$
  1070.          Case  #EAMP_OPEN_INDLL     :  \ErrorStr$  =  #SAMP_OPEN_INDLL$
  1071.          Case  #EAMP_OPEN_OUTDLL    :  \ErrorStr$  =  #SAMP_OPEN_OUTDLL$
  1072.          Case  #EAMP_UNKOWN_FORMAT  :  \ErrorStr$  =  #SAMP_UNKOWN_FORMAT$
  1073.          Case  #EAMP_INITIALIZE     :  \ErrorStr$  =  #SAMP_INITIALIZE$
  1074.          Default
  1075.             \ErrorStr$  =  #SAMP_UNKNOWN$
  1076.       EndSelect
  1077.  
  1078.       ProcedureReturn   @\ErrorStr$
  1079.  
  1080.    EndWith
  1081.  
  1082. EndProcedure
  1083. ProcedureCDLL  Amp_GetError()
  1084.    ProcedureReturn   RS_AMPMASTER\ErrorN
  1085. EndProcedure
  1086.  
  1087. ProcedureCDLL  Amp_GetInInfoStr()
  1088.    ProcedureReturn   @RS_AMPMASTER\InInfo$
  1089. EndProcedure
  1090. ProcedureCDLL  Amp_GetOutInfoStr()
  1091.    ProcedureReturn   @RS_AMPMASTER\OutInfo$
  1092. EndProcedure
  1093.  
  1094. ;-
  1095. ;- *** Sub-Songs ***
  1096. ProcedureCDLL  Amp_SetSubSong(*File, SubSong.i)
  1097.    ;***************************************
  1098.    ; Set number of subsong to replay
  1099.    ; --------------------------------------
  1100.    ; *File:    @Ptr to full Path + Filename
  1101.    ; SubSong:  Number of subsong
  1102.    ; --------------------------------------
  1103.    ; Return:   #EAMP_OK if all ok
  1104.    ;***************************************
  1105.    With  RS_AMPMASTER
  1106.  
  1107.       If Amp_IsFile(*File) =  #False   :  RETURN_ERR(#EAMP_OPEN_FILE)   :  EndIf
  1108.       If SubSong  <= #Null :  SubSong  =  1  :  EndIf
  1109.  
  1110.       Protected   hF, i, TFM_OFFSET
  1111.       Protected   RS_PSID.RS_PSID
  1112.       Protected   RS_TFMX.RS_TFMX, *TFMX.RS_TFMX_AMP
  1113.  
  1114.       \SubSong =  SubSong
  1115.  
  1116.       hF =  OpenFile(#PB_Any, PeekS(*File))
  1117.       If hF
  1118.  
  1119.          \ID   =  ReadLong(hF)
  1120.  
  1121.          Select   \ID
  1122.  
  1123.             ; *** PSID
  1124.             Case  #ID_PSID
  1125.                FileSeek(hF, #Null)
  1126.                If ReadData(hF, @RS_PSID, SizeOf(RS_PSID))   =  SizeOf(RS_PSID)
  1127.                   \NumSongs   =  UINT16(RS_PSID\songs)
  1128.                   If \SubSong <= \NumSongs   And   \SubSong <> UINT16(RS_PSID\startSong)
  1129.                      FileSeek(hF,   OffsetOf(RS_PSID\startSong))
  1130.                      WriteWord(hF,  UINT16(\SubSong))
  1131.                      FlushFileBuffers(hF)
  1132.                   EndIf
  1133.                EndIf
  1134.  
  1135.             ; *** TFMX Hardcoded! Creates a not official TAG -> would be glad if another way to play subsongs in WinAMP!?
  1136.             Case  #ID_TFMX
  1137.  
  1138.                i  =  ReadLong(hF)
  1139.  
  1140.                Select   i
  1141.                   Case  #ID_SONG, #ID_2001, #ID_TMOD  ; Really TFMX-Song?
  1142.  
  1143.                      If i  =  #ID_TMOD :  TFM_OFFSET  =  $14   :  EndIf ; TFM -> Merged MDAT + SMPL?
  1144.  
  1145.                      FileSeek(hF, TFM_OFFSET)
  1146.  
  1147.                      If ReadData(hF, @RS_TFMX, SizeOf(RS_TFMX))   =  SizeOf(RS_TFMX)
  1148.  
  1149.                         *TFMX =  @RS_TFMX\StartPos -  SizeOf(RS_TFMX_AMP)
  1150.  
  1151.                         If *TFMX\ID =  #ID_AMP0 And   *TFMX\NumSongs >= \SubSong
  1152.  
  1153.                            \NumSongs   =  *TFMX\NumSongs
  1154.  
  1155.                            RS_TFMX\StartPos  [0]   =  *TFMX\StartPos ; Get/Restore SubSong[0] Start
  1156.                            RS_TFMX\EndPos    [0]   =  *TFMX\EndPos   ; Get/Restore SubSong[0] End
  1157.                            RS_TFMX\Tempo     [0]   =  *TFMX\Tempo    ; Get/Restore SubSong[0] Tempo
  1158.  
  1159.                            *TFMX\SubSong  =  \SubSong -  1  ; Set SubSong[n] as SubSong[0]
  1160.  
  1161.                            FileSeek(hF,   #TFMX_AMP_OFFSET  +  OffsetOf(RS_TFMX_AMP\SubSong) +  TFM_OFFSET) :  WriteByte(hF,  *TFMX\SubSong) ; Default SubSong
  1162.  
  1163.                            FileSeek(hF,   OffsetOf(RS_TFMX\StartPos) +  TFM_OFFSET) :  WriteData(hF,  @RS_TFMX\StartPos [*TFMX\SubSong],  SizeOf(Word))  ; $100
  1164.                            FileSeek(hF,   OffsetOf(RS_TFMX\EndPos)   +  TFM_OFFSET) :  WriteData(hF,  @RS_TFMX\EndPos   [*TFMX\SubSong],  SizeOf(Word))  ; $140
  1165.                            FileSeek(hF,   OffsetOf(RS_TFMX\Tempo)    +  TFM_OFFSET) :  WriteData(hF,  @RS_TFMX\Tempo    [*TFMX\SubSong],  SizeOf(Word))  ; $180
  1166.  
  1167.                         EndIf
  1168.                      EndIf
  1169.                EndSelect
  1170.  
  1171.             Case  #ID_FR10, #ID_FR12, #ID_FR4E, #ID_FR78 ; Really FRED Song? (*.fred)
  1172.                FileSeek(hF, $40)       ; Min. Offset
  1173.                For   i  =  0  To $80
  1174.                   If ReadWord(hF)&$FFFF   =  #ID_FRSS ; ID SubSongs?
  1175.                      \NumSongs   =  ReadByte(hF)   ; always $60 -> 6 Songs so we set it to 15 (#MAX_FRED)
  1176.                      \NumSongs   =  #MAX_FRED-1
  1177.                      \SubSong -  1
  1178.                      If \SubSong <= \NumSongs
  1179.                         \SubSong << 4  ; Nibblebyte to max. $F0
  1180.                         WriteByte(hF, \SubSong)
  1181.                      EndIf
  1182.                      Break
  1183.                   EndIf
  1184.                Next
  1185.  
  1186.             ; *** NSF
  1187.             Case  #ID_NESM
  1188.                If ReadWord(hF)   =  $011A
  1189.                   \NumSongs   =  ReadByte(hF)
  1190.                   If \SubSong <= \NumSongs
  1191.                      WriteByte(hF, \SubSong)
  1192.                   EndIf
  1193.                EndIf
  1194.  
  1195.             ; *** GBS
  1196.             Case  #ID_GBS1
  1197.                \NumSongs   =  ReadByte(hF)
  1198.                If \SubSong <= \NumSongs
  1199.                   WriteByte(hF, \SubSong)
  1200.                EndIf
  1201.  
  1202.          EndSelect
  1203.  
  1204.          CloseFile(hF)
  1205.       EndIf
  1206.  
  1207.    EndWith
  1208.  
  1209.    RETURN_ERR(#EAMP_OK)
  1210.  
  1211. EndProcedure
  1212. ProcedureCDLL  Amp_GetSubSong(*File)
  1213.    ;***************************************************************************
  1214.    ; Get actual subsong of format:  *.sid;*.mdat;*.tfm;*.tfx;*.nsf;*.gbs;*.fred
  1215.    ; --------------------------------------------------------------------------
  1216.    ; *File:    @Ptr to full Path + Filename
  1217.    ; --------------------------------------------------------------------------
  1218.    ; Return:   Number of actual subsong or < #NULL if error
  1219.    ;***************************************************************************
  1220.    With  RS_AMPMASTER
  1221.  
  1222.       If Amp_IsFile(*File) =  #False   :  RETURN_ERR(#EAMP_OPEN_FILE)   :  EndIf
  1223.  
  1224.       Protected   hF, i, TFM_OFFSET
  1225.  
  1226.       \SubSong =  #Null
  1227.  
  1228.       hF =  OpenFile(#PB_Any, PeekS(*File))
  1229.       If hF
  1230.  
  1231.          \ID   =  ReadLong(hF)
  1232.  
  1233.          Select   \ID
  1234.             Case  #ID_PSID ; *.sid
  1235.                FileSeek(hF, OffsetOf(RS_PSID\startSong))
  1236.                \SubSong =  ReadWord(hF)
  1237.                \SubSong =  UINT16(\SubSong)
  1238.  
  1239.             Case  #ID_TFMX ; mdat.*
  1240.  
  1241.                i  =  ReadLong(hF)
  1242.  
  1243.                Select   i
  1244.                   Case  #ID_SONG, #ID_2001, #ID_TMOD  ; Really TFMX-Song?
  1245.  
  1246.                      If i  =  #ID_TMOD :  TFM_OFFSET  =  $14   :  EndIf ; Merged MDAT + SMPL?
  1247.  
  1248.                      FileSeek(hF, #TFMX_AMP_OFFSET+TFM_OFFSET)
  1249.                      If ReadLong(hF)=  #ID_AMP0       ; You must! have called Amp_CountSubSongs() first (creates AMP0 tag)
  1250.                         \NumSongs   =  ReadByte(hF)
  1251.                         \SubSong    =  ReadByte(hF)   +  1
  1252.                      EndIf
  1253.                EndSelect
  1254.  
  1255.             Case  #ID_FR10, #ID_FR12, #ID_FR4E, #ID_FR78 ; Really FRED Song? (*.fred)
  1256.                FileSeek(hF, $40) ; Min. Offset
  1257.                For   i  =  0  To $80
  1258.                   If ReadWord(hF)&$FFFF   =  #ID_FRSS ; ID SubSongs?
  1259.                      \NumSongs   =  ReadByte(hF)
  1260.                      \SubSong    =  ReadByte(hF)   :  \SubSong    =  (\SubSong   >> 4) &  #MAX_FRED   +  1
  1261.                      Break
  1262.                   EndIf
  1263.                Next
  1264.  
  1265.             Case  #ID_NESM ; *.nsf
  1266.                If ReadWord(hF)=  $011A ; Really NSF-Song?
  1267.                   \NumSongs   =  ReadByte(hF)
  1268.                   \SubSong    =  ReadByte(hF)
  1269.                EndIf
  1270.  
  1271.             Case  #ID_GBS1 ; *.gbs
  1272.                \NumSongs   =  ReadByte(hF)
  1273.                \SubSong    =  ReadByte(hF)
  1274.  
  1275.          EndSelect
  1276.  
  1277.          CloseFile(hF)
  1278.       EndIf
  1279.  
  1280.       ProcedureReturn   \SubSong
  1281.  
  1282.    EndWith
  1283.  
  1284. EndProcedure
  1285. ProcedureCDLL  Amp_CountSubSongs(*File)
  1286.    ;******************************************************************
  1287.    ; Calculate subsongs of *.sid;*.mdat;*.tfm;*.tfx;*.nsf;*.gbs;*.fred
  1288.    ;******************************************************************
  1289.    With  RS_AMPMASTER
  1290.  
  1291.       If Amp_IsFile(*File) =  #False   :  RETURN_ERR(#EAMP_OPEN_FILE)   :  EndIf
  1292.  
  1293.       Protected   hF, i, TFM_OFFSET
  1294.       Protected   RS_TFMX.RS_TFMX
  1295.  
  1296.       \NumSongs   =  #Null
  1297.  
  1298.       hF =  OpenFile(#PB_Any, PeekS(*File))  ; read/write
  1299.       If hF
  1300.  
  1301.          \ID   =  ReadLong(hF)
  1302.  
  1303.          Select   \ID
  1304.             Case  #ID_PSID ; *.sid
  1305.                FileSeek(hF, OffsetOf(RS_PSID\songs))
  1306.                \NumSongs   =  ReadWord(hF)
  1307.                \NumSongs   =  UINT16(\NumSongs)
  1308.  
  1309.             Case  #ID_TFMX
  1310.  
  1311.                i  =  ReadLong(hF)
  1312.  
  1313.                Select   i
  1314.                   Case  #ID_SONG, #ID_2001, #ID_TMOD  ; Really TFMX (Custom) - Song? *.mdat(7), *.tfm, *.tfx
  1315.  
  1316.                      If i  =  #ID_TMOD :  TFM_OFFSET  =  $14   :  EndIf ; Skip merged MDAT + SMPL header of *.tfm?
  1317.  
  1318.                      FileSeek(hF, TFM_OFFSET)
  1319.  
  1320.                      If ReadData(hF, @RS_TFMX, SizeOf(RS_TFMX))   =  SizeOf(RS_TFMX)
  1321.  
  1322.                         FileSeek(hF, #TFMX_AMP_OFFSET+TFM_OFFSET)
  1323.  
  1324.                         If ReadLong(hF)   <> #ID_AMP0 ; Create AMP0 Tag?
  1325.  
  1326.                            \NumSongs   =  1  ; always 1 song!
  1327.  
  1328.                            For   i  =  1  To 31 ; Calculate real NumSongs[2..32]
  1329.                               If (RS_TFMX\StartPos[i] Or RS_TFMX\EndPos[i])   And   RS_TFMX\StartPos[i]<>$FF01 ; Code end of songs?
  1330.                                  If (RS_TFMX\StartPos[i-1]<>RS_TFMX\StartPos[i]  Or RS_TFMX\EndPos[i-1]<>RS_TFMX\EndPos[i])   ; no similar songs
  1331.                                     \NumSongs   +  1
  1332.                                  EndIf
  1333.                               EndIf
  1334.                            Next
  1335.  
  1336.                            FileSeek(hF,   #TFMX_AMP_OFFSET+TFM_OFFSET)  ; Hardcoded Tag RSET
  1337.  
  1338.                            ;i =  #ID_AMP0
  1339.                            WriteLong(hF,  #ID_AMP0)   ; ID-TAG
  1340.                            WriteByte(hF,  \NumSongs)  ; Number of avail songs (1-32)
  1341.  
  1342.                            ;i =  #Null
  1343.                            WriteByte(hF,  #Null)   ; Default SubSong[0-31] always NULL at first time
  1344.                            WriteData(hF,  @RS_TFMX\StartPos,SizeOf(Word))  ; Default StartSong[0]
  1345.                            WriteData(hF,  @RS_TFMX\EndPos,  SizeOf(Word))  ; Default EndSong[0]
  1346.                            WriteData(hF,  @RS_TFMX\Tempo,   SizeOf(Word))  ; Default Tempo[0]
  1347.  
  1348.                         Else  ; AMP0-Tag already exist!
  1349.                            \NumSongs   =  ReadByte(hF)
  1350.                            \SubSong    =  ReadByte(hF)
  1351.                         EndIf
  1352.  
  1353.                      EndIf
  1354.                EndSelect
  1355.  
  1356.             Case  #ID_FR10, #ID_FR12, #ID_FR4E, #ID_FR78 ; Really FRED Song? (*.fred)
  1357. ;              FileSeek(hF, $40)       ; Min. Offset
  1358. ;              For   i  =  0  To $80
  1359. ;                 If ReadWord(hF)&$FFFF   =  #ID_FRSS ; ID SubSongs?
  1360. ;                    \NumSongs   =  ReadByte(hF)
  1361. ;                    \NumSongs   =  UINT8(\NumSongs)  +  1
  1362. ;                    Break
  1363. ;                 EndIf
  1364. ;              Next
  1365.  
  1366.                ; *** NOTE:
  1367.                ; That is constant crap, but no info of variable header! There are not always
  1368.                ; subsongs, or/and wrong calculated by in_oldskool.dll!
  1369.                \NumSongs   =  #MAX_FRED   ; please check the songinfo
  1370.  
  1371.             Case  #ID_NESM
  1372.                If ReadWord(hF)   =  $011A
  1373.                   \NumSongs   =  ReadByte(hF)
  1374.                   \SubSong    =  ReadByte(hF)
  1375.                EndIf
  1376.  
  1377.             Case  #ID_GBS1
  1378.                \NumSongs   =  ReadByte(hF)
  1379.                \SubSong    =  ReadByte(hF)
  1380.  
  1381.          EndSelect
  1382.  
  1383.          CloseFile(hF)
  1384.       EndIf
  1385.  
  1386.       ProcedureReturn   \NumSongs
  1387.  
  1388.    EndWith
  1389.  
  1390. EndProcedure
  1391.  
  1392. ;-
  1393. ;- *** Intern time-handling ***
  1394. ProcedureCDLL  Amp_SetLength(Milliseconds.i)
  1395.    RS_AMPMASTER\MusicLength   =  Milliseconds
  1396. EndProcedure
  1397. ProcedureCDLL  Amp_GetPlayTime()
  1398.  
  1399.    ; return played time in ms
  1400.    With  RS_AMPTIME
  1401.  
  1402.       If RS_AMPMASTER\IsPlay
  1403.          \msPlay  =  MA_GetTime()   -  \msStart
  1404.       EndIf
  1405.  
  1406.       ProcedureReturn   \msPlay
  1407.  
  1408.    EndWith
  1409.  
  1410. EndProcedure
  1411. ProcedureCDLL  Amp_GetStopTime()
  1412.  
  1413.    ; return rest of time until stop
  1414.    With  RS_AMPTIME
  1415.  
  1416.       If RS_AMPMASTER\IsPlay
  1417.  
  1418.          \msStop  =  RS_AMPMASTER\MusicLength   -  (MA_GetTime()  -  \msStart)
  1419.  
  1420.          If \msStop  <  #Null
  1421.             \msStop  =  #Null
  1422.          EndIf
  1423.  
  1424.       EndIf
  1425.  
  1426.       ProcedureReturn   \msStop
  1427.  
  1428.    EndWith
  1429.  
  1430. EndProcedure
  1431. ProcedureCDLL  Amp_GetPercent()
  1432.  
  1433.    ; return percent of played time
  1434.    With  RS_AMPTIME
  1435.  
  1436.       If RS_AMPMASTER\IsPlay
  1437.  
  1438.          \msPercent  =  100.0 /  (RS_AMPMASTER\MusicLength * 0.001)  *  ((MA_GetTime() -  \msStart) * 0.001)
  1439.  
  1440.          If \msPercent  <  #Null
  1441.             \msPercent  =  #Null
  1442.          ElseIf   \msPercent  >  100
  1443.             \msPercent  =  100
  1444.          EndIf
  1445.  
  1446.       EndIf
  1447.  
  1448.       ProcedureReturn   \msPercent
  1449.  
  1450.    EndWith
  1451.  
  1452. EndProcedure
  1453.  
  1454. ;-
  1455. ;- *** Quick replay ***
  1456. ProcedureCDLL  Amp_Play(*File, Volume.i)
  1457.  
  1458.    Protected   t$, i$, i
  1459.  
  1460.    With  RS_AMPMASTER
  1461.  
  1462.       If Amp_IsFile(*File) =  #False   :  RETURN_ERR(#EAMP_OPEN_FILE)   :  EndIf
  1463.  
  1464.       Amp_Init()
  1465.  
  1466.       ; get all avail in_libs for format
  1467.       t$ =  PeekS(Amp_GetAmpInDllsStrAll(*File))
  1468.  
  1469.       ; try until replay song by one of given in_libs
  1470.       For   i  =  1  To CountString(t$, ";")
  1471.  
  1472.          ; out_wave_audio.dll doesn't play mp3
  1473.          If StrStrI_(*File, @".mp3")
  1474.             Amp_SetOutDll(@"out_wave_gpl.dll")
  1475.          Else
  1476.             Amp_SetOutDll(@"out_wave_audio.dll")
  1477.          EndIf
  1478.  
  1479.          Amp_SetAmpPath(0)
  1480.  
  1481.          SetCurrentDirectory(\Path$)
  1482.  
  1483.          ; try first/next in_lib
  1484.          i$ =  StringField(t$, i, ";")
  1485.          Amp_SetInDll(@i$)
  1486.  
  1487.          If Amp_Open()  =  #EAMP_OK
  1488.  
  1489.             \Volume  =  Volume
  1490.  
  1491.             If Amp_MusicPlay(*File) =  #EAMP_OK
  1492.                Break
  1493.             EndIf
  1494.  
  1495.          EndIf
  1496.  
  1497.       Next
  1498.  
  1499.       ProcedureReturn   \ErrorN
  1500.  
  1501.    EndWith
  1502.  
  1503. EndProcedure
  1504. ProcedureCDLL  Amp_QuickPlay(*File, *Path)
  1505.  
  1506.    ;If   Amp_IsFile(*File)    =  #False   :  RETURN_ERR(#EAMP_OPEN_FILE)   :  EndIf
  1507.  
  1508.    Protected   t$, RetVal
  1509.  
  1510.    With  RS_AMPMASTER
  1511.  
  1512.       Amp_Init()
  1513.  
  1514.       Amp_GetAmpInDllStr(*File)
  1515.       If Len(\InDll$)   =  #Null :  RETURN_ERR(#EAMP_NO_INDLL) :  EndIf
  1516.  
  1517.       Amp_SetAmpPath(*Path)
  1518.       SetCurrentDirectory(\Path$)
  1519.  
  1520.       If Amp_Open()  =  #EAMP_OK And   Amp_MusicPlay(*File) =  #EAMP_OK
  1521.  
  1522.          Amp_MusicSetVolume(#DAMP_VOLUME)
  1523.  
  1524.          t$ =  RSet(StrU((\MusicLength/(1000*60*60))),2, "0")  +  ":"   +  ; HH:
  1525.                RSet(StrU((\MusicLength/(1000*60))%60),2, "0")  +  ":"   +  ; MM:
  1526.                RSet(StrU((\MusicLength/1000)%60),     2, "0")              ; SS
  1527.  
  1528.          If (\MusicLength%1000)  ; ,TTT -> Rest milliseconds?
  1529.             t$ +  ","   +  RTrim(StrU(\MusicLength%1000), "0")
  1530.          EndIf
  1531.  
  1532.          t$ =  "File:"     +  #TAB$ +  GetFilePart(\MusicFile$)+  #CR$  +  #CR$  +
  1533.                "Plugin:"   +  #TAB$ +  GetFilePart(\InDll$)    +  #CR$  +
  1534.                               #TAB$ +  \InInfo$                +  #CR$  +  #CR$  +
  1535.                ;"Plugout:" +  #TAB$ +  GetFilePart(\OutDll$)   +  #CR$  +
  1536.                ;              #TAB$ +  \OutInfo$               +  #CR$  +  #CR$  +
  1537.                "Time:"     +  #TAB$ +  t$
  1538.       Else
  1539.          t$ =  PeekS(Amp_GetErrorStr(\ErrorN))
  1540.       EndIf
  1541.  
  1542.       Amp_VersionStr(0)
  1543.  
  1544.       MA_MsgBox(\WindowID, t$, \Version$)
  1545.  
  1546.       RetVal   =  \ErrorN
  1547.  
  1548.       Amp_Free()
  1549.  
  1550.       ProcedureReturn   RetVal
  1551.  
  1552.    EndWith
  1553.  
  1554. EndProcedure
  1555. ProcedureCDLL  Amp_MusicBox(*File, iFlags.i)
  1556.  
  1557.    Protected   t$, RetVal
  1558.  
  1559.    If *File :  t$ =  PeekS(*File)   :  EndIf
  1560.  
  1561.    RetVal   =  AmpPlayer::AmpBox(t$, iFlags)
  1562.  
  1563.    ProcedureReturn   RetVal
  1564.  
  1565. EndProcedure
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
Top