![]() |
Re: Dynamisches Array oder Klasse als Array auslegen
Hier fängt die geschichte an.
Delphi-Quellcode:
Ist OK !!
// Initialisiert das BASS_WADSP add-on
Function BASS_WADSP_Init(hwndMain: HWND): DWORD; stdcall; begin mainhwnd := hwndMain; Result:= mainhwnd; end; Plugins werden eingeladen
Delphi-Quellcode:
Ist OK !!
// Läd ein Winamp DSP Plugin und übergibt das handle
// Koordinaten und ein User Callback können übergeben werden function BASS_WADSP_Load(const dspfile: PChar; x, y, Width, Height: integer; proc: WINAMPWINPROC): HDSP; stdcall; var winampDsp: WINAMPPLUGINPROPDSP; cnt: integer; begin winampDsp := AllocMem(sizeof(WINAMPPLUGINPROPDSP)); FillChar(winampDsp, 0, sizeof(winampDsp)); Saved8087CW := Default8087CW; //FPU - Exceptions deaktivieren Set8087CW($133f); // Library laden // zuerst mit unicode versuchen winampDsp^.hDll := LoadLibraryW(PWideChar(dspfile)); if (not winampDsp^.hDll) <> 0 then begin // ansonsten Ansi winampDsp^.hDll := LoadLibrary(dspfile); end; // Exceptions zurück auf Defaultwert Set8087CW(Saved8087CW); Result := 0; if winampDsp^.hDll <> 0 then begin FreeMem(winampDsp); pGetMod := GetProcAddress(winampDsp^.hDll, 'winampDSPGetHeader2'); if pGetMod <> nil then begin // Fake Winamp Window erstellen if (Create_Winamp_Window(winampDsp, x, y, Width, Height, proc)) = True then begin cnt := 0; winampDsp^.pModule := pGetMod; if winampDsp^.pModule <> nil then begin // Schleife durchlaufen bis kein Modul mehr gefunden wurde repeat Inc(cnt); until winampDsp^.pModule^.getModule(cnt) = nil; // Anzahl der Module speichern winampDsp^.NumberOfModules := cnt; winampDsp^.module := -1; InitializeCriticalSection(winampDsp^.csh); // Addiere ein neues Winamp DSP Plugin AddDSP(winampDsp); // Übergebe das Handle Result := winampDsp^.handle end else // Bei Fehler Winamp Fake Window beenden Destroy_Winamp_Window(winampDsp); end else // Library freigeben FreeLibrary(winampDsp^.hDll); end end end; FakeWindow wird erstellt! Für jedes Plugin einzeln.
Delphi-Quellcode:
Ist OK!
// Erstellt ein Fake Winamp window
function Create_Winamp_Window(winampDsp: WINAMPPLUGINPROPDSP; x, y, width, height: integer; proc: WINAMPWINPROC): Boolean; stdcall; var wndclass: WNDCLASSEX; dspCount : DWORD; AppClass : Pchar; begin dspCount := GetActiveDSPs; if dspCount > 0 then begin AppClass := PChar(Format(Pchar('Winamp v1.x : %d'), [winampDSPcounter + 1])); end else AppClass := 'Winamp v1.x'; Inst := GetModuleHandle(nil); with wndclass do begin cbSize := sizeof(wndclass); style := CS_PARENTDC or CS_VREDRAW; cbClsExtra := 0; cbWndExtra := 0; hInstance := Inst; hIcon := 0; hCursor := LoadCursor(0, IDC_ARROW); hbrBackground := 0; lpszMenuName := nil; lpszClassName := AppClass; if proc = 0 then lpfnWndProc := @WinampWndProc else lpfnWndProc := @proc; hIconSm := 0; end; winampDsp^.DSP_Atom_Emu := RegisterClassEx(wndclass); if winampDsp^.DSP_Atom_Emu <> 0 then winampDsp^.DSP_Atom_Emu := CreateWindowEx(0, // DWORD dwExStyle AppClass, // LPCTSTR lpClassName 'Winamp 2.40', // LPCTSTR lpWindowName WS_POPUP, // DWORD dwStyle x, // int x y, // int y width, // int nWidth height, // int nHeight mainhwnd, // HWND hWndParent 0, // HMENU hMenu Inst, // // HINSTANCE hInstance nil); // LPVOID lpParam if winampDsp^.DSP_Window_Emu = 0 then begin UnRegisterClass(PChar(WORD(winampDsp^.DSP_Atom_Emu)), Inst); MessageBox(mainhwnd, 'Unable to emulate Winamp Window!', 'BASS DSP Error!', MB_ICONEXCLAMATION or MB_ICONWARNING); Result := false end else Result := true; end; Aus der Winproc wird die Funktion GetActiveDSPs aufgerufen welche den Counter hochzählt und abhängig davon den ClassenNamen ändert AppClass := PChar(Format(Pchar('Winamp v1.x : %d'), [winampDSPcounter + 1])); damit nicht zwei die gleichen Windows erstellt werden.
Delphi-Quellcode:
Das ist auch in Ornung!
function GetActiveDSPs(): DWORD; stdcall;
var a: DWORD; cnt: DWORD; winampDSP: WINAMPPLUGINPROPDSP; begin cnt := 0; if Winamp_DSP <> nil then for a := 0 to winampDSPcounter do begin winampDSP := Winamp_DSP[a]; if winampDSP <> nil then Inc(cnt); end; Result := cnt; end; Dann wir das gewählte Plugin addiert.
Delphi-Quellcode:
Scheint OK zu sein. Obwohl bisher noch nie in ReallocMem reingesprungen wurde.
Procedure AddDSP(winampDsp: WINAMPPLUGINPROPDSP); stdcall;
var a: DWORD; begin Winamp_DSP := DspPtrArray(winampDsp); for a := 0 to winampDSPcounter do if not Assigned(Winamp_DSP[a]) then Break; if a = winampDSPcounter then begin // Array nicht leer, füge ein neues hinzu ReallocMem(Winamp_DSP, (winampDSPcounter + 1) * SizeOf(WINAMPPLUGINPROPDSP)); Dec(winampDSPcounter); end; Inc(winampDSPhandle); winampDsp^.handle := winampDSPhandle; // addiere ein Winamp DSP Plugin zum Array Winamp_DSP[a] := winampDsp; end; Nun wird der Name des Moduls übergeben
Delphi-Quellcode:
ist auch OK!
// Returns the name of a loaded Winamp DSP plugin
function BASS_WADSP_GetName(plugin: HDSP): LPTSTR; stdcall; Var strRet: PChar; winampDSP: WINAMPPLUGINPROPDSP; begin strRet := nil; winampDsp := GetDSP(plugin); if winampDsp <> nil then begin strRet := winampDsp^.pModule^.description; end; Result := strRet; end; GetDSP übergibt den wert aus dem ArrayWinamp_DSP[a]
Delphi-Quellcode:
ist auch in Ordnung!
function GetDSP(handle: DWORD): WINAMPPLUGINPROPDSP;
var a: DWORD; begin if handle <> 0 then for a := 0 to Pred(winampDSPcounter) do begin Result := Winamp_DSP[a]; if Assigned(Result) and (Result^.handle = handle) then Exit; end; Result := nil; end; Dann wird das Plugin entladen und das nächste eingeladen falls vorhanden.
Delphi-Quellcode:
So bis hier ist alles OK!
// Entlade das übergebene Winamp DSP Plugin
Procedure BASS_WADSP_FreeDSP(plugin: HDSP); stdcall ; begin FreeDSP(plugin); end; gruß |
Re: Dynamisches Array oder Klasse als Array auslegen
Emil, ich bin sehr müde, aber das hier erkenne ich, wenn ich deinen Beitrag #50 sequentiell durchgehe:
Delphi-Quellcode:
Du erkennst den Unterschied? Dann wirst du auch ähnliche Stellen in deinem Code erkennen, falls noch weitere solche Fehler drin stecken.
function BASS_WADSP_Load(const dspfile: PChar; x, y, Width, Height: integer;
proc: WINAMPWINPROC): HDSP; stdcall; var winampDsp: WINAMPPLUGINPROPDSP; cnt: integer; begin // so holst du dir nur 4 Byte Speicher für einen Pointer: // winampDsp := AllocMem(sizeof(WINAMPPLUGINPROPDSP)); // Besser so: winampDsp := AllocMem(sizeof(WINAMPPLUGINPROPDSP^)); // So löschst du den Zeiger genauso effektiv, als ob du ihn auf NIL setzt: // FillChar(winampDsp, 0, sizeof(winampDsp)); // Besser so: FillChar(winampDsp^, 0, sizeof(winampDsp^)); // ... end; Grüße vom marabu |
Re: Dynamisches Array oder Klasse als Array auslegen
Zitat:
Werde es mir genau ansehen und vergleichen im Quelltext- Dann ein gutes Nächtele man schreibt sich. Gruß |
Re: Dynamisches Array oder Klasse als Array auslegen
Delphi-Quellcode:
Ich denke das Problem lokalisiert zu haben.
Werde es mir genau ansehen und vergleichen im Quelltext-
Dann ein gutes Nächtele man schreibt sich. Wie angenommen liegt es immer noch an AddDSP Der Lokale Zähler welcher die Plugins incrementiert? wird nicht hochgerechnet. Ist der grund das mir überall falsche werte angezeigt werden. Original
Code:
Dieser zähler winampDSPcounter++; wird nie angeprochen
void AddDSP(WINAMPPLUGINPROPDSP *winampDsp)
{ DWORD a; for (a=0;a<winampDSPcounter;a++) if (!winampDSP[a]) break; if (a==winampDSPcounter) { // no empty slot, so add a new one winampDSP = (WINAMPPLUGINPROPDSP**)realloc(winampDSP, (winampDSPcounter+1)*sizeof(WINAMPPLUGINPROPDSP*)); winampDSPcounter++; } winampDsp->handle = ++winampDSPhandle; // insert the new Winamp DSP winampDSP[a] = winampDsp; } Übersetzt
Delphi-Quellcode:
Im grunde geht es jetzt nur um diese eine Zeile.
Procedure AddDSP(winampDsp: WINAMPPLUGINPROPDSP); stdcall;
var a: DWORD; begin // Habe ich addiert weil bei 'if not Assigned(Winamp_DSP[a])' immer ein AV auftrat // Kann aber nicht stimmen da im C++ auch nicht enthalten. Winamp_DSP := DspPtrArray(winampDsp); for a := 0 to winampDSPcounter do // Wenn oben auskommentiert gibts hier einen AV if not Assigned(Winamp_DSP[a]) then Break; if a = winampDSPcounter then begin // Kein leerer Speicherbereich, einen neuen hinzufügen ReallocMem(Winamp_DSP, (winampDSPcounter + 1) * SizeOf(WINAMPPLUGINPROPDSP)); // Bin nicht sicher ob DEC oder INC da dies ein Postfix-Operator in c++ ist: // Denke aber da hier nur ein Wert steht, er hochzählen soll. // Wird der zähler nicht verwendet funktioniert der ganze Code nicht // In fast jeder Function wird dieser mit a verglichen. Inc(winampDSPcounter); end; Inc(winampDSPhandle); winampDsp^.handle := winampDSPhandle; // addiere ein Winamp DSP Plugin zum Array (im neuangelegten leeren Speicherbereich) Winamp_DSP[a] := winampDsp; end;
Code:
if (!winampDSP[a]) break;
Delphi-Quellcode:
Kann irgendwie nicht stimmen, weil so, wenn ich in Break hineinspringe, 'a' um eins hochgezählt wird.
if not Assigned(Winamp_DSP[a]) then
Break; 'a = winampDSPcounter' kann also niemals eintreten. a wird immer um einen zähler höher sein. Das Resultat ist das winampDSPcounter immer 0 ist. Dies hat wiederum zur folge das ich keine richtigen werte im Speicher finde da sie nicht an der richtigen position stehen und kein Speicherbereich dafür bereitgestellt wurde. Auch die FakeWindows welche von dem Zähler abhängig sind werden nicht korrekt erstellt.
Delphi-Quellcode:
Der KlassenName wird ja um den wert '%d' mit dem winampDSPcounter hochgezählt.
AppClass := PChar(Format(Pchar('Winamp v1.x : %d'), [winampDSPcounter + 1]));
Grüße Emil |
Re: Dynamisches Array oder Klasse als Array auslegen
Guten Morgen Emil,
du hast Recht - die Prozedur AddDSP() ist fehlerhaft. Zuerst musst du die Initailsierung von winampDSPcounter sicher stellen:
Delphi-Quellcode:
Dann müssen ein paar Änderungen an der Prozedur AddDSP() vorgenommen werden:
// unit BassWaDSP;
var winampDSPcounter : DWORD = 0;
Delphi-Quellcode:
Testen musst du.
Procedure AddDSP(winampDsp: WINAMPPLUGINPROPDSP); stdcall;
var a: DWORD; begin a := 0; // freien slot suchen while (a < winampDSPcounter) and Assigned(Winamp_DSP[a]) do Inc(a); if a = winampDSPcounter then // neuer slot wird gebraucht begin // array um ein Element vergrößern Inc(winampDSPcounter); ReallocMem(Winamp_DSP, winampDSPcounter * SizeOf(WINAMPPLUGINPROPDSP)); end; Inc(winampDSPhandle); winampDsp^.handle := winampDSPhandle; // plugin an freier Stelle einfügen Winamp_DSP^[a] := winampDsp; end; Grüße |
Re: Dynamisches Array oder Klasse als Array auslegen
Guten Morgen .. mara ? oder bu ;)
Zitat:
Delphi-Quellcode:
ReallocMem(Winamp_DSP, (winampDSPcounter + 1) * SizeOf(WINAMPPLUGINPROPDSP));
Inc(winampDSPcounter); Nebenbei zum lernen. War meine Annahme nicht richtig mit dem speicher? Freier Slot nicht freier Speicherbereich. Wird bei ReallocMem nicht der speicher verschoben damit das nächste Plugin dort eingebunden wird sondern nur das array um ein Element vergrößert. gruß |
Re: Dynamisches Array oder Klasse als Array auslegen
Hallo Emil,
ich hatte einen blöden Fehler in der Suchschleife. Ich habe ihn im Beitrag #55 korrigiert. Zu deiner Frage bezüglich ReallocMem(): Der Speicher wird auf seine neue Größe gebracht, der alte Inhalt wird automatisch beibehalten - zur Not per copy, falls kein inplace resizing möglich war. Der Zeiger muss call-by-reference sein, damit bei einer Verschiebung an eine andere Adresse der Zeiger aktualisiert werden kann. Der neue Speicherbereich wird nicht initialisiert. Grüße |
Re: Dynamisches Array oder Klasse als Array auslegen
Zitat:
Wenn der Quelltext schon nicht läuft möchte ich zumindest was bei der ganzen Geschichte hier lernen. Jetzt tritt ein neues Phänomen auf. Die Fake Windows werden nicht mehr initialisiert. Aber das löse ich selber! Mit dem was ich bisher von dir gelernt habe. An deiner neuen AddDSP liegt es aber nicht. :wink: Grüße |
Re: Dynamisches Array oder Klasse als Array auslegen
Hier nochmal das komplette archiv.
Change .. gruß |
Alle Zeitangaben in WEZ +1. Es ist jetzt 17:57 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz