/'==============================================================================
 Programmer Sound Example
 Copyright (c), Firelight Technologies Pty, Ltd 2006-2011.

 Demonstrates how to use the "programmer sound" feature of the FMOD event system
=============================================================================='/
#include "windows.bi"
#include "crt.bi"

#include "fmodex/fmod_event.bi"
#include "fmodex/fmod_errors.bi"

const as string MEDIA_PATH = "media\\"
const as string FSB_NAME   = "media\\tutorial_bank.fsb"

static shared as integer g_sound_index = 0
#define SOUND_INDEX_MAX 4
static shared as integer g_index_map(SOUND_INDEX_MAX-1)

dim shared as FMOD_SOUND  ptr fsb
dim shared as FMOD_SYSTEM ptr sys


sub ERRCHECK(byval result as FMOD_RESULT)
    if (result <> FMOD_OK) then
        printf(!"FMOD error! (%d) %s\n", result, FMOD_ErrorString(result))
        end -1
end if
end sub


sub initIndexMap(byval fsb as FMOD_SOUND ptr)
    dim as FMOD_RESULT result = any
    dim as integer numsubsounds = any, i = any

    /' Sounds aren't in a logical order in the FSB, so we need to iterate
       through and assign the appropriate filenames to the index map
     '/

    dim as FMOD_OPENSTATE openstate = any
    do
        FMOD_Sound_GetOpenState(fsb, @openstate, 0, 0, 0)
    loop while (openstate <> FMOD_OPENSTATE_READY)
result = FMOD_Sound_GetNumSubSounds(fsb, @numsubsounds)
	ERRCHECK(result)

    for i = 0 to SOUND_INDEX_MAX-1
        g_index_map(i) = -1
    next

    for i = 0 to numsubsounds-1
        dim as FMOD_SOUND ptr sound = any
        dim as zstring * 100 sname = any

result = FMOD_Sound_GetSubSound(fsb, i, @sound)
        ERRCHECK(result)

		do
			FMOD_Sound_GetOpenState(fsb, @openstate, 0, 0, 0)
		loop while (openstate <> FMOD_OPENSTATE_READY)

result = FMOD_Sound_GetName(sound, @sname, 100)
        ERRCHECK(result)
        if(strncmp(@sname, "sequence-one", 100) = 0) then
            g_index_map(0) = i
        ElseIf(strncmp(@sname, "sequence-two", 100) = 0) then
            g_index_map(1) = i
        ElseIf(strncmp(@sname, "sequence-three", 100) = 0) then
            g_index_map(2) = i
        ElseIf(strncmp(@sname, "sequence-four", 100) = 0) then
            g_index_map(3) = i
        end if
    next
end sub


function eventcallback(byval event as FMOD_EVENT ptr, byval eType as FMOD_EVENT_CALLBACKTYPE, byval param1 as any ptr, byval param2 as any ptr, byval userdata as any ptr) as FMOD_RESULT
    dim as FMOD_RESULT result = any

    select case  eType
        case FMOD_EVENT_CALLBACKTYPE_SOUNDDEF_CREATE :
            dim as zstring ptr sname      = param1               ' [in]  (char *) name of sound definition
            dim as integer entryindex  = *cast(integer ptr,param2)             ' [in]  (int) index of sound definition entry
            dim as FMOD_SOUND ptr ptr s = param2       ' [out] (FMOD::Sound *) a valid lower level API FMOD Sound handle
            dim as zstring * 128 sound_name = any

result = iif((g_index_map(g_sound_index) >= 0), FMOD_OK, FMOD_ERR_SUBSOUNDS)
            ERRCHECK(result)
            result = FMOD_Sound_GetSubSound(fsb, g_index_map(g_sound_index), s)
			if (result <> FMOD_OK) then
				printf(!"FMOD_EVENT_CALLBACKTYPE_SOUNDDEF_CREATE: %d: sound not ready, retry next frame\n", g_index_map(g_sound_index))
				return result
			end if
            result = FMOD_Sound_GetName(*s, @sound_name, 128)
			if (result <> FMOD_OK) then
				printf(!"FMOD_EVENT_CALLBACKTYPE_SOUNDDEF_CREATE: %d: sound not ready, retry next frame\n", g_index_map(g_sound_index))
				return result
			end if
            printf(!"FMOD_EVENT_CALLBACKTYPE_SOUNDDEF_CREATE '%s' (%d)\n", sound_name, g_index_map(g_sound_index))

        case FMOD_EVENT_CALLBACKTYPE_SOUNDDEF_RELEASE :
            dim as FMOD_SOUND ptr s = param2         ' [in]  (FMOD::Sound *) the FMOD sound handle that was previously created in FMOD_EVENT_CALLBACKTYPE_SOUNDDEF_CREATE
            dim as zstring * 128 sound_name = any

result = FMOD_Sound_GetName(s, @sound_name, 128)
            ERRCHECK(result)
            printf(!"FMOD_EVENT_CALLBACKTYPE_SOUNDDEF_RELEASE '%s'\n", sound_name)
        end select

    return FMOD_OK
end function


'program start
    dim as FMOD_RESULT        result = any
    dim as FMOD_EVENTSYSTEM  ptr eventsystem = any
    dim as FMOD_EVENTGROUP   ptr eventgroup = any
    dim as FMOD_EVENT        ptr event = any
    dim as string                key

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

result = FMOD_EventSystem_Create(@eventsystem)
    ERRCHECK(result)
result = FMOD_EventSystem_Init(eventsystem, 64, FMOD_INIT_NORMAL, 0, FMOD_EVENT_INIT_NORMAL)
    ERRCHECK(result)
result = FMOD_EventSystem_SetMediaPath(eventsystem, MEDIA_PATH)
    ERRCHECK(result)
result = FMOD_EventSystem_Load(eventsystem, "examples.fev", 0, 0)
    ERRCHECK(result)
result = FMOD_EventSystem_GetGroup(eventsystem, "examples/FeatureDemonstration/SequencingAndStitching", FMOD_EVENT_DEFAULT, @eventgroup)
    ERRCHECK(result)

result = FMOD_EventSystem_GetSystemObject(eventsystem, @sys)
    ERRCHECK(result)
result = FMOD_System_CreateStream(sys, FSB_NAME, FMOD_2D or FMOD_NONBLOCKING or FMOD_SOFTWARE, 0, @fsb)
    ERRCHECK(result)

    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)

    do
            key = inkey

            select case key
                case " " :
result = FMOD_EventGroup_GetEvent(eventgroup, "ProgrammerSounds", FMOD_EVENT_DEFAULT, @event)
                    ERRCHECK(result)
result = FMOD_Event_SetCallback(event, @eventcallback, 0)
                    ERRCHECK(result)
result = FMOD_Event_Start(event)
                    ERRCHECK(result)
                case ">", ".":
                    g_sound_index +=1
                    g_sound_index = iif((g_sound_index >= SOUND_INDEX_MAX), SOUND_INDEX_MAX - 1, g_sound_index)
                    printf(!"Sound index = %d\n", g_sound_index + 1)

                case "<", ",":
                    g_sound_index -= 1
                    g_sound_index = iif((g_sound_index < 0), 0, g_sound_index)
                    printf(!"Sound index = %d\n", g_sound_index + 1)

            end select

result = FMOD_EventSystem_Update(eventsystem)
        ERRCHECK(result)
        Sleep(10)

    loop while (key <> chr(27))

result = FMOD_EventSystem_Unload(eventsystem)
    ERRCHECK(result)
result = FMOD_Sound_Release(fsb)
    ERRCHECK(result)
result = FMOD_EventSystem_Release(eventsystem)
    ERRCHECK(result)
