/*==============================================================================
Net Stream Example
Copyright (c), Firelight Technologies Pty, Ltd 2004-2015.
This example shows how to play streaming audio from an Internet source
==============================================================================*/
#include "fmod.hpp"
#include "common.h"
static FMOD_RESULT F_CALLBACK dummy_open(FMOD_CODEC_STATE *codec, FMOD_MODE usermode, FMOD_CREATESOUNDEXINFO *userexinfo);
static FMOD_RESULT F_CALLBACK dummy_close(FMOD_CODEC_STATE *codec);
static FMOD_RESULT F_CALLBACK dummy_read(FMOD_CODEC_STATE *codec, void *buffer, unsigned int size, unsigned int *read);
static FMOD_RESULT F_CALLBACK dummy_setposition(FMOD_CODEC_STATE *codec, int subsound, unsigned int position, FMOD_TIMEUNIT postype);
static FMOD_CODEC_DESCRIPTION dummy_codec_desc =
{
"FMOD dummy plugin", // Name.
0x00010000, // Version 0xAAAABBBB A = major, B = minor.
0, // Don't force everything using this codec to be a stream
FMOD_TIMEUNIT_PCM, // The time format we would like to accept into setposition/getposition.
&dummy_open, // Open callback.
&dummy_close, // Close callback.
&dummy_read, // Read callback.
0, // Getlength callback. (If not specified FMOD return the length in FMOD_TIMEUNIT_PCM, FMOD_TIMEUNIT_MS or FMOD_TIMEUNIT_PCMBYTES units based on the lengthpcm member of the FMOD_CODEC structure).
&dummy_setposition, // Setposition callback.
0, // Getposition callback. (only used for timeunit types that are not FMOD_TIMEUNIT_PCM, FMOD_TIMEUNIT_MS and FMOD_TIMEUNIT_PCMBYTES).
0 // Sound create callback (don't need it)
};
F_DECLSPEC F_DLLEXPORT FMOD_CODEC_DESCRIPTION * F_API FMODGetDummyCodecDescription()
{
return &dummy_codec_desc;
}
static FMOD_RESULT F_CALLBACK dummy_open(FMOD_CODEC_STATE *codec, FMOD_MODE usermode, FMOD_CREATESOUNDEXINFO *userexinfo)
{
return FMOD_ERR_FORMAT;
}
static FMOD_RESULT F_CALLBACK dummy_close(FMOD_CODEC_STATE *codec)
{
codec->plugindata = 0;
return FMOD_OK;
}
static FMOD_RESULT F_CALLBACK dummy_read(FMOD_CODEC_STATE *codec, void *buffer, unsigned int size, unsigned int *read)
{
return FMOD_ERR_FILE_BAD;
}
static FMOD_RESULT F_CALLBACK dummy_setposition(FMOD_CODEC_STATE *codec, int subsound, unsigned int position, FMOD_TIMEUNIT postype)
{
return FMOD_ERR_FILE_BAD;
}
int FMOD_Main()
{
FMOD::System *system = 0;
FMOD::Sound *sound = 0;
FMOD::Channel *channel = 0;
FMOD_RESULT result = FMOD_OK;
FMOD_OPENSTATE openstate = FMOD_OPENSTATE_READY;
unsigned int version = 0;
void *extradriverdata = 0;
const int tagcount = 4;
int tagindex = 0;
char tagstring[tagcount][128] = { 0 };
Common_Init(&extradriverdata);
/*
Create a System object and initialize.
*/
result = FMOD::System_Create(&system);
ERRCHECK(result);
result = system->getVersion(&version);
ERRCHECK(result);
if (version < FMOD_VERSION)
{
Common_Fatal("FMOD lib version %08x doesn't match header version %08x", version, FMOD_VERSION);
}
result = system->init(1, FMOD_INIT_NORMAL, extradriverdata);
ERRCHECK(result);
result = system->registerCodec(FMODGetDummyCodecDescription(), 0, 599);
ERRCHECK(result);
/* Increase the file buffer size a little bit to account for Internet lag. */
result = system->setStreamBufferSize(128*1024, FMOD_TIMEUNIT_RAWBYTES);
ERRCHECK(result);
FMOD_CREATESOUNDEXINFO info;
memset(&info, 0, sizeof(info));
info.cbsize = sizeof(info);
const char* url = "http://shoutmedia.abc.net.au:10426";
url = "http://uploadserver.oss.aliyuncs.com/745/699745/1443431047-55.mp3";
result = system->createSound(url, FMOD_CREATESTREAM| FMOD_NONBLOCKING, &info, &sound);
ERRCHECK(result);
/*
Main loop
*/
do
{
unsigned int pos = 0;
unsigned int percent = 0;
bool playing = false;
bool paused = false;
bool starving = false;
const char *state = "Stopped";
Common_Update();
if (Common_BtnPress(BTN_ACTION1))
{
if (channel)
{
bool paused = false;
result = channel->getPaused(&paused);
ERRCHECK(result);
result = channel->setPaused(!paused);
ERRCHECK(result);
}
}
result = system->update();
ERRCHECK(result);
result = sound->getOpenState(&openstate, &percent, &starving, 0);
ERRCHECK(result);
if (channel)
{
FMOD_TAG tag;
/*
Read any tags that have arrived, this could happen if a radio station switches
to a new song.
*/
while (sound->getTag(0, -1, &tag) == FMOD_OK)
{
if (tag.datatype == FMOD_TAGDATATYPE_STRING)
{
sprintf(tagstring[tagindex], "%s = '%s' (%d bytes)", tag.name, (char *)tag.data, tag.datalen);
tagindex = (tagindex + 1) % tagcount;
}
else if (tag.type == FMOD_TAGTYPE_FMOD)
{
/* When a song changes, the sample rate may also change, so compensate here. */
if (!strcmp(tag.name, "Sample Rate Change"))
{
float frequency = *((float *)tag.data);
result = channel->setFrequency(frequency);
ERRCHECK(result);
}
}
}
result = channel->getPaused(&paused);
ERRCHECK(result);
result = channel->isPlaying(&playing);
ERRCHECK(result);
result = channel->getPosition(&pos, FMOD_TIMEUNIT_MS);
ERRCHECK(result);
/* Silence the stream until we have sufficient data for smooth playback. */
result = channel->setMute(starving);
ERRCHECK(result);
}
else
{
/* This may fail if the stream isn't ready yet, so don't check the error code. */
if (openstate == FMOD_OPENSTATE_READY)
{
result = system->playSound(sound, 0, false, &channel);
ERRCHECK(result);
}
}
if (openstate == FMOD_OPENSTATE_BUFFERING)
{
state = "Buffering...";
}
else if (openstate == FMOD_OPENSTATE_CONNECTING)
{
state = "Connecting...";
}
else if (paused)
{
state = "Paused";
}
else if (playing)
{
state = "Playing";
}
Common_Draw("==================================================");
Common_Draw("Net Stream Example.");
Common_Draw("Copyright (c) Firelight Technologies 2004-2015.");
Common_Draw("==================================================");
Common_Draw("");
Common_Draw("Press %s to toggle pause", Common_BtnStr(BTN_ACTION1));
Common_Draw("Press %s to quit", Common_BtnStr(BTN_QUIT));
Common_Draw("");
Common_Draw("Time = %02d:%02d:%02d", pos / 1000 / 60, pos / 1000 % 60, pos / 10 % 100);
Common_Draw("State = %s %s", state, starving ? "(STARVING)" : "");
Common_Draw("Buffer Percentage = %d", percent);
Common_Draw("");
Common_Draw("Tags:");
for (int i = tagindex; i < (tagindex + tagcount); i++)
{
Common_Draw("%s", tagstring[i % tagcount]);
Common_Draw("");
}
Common_Sleep(50);
} while (!Common_BtnPress(BTN_QUIT));
/*
Stop the channel, then wait for it to finish opening before we release it.
*/
if (channel)
{
result = channel->stop();
ERRCHECK(result);
}
do
{
Common_Update();
Common_Draw("Waiting for sound to finish opening before trying to release it....", Common_BtnStr(BTN_ACTION1));
Common_Sleep(50);
result = system->update();
ERRCHECK(result);
result = sound->getOpenState(&openstate, 0, 0, 0);
ERRCHECK(result);
} while (openstate != FMOD_OPENSTATE_READY);
/*
Shut down
*/
result = sound->release();
ERRCHECK(result);
result = system->close();
ERRCHECK(result);
result = system->release();
ERRCHECK(result);
Common_Close();
return 0;
}