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

 This example shows how to play CD tracks digitally and generate a CDDB query
==============================================================================================='/
#include "windows.bi"
#include "crt.bi"
#include "fmodex/fmodex.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

function cddb_sum(byval n as integer) as integer
    dim as integer	ret = 0

    while (n > 0)
        ret += (n mod 10)
        n /= 10
    wend

    return ret
end function

function cddb_discid(byval toc as FMOD_CDTOC ptr) as ulong
    dim as integer	i = any, t = any, n = 0

    for i = 0 to toc->numtracks-1
        n += cddb_sum((toc->min_(i) * 60) + toc->sec(i))
    next

    t = ((toc->min_(toc->numtracks) * 60) + toc->sec(toc->numtracks)) - ((toc->min_(0) * 60) + toc->sec(0))

    return ((n mod &hff) shl 24 or t shl 8 or toc->numtracks)
end function

sub dump_cddb_query(byval toc as FMOD_CDTOC ptr)
    dim as integer i = any

    printf(!"cddb query %08x %d", cddb_discid(toc), toc->numtracks)

    for i = 0 to toc->numtracks-1
        printf(!" %d", (toc->min_(i) * (60 * 75)) + (toc->sec(i) * 75) + toc->frame(i))
    next

    printf(!" %d\n", (toc->min_(toc->numtracks) * 60) + toc->sec(toc->numtracks))
end sub


' program start
    dim as FMOD_SYSTEM ptr fsystem = any
    dim as FMOD_SOUND ptr cdsound = any
    dim as FMOD_CHANNEL ptr channel = 0
    dim as FMOD_RESULT      result = any
    dim as string key
    dim as uinteger numtracks = any, currenttrack = 0
    dim as integer version = any

    printf(!"==================================================================\n")
    printf(!"CDPlayer Example.  Copyright (c) Firelight Technologies 2004-2011.\n")
    printf(!"==================================================================\n\n")

    /'
        Create a System object and initialize.
    '/
    result = FMOD_System_Create(@fsystem)
    ERRCHECK(result)

    result = FMOD_System_GetVersion(fsystem, @version)
    ERRCHECK(result)

    if (version < FMOD_VERSION) then
        printf(!"Error!  You are using an old version of FMOD %08x.  This program requires %08x\n", version, FMOD_VERSION)
        end 0
    end if

    result = FMOD_System_Init(fsystem, 1, FMOD_INIT_NORMAL, NULL)
    ERRCHECK(result)

    /'
        Bump up the file buffer size a bit from the 16k default for CDDA, because it is a slower medium.
    '/
    result = FMOD_System_SetStreamBufferSize(fsystem, 64*1024, FMOD_TIMEUNIT_RAWBYTES)
    ERRCHECK(result)

    /'
        Try a few drive letters.
    '/
    result = FMOD_System_CreateStream(fsystem, "d:", FMOD_OPENONLY, 0, @cdsound)
    if (result <> FMOD_OK) then
        result = FMOD_System_CreateStream(fsystem, "e:", FMOD_OPENONLY, 0, @cdsound)
        if (result <> FMOD_OK) then
            result = FMOD_System_CreateStream(fsystem, "f:", FMOD_OPENONLY, 0, @cdsound)
        if (result <> FMOD_OK) then
            result = FMOD_System_CreateStream(fsystem, "g:", FMOD_OPENONLY, 0, @cdsound)
        if (result <> FMOD_OK) then
            result = FMOD_System_CreateStream(fsystem, "h:", FMOD_OPENONLY, 0, @cdsound)
        if (result <> FMOD_OK) then
            result = FMOD_System_CreateStream(fsystem, "i:", FMOD_OPENONLY, 0, @cdsound)
        if (result <> FMOD_OK) then
            result = FMOD_System_CreateStream(fsystem, "j:", FMOD_OPENONLY, 0, @cdsound)
            ERRCHECK(result)
end if
end if
        end if
end if
end if
    end if
    result = FMOD_Sound_GetNumSubSounds(cdsound, @numtracks)
    ERRCHECK(result)

while 1
        dim as FMOD_TAG tag = any

        if (FMOD_Sound_GetTag(cdsound, 0, -1, @tag) <> FMOD_OK) then
            exit while
        end if
        if (tag.datatype = FMOD_TAGDATATYPE_CDTOC) then
            dump_cddb_query(cast(FMOD_CDTOC ptr,tag.data))
        end if
    wend

    printf(!"\n========================================\n")
    printf(!"Press SPACE to pause\n")
    printf(!"      n     to skip to next track\n")
    printf(!"      <     re-wind 10 seconds\n")
    printf(!"      >     fast-forward 10 seconds\n")
    printf(!"      ESC   to exit\n")
    printf(!"========================================\n\n")

    /'
        Print out length of entire CD.  Did you know you can also play 'cdsound' and it will play the whole CD without gaps?
    '/
    scope
        dim as integer lenms = any

        result = FMOD_Sound_GetLength(cdsound, @lenms, FMOD_TIMEUNIT_MS)
        ERRCHECK(result)

        printf(!"Total CD length %02d:%02d\n\n", lenms / 1000 / 60, lenms / 1000 mod 60, lenms / 10 mod 100)
    end scope

    /'
        Play whole CD
    '/
    result = FMOD_System_PlaySound(fsystem, FMOD_CHANNEL_FREE, cdsound, FALSE, @channel)
    ERRCHECK(result)

    /'
        Main loop
    '/
    do
key = inkey
select case key
                case " " :
                    dim as integer paused = any
                    FMOD_Channel_GetPaused(channel, @paused)
paused xor=1
                    FMOD_Channel_SetPaused(channel, paused)
                case "<" :
                    dim as uinteger ms = any

                    FMOD_Channel_GetPosition(channel, @ms, FMOD_TIMEUNIT_SENTENCE_MS)

                    if (ms <> 10000) then
                        ms -= 10000
                    else
                        ms = 0
                    end if

                    FMOD_Channel_SetPosition(channel, ms, FMOD_TIMEUNIT_SENTENCE_MS)
                case ">" :
                    dim as uinteger ms = any

                    FMOD_Channel_GetPosition(channel, @ms, FMOD_TIMEUNIT_SENTENCE_MS)

                    ms += 10000

                    FMOD_Channel_SetPosition(channel, ms, FMOD_TIMEUNIT_SENTENCE_MS)
                case "n" :
                    FMOD_Channel_GetPosition(channel, @currenttrack, FMOD_TIMEUNIT_SENTENCE_SUBSOUND)

                    currenttrack+=1
                    if (currenttrack >= numtracks) then
                        currenttrack = 0
                    end if

                    FMOD_Channel_SetPosition(channel, currenttrack, FMOD_TIMEUNIT_SENTENCE_SUBSOUND)
end select

        FMOD_System_Update(fsystem)

        if (channel) then
            dim as uinteger ms = any
            dim as uinteger lenms = any
            dim as FMOD_BOOL    playing = any
            dim as FMOD_BOOL    paused = any
            dim as integer          busy = any

            result = FMOD_Channel_GetPaused(channel, @paused)
            ERRCHECK(result)
            result = FMOD_Channel_IsPlaying(channel, @playing)
            ERRCHECK(result)
            result = FMOD_Channel_GetPosition(channel, @ms, FMOD_TIMEUNIT_SENTENCE_MS)
            ERRCHECK(result)
            result = FMOD_Sound_GetLength(cdsound, @lenms, FMOD_TIMEUNIT_SENTENCE_MS)
            ERRCHECK(result)

            result = FMOD_File_GetDiskBusy(@busy)
            ERRCHECK(result)

            printf(!"Track %d/%d : %02d:%02d:%02d/%02d:%02d:%02d : %s (%s)\r", currenttrack + 1, numtracks, ms \ 1000 \ 60, _
            ms \ 1000 mod 60, ms \ 10 mod 100, lenms \ 1000 \ 60, lenms \ 1000 mod 60, lenms \ 10 mod 100, _
            iif(paused, @"Paused ",iif(playing, @"Playing", @"Stopped")), iif(busy, @"*", @" "))
        end if

        Sleep(50)

    loop while (key <> chr(27))

    printf(!"\n")

    /'
        Shut down
    '/
    result = FMOD_Sound_Release(cdsound)
    ERRCHECK(result)
    result = FMOD_System_Close(fsystem)
    ERRCHECK(result)
    result = FMOD_System_Release(fsystem)
    ERRCHECK(result)
