FMOD_RESULT F_CALLBACK FMODSoundEvent::FMODEventCallback(FMOD_EVENT *event, FMOD_EVENT_CALLBACKTYPE type, void *param1, void *param2, void *userdata)
{
    if(type == FMOD_EVENT_CALLBACKTYPE_STOLEN || type == FMOD_EVENT_CALLBACKTYPE_EVENTFINISHED)
	{
		DVASSERT_MSG(Thread::IsMainThread(), DAVA::Format("FMOD Callback type %d", type).c_str());

        FMOD::Event * fEvent = (FMOD::Event *)event;
        FMODSoundEvent * sEvent = (FMODSoundEvent *)userdata;
        if(sEvent && fEvent)
		{
			FMOD_VERIFY(fEvent->setCallback(0, 0));
			sEvent->PerformCallback(fEvent);
		}
    }
    return FMOD_OK;
}
void FMODSoundEvent::Stop(bool force /* = false */)
{
    SoundSystem * soundSystem = SoundSystem::Instance();

	Vector<FMOD::Event *> instancesCopy(fmodEventInstances);
	int32 instancesCount = instancesCopy.size();
	for(int32 i = 0; i < instancesCount; ++i)
	{
        FMOD::Event * fEvent = instancesCopy[i];
		FMOD_VERIFY(fEvent->setCallback(0, 0));
        FMOD_VERIFY(fEvent->stop(force));

		PerformEvent(SoundEvent::EVENT_END);
		soundSystem->ReleaseOnUpdate(this);
	}
	fmodEventInstances.clear();
}
bool FMODSoundEvent::Trigger()
{
    SoundSystem * soundSystem = SoundSystem::Instance();
    FMOD::EventSystem * fmodEventSystem = soundSystem->fmodEventSystem;
    
    if(is3D)
    {
        FMOD::Event * fmodEventInfo = 0;
        FMOD_VERIFY(fmodEventSystem->getEvent(eventName.c_str(), FMOD_EVENT_INFOONLY, &fmodEventInfo));
        if(fmodEventInfo)
        {
            FMOD_VERIFY(fmodEventInfo->set3DAttributes((FMOD_VECTOR*)&position, 0, isDirectional ? (FMOD_VECTOR*)&direction : NULL));
            FMOD_VERIFY(fmodEventInfo->setVolume(volume));
            ApplyParamsToEvent(fmodEventInfo);
        }
    }
    
    FMOD::Event * fmodEvent = 0;
    FMOD_RESULT result = fmodEventSystem->getEvent(eventName.c_str(), FMOD_EVENT_DEFAULT, &fmodEvent);
    if(result == FMOD_OK)
    {
        ApplyParamsToEvent(fmodEvent);

		FMOD_VERIFY(fmodEvent->setVolume(volume));
		FMOD_RESULT startResult = fmodEvent->start();
		if(startResult == FMOD_OK)
		{
			FMOD_VERIFY(fmodEvent->setCallback(FMODEventCallback, this));
			fmodEventInstances.push_back(fmodEvent);
			Retain();
		}
		else if(startResult != FMOD_ERR_EVENT_FAILED) //'just fail' max playbacks behavior
		{
			Logger::Error("[FMODSoundEvent::Trigger()] Failed to start event by %d on eventID: %s", startResult, eventName.c_str());
		}
    }
    else if(result != FMOD_ERR_EVENT_FAILED) //'just fail' max playbacks behavior
    {
        Logger::Error("[FMODSoundEvent::Trigger()] Failed to retrieve event by %d on eventID: %s", result, eventName.c_str());
    }

    PerformEvent(EVENT_TRIGGERED);

    return fmodEvent != 0;
}
int main(int argc, char *argv[])
{
    FMOD_RESULT        result;
    FMOD::EventSystem *eventsystem;
    FMOD::EventGroup  *eventgroup;
    FMOD::Event       *event;
    int                key;

    printf("======================================================================\n");
    printf("Programmer Sound. Copyright (c) Firelight Technologies 2006-2014.\n");
    printf("======================================================================\n");

    ERRCHECK(result = FMOD::EventSystem_Create(&eventsystem));
    ERRCHECK(result = eventsystem->init(64, FMOD_INIT_NORMAL, 0, FMOD_EVENT_INIT_NORMAL));
    ERRCHECK(result = eventsystem->setMediaPath((char *)MEDIA_PATH));
    ERRCHECK(result = eventsystem->load("examples.fev", 0, 0));
    ERRCHECK(result = eventsystem->getGroup("examples/FeatureDemonstration/SequencingAndStitching", FMOD_EVENT_DEFAULT, &eventgroup));

    ERRCHECK(result = eventsystem->getSystemObject(&sys));
    ERRCHECK(result = sys->createStream(FSB_NAME, FMOD_2D | FMOD_NONBLOCKING | FMOD_SOFTWARE, 0, &fsb));

    initIndexMap(fsb);

    printf("======================================================================\n");
    printf("Press 'Space' to start the 'Programmer Sound' event\n");
    printf("Press '>'     to increase sound index\n");
    printf("Press '<'     to decrease sound index\n");
    printf("Press 'Esc'   to quit\n");
    printf("======================================================================\n");
    printf("Sound index = %d\n", g_sound_index + 1);

    key = 0;
    do
    {
        if (_kbhit())
        {
            key = _getch();

            switch(key)
            {
                case ' ' :
                    ERRCHECK(result = eventgroup->getEvent("ProgrammerSounds", FMOD_EVENT_DEFAULT, &event));
                    ERRCHECK(result = event->setCallback(eventcallback, 0));
                    ERRCHECK(result = event->start());
                    break;

                case '>' : case '.':
                    ++g_sound_index;
                    g_sound_index = (g_sound_index >= SOUND_INDEX_MAX) ? SOUND_INDEX_MAX - 1 : g_sound_index;
                    printf("Sound index = %d\n", g_sound_index + 1);
                    break;

                case '<' : case ',':
                    --g_sound_index;
                    g_sound_index = (g_sound_index < 0) ? 0 : g_sound_index;
                    printf("Sound index = %d\n", g_sound_index + 1);
                    break;
            }
        }

        ERRCHECK(result = eventsystem->update());
        Sleep(10);

    } while (key != 27);

    ERRCHECK(result = eventsystem->unload());
    ERRCHECK(result = fsb->release());
    ERRCHECK(result = eventsystem->release());
    return 0;
}