Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi [BASS DLL] Callbackfunktion darf kein Methodenzeiger sein? (https://www.delphipraxis.net/142008-%5Bbass-dll%5D-callbackfunktion-darf-kein-methodenzeiger-sein.html)

Mithrandir 20. Okt 2009 16:44


[BASS DLL] Callbackfunktion darf kein Methodenzeiger sein?
 
Hi ihr,

ich habe gerade folgendes Problem, an dem ich nicht weiter komme: Ich möchte mit der BASS.DLL innerhalb einer Klasse einen Internetstream wiedergeben. Über die ChannelSetSync-Funktion der BASS.DLL möchte ich bei neuen Meta-Daten die Anzeige aktualisieren lassen. Dafür brauche ich einen Callback-Funktion. Die Deklaration dieser Funktion habe ich aus dem Delphi-Beispiel entnommen, das bei der BASS-Lib mitgeliefert wird.

Die Funktion InternetStreamMeta hat als Aufrufkonvention "stdcall;" bekommen, so wie es das Beispiel auch macht. Hier mein Code:

Internet-Stream abspielen
Delphi-Quellcode:
procedure TMediaClass.RunInternetStream(StreamURL: String);
begin
  if StreamURL <> '' then
  begin
    if fCurrentStream <> 0 then
      BASS_StreamFree(fCurrentStream);
    fCurrentStream := BASS_StreamCreateURL(PChar(StreamURL), 0, BASS_STREAM_BLOCK or BASS_STREAM_AUTOFREE, nil, nil);
    BASS_ChannelSetSync(fCurrentStream, BASS_SYNC_META, 0, @TMediaClass.InternetStreamMeta, nil);
    Play;
  end;

end;
Callback-Funktion für Metadaten
Delphi-Quellcode:
procedure TMediaClass.DoMeta;
var
  p: Integer;
  meta: PChar;
begin
  meta := BASS_ChannelGetTags(fCurrentStream, BASS_TAG_META);
  if (meta <> nil) then
  begin
    p := Pos('StreamTitle=', meta);
    if (p = 0) then
      Exit;
    p := p + 13;
    fCurrentMediaItem.Title := String(Pchar(Copy(meta, p, Pos(';', meta) - p - 1)));
  end;
end;

procedure TMediaClass.InternetStreamMeta(handle: HSYNC; channel, data, user: DWORD); stdcall;
begin
  DoMeta;
end;
Kommt es nun zum Wechsel der MetaDaten, erscheint folgende, für mich überaus hilfreiche Meldung:

Zitat:

---------------------------
Benachrichtigung über Debugger-Problem
---------------------------
In Projekt C:\Users\Daniel\Documents\Borland Studio-Projekte\SmallTune\bin\smalltune.exe trat ein Problem mit folgender Meldung auf: 'access violation at 0x0040e466: read of address 0xd0000012'. Prozess angehalten. Mit Einzelne Anweisung oder Start fortsetzen.
---------------------------
OK
---------------------------
Danach hängt das Programm in dieser Zeile fest:

Delphi-Quellcode:
meta := BASS_ChannelGetTags(fCurrentStream, BASS_TAG_META);
Springe ich mit F8 weiter, lande ich wieder an dieser Stelle.

Hat jemand Erfahrung damit, oder sieht, was ich hier falsch mache?

mirage228 20. Okt 2009 16:50

Re: [BASS DLL] Callbackfunktion darf kein Methodenzeiger sei
 
Ein Methodenzeiger hat den versteckten "Self"-Parameter, eine reguläre Prozedur ja nicht. Da wird das Problem wohl liegen... versuche ggf. eine Klassenmethode...

Apollonius 20. Okt 2009 16:58

Re: [BASS DLL] Callbackfunktion darf kein Methodenzeiger sei
 
Dieser User-Parameter sieht verdächtig danach aus, als könne er im Aufruf von BASS_ChannelSetSync angegeben werden. Zeig doch bitte mal die Deklaration dieser Funktion.

Mithrandir 20. Okt 2009 17:01

Re: [BASS DLL] Callbackfunktion darf kein Methodenzeiger sei
 
Hmm... Aber wie setze ich dann die Variable fCurrentMediaItem.Title ? Weil, darauf zugreifen kann ich dann ja nicht mehr, und dann könnte ich auch ne "normale" Prozedur nutzen... :gruebel:

@Appolonius:

Meintest du mit "diese" die SetSync-Funktion?

Delphi-Quellcode:
var BASS_ChannelSetSync:function(handle: DWORD; type_: DWORD; param: QWORD; proc: SYNCPROC; user: Pointer): HSYNC; stdcall;

himitsu 20. Okt 2009 17:06

Re: [BASS DLL] Callbackfunktion darf kein Methodenzeiger sei
 
wie schon gesagt, der CallBack ist eine Prozedur und keine Methode!

du könntest den User-Parameter dafür benutzen, um die Klassenreferenz zu übergeben ... für sowas ist dieser schließlich da :zwinker:

etwa so:
Delphi-Quellcode:
BASS_ChannelSetSync(fCurrentStream, BASS_SYNC_META, 0, InternetStreamMeta, Pointer(Self));


procedure InternetStreamMeta(handle: HSYNC; channel, data, user: DWORD); stdcall;
begin
  TMediaClass(user).DoMeta;
end;

[edit]
@Apollonius: nöö, meine :tongue:

Apollonius 20. Okt 2009 17:07

Re: [BASS DLL] Callbackfunktion darf kein Methodenzeiger sei
 
Nein, ich meinte BASS_ChannelSetSync. Mittlerweile hat sich mein Verdacht aber bestätigt. Du kannst im letzten Parameter von BASS_ChannelSetSync nämlich Pointer(Self) angeben. Das landet dann im User-Parameter deiner Callback-Routine, sodass du dort zurück nach TMediaClass casten kannst und dein Self erhältst.

Himitsu, das war meiner! :mrgreen:

Mithrandir 20. Okt 2009 17:10

Re: [BASS DLL] Callbackfunktion darf kein Methodenzeiger sei
 
Zitat:

Zitat von Daniel G
Meintest du mit "diese" die SetSync-Funktion?
Delphi-Quellcode:
var BASS_ChannelSetSync:function(handle: DWORD; type_: DWORD; param: QWORD; proc: SYNCPROC; user: Pointer): HSYNC; stdcall;

Zitat:

Zitat von Apollonius
Nein, ich meinte BASS_ChannelSetSync.

:mrgreen:

Das ich da nicht von selbst drauf gekommen bin. Und ich Depp hab mich noch gefragt, wann man diesen User-Parameter wohl brauchen könnte. Argh... :wall:

Danke euch. ;)

Apollonius 20. Okt 2009 17:20

Re: [BASS DLL] Callbackfunktion darf kein Methodenzeiger sei
 
Wer lesen kann, ist klar im Vorteil. 8) Dass du das auch dynamisch linken musst...


Alle Zeitangaben in WEZ +1. Es ist jetzt 10:10 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