Page 1 of 2

Posted: Sat Feb 08, 2003 4:33 pm
by BackupUser
Restored from previous forum. Originally posted by GPI.

First of all: It's done, i can use Winamp Plugin! Almost. there is only a little Problem.

First of all: the code:

Code: Select all

;***;*** Winamp-Pluginuser
;***

Procedure setinfo():EndProcedure
Procedure dsp_isactive():EndProcedure
Procedure dsp_dosamples(pointer,numsamples,bps,nch,srate)
  ProcedureReturn numsamples
EndProcedure
Procedure SAVSAInit():EndProcedure
Procedure SAVSADeInit():EndProcedure
Procedure SAAddPCMData():EndProcedure
Procedure SAGetMode():EndProcedure
Procedure SAAdd():EndProcedure
Procedure VSAAddPCMData():EndProcedure
Procedure VSAGetMode():EndProcedure
Procedure VSAAdd():EndProcedure
Procedure VSASetInfo():EndProcedure

Structure out_module
  version.l             ;module version (OUT_VER)
  *description.s        ;description of module, with version string
  id.l                  ;module id. each input module gets its own. non-nullsoft modules should be >= 65536.
  hMainWindow.l         ;winamp's main window (filled in by winamp)
  hDllInstance.l        ;DLL instance handle (filled in by winamp)
  Config.l              ;void (*Config)(HWND hwndParent); // configuration dialog 
  About.l               ;void (*About)(HWND hwndParent);  // about dialog
  Init.l                ;void (*Init)();                  // called when loaded
  Quit.l                ;void (*Quit)();                  // called when unloaded
  Open.l                ; Int (*Open)(int samplerate, int numchannels, int bitspersamp, int bufferlenms, int prebufferms); 
                        ;  // returns >=0 on success, GetOutputTime()
  SetOutputTime.l       ;void (*SetOutputTime)(int time_in_ms);   // seeks to point in stream (in ms). Usually you signal yoru thread to seek, which seeks and calls outMod->Flush()..

;volume stuff
  SetVolume.l           ;void (*SetVolume)(int volume);           // from 0 to 255.. usually just call outMod->SetVolume
  SetPan.l              ;void (*SetPan)(int pan);                 // from -127 to 127.. usually just call outMod->SetPan

;in-window builtin vis stuff
  SAVSAInit.l           ;void (*SAVSAInit)(int maxlatency_in_ms, int srate);
                        ;  // call once in Play(). maxlatency_in_ms should be the value returned from outMod->Open()
                        ;  // call after opening audio device with max latency in ms And samplerate
  SAVSADeInit.l         ;void (*SAVSADeInit)();                   // call in Stop()

;simple vis supplying mode
  SAAddPCMData.l        ;void (*SAAddPCMData)(void *PCMData, int nch, int bps, int timestamp); 
                        ;  // sets the spec Data directly from PCM Data
                        ;  // quick And easy way To get vis working :)
                        ;  // needs at least 576 samples :)
;advanced vis supplying mode, only use If you're cool. Use SAAddPCMData for most stuff.
  SAGetMode.l           ; Int (*SAGetMode)();                     // gets csa (the current type (4=ws,2=osc,1=spec))
                        ;  // use when calling SAAdd()
  SAAdd.l               ;void (*SAAdd)(void *data, int timestamp, int csa);
                        ;  // sets the spec data, filled in by winamp
;vis stuff (plug-in) 
;  simple vis supplying mode
  VSAAddPCMData.l       ;void (*VSAAddPCMData)(void *PCMData, int nch, int bps, int timestamp)
                        ;  // sets the vis data directly from PCM data
                        ;  // quick And easy way To get vis working :)
                        ;  // needs at least 576 samples :)
;  advanced vis supplying mode, only use If you're cool. Use VSAAddPCMData for most stuff.
  VSAGetMode.l          ;Int (*VSAGetMode)(int *specNch, int *waveNch)
                        ;  // use to figure out what to give to VSAAdd
  VSAAdd.l              ;void (*VSAAdd)(void *data, int timestamp);// filled in by winamp, called by plug-in

;call this in Play() To tell the vis plug-ins the current output params. 
  VSASetInfo.l          ;void (*VSASetInfo)(int nch, int srate);

;dsp plug-in processing: 
;(filled in by winamp, called by input plug)
;returns 1 If active (which means that the number of samples returned by dsp_dosamples
;could be greater than went in.. Use it To estimate If you'll have enough room in the
;output buffer
  dsp_isactive.l        ;Int (*dsp_isactive)(); 

;returns number of samples To output. This can be as much as twice numsamples. 
;be sure To allocate enough buffer For samples, then.
  dsp_dosamples.l       ;Int (*dsp_dosamples)(short int *samples, int numsamples, int bps, int nch, int srate);

;eq stuff
   EQSet.l              ;void (*EQSet)(int on, char data[10], int preamp); // 0-64 each, 31 is +0, 0 is +12, 63 is -12. Do nothing to ignore.

;info setting (filled in by winamp)
   SetInfo.l            ;void (*SetInfo)(int bitrate, int srate, int stereo, int synched); // if -1, changes ignored? :)

   outMod.l             ;Out_Module *outMod; // filled in by winamp, optionally used :)
EndStructure

Global *out_head.out_module
Global *in_head.in_module

Procedure quit_winamp()
  If *in_head
    CallFunctionFast(*in_head\quit)
    CloseLibrary(100)
    *in_head=0
  EndIf
  If *out_head
    CallFunctionFast(*out_head\quit)
    CloseLibrary(101)
    *out_head=0
  EndIf
EndProcedure

Procedure Init_Winamp(in_dll$,out_dll$,windowid)
  ;return 
  ;  0    no error.
  ;  -1   out_dll is no winamp-dll
  ;  -2   can't open out_dll
  ;  -3   in_dll is no winamp-dll
  ;  -4   can't open in_dll
  Debug in_dll$
  If *out_head0 Or *in_head0 
    quit_winamp()
  EndIf
  out_DLLinstance=OpenLibrary(101, out_dll$)
  If out_DLLinstance
    *out_head=CallFunction(101,"winampGetOutModule")
    If *out_head
      *out_head\hMainWindow=WindowID()
      *out_head\hDllInstance=out_DLLinstance
          
      CallFunctionFast(*out_head\Init)
    Else
      CloseLibrary(101)
      *out_head=0:*in_head=0
      ProcedureReturn -1
    EndIf
  Else
    *out_head=0:*in_head=0
    ProcedureReturn -2
  EndIf 
  Debug in_dll$
  in_DLLinstance= OpenLibrary(100, in_dll$)
  Debug in_dllinstance
  If in_DLLinstance
    *in_head = CallFunction(100, "winampGetInModule2" ) 
    If *in_head
      *in_head\hMainWindow=WindowID
      *in_head\hDllInstance=in_DLLinstance
      *in_head\outMod=*out_head
      CallFunctionFast(*in_head\Init)

      ;dummy-routines          
      *in_head\SetInfo=@setinfo()
      *in_head\dsp_isactive =@dsp_isactive()
      *in_head\dsp_dosamples=@dsp_dosamples();----
      *in_head\SAVSAInit    =@SAVSAInit()
      *in_head\SAVSADeInit  =@SAVSADeInit()  ;----
      *in_head\SAAddPCMData =@SAAddPCMData()
      *in_head\SAGetMode    =@SAGetMode()    ;----
      *in_head\SAAdd        =@SAAdd()        ;----
      *in_head\VSASetInfo   =@VSASetInfo()      
      *in_head\VSAAddPCMData=@VSAAddPCMData()
      *in_head\VSAGetMode   =@VSAGetMode()   ;----
      *in_head\VSAAdd       =@VSAAdd()       ;----
    Else
      CallFunctionFast(*out_head\quit)
      CloseLibrary(101)
      CloseLibrary(100)
      *out_head=0:*in_head=0
      ProcedureReturn -3
    EndIf
  Else
    CallFunctionFast(*out_head\quit)
    CloseLibrary(101)
    *out_head=0:*in_head=0
    ProcedureReturn -4
  EndIf
  ProcedureReturn 0
EndProcedure
Procedure winamp_play(playfile$)
  Debug CallFunctionFast(*in_head\play,@playfile$)
Endprocedure

;Small Winamp-Demo

in_dll$="in_psf"
out_dll$="out_ds"
playfile$="dark.psf"


If OpenWindow(0, 0,0,100,100,#PB_Window_ScreenCentered ,"Winamp-Plugin-Test")
  
  ret=init_winamp("in_psf","out_ds",WindowID())
  If ret=0
      ;***********************************************************************************
      ;this line will crash (but it play!):   
      ret= winamp_play(playfile$)
      ;but this line function!
      ret=CallFunctionFast(*in_head\play,@playfile$)
      ;***********************************************************************************
   
      titel$=Space(1000):title_len.l=0
      CallFunctionFast(*in_head\GetFileInfo,@playfile$,@titel$,@title_len)
      Debug playfile$+" "+titel$+" "+Str(title_len)
      If ret=0
        MessageRequester("Winamp-Plugin-Test", playfile$+Chr(16)+"Ok to stop", Flags)
        CallFunctionFast(*in_head\stop)
      Else
        MessageRequester("Winamp-Plugin-Test", "Can't play:"+Str(ret), Flags)
      EndIf
  Else
    Debug ret
  EndIf
EndIf

quit_winamp()
The programm start and play the sound correctly, but then it crash (at the endprocedure - command).
When i don't use the procedure winamp_play() and insert the code direct, it will work without any problem.
also:
CallFunctionFast(*in_head\stop)
have no problems.
I think the callfunction doesn't work right, when a parameter is given to the callfunctionfast-command). I think, that the "Stack" does have the parameter in it (or somebody had read to many informations out of the stack, so the endprocedure-command can't read the right return-adress and the programm will crash.
Maybe it can be correct with assembler-commands, but i don't know any command...

Who can help?

PII 333, 256MB, Asus TNT2Ultra 32MB, AWE Gold 64 4MB

Posted: Sat Feb 08, 2003 4:55 pm
by BackupUser
Restored from previous forum. Originally posted by freak.

I think, your Plugin DLL is CDECL, not an STDCALL one.

After CallFunctionFast(), do the following:

!ADD esp,12

Where 12 is the Number of Bytes your Call has put on the Stack (for each Long Value -> 4 Bytes, so if you Call has 3 Args, it is 12, if it is 1 Arg, the Value is 4 and so on...)


This should solve the problem...

Timo

Posted: Sat Feb 08, 2003 10:15 pm
by BackupUser
Restored from previous forum. Originally posted by GPI.

Hi freak.

IT WORKS!

Thanks.

PII 333, 256MB, Asus TNT2Ultra 32MB, AWE Gold 64 4MB

Posted: Sat Feb 08, 2003 10:45 pm
by BackupUser
Restored from previous forum. Originally posted by MrVainSCL.

Mhhhhh..
can someone explain please what and where is the different of such CDECL and STDCALL called DLLs and how to check what kind it is? Thx!

greetz
MrVainSCL! aka Thorsten

PIII450, 256MB Ram, 80GB HD + 6,4 GB, RivaTNT, DirectX9.0, SB AWE64, Win2000 + all Updates...

Posted: Sat Feb 08, 2003 10:55 pm
by BackupUser
Restored from previous forum. Originally posted by Jon.

Hi GPI, any chance you can post the finished code with links to any required dll's etc, I'd love to play around with this (Now that you've done all the hard work :) )

Cheers, Jon.

Posted: Sat Feb 08, 2003 11:19 pm
by BackupUser
Restored from previous forum. Originally posted by freak.

@MrVain

If you read the forums in the last few weeks, you should know this.

STDCALL/CDECL specify the way, a DLL's procedures are called.
The main difference is, that in STDCALL, the Procedure has to clear the Stack, and in CDECL, the calling Program has to do so.

That is why it works with the !ADD esp,12 Stuff. It removes the Arguments from the Stack, that's all.

CDECL comes from C, where STDCALL is the standart one, so most DLLs are STDCALL.

How to check? I don't know, just try the usual way, if it crashes, it may be CDECL.

That's all I know... all read here in the forums...

Timo

Posted: Sat Feb 08, 2003 11:21 pm
by BackupUser
Restored from previous forum. Originally posted by MrVainSCL.

@freak,
thx for info... i dont have ever such time to read/check all posting... i am very busy since some time! Anyway for explaining it :wink:

greetz
MrVainSCL! aka Thorsten

PIII450, 256MB Ram, 80GB HD + 6,4 GB, RivaTNT, DirectX9.0, SB AWE64, Win2000 + all Updates...

Posted: Sun Feb 09, 2003 5:42 pm
by BackupUser
Restored from previous forum. Originally posted by ricardo.
Originally posted by GPI

First of all: It's done, i can use Winamp Plugin! Almost. there is only a little Problem.
Hi, Congratullations!!!

One question:

Its possible to use an other in/out plugins? What do i need to change to your code?



Best Regards

Ricardo

Dont cry for me Argentina...

Posted: Sun Feb 09, 2003 5:57 pm
by BackupUser
Restored from previous forum. Originally posted by GPI.

Monday i write a pbi for all winamp-calls and yes, you can use all in/out-plugins.

(Today i modified the Editor)

PII 333, 256MB, Asus TNT2Ultra 32MB, AWE Gold 64 4MB

Posted: Sun Feb 09, 2003 6:59 pm
by BackupUser
Restored from previous forum. Originally posted by ricardo.
Originally posted by GPI

Monday i write a pbi for all winamp-calls and yes, you can use all in/out-plugins.

(Today i modified the Editor)

PII 333, 256MB, Asus TNT2Ultra 32MB, AWE Gold 64 4MB
Hi,

I try to play an mp3 using in_mp3 and out_wave plugins and marking as comment this line:

;this line will crash (but it play!):
;ret= winamp_play(playfile$)

then i get 0 as ret in this line

ret=CallFunctionFast(*in_head\play,@playfile$)

if i ask the return here i dont get 0

debug CallFunctionFast(*in_head\GetFileInfo,@playfile$,@titel$,@title_len)


however i get the msgbox telling me to press ok to stop but i cant hear nothing.

I put the plugins in both places:

in_dll$="in_mp3"
out_dll$="out_wave"
playfile$="Neil.mp3"

AND

ret=init_winamp("in_mp3","out_wave",WindowID())

What im doing wrong?



Best Regards

Ricardo

Dont cry for me Argentina...

Posted: Sun Feb 09, 2003 7:54 pm
by BackupUser
Restored from previous forum. Originally posted by GPI.

Hi ricardo,

BIG WARNING, without the Stack-correction (!ADD esp,12) the programm will crash (at a later moment) and you don't know why.

I write tomorrow the pbi.

btw:
the return-value of winamp_init()
;return
; 0 no error.
; -1 out_dll is no winamp-dll
; -2 can't open out_dll
; -3 in_dll is no winamp-dll
; -4 can't open in_dll


PII 333, 256MB, Asus TNT2Ultra 32MB, AWE Gold 64 4MB

Posted: Mon Feb 10, 2003 7:40 pm
by BackupUser
Restored from previous forum. Originally posted by ricardo.

@GPI:

I try again and now its working here : )
I add set the volume to 255 and now its playing!

Didnt you think on adding DSP plugins? Could be cool.
Im interested on this matter if you want contact me because i dont want to flood this forums with many posts about this matter, but its quite interesting.

Calling dll from inside the main procedure dont give any errors, i found this in another project of mine, just calling from procedures fails.

With this test im able to call any in or out plugins, just must be in the same folder of the code or executable.

Code: Select all

If OpenWindow(0,100,150,450,200,#PB_Window_SystemMenu,"Winamp Plugins Test")
  
  CreateGadgetList(WindowID())
  StringGadget(0,10,10,150,20,"in_mad")
  StringGadget(1,250,10,150,20,"out_wave")
  ButtonGadget(2,160,10,50,20,"InPlug")
  ButtonGadget(3,400,10,50,20,"OutPlug")
  ButtonGadget(4,200,40,50,25,"Play")
  ButtonGadget(5,200,70,50,25,"Stop")
  ButtonGadget(6,190,100,70,25,"In Config")
  ButtonGadget(7,190,130,70,25,"Out Config")
  Repeat
    EventID=WaitWindowEvent()
    
    Select EventID
    
      Case #PB_EventGadget
        Select EventGadgetID()
          Case 2
          FileName$ = GetFilePart(OpenFileRequester("Select IN PlugIn", "", "*.dll", 0))
            If FindString(FileName$,"in_",0)   0
              SetGadgetText(0,ReplaceString(FileName$,".dll",""))
              ret=init_winamp(GetGadgetText(0),GetGadgetText(1),WindowID())
            Else
              MessageRequester("Error",FileName$ + " is not an IN plugin",0)
            EndIf
          Case 3
          FileName$ = GetFilePart(OpenFileRequester("Select OUT PlugIn", "", "*.dll", 0))
            If FindString(FileName$,"out_",0)   0
              SetGadgetText(1,ReplaceString(FileName$,".dll",""))
              ret=init_winamp(GetGadgetText(0),GetGadgetText(1),WindowID())
            Else
              MessageRequester("Error",FileName$ + " is not an OUT plugin",0)
            EndIf
          Case 4

              ret=init_winamp(GetGadgetText(0),GetGadgetText(1),WindowID())

              If ret = 0
                ret=CallFunctionFast(*in_head\play,@playfile$)
                CallFunctionFast(*Out_head\SetVolume,255)
              EndIf

          Case 5
            CallFunctionFast(*in_head\stop)
          Case 6
            ret=init_winamp(GetGadgetText(0),GetGadgetText(1),WindowID())

            CallFunctionFast(*In_head\Config,WindowID())
          Case 7
            ret=init_winamp(GetGadgetText(0),GetGadgetText(1),WindowID())

            CallFunctionFast(*Out_head\Config,WindowID())
          
        EndSelect
    
    EndSelect
    
  Until EventID=#PB_EventCloseWindow
EndIf
quit_winamp()
End
Best Regards

Ricardo

Dont cry for me Argentina...

Posted: Wed Feb 12, 2003 12:51 pm
by BackupUser
Restored from previous forum. Originally posted by GPI.

@ricardo
you don't must init the winamp bevor every moment.

Of course it is no problem to use dll in subroutines and procedures, but i call with "CallFunctionFast" a c-procedure and this c-procedure will change the stack. It must corrected or the program can Crash at a later moment and then you don't know why.

I have now finaly complete the winamp-plugin-user
viewtopic.php?t=5104

>DSP plugins?

No i don't want to use it. I don't want to write a alternate for Winamp.


PII 333, 256MB, Asus TNT2Ultra 32MB, AWE Gold 64 4MB

Posted: Wed Feb 12, 2003 3:28 pm
by BackupUser
Restored from previous forum. Originally posted by ricardo.
>DSP plugins?

No i don't want to use it. I don't want to write a alternate for Winamp.
But using DSP is not making another winamp... is just having the possibilitie to add many sound effects in realtime!!

Best Regards

Ricardo

Dont cry for me Argentina...

Posted: Wed Feb 12, 2003 4:21 pm
by BackupUser
Restored from previous forum. Originally posted by GPI.

a moment please, dsp stands not for DiSPlay?.

Ok i check this...

PII 333, 256MB, Asus TNT2Ultra 32MB, AWE Gold 64 4MB