[VC++ 2005 mit FMOD] Problem with FMOD_CHANNEL_CALLBACKTYPE_END

Baron Sengir

Mitglied
Hallo Ihr Lieben,

ich programmiere eine dialogfeldbasierende MFC-Apllikation in VC++ 2005. Mein Programm muss unter anderem auch MP3s abspielen können. Dies soll FMOD (http://www.fmod.org) für mich tun. Klappt auch fast alles wunderbar. Alles was mit MP3 zu tun hat, habe ich in eine eine eigene Klasse gepackt. Nun muss die Klasse am Ende eines Streams auf dessen Ende reagieren. Dafür ist laut Doku
Code:
Channel::setCallback()
mit
Code:
FMOD_CHANNEL_CALLBACKTYPE_END
vorgesehen. Leider kriege ich den richtigen Callbackaufruf nicht hin. Der Callback wird immer zu Beginn des Streams ausgelöst und nicht am Ende. Ich hoffe Ihr könnt mir da helfen...


Player.h:

Code:
#pragma once
#include "fmod.hpp"
#include "fmod.h"
#define WM_PLAYER_CALLBACK      WM_USER + 9427
class CPlayer
{
public:
   CPlayer(void);
   ~CPlayer(void);
   void Play(CString Datei);
[...]
private:
[…]
   FMOD::System *fmodSYSTEM;
   FMOD::Sound *fmodSOUND;
   FMOD::Channel *fmodCHANNEL;
   FMOD::DSP *fmodDSP;
   FMOD_RESULT F_CALLBACK endCallBackFunc(void);
};

Player.cpp:
Code:
#include "StdAfx.h"
#include ".\player.h"

CPlayer::CPlayer(void)
: used_driver(0)
, fmodSYSTEM(NULL)
, fmodSOUND(NULL)
, fmodCHANNEL(NULL)
, useNormalize(false)
, fmodDSP(NULL)
, m_playerID(0)
, m_ParentName(_T(""))
{
   useNormalize = true;
   used_driver = -1;
   FMOD::System_Create(&fmodSYSTEM);
   fmodSYSTEM->setDriver(used_driver);
   fmodSYSTEM->init(1, FMOD_INIT_NORMAL, NULL);
   fmodSYSTEM->createDSPByType(FMOD_DSP_TYPE_NORMALIZE, &fmodDSP);
   fmodSYSTEM->addDSP(fmodDSP);
   fmodDSP->setActive(true);
   setNormalize(useNormalize);
}

CPlayer::~CPlayer(void)
{
//   if (fmodSOUND) fmodSOUND->release();
   fmodSYSTEM->close();
   fmodSYSTEM->release();
}

void CPlayer::Play(CString Datei)
{
   bool result;
   fmodCHANNEL->getPaused(&result);
   if (result) fmodCHANNEL->setPaused(false); else
   {
      fmodSYSTEM->createStream(Datei, FMOD_SOFTWARE, 0, &fmodSOUND);
      fmodSYSTEM->playSound(FMOD_CHANNEL_FREE, fmodSOUND, 0, &fmodCHANNEL);
      fmodCHANNEL->setCallback(FMOD_CHANNEL_CALLBACKTYPE_END, 0, endCallBackFunc());
      fmodSYSTEM->update();
   }
}

[…]

FMOD_RESULT F_CALLBACK  CPlayer::endCallBackFunc(void)
{
   WPARAM wParam = m_playerID;
   LPARAM lParam = m_playerID;
 
   HWND hWnd = ::FindWindow(NULL, _T(m_ParentName));
   if (hWnd) PostMessage( hWnd, WM_PLAYER_CALLBACK, wParam , lParam);

   return FMOD_OK;
}

Ich habe mir mal erlaubt, oben die relevanten Teile zu posten.

Selbstverständlich habe ich die Doku mehrmals durchgelesen und auch schon im Netz geschaut. Nur leider habe ich nix gefunden, das mir weitergeholfen hat. Auch habe ich im offiziellen fmod-Forum schon einmal nachgefragt. Das Dumme ist nur, das da alles auf Englisch diskutiert wird und ich nicht wirklich topfit in Englisch bin. Und mit dem Hinweis, ich solle
Code:
CPlayer::endCallBackFunc(void)
zu einer statischen Funktion umdefinieren und dann im Aufruf
Code:
fmodCHANNEL->setCallback(FMOD_CHANNEL_CALLBACKTYPE_END, 0, endCallBackFunc());
die runden Klammern () hinter endCallBackFunc weglassen, bin ich nicht zurechtgekommen.

Ich hoffe, Ihr helft mir (mal wieder) auf die Sprünge. Vielen Dank vorweg

Markus
Markus
 
Hi.
Baron Sengir hat gesagt.:
Und mit dem Hinweis, ich solle
Code:
CPlayer::endCallBackFunc(void)
zu einer statischen Funktion umdefinieren und dann im Aufruf
Code:
fmodCHANNEL->setCallback(FMOD_CHANNEL_CALLBACKTYPE_END, 0, endCallBackFunc());
die runden Klammern () hinter endCallBackFunc weglassen, bin ich nicht zurechtgekommen.
Naja, wenn du da die runden Klammern stehen läßt, dann rufst du die Funktion ja bereits direkt auf! Du mußt nur die Adresse der (statischen) Funktion dort übergeben. Erhälst du denn keine Warnung von deinem Compiler an der Stelle?

Entweder du definierst die Funktion wirklich als statisch oder du könntest den mem_fun Funktionsadapter mit bind1st aus der Standardbibliothek verwenden:
C++:
#include <functional>
...
fmodCHANNEL->setCallback(FMOD_CHANNEL_CALLBACKTYPE_END, 0, bind1st(mem_fun(&CPlayer::endCallBackFunc), this));

/edit: Das mit dem mem_fun Adapter funktioniert natürlich nur, wenn die setCallback Methode auch Funktionsobjekte akzeptiert bzw. überladen wurde.

Gruß
 
Zuletzt bearbeitet:
Hi,

habe ich jetzt auch ohne Compilerfehler zum Laufen bekommen. Das Problem ist nur, dass sich das Verhalten des Callbacks gegenüber meiner Fassung nicht geändert hat.

Der Callback wird noch immer zu Beginn des Streams ausgelöst und nicht am Ende wie ich es eigentlich bräuchte.

Vielleicht noch 'ne Idee?

LG

Markus
 
Zurück