Merge with develop
This commit is contained in:
parent
5e712f3e02
commit
3610c6c8cb
10 changed files with 128 additions and 28 deletions
|
@ -67,7 +67,7 @@ public:
|
||||||
static IAudioDecoder *createAudioDecoder(const std::string &type, NLMISC::IStream *stream, bool loop);
|
static IAudioDecoder *createAudioDecoder(const std::string &type, NLMISC::IStream *stream, bool loop);
|
||||||
|
|
||||||
/// Get information on a music file (only artist and title at the moment).
|
/// Get information on a music file (only artist and title at the moment).
|
||||||
static bool getInfo(const std::string &filepath, std::string &artist, std::string &title);
|
static bool getInfo(const std::string &filepath, std::string &artist, std::string &title, float &length);
|
||||||
|
|
||||||
/// Get audio/container extensions that are currently supported by the nel sound library.
|
/// Get audio/container extensions that are currently supported by the nel sound library.
|
||||||
static void getMusicExtensions(std::vector<std::string> &extensions);
|
static void getMusicExtensions(std::vector<std::string> &extensions);
|
||||||
|
|
|
@ -77,7 +77,7 @@ public:
|
||||||
inline sint32 getStreamOffset() { return _StreamOffset; }
|
inline sint32 getStreamOffset() { return _StreamOffset; }
|
||||||
|
|
||||||
/// Get information on a music file (only artist and title at the moment).
|
/// Get information on a music file (only artist and title at the moment).
|
||||||
static bool getInfo(NLMISC::IStream *stream, std::string &artist, std::string &title);
|
static bool getInfo(NLMISC::IStream *stream, std::string &artist, std::string &title, float &length);
|
||||||
|
|
||||||
/// Get how many bytes the music buffer requires for output minimum.
|
/// Get how many bytes the music buffer requires for output minimum.
|
||||||
virtual uint32 getRequiredBytes();
|
virtual uint32 getRequiredBytes();
|
||||||
|
|
|
@ -332,7 +332,7 @@ public:
|
||||||
virtual bool isMusicEnded();
|
virtual bool isMusicEnded();
|
||||||
virtual void setMusicVolume(float gain);
|
virtual void setMusicVolume(float gain);
|
||||||
virtual float getMusicLength();
|
virtual float getMusicLength();
|
||||||
virtual bool getSongTitle(const std::string &filename, std::string &result);
|
virtual bool getSongTitle(const std::string &filename, std::string &result, float &length);
|
||||||
virtual void enableBackgroundMusic(bool enable);
|
virtual void enableBackgroundMusic(bool enable);
|
||||||
virtual void enableBackgroundMusicTimeConstraint(bool enable);
|
virtual void enableBackgroundMusicTimeConstraint(bool enable);
|
||||||
CMusicSoundManager *getBackgroundMusicManager() const {return _BackgroundMusicManager;}
|
CMusicSoundManager *getBackgroundMusicManager() const {return _BackgroundMusicManager;}
|
||||||
|
|
|
@ -432,7 +432,7 @@ public:
|
||||||
/** Get the song title. Returns false if the song is not found or the function is not implemented.
|
/** Get the song title. Returns false if the song is not found or the function is not implemented.
|
||||||
* If the song as no name, result is filled with the filename.
|
* If the song as no name, result is filled with the filename.
|
||||||
*/
|
*/
|
||||||
virtual bool getSongTitle(const std::string &filename, std::string &result) =0;
|
virtual bool getSongTitle(const std::string &filename, std::string &result, float &length) =0;
|
||||||
/** enable or disable the background music system. disable it when you want to play your own mp3 for instance
|
/** enable or disable the background music system. disable it when you want to play your own mp3 for instance
|
||||||
*/
|
*/
|
||||||
virtual void enableBackgroundMusic(bool enable) =0;
|
virtual void enableBackgroundMusic(bool enable) =0;
|
||||||
|
|
|
@ -94,7 +94,7 @@ IAudioDecoder *IAudioDecoder::createAudioDecoder(const std::string &type, NLMISC
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IAudioDecoder::getInfo(const std::string &filepath, std::string &artist, std::string &title)
|
bool IAudioDecoder::getInfo(const std::string &filepath, std::string &artist, std::string &title, float &length)
|
||||||
{
|
{
|
||||||
std::string lookup = CPath::lookup(filepath, false);
|
std::string lookup = CPath::lookup(filepath, false);
|
||||||
if (lookup.empty())
|
if (lookup.empty())
|
||||||
|
@ -111,7 +111,7 @@ bool IAudioDecoder::getInfo(const std::string &filepath, std::string &artist, st
|
||||||
ifile.setCacheFileOnOpen(false);
|
ifile.setCacheFileOnOpen(false);
|
||||||
ifile.allowBNPCacheFileOnOpen(false);
|
ifile.allowBNPCacheFileOnOpen(false);
|
||||||
if (ifile.open(lookup))
|
if (ifile.open(lookup))
|
||||||
return CAudioDecoderVorbis::getInfo(&ifile, artist, title);
|
return CAudioDecoderVorbis::getInfo(&ifile, artist, title, length);
|
||||||
|
|
||||||
nlwarning("Unable to open: '%s'", filepath.c_str());
|
nlwarning("Unable to open: '%s'", filepath.c_str());
|
||||||
}
|
}
|
||||||
|
|
|
@ -117,7 +117,7 @@ CAudioDecoderVorbis::~CAudioDecoderVorbis()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get information on a music file (only artist and title at the moment).
|
/// Get information on a music file (only artist and title at the moment).
|
||||||
bool CAudioDecoderVorbis::getInfo(NLMISC::IStream *stream, std::string &artist, std::string &title)
|
bool CAudioDecoderVorbis::getInfo(NLMISC::IStream *stream, std::string &artist, std::string &title, float &length)
|
||||||
{
|
{
|
||||||
CAudioDecoderVorbis mbv(stream, false); // just opens and closes the oggvorbisfile thing :)
|
CAudioDecoderVorbis mbv(stream, false); // just opens and closes the oggvorbisfile thing :)
|
||||||
vorbis_comment *vc = ov_comment(&mbv._OggVorbisFile, -1);
|
vorbis_comment *vc = ov_comment(&mbv._OggVorbisFile, -1);
|
||||||
|
@ -125,6 +125,7 @@ bool CAudioDecoderVorbis::getInfo(NLMISC::IStream *stream, std::string &artist,
|
||||||
if (title_c) title = title_c; else title.clear();
|
if (title_c) title = title_c; else title.clear();
|
||||||
char *artist_c = vorbis_comment_query(vc, "artist", 0);
|
char *artist_c = vorbis_comment_query(vc, "artist", 0);
|
||||||
if (artist_c) artist = artist_c; else artist.clear();
|
if (artist_c) artist = artist_c; else artist.clear();
|
||||||
|
length = (float)ov_time_total(&mbv._OggVorbisFile, -1);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2684,7 +2684,7 @@ float CAudioMixerUser::getMusicLength()
|
||||||
}
|
}
|
||||||
|
|
||||||
// ***************************************************************************
|
// ***************************************************************************
|
||||||
bool CAudioMixerUser::getSongTitle(const std::string &filename, std::string &result)
|
bool CAudioMixerUser::getSongTitle(const std::string &filename, std::string &result, float &length)
|
||||||
{
|
{
|
||||||
if (_SoundDriver)
|
if (_SoundDriver)
|
||||||
{
|
{
|
||||||
|
@ -2694,7 +2694,7 @@ bool CAudioMixerUser::getSongTitle(const std::string &filename, std::string &res
|
||||||
if (!_SoundDriver->getMusicInfo(filename, artist, title))
|
if (!_SoundDriver->getMusicInfo(filename, artist, title))
|
||||||
{
|
{
|
||||||
// use 3rd party libraries supported formats
|
// use 3rd party libraries supported formats
|
||||||
IAudioDecoder::getInfo(filename, artist, title);
|
IAudioDecoder::getInfo(filename, artist, title, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!title.empty())
|
if (!title.empty())
|
||||||
|
@ -2715,6 +2715,7 @@ bool CAudioMixerUser::getSongTitle(const std::string &filename, std::string &res
|
||||||
}
|
}
|
||||||
|
|
||||||
result = "???";
|
result = "???";
|
||||||
|
length = 0;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,23 +25,38 @@
|
||||||
<group type="menu"
|
<group type="menu"
|
||||||
id="mp3_player_menu"
|
id="mp3_player_menu"
|
||||||
extends="base_menu_with_color"></group>
|
extends="base_menu_with_color"></group>
|
||||||
|
|
||||||
|
<template name="playlist_song" keep="true" id="" posparent="parent" posref="TL TL" w="206" h="20" line_maxw="160" index="0">
|
||||||
|
<group id="#id" w="#w" child_resize_h="true" posparent="#posparent" posref="#posref" group_onclick_r="" group_params_r="">
|
||||||
|
<ctrl type="button" id="btn" button_type="toggle_button" sizeref="wh" tx_normal="blank.tga" tx_pushed="blank.tga" tx_over="blank.tga" scale="true"
|
||||||
|
color="255 255 255 0" col_pushed="255 255 255 0" col_over="255 255 255 90"
|
||||||
|
global_color_normal="true" global_color_pushed="true" global_color_over="true"
|
||||||
|
ondblclick_l="music_player" params_dblclick_l="song=#index" />
|
||||||
|
|
||||||
|
<view type="text" id="title" posref="ML ML" x="0" line_maxw="#line_maxw" fontsize="8" shadow="true" multi_line="true" multi_line_space="0" />
|
||||||
|
<view type="text" id="duration" posref="MR MR" x="0" fontsize="8" shadow="true" color="255 255 255 128" />
|
||||||
|
</group>
|
||||||
|
</template>
|
||||||
|
|
||||||
<group type="modal"
|
<group type="modal"
|
||||||
id="playlist"
|
id="playlist"
|
||||||
posparent="mp3_player"
|
posparent="mp3_player"
|
||||||
posref="BM TM"
|
posref="BM TM"
|
||||||
w="234"
|
w="234"
|
||||||
h="256"
|
max_h="250"
|
||||||
|
child_resize_h="true"
|
||||||
|
child_resize_hmargin="10"
|
||||||
options="layer0"
|
options="layer0"
|
||||||
mouse_pos="false"
|
mouse_pos="false"
|
||||||
escapable="false"
|
escapable="true"
|
||||||
exit_click_out="false"
|
exit_click_out="true"
|
||||||
on_active=""
|
on_active=""
|
||||||
on_active_params="">
|
on_active_params="">
|
||||||
<view type="text"
|
<view type="text"
|
||||||
id="title"
|
id="title"
|
||||||
posref="TL TL"
|
posref="TL TL"
|
||||||
x="4"
|
x="8"
|
||||||
y="-4"
|
y="-8"
|
||||||
hardtext="uiPlaylistTitle"
|
hardtext="uiPlaylistTitle"
|
||||||
shadow="true"
|
shadow="true"
|
||||||
color="255 255 255 255"
|
color="255 255 255 255"
|
||||||
|
@ -50,14 +65,33 @@
|
||||||
id="close"
|
id="close"
|
||||||
button_type="push_button"
|
button_type="push_button"
|
||||||
posref="TR TR"
|
posref="TR TR"
|
||||||
x="-4"
|
x="-8"
|
||||||
y="-4"
|
y="-8"
|
||||||
tx_normal="w_win_close.tga"
|
tx_normal="w_win_close.tga"
|
||||||
tx_pushed="w_win_close.tga"
|
tx_pushed="w_win_close.tga"
|
||||||
tx_over="W_button_14_over.tga"
|
tx_over="W_button_14_over.tga"
|
||||||
onclick_l="leave_modal"
|
onclick_l="leave_modal"
|
||||||
params_l="" />
|
params_l="" />
|
||||||
|
<ctrl style="text_button_header"
|
||||||
|
button_type="push_button"
|
||||||
|
id="refresh"
|
||||||
|
posparent="close"
|
||||||
|
posref="ML MR"
|
||||||
|
x="-4"
|
||||||
|
y="0"
|
||||||
|
hardtext="uiPlaylistRefresh"
|
||||||
|
onclick_l="music_player"
|
||||||
|
params_l="play_songs" />
|
||||||
|
|
||||||
|
<group id="content" x="8" y="-24" over="true" sizeref="w" posref="TL TL" child_resize_h="true" child_resize_hmargin="4">
|
||||||
|
<group id="songs" x="10" y="0" sizeref="w" posref="TL TL" child_resize_h="true" max_h="215">
|
||||||
|
<group id="list" type="list" x="0" y="0" posref="TL TL" />
|
||||||
</group>
|
</group>
|
||||||
|
<ctrl style="skin_scroll" id="sv" posref="TL TL" target="songs" />
|
||||||
|
</group>
|
||||||
|
</group>
|
||||||
|
<tree node="playlist" />
|
||||||
|
|
||||||
<link expr="@UI:SAVE:MP3_VOLUME"
|
<link expr="@UI:SAVE:MP3_VOLUME"
|
||||||
action="music_player"
|
action="music_player"
|
||||||
params="volume=@UI:SAVE:MP3_VOLUME" />
|
params="volume=@UI:SAVE:MP3_VOLUME" />
|
||||||
|
@ -223,12 +257,12 @@
|
||||||
button_type="push_button"
|
button_type="push_button"
|
||||||
posref="MM MM"
|
posref="MM MM"
|
||||||
posparent="slot5"
|
posparent="slot5"
|
||||||
tx_normal="mp3_button_open.tga"
|
tx_normal="mp3_button_list.tga"
|
||||||
tx_pushed="mp3_button_open.tga"
|
tx_pushed="mp3_button_list.tga"
|
||||||
tx_over="mp3_button_over.tga"
|
tx_over="mp3_button_over.tga"
|
||||||
onclick_l="music_player"
|
onclick_l="enter_modal"
|
||||||
params_l="play_songs"
|
params_l="group=ui:interface:playlist"
|
||||||
tooltip="uiMP3Open" />
|
tooltip="uiMP3Playlist" />
|
||||||
<!--
|
<!--
|
||||||
<ctrl type="button" id="but_list" button_type="push_button" posref="MM MM" posparent="slot6"
|
<ctrl type="button" id="but_list" button_type="push_button" posref="MM MM" posparent="slot6"
|
||||||
tx_normal="mp3_button_list.tga" tx_pushed="mp3_button_list.tga" tx_over="mp3_button_over.tga"
|
tx_normal="mp3_button_list.tga" tx_pushed="mp3_button_list.tga" tx_over="mp3_button_over.tga"
|
||||||
|
|
|
@ -34,6 +34,12 @@ using namespace NL3D;
|
||||||
|
|
||||||
extern UDriver *Driver;
|
extern UDriver *Driver;
|
||||||
|
|
||||||
|
// xml element ids
|
||||||
|
#define MP3_PLAYER_PLAYLIST_LIST "ui:interface:playlist:content:songs:list"
|
||||||
|
#define TEMPLATE_PLAYLIST_SONG "playlist_song"
|
||||||
|
#define TEMPLATE_PLAYLIST_SONG_TITLE "title"
|
||||||
|
#define TEMPLATE_PLAYLIST_SONG_DURATION "duration"
|
||||||
|
|
||||||
static const std::string MediaPlayerDirectory("music/");
|
static const std::string MediaPlayerDirectory("music/");
|
||||||
|
|
||||||
CMusicPlayer MusicPlayer;
|
CMusicPlayer MusicPlayer;
|
||||||
|
@ -48,27 +54,76 @@ CMusicPlayer::CMusicPlayer ()
|
||||||
|
|
||||||
|
|
||||||
// ***************************************************************************
|
// ***************************************************************************
|
||||||
|
|
||||||
void CMusicPlayer::playSongs (const std::vector<CSongs> &songs)
|
void CMusicPlayer::playSongs (const std::vector<CSongs> &songs)
|
||||||
{
|
{
|
||||||
_Songs = songs;
|
_Songs = songs;
|
||||||
|
|
||||||
|
// reset song index if out of bounds
|
||||||
|
if (_CurrentSong > _Songs.size())
|
||||||
_CurrentSong = 0;
|
_CurrentSong = 0;
|
||||||
|
|
||||||
|
CGroupList *pList = dynamic_cast<CGroupList *>(CWidgetManager::getInstance()->getElementFromId(MP3_PLAYER_PLAYLIST_LIST));
|
||||||
|
if (pList)
|
||||||
|
{
|
||||||
|
pList->clearGroups();
|
||||||
|
pList->setDynamicDisplaySize(true);
|
||||||
|
for (uint i=0; i < _Songs.size(); ++i)
|
||||||
|
{
|
||||||
|
uint min = (sint32)(_Songs[i].Length / 60) % 60;
|
||||||
|
uint sec = (sint32)(_Songs[i].Length) % 60;
|
||||||
|
uint hour = _Songs[i].Length / 3600;
|
||||||
|
std::string duration(toString("%02d:%02d", min, sec));
|
||||||
|
if (hour > 0)
|
||||||
|
duration = toString("%02d:", hour) + duration;
|
||||||
|
|
||||||
|
vector< pair<string, string> > vParams;
|
||||||
|
vParams.push_back(pair<string, string>("id", "s" + toString(i)));
|
||||||
|
vParams.push_back(pair<string, string>("index", toString(i)));
|
||||||
|
CInterfaceGroup *pNew = CWidgetManager::getInstance()->getParser()->createGroupInstance(TEMPLATE_PLAYLIST_SONG, pList->getId(), vParams);
|
||||||
|
if (pNew)
|
||||||
|
{
|
||||||
|
CViewText *pVT = dynamic_cast<CViewText *>(pNew->getView(TEMPLATE_PLAYLIST_SONG_TITLE));
|
||||||
|
if (pVT)
|
||||||
|
{
|
||||||
|
ucstring title;
|
||||||
|
title.fromUtf8(_Songs[i].Title);
|
||||||
|
pVT->setText(title);
|
||||||
|
}
|
||||||
|
|
||||||
|
pVT = dynamic_cast<CViewText *>(pNew->getView(TEMPLATE_PLAYLIST_SONG_DURATION));
|
||||||
|
if (pVT)
|
||||||
|
{
|
||||||
|
pVT->setText(duration);
|
||||||
|
}
|
||||||
|
|
||||||
|
pNew->setParent(pList);
|
||||||
|
pList->addChild(pNew);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pList->invalidateCoords();
|
||||||
|
}
|
||||||
|
|
||||||
// If pause, stop, else play will resume
|
// If pause, stop, else play will resume
|
||||||
if (_State == Paused)
|
if (_State == Paused)
|
||||||
_State = Stopped;
|
_State = Stopped;
|
||||||
|
|
||||||
play ();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// ***************************************************************************
|
// ***************************************************************************
|
||||||
|
|
||||||
void CMusicPlayer::play ()
|
void CMusicPlayer::play (sint index)
|
||||||
{
|
{
|
||||||
if(!SoundMngr)
|
if(!SoundMngr)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (index >= 0 && index < _Songs.size())
|
||||||
|
{
|
||||||
|
if (_State == Paused)
|
||||||
|
stop();
|
||||||
|
|
||||||
|
_CurrentSong = index;
|
||||||
|
}
|
||||||
|
|
||||||
if (!_Songs.empty())
|
if (!_Songs.empty())
|
||||||
{
|
{
|
||||||
nlassert (_CurrentSong<_Songs.size());
|
nlassert (_CurrentSong<_Songs.size());
|
||||||
|
@ -300,7 +355,7 @@ public:
|
||||||
|
|
||||||
CMusicPlayer::CSongs song;
|
CMusicPlayer::CSongs song;
|
||||||
song.Filename = filenames[i];
|
song.Filename = filenames[i];
|
||||||
SoundMngr->getMixer()->getSongTitle(filenames[i], song.Title);
|
SoundMngr->getMixer()->getSongTitle(filenames[i], song.Title, song.Length);
|
||||||
songs.push_back (song);
|
songs.push_back (song);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -330,6 +385,14 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string song = getParam(Params, "song");
|
||||||
|
if (!song.empty())
|
||||||
|
{
|
||||||
|
sint index=0;
|
||||||
|
fromString(song, index);
|
||||||
|
MusicPlayer.play(index);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -41,10 +41,11 @@ public:
|
||||||
public:
|
public:
|
||||||
std::string Filename;
|
std::string Filename;
|
||||||
std::string Title;
|
std::string Title;
|
||||||
|
float Length;
|
||||||
};
|
};
|
||||||
|
|
||||||
void playSongs (const std::vector<CSongs> &songs);
|
void playSongs (const std::vector<CSongs> &songs);
|
||||||
void play (); // Play the song at current position, if playing, restart. If paused, resume.
|
void play (sint index = -1); // Play the song at current position, if playing, restart. If paused, resume.
|
||||||
void pause ();
|
void pause ();
|
||||||
void stop ();
|
void stop ();
|
||||||
void previous ();
|
void previous ();
|
||||||
|
|
Loading…
Reference in a new issue