2012-09-22 15:47:52 +02:00
|
|
|
/****************************************************************************
|
|
|
|
* Copyright (C) 2012 FIX94
|
|
|
|
*
|
|
|
|
* This program is free software: you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
****************************************************************************/
|
|
|
|
#include <cstdio>
|
2012-11-03 20:16:03 +01:00
|
|
|
#include <algorithm>
|
2018-11-03 16:03:58 +01:00
|
|
|
#include <fstream>
|
|
|
|
|
2012-09-22 15:47:52 +02:00
|
|
|
#include "MusicPlayer.hpp"
|
|
|
|
#include "SoundHandler.hpp"
|
2018-11-03 16:03:58 +01:00
|
|
|
#include "devicemounter/DeviceHandler.hpp"
|
2012-10-04 13:37:53 +02:00
|
|
|
#include "list/ListGenerator.hpp"
|
2012-09-22 15:47:52 +02:00
|
|
|
#include "gui/text.hpp"
|
2012-12-08 17:17:35 +01:00
|
|
|
#include "gecko/gecko.hpp"
|
2012-09-22 15:47:52 +02:00
|
|
|
|
2012-10-04 13:37:53 +02:00
|
|
|
#define MUSIC_DEPTH 10
|
2012-09-22 15:47:52 +02:00
|
|
|
Musicplayer MusicPlayer;
|
|
|
|
|
2012-10-06 18:38:21 +02:00
|
|
|
static vector<string> FileNames;
|
|
|
|
static vector<string>::const_iterator CurrentFileName;
|
|
|
|
|
2012-09-22 15:47:52 +02:00
|
|
|
void Musicplayer::Cleanup()
|
|
|
|
{
|
|
|
|
Stop();
|
|
|
|
DisplayTime = 0;
|
|
|
|
CurrentPosition = 0;
|
|
|
|
MusicChanged = false;
|
|
|
|
MusicStopped = true;
|
|
|
|
FileNames.clear();
|
|
|
|
}
|
|
|
|
|
2012-10-06 18:38:21 +02:00
|
|
|
static inline void FileNameAdder(char *Path)
|
|
|
|
{
|
|
|
|
/* No need for more checks */
|
|
|
|
FileNames.push_back(Path);
|
|
|
|
}
|
|
|
|
|
2012-10-04 13:37:53 +02:00
|
|
|
void Musicplayer::Init(Config &cfg, const string& musicDir, const string& themeMusicDir)
|
2012-09-22 15:47:52 +02:00
|
|
|
{
|
2018-11-03 16:03:58 +01:00
|
|
|
if(usingPlaylist)
|
|
|
|
{
|
|
|
|
InitPlaylist(cfg, curPlaylist, pl_device);
|
|
|
|
return;
|
|
|
|
}
|
2012-09-22 15:47:52 +02:00
|
|
|
Cleanup();
|
|
|
|
FadeRate = cfg.getInt("GENERAL", "music_fade_rate", 8);
|
|
|
|
Volume = cfg.getInt("GENERAL", "sound_volume_music", 255);
|
|
|
|
|
|
|
|
MusicFile.SetVoice(0);
|
2020-09-01 01:23:52 +02:00
|
|
|
SetVolume(0);
|
2012-09-22 15:47:52 +02:00
|
|
|
|
2012-10-04 13:37:53 +02:00
|
|
|
vector<string> Types = stringToVector(".mp3|.ogg", '|');
|
2012-10-06 18:38:21 +02:00
|
|
|
GetFiles(musicDir.c_str(), Types, FileNameAdder, false, MUSIC_DEPTH);
|
|
|
|
GetFiles(themeMusicDir.c_str(), Types, FileNameAdder, false, MUSIC_DEPTH);
|
2012-09-22 15:47:52 +02:00
|
|
|
if(cfg.getBool("GENERAL", "randomize_music", true) && FileNames.size() > 0)
|
|
|
|
{
|
|
|
|
srand(unsigned(time(NULL)));
|
|
|
|
random_shuffle(FileNames.begin(), FileNames.end());
|
|
|
|
}
|
2018-11-03 16:03:58 +01:00
|
|
|
usingPlaylist = false;
|
|
|
|
OneSong = (FileNames.size() == 1);
|
|
|
|
CurrentFileName = FileNames.begin();
|
|
|
|
}
|
|
|
|
|
|
|
|
int Musicplayer::InitPlaylist(Config &cfg, const char *playlist, u8 device)
|
|
|
|
{
|
2021-09-06 21:16:45 +02:00
|
|
|
std::ifstream filestr;
|
2018-11-03 16:03:58 +01:00
|
|
|
filestr.open(playlist);
|
|
|
|
|
|
|
|
if(filestr.fail())
|
|
|
|
return 0;
|
|
|
|
|
2021-09-06 21:16:45 +02:00
|
|
|
filestr.seekg(0, std::ios_base::end);
|
2018-11-03 16:03:58 +01:00
|
|
|
int size = filestr.tellg();
|
|
|
|
if(size <= 0)
|
|
|
|
return -1;
|
2021-09-06 21:16:45 +02:00
|
|
|
filestr.seekg(0, std::ios_base::beg);
|
2018-11-03 16:03:58 +01:00
|
|
|
|
|
|
|
string song;
|
|
|
|
FileNames.clear();
|
|
|
|
while(!filestr.eof())
|
|
|
|
{
|
|
|
|
getline(filestr, song, '\r');
|
|
|
|
if(song.find(".mp3") == string::npos && song.find(".ogg") == string::npos)// if not song path continue to next line
|
|
|
|
continue;
|
|
|
|
while(song.find("\\") != string::npos)// convert all '\' to '/'
|
|
|
|
song.replace(song.find("\\"), 1, "/");
|
|
|
|
string::size_type p = song.find("/");// remove drive letter and anything else before first /
|
|
|
|
song.erase(0, p);
|
|
|
|
const char *songPath = fmt("%s:%s", DeviceName[device], song.c_str());
|
|
|
|
FileNames.push_back(songPath);
|
|
|
|
}
|
|
|
|
filestr.close();
|
|
|
|
|
|
|
|
curPlaylist = playlist;
|
|
|
|
usingPlaylist = true;
|
|
|
|
pl_device = device;
|
|
|
|
if(cfg.getBool("GENERAL", "randomize_music", true) && FileNames.size() > 0)
|
|
|
|
{
|
|
|
|
srand(unsigned(time(NULL)));
|
|
|
|
random_shuffle(FileNames.begin(), FileNames.end());
|
|
|
|
}
|
2013-02-23 18:41:26 +01:00
|
|
|
OneSong = (FileNames.size() == 1);
|
2012-09-22 15:47:52 +02:00
|
|
|
CurrentFileName = FileNames.begin();
|
2018-11-03 16:03:58 +01:00
|
|
|
LoadCurrentFile();
|
|
|
|
return 1;
|
2012-09-22 15:47:52 +02:00
|
|
|
}
|
|
|
|
|
2018-10-31 20:51:15 +01:00
|
|
|
void Musicplayer::SetFadeRate(u8 faderate)
|
|
|
|
{
|
|
|
|
FadeRate = faderate;
|
|
|
|
}
|
|
|
|
|
2012-09-22 15:47:52 +02:00
|
|
|
void Musicplayer::SetMaxVolume(u8 volume)
|
|
|
|
{
|
|
|
|
Volume = volume;
|
|
|
|
SetVolume(volume);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Musicplayer::SetVolume(u8 volume)
|
|
|
|
{
|
|
|
|
CurrentVolume = volume;
|
|
|
|
MusicFile.SetVolume(CurrentVolume);
|
|
|
|
}
|
|
|
|
|
2020-05-26 00:17:50 +02:00
|
|
|
void Musicplayer::SetResampleSetting(bool resample)
|
|
|
|
{
|
|
|
|
ResampleSetting = resample;
|
|
|
|
}
|
|
|
|
|
2012-09-22 15:47:52 +02:00
|
|
|
void Musicplayer::Previous()
|
|
|
|
{
|
|
|
|
if(FileNames.empty() || PosFromPrevFile())
|
|
|
|
return;
|
|
|
|
|
|
|
|
if(CurrentFileName == FileNames.begin())
|
|
|
|
CurrentFileName = FileNames.end();
|
2012-10-06 18:38:21 +02:00
|
|
|
--CurrentFileName;
|
2012-09-22 15:47:52 +02:00
|
|
|
LoadCurrentFile();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Musicplayer::Next()
|
|
|
|
{
|
|
|
|
if(FileNames.empty() || PosFromPrevFile())
|
|
|
|
return;
|
|
|
|
|
2012-10-06 18:38:21 +02:00
|
|
|
++CurrentFileName;
|
2012-09-22 15:47:52 +02:00
|
|
|
if(CurrentFileName == FileNames.end())
|
|
|
|
CurrentFileName = FileNames.begin();
|
|
|
|
LoadCurrentFile();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Musicplayer::PosFromPrevFile()
|
|
|
|
{
|
|
|
|
if(!CurrentPosition)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
MusicFile.Load((*CurrentFileName).c_str());
|
2012-10-15 21:16:14 +02:00
|
|
|
SoundHandle.Decoder(MusicFile.GetVoice())->Seek(CurrentPosition);
|
2012-09-22 15:47:52 +02:00
|
|
|
SetVolume(CurrentVolume);
|
|
|
|
MusicFile.Play();
|
|
|
|
CurrentPosition = 0;
|
|
|
|
MusicStopped = false;
|
|
|
|
MusicChanged = false;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Musicplayer::Stop()
|
|
|
|
{
|
|
|
|
if(!MusicFile.IsPlaying())
|
|
|
|
return;
|
2018-11-19 19:14:40 +01:00
|
|
|
MusicFile.Pause();// pause for now
|
2012-10-15 21:16:14 +02:00
|
|
|
CurrentPosition = SoundHandle.Decoder(MusicFile.GetVoice())->Tell();
|
2018-11-19 19:14:40 +01:00
|
|
|
MusicFile.FreeMemory();// does MusicFile.Stop() then frees mem
|
2012-09-22 15:47:52 +02:00
|
|
|
MusicStopped = true;
|
|
|
|
}
|
|
|
|
|
2018-11-19 19:14:40 +01:00
|
|
|
void Musicplayer::Pause()
|
|
|
|
{
|
|
|
|
if(!MusicFile.IsPlaying())
|
|
|
|
return;
|
|
|
|
MusicFile.Pause();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Musicplayer::Resume()
|
|
|
|
{
|
|
|
|
MusicFile.Resume();
|
|
|
|
}
|
|
|
|
|
2016-06-10 01:02:40 +02:00
|
|
|
void Musicplayer::Tick(bool attenuate)// attenuate means fade to zero volume
|
2012-09-22 15:47:52 +02:00
|
|
|
{
|
|
|
|
if(FileNames.empty())
|
|
|
|
return;
|
|
|
|
if(!attenuate && CurrentVolume < Volume)
|
|
|
|
SetVolume(CurrentVolume + FadeRate > Volume ? Volume : CurrentVolume + FadeRate);
|
|
|
|
else if(attenuate && CurrentVolume > 0)
|
|
|
|
SetVolume(CurrentVolume - FadeRate < 0 ? 0 : CurrentVolume - FadeRate);
|
|
|
|
if(!attenuate && !MusicFile.IsPlaying())
|
|
|
|
Next();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Musicplayer::LoadCurrentFile()
|
|
|
|
{
|
2013-03-23 18:06:06 +01:00
|
|
|
LoadFile(CurrentFileName->c_str());
|
|
|
|
}
|
|
|
|
|
|
|
|
void Musicplayer::LoadFile(const char *name, bool display_change)
|
|
|
|
{
|
2013-04-20 21:24:04 +02:00
|
|
|
if(FileNames.empty())
|
2013-04-20 21:50:09 +02:00
|
|
|
{
|
2013-04-20 21:24:04 +02:00
|
|
|
FileNames.push_back(PLUGIN_DOMAIN);
|
2013-04-20 21:50:09 +02:00
|
|
|
CurrentFileName = FileNames.begin();
|
|
|
|
}
|
2013-04-20 21:24:04 +02:00
|
|
|
else if(FileNames.size() == 1 && strcmp(name, PLUGIN_DOMAIN) == 0)
|
|
|
|
{
|
2018-06-27 14:47:03 +02:00
|
|
|
MusicFile.FreeMemory();// GuiSound is MusicFile in gui_sound.cpp
|
2013-04-21 13:59:58 +02:00
|
|
|
MusicStopped = true;
|
2013-04-20 21:24:04 +02:00
|
|
|
return;
|
|
|
|
}
|
2013-03-23 18:06:06 +01:00
|
|
|
MusicFile.Load(name);
|
2012-09-22 15:47:52 +02:00
|
|
|
SetVolume(CurrentVolume);
|
|
|
|
MusicFile.Play();
|
|
|
|
CurrentPosition = 0;
|
|
|
|
MusicStopped = false;
|
2013-03-23 18:06:06 +01:00
|
|
|
MusicChanged = display_change;
|
2012-09-22 15:47:52 +02:00
|
|
|
}
|
|
|
|
|
2020-09-01 01:23:52 +02:00
|
|
|
void Musicplayer::ReLoadCurrentFile()
|
|
|
|
{
|
|
|
|
char curFile[1024];
|
|
|
|
strcpy(curFile, MusicFile.GetName());
|
|
|
|
if(strlen(curFile) == 0)
|
|
|
|
return;
|
|
|
|
Stop();
|
|
|
|
LoadFile(curFile, false);
|
|
|
|
}
|
|
|
|
|
2012-09-22 15:47:52 +02:00
|
|
|
/* For our GUI */
|
|
|
|
wstringEx Musicplayer::GetFileName()
|
|
|
|
{
|
|
|
|
wstringEx CurrentFile;
|
|
|
|
string CurrentFileStr((*CurrentFileName).begin()+(*CurrentFileName).find_last_of('/')+1,
|
|
|
|
(*CurrentFileName).begin()+(*CurrentFileName).find_last_of('.'));
|
|
|
|
CurrentFile.fromUTF8(CurrentFileStr.c_str());
|
|
|
|
return CurrentFile;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Musicplayer::SongChanged()
|
|
|
|
{
|
|
|
|
if(!MusicChanged)
|
|
|
|
return false;
|
|
|
|
MusicChanged = false;
|
|
|
|
return true;
|
|
|
|
}
|