/'===============================================================================================
 Load From Memory Example
 Copyright (c), Firelight Technologies Pty, Ltd 2004-2011.

 Demonstrates loading all resources from memory allocated and filled by the user.
==============================================================================================='/
#include "windows.bi"
#include "crt.bi"
#include "fmodex/fmod_event.bi"
#include "fmodex/fmod_errors.bi"

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 loadFileIntoMemory(byval file_name as zstring ptr, byval data_ as any ptr ptr, byval length as uinteger ptr)
    dim as FILE ptr file = 0
    dim as uinteger len_ = 0
    dim as uinteger read_ = 0
    dim as any ptr mem = 0

    printf(!"loading file: %s\n", file_name)
    file = fopen(file_name, "rb")
    if (file = 0) then
        printf(!"error opening file %s\n", file_name)
        end(1)
    end if
    fseek(file, 0, SEEK_END)
    len_ =  ftell(file)
    mem = allocate(len_)
    if (mem = 0) then
        printf(!"allocation failed\n")
        end(1)
    end if
    rewind(file)
    read_ = fread(mem, sizeof(byte), len_, file)
    if (read_ <> len_) then
        printf(!"error reading file\n")
        end(1)
    end if

    *data_   = mem
    *length = len_
end sub


' program start
    dim as FMOD_EVENTSYSTEM    ptr eventsystem = 0
    dim  as FMOD_SYSTEM         ptr fsystem      = 0

    dim as any                 ptr project_mem = 0
    dim as uinteger          project_len = 0

    dim as FMOD_EVENT           ptr sampleevent    = 0
    dim as FMOD_SOUND           ptr samplebank     = 0
    dim as any                 ptr samplebank_mem = 0
    dim as uinteger          samplebank_len = 0

    dim as FMOD_EVENT           ptr streamevent = 0
    dim as FMOD_SOUND           ptr streambank  = 0

    dim as FMOD_RESULT           result = FMOD_OK
    dim as string                   key
    dim as FMOD_EVENT_LOADINFO load_info

    printf(!"======================================================================\n")
    printf(!"Load Event Data Example.  Copyright (c) Firelight Technologies 2004-2011.\n")
    printf(!"==============================-------=================================\n")
    printf(!"This Demonstrates loading all resources from memory allocated and filled\n")
    printf(!"by the user.\n")
    printf(!"======================================================================\n\n")
    
    /' Load FEV file into memory '/
    loadFileIntoMemory("media\\examples.fev", @project_mem, @project_len)

result = FMOD_EventSystem_Create(@eventsystem)
    ERRCHECK(result)
result = FMOD_EventSystem_GetSystemObject(eventsystem, @fsystem)
    ERRCHECK(result)
result = FMOD_EventSystem_Init(eventsystem, 64, FMOD_INIT_NORMAL, 0, FMOD_EVENT_INIT_NORMAL)
    ERRCHECK(result)
result = FMOD_EventSystem_SetMediaPath(eventsystem, "..\\media\\")
    ERRCHECK(result)

    /' we require a loadinfo struct to tell FMOD how big the in memory FEV file is '/

    load_info.size = sizeof(FMOD_EVENT_LOADINFO)
    load_info.loadfrommemory_length = project_len

    /' load the project from memory '/
result = FMOD_EventSystem_Load(eventsystem, project_mem, @load_info, NULL)
    ERRCHECK(result)

    printf(!"======================================================================\n")
    printf(!"Press 'e'        to load sample data\n")
    printf(!"Press 'E'        to unload sample data\n")
    printf(!"Press 'd'        to start sample event\n")
    printf(!"Press 'w'        to open stream\n")
    printf(!"Press 'W'        to close stream\n")
    printf(!"Press 's'        to start stream event\n")
    printf(!"Press ESC        to quit\n")
    printf(!"======================================================================\n")

    do
            key = inkey

            if (key = "e") then
                /' Attempt to get the event without disk access '/
                result = FMOD_EventSystem_GetEvent(eventsystem, "examples/FeatureDemonstration/Basics/SimpleEvent", FMOD_EVENT_ERROR_ON_DISKACCESS, @sampleevent)
                if (result <> FMOD_ERR_FILE_UNWANTED) then
                    ERRCHECK(result)
                else
                    /' file unwanted error tells us we haven't got the soundbank preloaded, so preload it now... '/
                    dim as FMOD_CREATESOUNDEXINFO info = type(0)
                    printf(!"Loading event data\n")

                    loadFileIntoMemory("media\\tutorial_bank.fsb", @samplebank_mem, @samplebank_len)

                    /' We need to create a FMOD_SOUND object to use with preloadFSB '/
                    info.cbsize = sizeof(FMOD_CREATESOUNDEXINFO)
                    info.length = samplebank_len
result = FMOD_System_CreateSound(fsystem, samplebank_mem, FMOD_OPENMEMORY_POINT or FMOD_CREATECOMPRESSEDSAMPLE, @info, @samplebank)
                    ERRCHECK(result)

                    /' Tell FMOD that we have loaded this FSB '/
result = FMOD_EventSystem_PreloadFSB(eventsystem, "tutorial_bank.fsb", 0, samplebank,0)
                    ERRCHECK(result)

                    /' Now we can get the event without diskaccess '/
result = FMOD_EventSystem_GetEvent(eventsystem, "examples/FeatureDemonstration/Basics/SimpleEvent", FMOD_EVENT_ERROR_ON_DISKACCESS, @sampleevent)
                    ERRCHECK(result)
                end if
                printf(!"Sample event ready\n")
            ElseIf (key = "E") then
                if (samplebank = 0) then
                    printf(!"Nothing to unload\n")
                else
result = FMOD_Event_Stop(sampleevent, 0)
                    ERRCHECK(result)
                    sampleevent = 0
                    /' Note: we *MUST* call unload before freeing data '/
result = FMOD_EventSystem_UnloadFSB(eventsystem, "tutorial_bank.fsb", 0)
                    ERRCHECK(result)
result = FMOD_Sound_Release(samplebank)
                    ERRCHECK(result)
                    samplebank = 0
                    if (samplebank_mem) then
                        deallocate(samplebank_mem)
                        samplebank_mem = 0
                    end if
                    printf(!"Event data unloaded\n")
                end if
            ElseIf (key = "d") then
                if (sampleevent = 0) then
                    printf(!"no event loaded!\n")
                else
result = FMOD_Event_Start(sampleevent)
                    ERRCHECK(result)
                end if
            ElseIf (key = "w") then
                /' Attempt to get the event without opening a new stream '/
                result = FMOD_EventSystem_GetEvent(eventsystem, "examples/AdvancedTechniques/MultiChannelMusic", FMOD_EVENT_ERROR_ON_DISKACCESS, @streamevent)
                if (result <> FMOD_ERR_FILE_UNWANTED) then
                    ERRCHECK(result)
                                else
                    /'  file unwanted error tells us we haven't got the stream instance preloaded so preload it now '/
                    printf(!"Opening stream\n")

                    /' If the 'Max Streams' property of the sound bank is greater than 1 then mutiple streams can be opened. This means we need
                       to preload it multiple times if we want to prevent FMOD from creating streams internally. Each stream is uniquely identified
                       using the 'streaminstance' parameter to preloadFSB which counts upwards from 0.
                    '/
result = FMOD_System_CreateSound(fsystem, "media\\streaming_bank.fsb", FMOD_CREATESTREAM, 0, @streambank)
                    ERRCHECK(result)
result = FMOD_EventSystem_PreloadFSB(eventsystem, "streaming_bank.fsb", 0, streambank,0)
                    ERRCHECK(result)
                    
                    /' Now we can get the event without opening a new stream '/
result = FMOD_EventSystem_GetEvent(eventsystem, "examples/AdvancedTechniques/MultiChannelMusic", FMOD_EVENT_ERROR_ON_DISKACCESS, @streamevent)
                    ERRCHECK(result)
                end if
                printf(!"Stream event ready\n")
            ElseIf (key = "W") then
                if (streambank = 0) then
                    printf(!"Nothing to unload\n")
                else
result = FMOD_Event_Stop(streamevent, 0)
                    ERRCHECK(result)
                    streamevent = 0
                    /' Note: we *MUST* call unload before releasing stream '/
result = FMOD_EventSystem_UnloadFSB(eventsystem, "streaming_bank.fsb", 0)
                    ERRCHECK(result)
result = FMOD_Sound_Release(streambank)
                    ERRCHECK(result)
                    streambank = 0
                    printf(!"Stream closed\n")
                end if
            ElseIf (key = "s") then
                if (streamevent = 0) then
                    printf(!"no event loaded!\n")
                else
result = FMOD_Event_Start(streamevent)
                    ERRCHECK(result)
                end if
            end if

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

    loop while (key <> chr(27))
    
    if (samplebank) then
        /' Note: we *MUST* call unload before freeing data '/
result = FMOD_EventSystem_UnloadFSB(eventsystem, "tutorial_bank.fsb", 0)
        ERRCHECK(result)
result = FMOD_Sound_Release(samplebank)
        ERRCHECK(result)
        if (samplebank_mem) then
            deallocate(samplebank_mem)
        end if
    end if
    
    if (streambank) then
        /' Note: we *MUST* call unload before releasing stream '/
result = FMOD_EventSystem_UnloadFSB(eventsystem, "streaming_bank.fsb", 0)
        ERRCHECK(result)
result = FMOD_Sound_Release(streambank)
        ERRCHECK(result)
    end if

result = FMOD_EventSystem_Release(eventsystem)
    ERRCHECK(result)

    /' Free the memory we have allocated '/
    deallocate(project_mem)
