AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Programmieren allgemein Dynamisches Array oder Klasse als Array auslegen
Thema durchsuchen
Ansicht
Themen-Optionen

Dynamisches Array oder Klasse als Array auslegen

Ein Thema von EWeiss · begonnen am 22. Sep 2006 · letzter Beitrag vom 30. Sep 2006
Antwort Antwort
Seite 6 von 6   « Erste     456   
EWeiss
(Gast)

n/a Beiträge
 
#51

Re: Dynamisches Array oder Klasse als Array auslegen

  Alt 27. Sep 2006, 09:00
Hier fängt die geschichte an.

Delphi-Quellcode:
// Initialisiert das BASS_WADSP add-on
Function BASS_WADSP_Init(hwndMain: HWND): DWORD; stdcall;

begin
   mainhwnd := hwndMain;

  Result:= mainhwnd;
end;
Ist OK !!

Plugins werden eingeladen

Delphi-Quellcode:
 // 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;
Ist OK !!

FakeWindow wird erstellt! Für jedes Plugin einzeln.
Delphi-Quellcode:
// 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;
Ist OK!

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:
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;
Das ist auch in Ornung!


Dann wir das gewählte Plugin addiert.

Delphi-Quellcode:
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;
Scheint OK zu sein. Obwohl bisher noch nie in ReallocMem reingesprungen wurde.

Nun wird der Name des Moduls übergeben

Delphi-Quellcode:
// 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;
ist auch OK!

GetDSP übergibt den wert aus dem ArrayWinamp_DSP[a]

Delphi-Quellcode:
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;
ist auch in Ordnung!

Dann wird das Plugin entladen und das nächste eingeladen falls vorhanden.

Delphi-Quellcode:
// Entlade das übergebene Winamp DSP Plugin
Procedure BASS_WADSP_FreeDSP(plugin: HDSP); stdcall ;
begin
   FreeDSP(plugin);
end;
So bis hier ist alles OK!

gruß
  Mit Zitat antworten Zitat
marabu

Registriert seit: 6. Apr 2005
10.109 Beiträge
 
#52

Re: Dynamisches Array oder Klasse als Array auslegen

  Alt 27. Sep 2006, 20:51
Emil, ich bin sehr müde, aber das hier erkenne ich, wenn ich deinen Beitrag #50 sequentiell durchgehe:

Delphi-Quellcode:
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;
Du erkennst den Unterschied? Dann wirst du auch ähnliche Stellen in deinem Code erkennen, falls noch weitere solche Fehler drin stecken.

Grüße vom marabu
  Mit Zitat antworten Zitat
EWeiss
(Gast)

n/a Beiträge
 
#53

Re: Dynamisches Array oder Klasse als Array auslegen

  Alt 27. Sep 2006, 21:23
Zitat von marabu:
Emil, ich bin sehr müde, aber das hier erkenne ich, wenn ich deinen Beitrag #50 sequentiell durchgehe:

Delphi-Quellcode:
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;
Du erkennst den Unterschied? Dann wirst du auch ähnliche Stellen in deinem Code erkennen, falls noch weitere solche Fehler drin stecken.

Grüße vom marabu
Danke..
Werde es mir genau ansehen und vergleichen im Quelltext-
Dann ein gutes Nächtele man schreibt sich.

Gruß
  Mit Zitat antworten Zitat
EWeiss
(Gast)

n/a Beiträge
 
#54

Re: Dynamisches Array oder Klasse als Array auslegen

  Alt 28. Sep 2006, 01:34
Delphi-Quellcode:
Werde es mir genau ansehen und vergleichen im Quelltext-
Dann ein gutes Nächtele man schreibt sich.
Ich denke das Problem lokalisiert zu haben.
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:
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;
}
Dieser zähler winampDSPcounter++; wird nie angeprochen

Übersetzt

Delphi-Quellcode:
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;
Im grunde geht es jetzt nur um diese eine Zeile.

Code:
if (!winampDSP[a]) break;
Delphi-Quellcode:
    if not Assigned(Winamp_DSP[a]) then
      Break;
Kann irgendwie nicht stimmen, weil so, wenn ich in Break hineinspringe, 'a' um eins hochgezählt wird.
'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.

AppClass := PChar(Format(Pchar('Winamp v1.x : %d'), [winampDSPcounter + 1])); Der KlassenName wird ja um den wert '%d' mit dem winampDSPcounter hochgezählt.

Grüße Emil
  Mit Zitat antworten Zitat
marabu

Registriert seit: 6. Apr 2005
10.109 Beiträge
 
#55

Re: Dynamisches Array oder Klasse als Array auslegen

  Alt 28. Sep 2006, 07:29
Guten Morgen Emil,

du hast Recht - die Prozedur AddDSP() ist fehlerhaft. Zuerst musst du die Initailsierung von winampDSPcounter sicher stellen:

Delphi-Quellcode:
// unit BassWaDSP;
var
  winampDSPcounter : DWORD   = 0;
Dann müssen ein paar Änderungen an der Prozedur AddDSP() vorgenommen werden:

Delphi-Quellcode:
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;
Testen musst du.

Grüße
  Mit Zitat antworten Zitat
EWeiss
(Gast)

n/a Beiträge
 
#56

Re: Dynamisches Array oder Klasse als Array auslegen

  Alt 28. Sep 2006, 07:55
Guten Morgen .. mara ? oder bu

Zitat:
du hast Recht - die Prozedur AddDSP() ist fehlerhaft. Zuerst musst du die Initailsierung von winampDSPcounter sicher stellen:
Springt nur einmal in

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ß
  Mit Zitat antworten Zitat
marabu

Registriert seit: 6. Apr 2005
10.109 Beiträge
 
#57

Re: Dynamisches Array oder Klasse als Array auslegen

  Alt 28. Sep 2006, 08:08
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
  Mit Zitat antworten Zitat
EWeiss
(Gast)

n/a Beiträge
 
#58

Re: Dynamisches Array oder Klasse als Array auslegen

  Alt 28. Sep 2006, 08:26
Zitat von marabu:
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
Danke!
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.

Grüße
  Mit Zitat antworten Zitat
EWeiss
(Gast)

n/a Beiträge
 
#59

Re: Dynamisches Array oder Klasse als Array auslegen

  Alt 30. Sep 2006, 15:43
Hier nochmal das komplette archiv.
Change ..
gruß
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 6 von 6   « Erste     456   


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 14:16 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz