337 lines
7.0 KiB
C++
337 lines
7.0 KiB
C++
|
// This program is an example application for the irrKlang audio library.
|
||
|
// It is copyright 2007-2014 by N.Gebhardt, Ambiera and licensed under the LGPL2 license.
|
||
|
// For more information, please see www.ambiera.com/irrklang.
|
||
|
|
||
|
#include "main.h"
|
||
|
#include "window.h"
|
||
|
#include <irrKlang.h>
|
||
|
#include <string.h>
|
||
|
#include <stdio.h>
|
||
|
|
||
|
using namespace irrklang;
|
||
|
|
||
|
|
||
|
// global variables
|
||
|
ISoundEngine* SoundEngine = 0;
|
||
|
ISound* CurrentPlayingSound = 0;
|
||
|
bool LoopSound = true;
|
||
|
char LastPlayedSoundFile[FL_PATH_MAX];
|
||
|
char lastDisplayedPlayStatus = -1;
|
||
|
bool PlayListVisible = true;
|
||
|
|
||
|
|
||
|
// our main() function, see main.h
|
||
|
IRRKLANG_MUSIC_PLAYER_APPENTRY
|
||
|
{
|
||
|
// create irrKlang sound device
|
||
|
|
||
|
SoundEngine = createIrrKlangDevice();
|
||
|
|
||
|
if (!SoundEngine)
|
||
|
{
|
||
|
fl_alert("Could not create audio device\n");
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
// create window
|
||
|
|
||
|
Fl_Double_Window* wnd = createPlayerWindow();
|
||
|
|
||
|
wnd->label("irrKlang Player");
|
||
|
MusicTitleDisplay->value("nothing selected to play");
|
||
|
|
||
|
LoopButton->value(LoopSound ? 1 : 0);
|
||
|
|
||
|
changeDir((char*)"../../media"); // try to select irrKlang media directory by default
|
||
|
|
||
|
FileBrowser->filter("{*.mp3|*.ogg|*.wav|*.flac|*.mod|*.s3m|*.it|*.xm}");
|
||
|
FileBrowser->type(FL_SELECT_BROWSER);
|
||
|
|
||
|
PlayPositionSlider->type(FL_HOR_NICE_SLIDER);
|
||
|
PlayPositionSlider->bounds(0, 1);
|
||
|
PlayPositionSlider->deactivate();
|
||
|
|
||
|
SpeedSlider->type(FL_HOR_NICE_SLIDER);
|
||
|
VolumeSlider->type(FL_HOR_NICE_SLIDER);
|
||
|
PanSlider->type(FL_HOR_NICE_SLIDER);
|
||
|
|
||
|
FileBrowser->load(".");
|
||
|
|
||
|
Fl_Tooltip::delay(0.2f);
|
||
|
Fl_Tooltip::size(10);
|
||
|
|
||
|
|
||
|
// initialize timer and other stuff
|
||
|
|
||
|
Fl::add_timeout(updateTimerSpeed, UpdateTimerCallback);
|
||
|
LastPlayedSoundFile[0] = 0x0;
|
||
|
|
||
|
|
||
|
// show and run player
|
||
|
|
||
|
wnd->show();
|
||
|
int ret = Fl::run();
|
||
|
|
||
|
|
||
|
// that's it, clean up and exit
|
||
|
|
||
|
if (CurrentPlayingSound)
|
||
|
CurrentPlayingSound->drop();
|
||
|
CurrentPlayingSound = 0;
|
||
|
|
||
|
SoundEngine->drop();
|
||
|
|
||
|
delete MainWindow;
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
|
||
|
void UpdateTimerCallback(void*)
|
||
|
{
|
||
|
if (CurrentPlayingSound)
|
||
|
{
|
||
|
// update play position
|
||
|
|
||
|
ik_u32 pos = CurrentPlayingSound->getPlayPosition();
|
||
|
if (pos == -1)
|
||
|
pos = 0;
|
||
|
|
||
|
PlayPositionSlider->value(pos * timeDisplayFactor);
|
||
|
}
|
||
|
|
||
|
// update play button
|
||
|
|
||
|
char valueToSet = (!CurrentPlayingSound || CurrentPlayingSound->isFinished()) ? 0 : 1;
|
||
|
if (lastDisplayedPlayStatus != valueToSet)
|
||
|
{
|
||
|
lastDisplayedPlayStatus = valueToSet;
|
||
|
PlayButton->value(valueToSet);
|
||
|
PlayButton->redraw();
|
||
|
}
|
||
|
|
||
|
// repeat timer
|
||
|
Fl::repeat_timeout(updateTimerSpeed, UpdateTimerCallback);
|
||
|
}
|
||
|
|
||
|
|
||
|
void PlayFile(const char* filename)
|
||
|
{
|
||
|
MusicTitleDisplay->value(filename);
|
||
|
lastDisplayedPlayStatus = -1;
|
||
|
|
||
|
if (SoundEngine)
|
||
|
{
|
||
|
strcpy(LastPlayedSoundFile, filename);
|
||
|
|
||
|
// display loading text
|
||
|
MusicTitleDisplay->value("loading...");
|
||
|
MusicTitleDisplay->redraw();
|
||
|
|
||
|
// stop previous sound and remove it from memory
|
||
|
if (CurrentPlayingSound)
|
||
|
CurrentPlayingSound->drop();
|
||
|
SoundEngine->stopAllSounds();
|
||
|
|
||
|
if (strcmp(LastPlayedSoundFile, filename))
|
||
|
SoundEngine->removeAllSoundSources();
|
||
|
|
||
|
// play new sound
|
||
|
CurrentPlayingSound = SoundEngine->play2D(filename, LoopSound, false, true);
|
||
|
if (!CurrentPlayingSound)
|
||
|
{
|
||
|
MusicTitleDisplay->value("");
|
||
|
MusicTitleDisplay->redraw();
|
||
|
fl_alert("Could not play sound %s", filename);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// update UI with info about the playing file
|
||
|
ik_u32 len = CurrentPlayingSound->getPlayLength();
|
||
|
PlayPositionSlider->bounds(0, len * timeDisplayFactor);
|
||
|
PlayPositionSlider->activate();
|
||
|
|
||
|
PlayButton->value(1);
|
||
|
PlayButton->redraw();
|
||
|
|
||
|
SAudioStreamFormat format = CurrentPlayingSound->getSoundSource()->getAudioFormat();
|
||
|
|
||
|
char display[2048];
|
||
|
sprintf(display, "%s [%dkHz %s %s %sbit]",
|
||
|
fl_filename_name(filename),
|
||
|
format.SampleRate / 1000,
|
||
|
format.ChannelCount > 1 ? "stereo" : "mono",
|
||
|
CurrentPlayingSound->getSoundSource()->getStreamMode() == ::ESM_STREAMING ? "stream" : "buffered",
|
||
|
format.SampleFormat == ::ESF_U8 ? "8" : "16");
|
||
|
|
||
|
MusicTitleDisplay->value(display);
|
||
|
MusicTitleDisplay->redraw();
|
||
|
|
||
|
// test sound for seeking capability and disable slider if not
|
||
|
if (!CurrentPlayingSound->getSoundSource()->getIsSeekingSupported())
|
||
|
{
|
||
|
PlayPositionSlider->deactivate();
|
||
|
PlayPositionSlider->redraw();
|
||
|
}
|
||
|
|
||
|
// reset speed and volume slider
|
||
|
SpeedSlider->value(1.0f);
|
||
|
SpeedSlider->redraw();
|
||
|
VolumeSlider->value(1.0f);
|
||
|
VolumeSlider->redraw();
|
||
|
PanSlider->value(0);
|
||
|
PanSlider->redraw();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
void OnPlayPressed(Fl_Light_Button*, void*)
|
||
|
{
|
||
|
// user pressed play button, toggle pause mode of sound
|
||
|
|
||
|
if (CurrentPlayingSound)
|
||
|
{
|
||
|
bool pause = PlayButton->value() == 0;
|
||
|
CurrentPlayingSound->setIsPaused(pause);
|
||
|
}
|
||
|
else
|
||
|
lastDisplayedPlayStatus = -1;
|
||
|
}
|
||
|
|
||
|
|
||
|
void OnBrowserChanged(Fl_File_Browser* browser, void*)
|
||
|
{
|
||
|
// user selected entry in playlist
|
||
|
|
||
|
if (!browser)
|
||
|
return;
|
||
|
|
||
|
int selected = browser->value();
|
||
|
int cnt = browser->size();
|
||
|
|
||
|
if (selected < 0 || selected > cnt)
|
||
|
return;
|
||
|
|
||
|
const char* tx = browser->text(selected);
|
||
|
if (!tx)
|
||
|
return;
|
||
|
|
||
|
char name[FL_PATH_MAX];
|
||
|
fl_filename_absolute(name, tx);
|
||
|
|
||
|
if (fl_filename_isdir(name))
|
||
|
{
|
||
|
if (!changeDir((char*)tx))
|
||
|
{
|
||
|
fl_alert("Could not change directory to %s", tx);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
PathDisplay->value(name);
|
||
|
PathDisplay->redraw();
|
||
|
|
||
|
FileBrowser->load(".");
|
||
|
FileBrowser->redraw();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
PlayFile(name);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
void OnAbout(Fl_Button*, void*)
|
||
|
{
|
||
|
// user pressed '?' button, show about box
|
||
|
|
||
|
fl_alert("This program is an example application for the irrKlang audio library.\n"\
|
||
|
"It is copyright 2007-2010 by N.Gebhardt, Ambiera and licensed under the LGPL2 license.\n"\
|
||
|
"For more information, please see www.ambiera.com/irrklang.\n\n"\
|
||
|
"This player currently support the following file formats:\n"\
|
||
|
"MP3, OGG, WAV, FLAC, MOD, IT, S3M, XM\n");
|
||
|
}
|
||
|
|
||
|
|
||
|
void OnDirectoryButton(Fl_Repeat_Button*, void*)
|
||
|
{
|
||
|
// user pressed directory button, show disk names
|
||
|
|
||
|
FileBrowser->load("");
|
||
|
FileBrowser->redraw();
|
||
|
}
|
||
|
|
||
|
|
||
|
void OnLoopPressed(Fl_Light_Button* button, void*)
|
||
|
{
|
||
|
// user pressed loop button, switch sound loop mode
|
||
|
|
||
|
char v = LoopButton->value();
|
||
|
LoopSound = v != 0;
|
||
|
|
||
|
if (CurrentPlayingSound)
|
||
|
CurrentPlayingSound->setIsLooped(LoopSound);
|
||
|
}
|
||
|
|
||
|
|
||
|
void OnTogglePlayList(Fl_Button*, void*)
|
||
|
{
|
||
|
// user pressed playlist button, show or hide playlist
|
||
|
|
||
|
PlayListVisible = !PlayListVisible;
|
||
|
|
||
|
if (PlayListVisible)
|
||
|
MainWindow->size(419, 281);
|
||
|
else
|
||
|
MainWindow->size(419, 115);
|
||
|
}
|
||
|
|
||
|
|
||
|
void OnSliderMoved(Fl_Value_Slider*, void*)
|
||
|
{
|
||
|
// user moved slider, seek to another play position
|
||
|
|
||
|
double pos = PlayPositionSlider->value();
|
||
|
|
||
|
if (CurrentPlayingSound)
|
||
|
{
|
||
|
ik_u32 pos = (ik_u32)(PlayPositionSlider->value() / timeDisplayFactor);
|
||
|
CurrentPlayingSound->setPlayPosition(pos);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
void OnPlaybackSpeedChanged(Fl_Value_Slider*, void*)
|
||
|
{
|
||
|
// user moved playbackspeed slider
|
||
|
|
||
|
double pos = SpeedSlider->value();
|
||
|
|
||
|
if (CurrentPlayingSound)
|
||
|
{
|
||
|
CurrentPlayingSound->setPlaybackSpeed((ik_f32)pos);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
void OnVolumeSliderChanged(Fl_Value_Slider*, void*)
|
||
|
{
|
||
|
double pos = VolumeSlider->value();
|
||
|
|
||
|
if (CurrentPlayingSound)
|
||
|
{
|
||
|
CurrentPlayingSound->setVolume((ik_f32)pos);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
void OnPanSliderChanged(Fl_Value_Slider*, void*)
|
||
|
{
|
||
|
double pos = PanSlider->value();
|
||
|
|
||
|
if (CurrentPlayingSound)
|
||
|
{
|
||
|
CurrentPlayingSound->setPan((ik_f32)pos);
|
||
|
}
|
||
|
}
|