mirror of
https://github.com/tuxbox-fork-migrations/recycled-ni-neutrino.git
synced 2025-08-27 07:22:57 +02:00
git-svn-id: file:///home/bas/coolstream_public_svn/THIRDPARTY/applications/neutrino-experimental@238 e54a6e83-5905-42d5-8d5c-058d10e6a962
Origin commit data
------------------
Branch: ni/coolstream
Commit: 529b5dce7c
Author: [CST] Focus <focus.cst@gmail.com>
Date: 2010-01-31 (Sun, 31 Jan 2010)
------------------
This commit was generated by Migit
2887 lines
80 KiB
C++
2887 lines
80 KiB
C++
/*
|
|
$Id: audioplayer.cpp,v 1.80 2009/10/18 14:38:03 dbt Exp $
|
|
Neutrino-GUI - DBoxII-Project
|
|
|
|
AudioPlayer by Dirch,Zwen
|
|
|
|
(C) 2002-2008 the tuxbox project contributors
|
|
(C) 2008 Novell, Inc. Author: Stefan Seyfried
|
|
|
|
Homepage: http://dbox.cyberphoria.org/
|
|
|
|
Kommentar:
|
|
|
|
Diese GUI wurde von Grund auf neu programmiert und sollte nun vom
|
|
Aufbau und auch den Ausbaumoeglichkeiten gut aussehen. Neutrino basiert
|
|
auf der Client-Server Idee, diese GUI ist also von der direkten DBox-
|
|
Steuerung getrennt. Diese wird dann von Daemons uebernommen.
|
|
|
|
|
|
License: GPL
|
|
|
|
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 2 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, write to the Free Software
|
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include <config.h>
|
|
#endif
|
|
|
|
#include <gui/audioplayer.h>
|
|
|
|
#include <global.h>
|
|
#include <neutrino.h>
|
|
|
|
#include <driver/encoding.h>
|
|
#include <driver/fontrenderer.h>
|
|
#include <driver/rcinput.h>
|
|
#include <driver/audioplay.h>
|
|
#include <driver/audiometadata.h>
|
|
|
|
#include <daemonc/remotecontrol.h>
|
|
|
|
#include <gui/eventlist.h>
|
|
#include <gui/color.h>
|
|
#include <gui/infoviewer.h>
|
|
#ifdef ENABLE_GUI_MOUNT
|
|
#include <gui/nfs.h>
|
|
#endif
|
|
|
|
#include <gui/widget/buttons.h>
|
|
#include <gui/widget/icons.h>
|
|
#include <gui/widget/menue.h>
|
|
#include <gui/widget/messagebox.h>
|
|
#include <gui/widget/hintbox.h>
|
|
#include <gui/widget/stringinput.h>
|
|
#include <gui/widget/stringinput_ext.h>
|
|
|
|
#include <system/settings.h>
|
|
#include <xmltree/xmlinterface.h>
|
|
#include <driver/screen_max.h>
|
|
|
|
#include <algorithm>
|
|
#include <sys/time.h>
|
|
#include <fstream>
|
|
#include <iostream>
|
|
#include <sstream>
|
|
|
|
#if 0
|
|
#ifdef ENABLE_LIRC
|
|
#include <irsend/irsend.h>
|
|
#endif
|
|
|
|
#if HAVE_DVB_API_VERSION >= 3
|
|
#include <linux/dvb/audio.h>
|
|
#include <linux/dvb/dmx.h>
|
|
#include <linux/dvb/video.h>
|
|
#define ADAP "/dev/dvb/adapter0"
|
|
#define ADEC ADAP "/audio0"
|
|
#define VDEC ADAP "/video0"
|
|
#define DMX ADAP "/demux0"
|
|
#define DVR ADAP "/dvr0"
|
|
#endif
|
|
#endif
|
|
|
|
#include <video_cs.h>
|
|
extern cVideo * videoDecoder;
|
|
|
|
#ifdef ConnectLineBox_Width
|
|
#undef ConnectLineBox_Width
|
|
#endif
|
|
#define ConnectLineBox_Width 16
|
|
|
|
#define AUDIOPLAYERGUI_SMSKEY_TIMEOUT 1000
|
|
#define SHOW_FILE_LOAD_LIMIT 50
|
|
|
|
//#define AUDIOPLAYER_TIME_DEBUG
|
|
|
|
// check if files to be added are already in the playlist
|
|
#define AUDIOPLAYER_CHECK_FOR_DUPLICATES
|
|
#define AUDIOPLAYER_START_SCRIPT CONFIGDIR "/audioplayer.start"
|
|
#define AUDIOPLAYER_END_SCRIPT CONFIGDIR "/audioplayer.end"
|
|
#define DEFAULT_RADIOSTATIONS_XMLFILE CONFIGDIR "/radio-stations.xml"
|
|
|
|
const long int GET_PLAYLIST_TIMEOUT = 10;
|
|
const char RADIO_STATION_XML_FILE[] = {DEFAULT_RADIOSTATIONS_XMLFILE};
|
|
|
|
const std::string icecasturl = "http://dir.xiph.org/yp.xml";
|
|
const long int GET_ICECAST_TIMEOUT = 90; // list is about 500kB!
|
|
|
|
CAudiofileExt::CAudiofileExt()
|
|
: CAudiofile(), firstChar('\0')
|
|
{
|
|
}
|
|
|
|
CAudiofileExt::CAudiofileExt(std::string name, CFile::FileType type)
|
|
: CAudiofile(name, type), firstChar('\0')
|
|
{
|
|
}
|
|
|
|
CAudiofileExt::CAudiofileExt(const CAudiofileExt& src)
|
|
: CAudiofile(src), firstChar(src.firstChar)
|
|
{
|
|
}
|
|
|
|
void CAudiofileExt::operator=(const CAudiofileExt& src)
|
|
{
|
|
if (&src == this)
|
|
return;
|
|
CAudiofile::operator=(src);
|
|
firstChar = src.firstChar;
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------
|
|
|
|
|
|
|
|
#include <curl/curl.h>
|
|
#include <curl/types.h>
|
|
#include <curl/easy.h>
|
|
|
|
struct MemoryStruct {
|
|
char *memory;
|
|
size_t size;
|
|
};
|
|
|
|
static void *myrealloc(void *ptr, size_t size)
|
|
{
|
|
/* There might be a realloc() out there that doesn't like reallocing
|
|
NULL pointers, so we take care of it here */
|
|
if (ptr)
|
|
return realloc(ptr, size);
|
|
else
|
|
return malloc(size);
|
|
}
|
|
|
|
static size_t
|
|
WriteMemoryCallback(void *ptr, size_t size, size_t nmemb, void *data)
|
|
{
|
|
size_t realsize = size * nmemb;
|
|
struct MemoryStruct *mem = (struct MemoryStruct *)data;
|
|
|
|
mem->memory = (char *)myrealloc(mem->memory, mem->size + realsize + 1);
|
|
if (mem->memory) {
|
|
memcpy(&(mem->memory[mem->size]), ptr, realsize);
|
|
mem->size += realsize;
|
|
mem->memory[mem->size] = 0;
|
|
}
|
|
return realsize;
|
|
}
|
|
|
|
// we borrow this from filebrowser
|
|
extern size_t CurlWriteToString(void *ptr, size_t size, size_t nmemb, void *data);
|
|
|
|
CAudioPlayerGui::CAudioPlayerGui(bool /*inetmode*/)
|
|
{
|
|
m_frameBuffer = CFrameBuffer::getInstance();
|
|
m_visible = false;
|
|
m_inetmode = false; //inetmode;//FIXME
|
|
|
|
Init();
|
|
}
|
|
|
|
void CAudioPlayerGui::Init(void)
|
|
{
|
|
stimer = 0;
|
|
m_selected = 0;
|
|
m_metainfo.clear();
|
|
|
|
m_select_title_by_name = g_settings.audioplayer_select_title_by_name==1;
|
|
|
|
if (strlen(g_settings.network_nfs_audioplayerdir)!=0)
|
|
m_Path = g_settings.network_nfs_audioplayerdir;
|
|
else
|
|
m_Path = "/";
|
|
|
|
audiofilefilter.Clear();
|
|
if (m_inetmode) {
|
|
audiofilefilter.addFilter("url");
|
|
audiofilefilter.addFilter("xml");
|
|
audiofilefilter.addFilter("m3u");
|
|
audiofilefilter.addFilter("pls");
|
|
} else {
|
|
audiofilefilter.addFilter("cdr");
|
|
audiofilefilter.addFilter("mp3");
|
|
audiofilefilter.addFilter("m2a");
|
|
audiofilefilter.addFilter("mpa");
|
|
audiofilefilter.addFilter("mp2");
|
|
audiofilefilter.addFilter("m3u");
|
|
audiofilefilter.addFilter("ogg");
|
|
audiofilefilter.addFilter("wav");
|
|
#ifdef ENABLE_FLAC
|
|
audiofilefilter.addFilter("flac");
|
|
#endif
|
|
}
|
|
m_SMSKeyInput.setTimeout(AUDIOPLAYERGUI_SMSKEY_TIMEOUT);
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
|
|
CAudioPlayerGui::~CAudioPlayerGui()
|
|
{
|
|
m_playlist.clear();
|
|
m_radiolist.clear();
|
|
m_filelist.clear();
|
|
m_title2Pos.clear();
|
|
g_Zapit->setStandby (false);
|
|
g_Sectionsd->setPauseScanning (false);
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
int CAudioPlayerGui::exec(CMenuTarget* parent, const std::string &)
|
|
{
|
|
CAudioPlayer::getInstance()->init();
|
|
m_state = CAudioPlayerGui::STOP;
|
|
|
|
m_show_playlist = g_settings.audioplayer_show_playlist==1;
|
|
|
|
if (m_select_title_by_name != (g_settings.audioplayer_select_title_by_name==1))
|
|
{
|
|
if ((g_settings.audioplayer_select_title_by_name == 1)
|
|
&& m_playlistHasChanged)
|
|
{
|
|
buildSearchTree();
|
|
}
|
|
m_select_title_by_name = g_settings.audioplayer_select_title_by_name;
|
|
}
|
|
|
|
if (m_playlist.empty())
|
|
m_current = -1;
|
|
else
|
|
m_current = 0;
|
|
|
|
m_selected = 0;
|
|
//m_width = 710;
|
|
//if((g_settings.screen_EndX - g_settings.screen_StartX) < m_width+ConnectLineBox_Width)
|
|
m_width=(g_settings.screen_EndX - g_settings.screen_StartX) - ConnectLineBox_Width - 5;
|
|
//m_height = 570;
|
|
//if((g_settings.screen_EndY - g_settings.screen_StartY) < m_height)
|
|
m_height = (g_settings.screen_EndY - g_settings.screen_StartY - 5);
|
|
m_sheight = g_Font[SNeutrinoSettings::FONT_TYPE_INFOBAR_SMALL]->getHeight();
|
|
m_buttonHeight = std::min(25, m_sheight);
|
|
m_theight = g_Font[SNeutrinoSettings::FONT_TYPE_MENU_TITLE]->getHeight();
|
|
m_fheight = g_Font[SNeutrinoSettings::FONT_TYPE_MENU]->getHeight();
|
|
m_title_height = m_fheight*2 + 20 + m_sheight + 4;
|
|
m_info_height = m_fheight*2;
|
|
m_listmaxshow = (m_height - m_info_height - m_title_height - m_theight - 2*m_buttonHeight) / (m_fheight);
|
|
m_height = m_theight + m_info_height + m_title_height + 2*m_buttonHeight + m_listmaxshow * m_fheight; // recalc height
|
|
|
|
m_x = getScreenStartX( m_width + ConnectLineBox_Width ) + ConnectLineBox_Width;
|
|
m_y = getScreenStartY( m_height );
|
|
|
|
m_idletime=time(NULL);
|
|
m_screensaver=false;
|
|
|
|
if (parent)
|
|
{
|
|
parent->hide();
|
|
}
|
|
#if 0
|
|
if (g_settings.video_Format != g_settings.video_backgroundFormat)
|
|
g_Controld->setVideoFormat(g_settings.video_backgroundFormat);
|
|
#endif
|
|
bool usedBackground = m_frameBuffer->getuseBackground();
|
|
if (usedBackground)
|
|
m_frameBuffer->saveBackgroundImage();
|
|
|
|
|
|
// set zapit in standby mode
|
|
g_Zapit->stopPlayBack();
|
|
|
|
videoDecoder->ShowPicture(DATADIR "/neutrino/icons/mp3.jpg");
|
|
|
|
// tell neutrino we're in audio mode
|
|
CNeutrinoApp::getInstance()->handleMsg( NeutrinoMessages::CHANGEMODE , NeutrinoMessages::mode_audio );
|
|
#if 0
|
|
// remember last mode
|
|
CZapitClient::responseGetLastChannel firstchannel;
|
|
g_Zapit->getLastChannel(firstchannel.channelNumber, firstchannel.mode);
|
|
if ((firstchannel.mode == 'r') ?
|
|
(CNeutrinoApp::getInstance()->zapto_radio_on_init_done) :
|
|
(CNeutrinoApp::getInstance()->zapto_tv_on_init_done))
|
|
m_LastMode=(CNeutrinoApp::getInstance()->getLastMode() | NeutrinoMessages::norezap);
|
|
else
|
|
m_LastMode=(CNeutrinoApp::getInstance()->getLastMode());
|
|
#endif
|
|
m_LastMode=(CNeutrinoApp::getInstance()->getLastMode());
|
|
// Stop sectionsd
|
|
g_Sectionsd->setPauseScanning(true);
|
|
|
|
puts("[audioplayer.cpp] executing " AUDIOPLAYER_START_SCRIPT ".");
|
|
if (system(AUDIOPLAYER_START_SCRIPT) != 0)
|
|
perror("Datei " AUDIOPLAYER_START_SCRIPT " fehlt.Bitte erstellen, wenn gebraucht.\nFile " AUDIOPLAYER_START_SCRIPT " not found. Please create if needed.\n");
|
|
|
|
show();
|
|
|
|
// Restore previous background
|
|
if (usedBackground)
|
|
m_frameBuffer->restoreBackgroundImage();
|
|
m_frameBuffer->useBackground(usedBackground);
|
|
m_frameBuffer->paintBackground();
|
|
|
|
// Restore last mode
|
|
//t_channel_id channel_id=CNeutrinoApp::getInstance()->channelList->getActiveChannel_ChannelID();
|
|
//g_Zapit->zapTo_serviceID(channel_id);
|
|
//g_Zapit->setStandby(false);
|
|
|
|
puts("[audioplayer.cpp] executing " AUDIOPLAYER_END_SCRIPT ".");
|
|
if (system(AUDIOPLAYER_END_SCRIPT) != 0)
|
|
perror("Datei " AUDIOPLAYER_END_SCRIPT " fehlt. Bitte erstellen, wenn gebraucht.\nFile " AUDIOPLAYER_END_SCRIPT " not found. Please create if needed.\n");
|
|
|
|
// Start Sectionsd
|
|
g_Sectionsd->setPauseScanning(false);
|
|
videoDecoder->StopPicture();
|
|
|
|
CNeutrinoApp::getInstance()->handleMsg( NeutrinoMessages::CHANGEMODE , m_LastMode );
|
|
g_RCInput->postMsg( NeutrinoMessages::SHOW_INFOBAR, 0 );
|
|
|
|
// always exit all
|
|
return menu_return::RETURN_EXIT_ALL;
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
|
|
int CAudioPlayerGui::show()
|
|
{
|
|
neutrino_msg_t msg;
|
|
neutrino_msg_data_t data;
|
|
|
|
int pic_index = 0;
|
|
|
|
int ret = -1;
|
|
|
|
CVFD::getInstance()->setMode(CVFD::MODE_AUDIO);
|
|
paintLCD();
|
|
|
|
bool loop = true;
|
|
bool update = true;
|
|
bool clear_before_update = false;
|
|
m_key_level = 0;
|
|
|
|
while (loop)
|
|
{
|
|
if (!m_screensaver)
|
|
{
|
|
updateMetaData();
|
|
}
|
|
updateTimes();
|
|
|
|
if (CNeutrinoApp::getInstance()->getMode() != NeutrinoMessages::mode_audio)
|
|
{
|
|
// stop if mode was changed in another thread
|
|
loop = false;
|
|
}
|
|
if ((m_state != CAudioPlayerGui::STOP) &&
|
|
(CAudioPlayer::getInstance()->getState() == CBaseDec::STOP) &&
|
|
(!m_playlist.empty()))
|
|
{
|
|
if (m_curr_audiofile.FileType != CFile::STREAM_AUDIO)
|
|
playNext();
|
|
}
|
|
|
|
if (update)
|
|
{
|
|
if (clear_before_update)
|
|
{
|
|
hide();
|
|
clear_before_update = false;
|
|
}
|
|
update = false;
|
|
paint();
|
|
}
|
|
g_RCInput->getMsg(&msg, &data, 10); // 1 sec timeout to update play/stop state display
|
|
|
|
if ( msg == CRCInput::RC_timeout || msg == NeutrinoMessages::EVT_TIMER)
|
|
{
|
|
int timeout = time(NULL) - m_idletime;
|
|
int screensaver_timeout = atoi(g_settings.audioplayer_screensaver);
|
|
if (screensaver_timeout !=0 && timeout > screensaver_timeout*60 && !m_screensaver)
|
|
screensaver(true);
|
|
|
|
if (msg == NeutrinoMessages::EVT_TIMER && data == stimer) {
|
|
if (m_screensaver) {
|
|
char fname[255];
|
|
|
|
sprintf(fname, "%s/mp3-%d.jpg", DATADIR "/neutrino/icons", pic_index);
|
|
|
|
int lret = access(fname, F_OK);
|
|
printf("CAudioPlayerGui::show: new pic %s: %s\n", fname, lret ? "not found" : "found");
|
|
if (lret == 0) {
|
|
pic_index++;
|
|
videoDecoder->StopPicture();
|
|
videoDecoder->ShowPicture(fname);
|
|
} else if (pic_index) {
|
|
pic_index = 0;
|
|
videoDecoder->StopPicture();
|
|
videoDecoder->ShowPicture(DATADIR "/neutrino/icons/mp3.jpg");
|
|
}
|
|
} else
|
|
pic_index = 0;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
m_idletime = time(NULL);
|
|
if (m_screensaver)
|
|
{
|
|
screensaver(false);
|
|
}
|
|
}
|
|
|
|
if ( msg == CRCInput::RC_tv)
|
|
{
|
|
if (m_inetmode) {
|
|
m_inetmode = false;
|
|
m_radiolist = m_playlist;
|
|
m_playlist = m_filelist;
|
|
} else {
|
|
m_inetmode = true;
|
|
m_filelist = m_playlist;
|
|
m_playlist = m_radiolist;
|
|
}
|
|
Init();
|
|
clear_before_update = true;
|
|
update = true;
|
|
}
|
|
else if (msg == CRCInput::RC_home || msg == CRCInput::RC_stop)
|
|
{
|
|
if (m_state != CAudioPlayerGui::STOP)
|
|
stop();
|
|
else
|
|
loop=false;
|
|
}
|
|
else if (msg == CRCInput::RC_left)
|
|
{
|
|
if (m_key_level == 1)
|
|
{
|
|
playPrev();
|
|
}
|
|
else
|
|
{
|
|
if (!m_show_playlist)
|
|
{
|
|
m_current--;
|
|
if (m_current < 0)
|
|
m_current = m_playlist.size()-1;
|
|
update = true;
|
|
}
|
|
else if (!m_playlist.empty())
|
|
{
|
|
if (m_selected < m_listmaxshow)
|
|
{
|
|
m_selected = m_playlist.size()-1;
|
|
}
|
|
else
|
|
m_selected -= m_listmaxshow;
|
|
m_liststart = (m_selected / m_listmaxshow) * m_listmaxshow;
|
|
update = true;
|
|
}
|
|
}
|
|
|
|
}
|
|
else if (msg == CRCInput::RC_right)
|
|
{
|
|
if (m_key_level == 1)
|
|
{
|
|
playNext();
|
|
}
|
|
else
|
|
{
|
|
if (!m_show_playlist)
|
|
{
|
|
m_current++;
|
|
if (m_current >= (int)m_playlist.size())
|
|
m_current = 0;
|
|
update = true;
|
|
}
|
|
else if (!m_playlist.empty())
|
|
{
|
|
m_selected += m_listmaxshow;
|
|
if (m_selected >= m_playlist.size()) {
|
|
if (((m_playlist.size() / m_listmaxshow) + 1) * m_listmaxshow == m_playlist.size() + m_listmaxshow)
|
|
m_selected = 0;
|
|
else
|
|
m_selected = m_selected < (((m_playlist.size() / m_listmaxshow) + 1) * m_listmaxshow) ? (m_playlist.size()-1) : 0;
|
|
}
|
|
m_liststart = (m_selected / m_listmaxshow) * m_listmaxshow;
|
|
update = true;
|
|
}
|
|
}
|
|
}
|
|
else if ((msg &~ CRCInput::RC_Repeat) == CRCInput::RC_up || (msg &~ CRCInput::RC_Repeat) == CRCInput::RC_page_up)
|
|
{
|
|
if (m_show_playlist && !m_playlist.empty() )
|
|
{
|
|
int step = 0;
|
|
int prevselected = m_selected;
|
|
|
|
step = msg == CRCInput::RC_page_up ? m_listmaxshow : 1;
|
|
m_selected -= step;
|
|
if ((prevselected-step) < 0)
|
|
m_selected = m_playlist.size()-1;
|
|
#if 0
|
|
if (m_selected == 0)
|
|
{
|
|
m_selected = m_playlist.size()-1;
|
|
}
|
|
else
|
|
{
|
|
m_selected--;
|
|
}
|
|
#endif
|
|
paintItem(prevselected - m_liststart);
|
|
unsigned int oldliststart = m_liststart;
|
|
m_liststart = (m_selected/m_listmaxshow)*m_listmaxshow;
|
|
if (oldliststart != m_liststart)
|
|
{
|
|
update = true;
|
|
}
|
|
else
|
|
{
|
|
paintItem(m_selected - m_liststart);
|
|
}
|
|
}
|
|
}
|
|
else if ((msg &~ CRCInput::RC_Repeat) == CRCInput::RC_down || (msg &~ CRCInput::RC_Repeat) == CRCInput::RC_page_down)
|
|
{
|
|
if (m_show_playlist && !m_playlist.empty() )
|
|
{
|
|
int prevselected = m_selected;
|
|
unsigned int step = msg == CRCInput::RC_page_down ? m_listmaxshow : 1;
|
|
m_selected += step;
|
|
|
|
if (m_selected >= m_playlist.size()) {
|
|
if (((m_playlist.size() / m_listmaxshow) + 1) * m_listmaxshow == m_playlist.size() + m_listmaxshow) // last page has full entries
|
|
m_selected = 0;
|
|
else
|
|
m_selected = ((step == m_listmaxshow) && (m_selected < (((m_playlist.size() / m_listmaxshow)+1) * m_listmaxshow))) ? (m_playlist.size() - 1) : 0;
|
|
}
|
|
//m_selected = (m_selected + 1) % m_playlist.size();
|
|
|
|
paintItem(prevselected - m_liststart);
|
|
unsigned int oldliststart = m_liststart;
|
|
m_liststart = (m_selected/m_listmaxshow)*m_listmaxshow;
|
|
if (oldliststart != m_liststart)
|
|
{
|
|
update = true;
|
|
}
|
|
else
|
|
{
|
|
paintItem(m_selected - m_liststart);
|
|
}
|
|
}
|
|
}
|
|
else if (msg == CRCInput::RC_ok || msg == CRCInput::RC_play)
|
|
{
|
|
if (!m_playlist.empty()) {
|
|
if (!m_show_playlist)
|
|
play(m_current);
|
|
else
|
|
play(m_selected);
|
|
}
|
|
}
|
|
else if (msg == CRCInput::RC_red)
|
|
{
|
|
if (m_key_level == 0)
|
|
{
|
|
if (!m_playlist.empty())
|
|
{
|
|
//xx CPlayList::iterator p = m_playlist.begin()+selected;
|
|
removeFromPlaylist(m_selected);
|
|
if ((int)m_selected == m_current)
|
|
{
|
|
m_current--;
|
|
//stop(); // Stop if song is deleted, next song will be startet automat.
|
|
}
|
|
if (m_selected >= m_playlist.size())
|
|
m_selected = m_playlist.size() == 0 ? m_playlist.size() : m_playlist.size() - 1;
|
|
update = true;
|
|
}
|
|
}
|
|
else if (m_key_level == 1)
|
|
{
|
|
stop();
|
|
}
|
|
else
|
|
{
|
|
// key_level==2
|
|
}
|
|
|
|
}
|
|
else if (msg == CRCInput::RC_stop)
|
|
{
|
|
if (m_key_level == 1)
|
|
stop();
|
|
}
|
|
else if (msg == CRCInput::RC_green)
|
|
{
|
|
if (m_key_level == 0)
|
|
{
|
|
openFilebrowser();
|
|
update=true;
|
|
}
|
|
else if (m_key_level == 1)
|
|
{
|
|
if (m_curr_audiofile.FileType != CFile::STREAM_AUDIO)
|
|
rev();
|
|
}
|
|
else
|
|
{ // key_level == 2
|
|
|
|
if (m_state == CAudioPlayerGui::STOP)
|
|
{
|
|
if (!m_playlist.empty())
|
|
{
|
|
savePlaylist();
|
|
CVFD::getInstance()->setMode(CVFD::MODE_AUDIO);
|
|
paintLCD();
|
|
update = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// keylevel 2 can only be reached if the currently played file
|
|
// is no stream, so we do not have to test for this case
|
|
int seconds=0;
|
|
CIntInput secondsInput(LOCALE_AUDIOPLAYER_JUMP_DIALOG_TITLE,
|
|
seconds,
|
|
5,
|
|
LOCALE_AUDIOPLAYER_JUMP_DIALOG_HINT1,
|
|
LOCALE_AUDIOPLAYER_JUMP_DIALOG_HINT2);
|
|
int res = secondsInput.exec(NULL,"");
|
|
if (seconds != 0 && res!= menu_return::RETURN_EXIT_ALL)
|
|
rev(seconds);
|
|
update=true;
|
|
}
|
|
}
|
|
}
|
|
else if (msg == CRCInput::RC_yellow)
|
|
{
|
|
if (m_key_level == 0)
|
|
{
|
|
if (!m_playlist.empty())
|
|
{
|
|
//stop();
|
|
clearPlaylist();
|
|
clear_before_update = true;
|
|
update = true;
|
|
}
|
|
}
|
|
else if (m_key_level == 1)
|
|
{
|
|
pause();
|
|
}
|
|
else
|
|
{ // key_level==2
|
|
m_select_title_by_name =! m_select_title_by_name;
|
|
if (m_select_title_by_name && m_playlistHasChanged)
|
|
buildSearchTree();
|
|
paint();
|
|
}
|
|
}
|
|
else if (msg == CRCInput::RC_blue)
|
|
{
|
|
if (m_key_level == 0)
|
|
{
|
|
if (m_inetmode) {
|
|
static int old_select = 0;
|
|
char cnt[5];
|
|
CMenuWidget InputSelector(LOCALE_AUDIOPLAYER_LOAD_RADIO_STATIONS, NEUTRINO_ICON_AUDIO, 400);
|
|
int count = 0;
|
|
int select = -1;
|
|
CMenuSelectorTarget *InetRadioInputChanger = new CMenuSelectorTarget(&select);
|
|
// -- setup menue for inetradio input
|
|
sprintf(cnt, "%d", count);
|
|
InputSelector.addItem(new CMenuForwarder(
|
|
LOCALE_AUDIOPLAYER_ADD_LOC, true, NULL, InetRadioInputChanger,
|
|
cnt, CRCInput::convertDigitToKey(count + 1)), old_select == count);
|
|
|
|
sprintf(cnt, "%d", ++count);
|
|
InputSelector.addItem(new CMenuForwarder(
|
|
LOCALE_AUDIOPLAYER_ADD_SC, true, NULL, InetRadioInputChanger,
|
|
cnt, CRCInput::convertDigitToKey(count + 1)), old_select == count);
|
|
|
|
sprintf(cnt, "%d", ++count);
|
|
InputSelector.addItem(new CMenuForwarder(
|
|
LOCALE_AUDIOPLAYER_ADD_IC, true, NULL, InetRadioInputChanger,
|
|
cnt, CRCInput::convertDigitToKey(count + 1)), old_select == count);
|
|
|
|
//InputSelector.addItem(GenericMenuSeparator);
|
|
hide();
|
|
InputSelector.exec(NULL, "");
|
|
if (select >= 0)
|
|
old_select = select;
|
|
switch (select) {
|
|
case 0:
|
|
scanXmlFile(RADIO_STATION_XML_FILE);
|
|
CVFD::getInstance()->setMode(CVFD::MODE_AUDIO);
|
|
paintLCD();
|
|
break;
|
|
case 1:
|
|
openSCbrowser();
|
|
break;
|
|
case 2:
|
|
readDir_ic();
|
|
CVFD::getInstance()->setMode(CVFD::MODE_AUDIO);
|
|
paintLCD();
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
update=true;
|
|
}
|
|
else if ( shufflePlaylist() )
|
|
{
|
|
update = true;
|
|
}
|
|
}
|
|
else if (m_key_level == 1)
|
|
{
|
|
if (m_curr_audiofile.FileType != CFile::STREAM_AUDIO)
|
|
ff();
|
|
}
|
|
else // key_level == 2
|
|
{
|
|
if (m_state != CAudioPlayerGui::STOP)
|
|
{
|
|
// keylevel 2 can only be reached if the currently played file
|
|
// is no stream, so we do not have to test for this case
|
|
int seconds=0;
|
|
CIntInput secondsInput(LOCALE_AUDIOPLAYER_JUMP_DIALOG_TITLE,
|
|
seconds,
|
|
5,
|
|
LOCALE_AUDIOPLAYER_JUMP_DIALOG_HINT1,
|
|
LOCALE_AUDIOPLAYER_JUMP_DIALOG_HINT2);
|
|
int res = secondsInput.exec(NULL,"");
|
|
if (seconds != 0 && res!= menu_return::RETURN_EXIT_ALL)
|
|
ff(seconds);
|
|
update = true;
|
|
}
|
|
}
|
|
}
|
|
else if (msg == CRCInput::RC_help)
|
|
{
|
|
if (m_key_level == 2)
|
|
m_key_level = 0;
|
|
else
|
|
m_key_level++;
|
|
|
|
if (m_state != CAudioPlayerGui::STOP)
|
|
{
|
|
// jumping in streams not supported
|
|
if (m_key_level == 2 &&
|
|
m_curr_audiofile.FileType == CFile::STREAM_AUDIO)
|
|
{
|
|
m_key_level = 0;
|
|
}
|
|
}
|
|
// there are only two keylevels in the "STOP"-case
|
|
else if (m_key_level == 1)
|
|
{
|
|
m_key_level = 2;
|
|
}
|
|
paintFoot();
|
|
}
|
|
else if (msg == CRCInput::RC_0)
|
|
{
|
|
if (m_current >= 0)
|
|
{
|
|
m_selected = m_current;
|
|
update = true;
|
|
}
|
|
}
|
|
else if (CRCInput::isNumeric(msg) && !(m_playlist.empty()))
|
|
{ //numeric zap or SMS zap
|
|
if (m_select_title_by_name)
|
|
{
|
|
//printf("select by name\n");
|
|
unsigned char smsKey = 0;
|
|
do
|
|
{
|
|
smsKey = m_SMSKeyInput.handleMsg(msg);
|
|
//printf(" new key: %c", smsKey);
|
|
g_RCInput->getMsg_ms(&msg, &data, AUDIOPLAYERGUI_SMSKEY_TIMEOUT - 200);
|
|
|
|
|
|
/* show a hint box with current char (too slow at the moment?)*/
|
|
#if 1
|
|
char selectedKey[1];
|
|
sprintf(selectedKey,"%c",smsKey);
|
|
int x1=(g_settings.screen_EndX- g_settings.screen_StartX)/2 + g_settings.screen_StartX-50;
|
|
int y1=(g_settings.screen_EndY- g_settings.screen_StartY)/2 + g_settings.screen_StartY;
|
|
int h = g_Font[SNeutrinoSettings::FONT_TYPE_CHANNEL_NUM_ZAP]->getHeight();
|
|
int w = g_Font[SNeutrinoSettings::FONT_TYPE_CHANNEL_NUM_ZAP]->getRenderWidth(selectedKey);
|
|
m_frameBuffer->paintBoxRel(x1 - 7, y1 - h - 5, w + 14, h + 10, COL_MENUCONTENT_PLUS_6);
|
|
m_frameBuffer->paintBoxRel(x1 - 4, y1 - h - 3, w + 8, h + 6, COL_MENUCONTENTSELECTED_PLUS_0);
|
|
g_Font[SNeutrinoSettings::FONT_TYPE_CHANNEL_NUM_ZAP]
|
|
->RenderString(x1,y1,w+1,selectedKey,COL_MENUCONTENTSELECTED,0);
|
|
#endif
|
|
|
|
} while (CRCInput::isNumeric(msg) && !(m_playlist.empty()));
|
|
|
|
if (msg == CRCInput::RC_timeout
|
|
|| msg == CRCInput::RC_nokey)
|
|
{
|
|
//printf("selected key: %c\n",smsKey);
|
|
selectTitle(smsKey);
|
|
update = true;
|
|
}
|
|
m_SMSKeyInput.resetOldKey();
|
|
}
|
|
else
|
|
{
|
|
//printf("numeric zap\n");
|
|
int val = 0;
|
|
if (getNumericInput(msg,val))
|
|
m_selected = std::min((int)m_playlist.size(), val) - 1;
|
|
update = true;
|
|
}
|
|
|
|
}
|
|
|
|
#ifdef ENABLE_GUI_MOUNT
|
|
else if ((msg == CRCInput::RC_setup) && !m_inetmode)
|
|
{
|
|
CNFSSmallMenu nfsMenu;
|
|
nfsMenu.exec(this, "");
|
|
CVFD::getInstance()->setMode(CVFD::MODE_AUDIO);
|
|
paintLCD();
|
|
update = true;
|
|
//pushback key if...
|
|
//g_RCInput->postMsg( msg, data );
|
|
//loop = false;
|
|
}
|
|
#endif
|
|
else if (msg == NeutrinoMessages::CHANGEMODE)
|
|
{
|
|
if ((data & NeutrinoMessages::mode_mask) != NeutrinoMessages::mode_audio)
|
|
{
|
|
loop = false;
|
|
m_LastMode=data;
|
|
}
|
|
}
|
|
else if (msg == NeutrinoMessages::RECORD_START ||
|
|
msg == NeutrinoMessages::ZAPTO ||
|
|
msg == NeutrinoMessages::STANDBY_ON ||
|
|
msg == NeutrinoMessages::SHUTDOWN ||
|
|
msg == NeutrinoMessages::SLEEPTIMER)
|
|
{
|
|
// Exit for Record/Zapto Timers
|
|
loop = false;
|
|
g_RCInput->postMsg(msg, data);
|
|
}
|
|
else if (msg == NeutrinoMessages::EVT_TIMER)
|
|
{
|
|
CNeutrinoApp::getInstance()->handleMsg( msg, data );
|
|
}
|
|
else
|
|
{
|
|
if ( CNeutrinoApp::getInstance()->handleMsg( msg, data ) & messages_return::cancel_all )
|
|
{
|
|
loop = false;
|
|
}
|
|
// update mute icon
|
|
//paintHead();
|
|
//paintLCD();
|
|
}
|
|
}
|
|
hide();
|
|
|
|
if (m_state != CAudioPlayerGui::STOP)
|
|
stop();
|
|
|
|
return ret;
|
|
}
|
|
|
|
bool CAudioPlayerGui::playNext(bool allow_rotate)
|
|
{
|
|
bool result = false;
|
|
|
|
if (!(m_playlist.empty()))
|
|
{
|
|
int next = getNext();
|
|
if (next >= 0)
|
|
play(next);
|
|
else if (allow_rotate)
|
|
play(0);
|
|
else
|
|
stop();
|
|
result = true;
|
|
}
|
|
|
|
return(result);
|
|
}
|
|
|
|
bool CAudioPlayerGui::playPrev(bool allow_rotate)
|
|
{
|
|
bool result = false;
|
|
|
|
if (!(m_playlist.empty()))
|
|
{
|
|
if (m_current == -1)
|
|
stop();
|
|
else if (m_current-1 > 0)
|
|
play(m_current-1);
|
|
else if (allow_rotate)
|
|
play(m_playlist.size()-1);
|
|
else
|
|
play(0);
|
|
result = true;
|
|
}
|
|
|
|
return(result);
|
|
}
|
|
|
|
bool CAudioPlayerGui::clearPlaylist(void)
|
|
{
|
|
bool result = false;
|
|
|
|
if (!(m_playlist.empty()))
|
|
{
|
|
m_playlist.clear();
|
|
m_current = -1;
|
|
m_selected = 0;
|
|
m_title2Pos.clear();
|
|
result = true;
|
|
}
|
|
return(result);
|
|
}
|
|
|
|
bool CAudioPlayerGui::shufflePlaylist(void)
|
|
{
|
|
RandomNumber rnd;
|
|
bool result = false;
|
|
if (!(m_playlist.empty()))
|
|
{
|
|
if (m_current > 0)
|
|
{
|
|
std::swap(m_playlist[0], m_playlist[m_current]);
|
|
m_current = 0;
|
|
}
|
|
|
|
std::random_shuffle((m_current != 0) ? m_playlist.begin() : m_playlist.begin() + 1, m_playlist.end(), rnd);
|
|
if (m_select_title_by_name)
|
|
{
|
|
buildSearchTree();
|
|
}
|
|
m_playlistHasChanged = true;
|
|
m_selected = 0;
|
|
|
|
result = true;
|
|
}
|
|
return(result);
|
|
}
|
|
|
|
void CAudioPlayerGui::addUrl2Playlist(const char *url, const char *name, const time_t bitrate) {
|
|
CAudiofileExt mp3( url, CFile::STREAM_AUDIO );
|
|
// tmp = tmp.substr(0,tmp.length()-4); //remove .url
|
|
//printf("[addUrl2Playlist], name = %s, url = %s\n", name, url);
|
|
if (name != NULL) {
|
|
mp3.MetaData.title = name;
|
|
} else {
|
|
std::string tmp = mp3.Filename.substr(mp3.Filename.rfind('/')+1);
|
|
mp3.MetaData.title = tmp;
|
|
}
|
|
if (bitrate)
|
|
mp3.MetaData.total_time = bitrate;
|
|
else
|
|
mp3.MetaData.total_time = 0;
|
|
|
|
if (url[0] != '#') {
|
|
addToPlaylist(mp3);
|
|
}
|
|
}
|
|
|
|
void CAudioPlayerGui::processPlaylistUrl(const char *url, const char *name, const time_t tim) {
|
|
CURL *curl_handle;
|
|
struct MemoryStruct chunk;
|
|
|
|
printf("CAudioPlayerGui::processPlaylistUrl (%s, %s)\n", url, name);
|
|
chunk.memory=NULL; /* we expect realloc(NULL, size) to work */
|
|
chunk.size = 0; /* no data at this point */
|
|
|
|
curl_global_init(CURL_GLOBAL_ALL);
|
|
|
|
/* init the curl session */
|
|
curl_handle = curl_easy_init();
|
|
|
|
/* specify URL to get */
|
|
curl_easy_setopt(curl_handle, CURLOPT_URL, url);
|
|
|
|
/* send all data to this function */
|
|
curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
|
|
|
|
/* we pass our 'chunk' struct to the callback function */
|
|
curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *)&chunk);
|
|
|
|
/* some servers don't like requests that are made without a user-agent
|
|
field, so we provide one */
|
|
curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "libcurl-agent/1.0");
|
|
|
|
/* don't use signal for timeout */
|
|
curl_easy_setopt(curl_handle, CURLOPT_NOSIGNAL, (long)1);
|
|
|
|
/* set timeout to 10 seconds */
|
|
curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT, GET_PLAYLIST_TIMEOUT);
|
|
|
|
/* get it! */
|
|
curl_easy_perform(curl_handle);
|
|
|
|
/* cleanup curl stuff */
|
|
curl_easy_cleanup(curl_handle);
|
|
|
|
/*
|
|
* Now, our chunk.memory points to a memory block that is chunk.size
|
|
* bytes big and contains the remote file.
|
|
*
|
|
* Do something nice with it!
|
|
*
|
|
* You should be aware of the fact that at this point we might have an
|
|
* allocated data block, and nothing has yet deallocated that data. So when
|
|
* you're done with it, you should free() it as a nice application.
|
|
*/
|
|
|
|
long res_code;
|
|
if (curl_easy_getinfo(curl_handle, CURLINFO_HTTP_CODE/*CURLINFO_RESPONSE_CODE*/, &res_code ) == CURLE_OK) {
|
|
if (200 == res_code) {
|
|
//printf("\nchunk = %s\n", chunk.memory);
|
|
std::istringstream iss;
|
|
iss.str (std::string(chunk.memory, chunk.size));
|
|
char line[512];
|
|
char *ptr;
|
|
while (iss.rdstate() == std::ifstream::goodbit) {
|
|
iss.getline(line, 512);
|
|
if (line[0] != '#') {
|
|
//printf("chunk: line = %s\n", line);
|
|
ptr = strstr(line, "http://");
|
|
if (ptr != NULL) {
|
|
char *tmp;
|
|
// strip \n and \r characters from url
|
|
tmp = strchr(line, '\r');
|
|
if (tmp != NULL)
|
|
*tmp = '\0';
|
|
tmp = strchr(line, '\n');
|
|
if (tmp != NULL)
|
|
*tmp = '\0';
|
|
addUrl2Playlist(ptr, name, tim);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (chunk.memory)
|
|
free(chunk.memory);
|
|
|
|
/* we're done with libcurl, so clean it up */
|
|
curl_global_cleanup();
|
|
}
|
|
|
|
|
|
void CAudioPlayerGui::readDir_ic(void)
|
|
{
|
|
std::string answer="";
|
|
std::cout << "[readDir_ic] IC URL: " << icecasturl << std::endl;
|
|
CURL *curl_handle;
|
|
CURLcode httpres;
|
|
/* init the curl session */
|
|
curl_handle = curl_easy_init();
|
|
/* specify URL to get */
|
|
curl_easy_setopt(curl_handle, CURLOPT_URL, icecasturl.c_str());
|
|
/* send all data to this function */
|
|
curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, CurlWriteToString);
|
|
/* we pass our 'chunk' struct to the callback function */
|
|
curl_easy_setopt(curl_handle, CURLOPT_FILE, (void *)&answer);
|
|
/* Generate error if http error >= 400 occurs */
|
|
curl_easy_setopt(curl_handle, CURLOPT_FAILONERROR, 1);
|
|
/* set timeout to 30 seconds */
|
|
curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT, GET_ICECAST_TIMEOUT);
|
|
|
|
/* error handling */
|
|
char error[CURL_ERROR_SIZE];
|
|
curl_easy_setopt(curl_handle, CURLOPT_ERRORBUFFER, error);
|
|
/* get it! */
|
|
CHintBox *scanBox = new CHintBox(LOCALE_AUDIOPLAYER_ADD_IC, g_Locale->getText(LOCALE_AUDIOPLAYER_RECEIVING_LIST)); // UTF-8
|
|
scanBox->paint();
|
|
|
|
httpres = curl_easy_perform(curl_handle);
|
|
|
|
/* cleanup curl stuff */
|
|
curl_easy_cleanup(curl_handle);
|
|
|
|
//std::cout << "Answer:" << std::endl << "----------------" << std::endl << answer << std::endl;
|
|
|
|
if (!answer.empty() && httpres == 0)
|
|
{
|
|
xmlDocPtr answer_parser = parseXml(answer.c_str());
|
|
scanBox->hide();
|
|
scanXmlData(answer_parser, "server_name", "listen_url", "bitrate", true);
|
|
}
|
|
else
|
|
scanBox->hide();
|
|
|
|
delete scanBox;
|
|
}
|
|
|
|
void CAudioPlayerGui::scanXmlFile(std::string filename)
|
|
{
|
|
xmlDocPtr answer_parser = parseXmlFile(filename.c_str());
|
|
scanXmlData(answer_parser, "name", "url");
|
|
}
|
|
|
|
void CAudioPlayerGui::scanXmlData(xmlDocPtr answer_parser, const char *nametag, const char *urltag,
|
|
const char *bitratetag, bool usechild)
|
|
{
|
|
#define IC_typetag "server_type"
|
|
|
|
if (answer_parser != NULL) {
|
|
xmlNodePtr element = xmlDocGetRootElement(answer_parser);
|
|
element = element->xmlChildrenNode;
|
|
xmlNodePtr element_tmp = element;
|
|
if (element == NULL) {
|
|
printf("[openFilebrowser] No valid XML File.\n");
|
|
} else {
|
|
CProgressWindow progress;
|
|
long maxProgress = 1;
|
|
// count # of entries
|
|
while (element) {
|
|
maxProgress++;
|
|
element = element->xmlNextNode;
|
|
}
|
|
element = element_tmp;
|
|
long listPos = -1;
|
|
progress.setTitle(LOCALE_AUDIOPLAYER_LOAD_RADIO_STATIONS);
|
|
progress.exec(this, "");
|
|
neutrino_msg_t msg;
|
|
neutrino_msg_data_t data;
|
|
g_RCInput->getMsg(&msg, &data, 0);
|
|
while (element && msg != CRCInput::RC_home) {
|
|
char *ptr = NULL;
|
|
char *name = NULL;
|
|
char *url = NULL;
|
|
char *type = NULL;
|
|
time_t bitrate = 0;
|
|
bool skip = true;
|
|
listPos++;
|
|
// show status
|
|
int global = 100*listPos / maxProgress;
|
|
progress.showGlobalStatus(global);
|
|
#ifdef LCD_UPDATE
|
|
CVFD::getInstance()->showProgressBar(global, "read xmldata...");
|
|
CVFD::getInstance()->setMode(CVFD::MODE_PROGRESSBAR);
|
|
#endif // LCD_UPDATE
|
|
|
|
if (usechild) {
|
|
xmlNodePtr child = element->xmlChildrenNode;
|
|
while (child) {
|
|
if (strcmp(xmlGetName(child), nametag) == 0)
|
|
name = xmlGetData(child);
|
|
else if (strcmp(xmlGetName(child), urltag) == 0)
|
|
url = xmlGetData(child);
|
|
else if (strcmp(xmlGetName(child), IC_typetag) == 0)
|
|
type = xmlGetData(child);
|
|
else if (bitratetag && strcmp(xmlGetName(child), bitratetag) == 0) {
|
|
ptr = xmlGetData(child);
|
|
if (ptr)
|
|
bitrate = atoi(ptr);
|
|
}
|
|
child = child->xmlNextNode;
|
|
}
|
|
if (strcmp("audio/mpeg", type) == 0) skip = false;
|
|
else if (strcmp("application/ogg", type) == 0) skip = false;
|
|
else if (strcmp("mp3", type) == 0) skip = false;
|
|
else if (strcmp("application/mp3", type) == 0) skip = false;
|
|
} else {
|
|
url = xmlGetAttribute(element, urltag);
|
|
name = xmlGetAttribute(element, nametag);
|
|
if (bitratetag) {
|
|
ptr = xmlGetAttribute(element, bitratetag);
|
|
if (ptr)
|
|
bitrate = atoi(ptr);
|
|
}
|
|
skip = false;
|
|
}
|
|
|
|
if ((url != NULL) && !skip) {
|
|
progress.showStatusMessageUTF(url);
|
|
//printf("Processing %s, %s\n", url, name);
|
|
if (strstr(url, ".m3u") || strstr(url, ".pls"))
|
|
processPlaylistUrl(url, name);
|
|
else
|
|
addUrl2Playlist(url, name, bitrate);
|
|
}
|
|
element = element->xmlNextNode;
|
|
g_RCInput->getMsg(&msg, &data, 0);
|
|
|
|
}
|
|
progress.hide();
|
|
}
|
|
xmlFreeDoc(answer_parser);
|
|
}
|
|
else
|
|
printf("[scanXmlData] answer_parser == NULL");
|
|
}
|
|
|
|
bool CAudioPlayerGui::openFilebrowser(void)
|
|
{
|
|
bool result = false;
|
|
CFileBrowser filebrowser((g_settings.filebrowser_denydirectoryleave)
|
|
? g_settings.network_nfs_audioplayerdir : "");
|
|
|
|
filebrowser.Multi_Select = true;
|
|
filebrowser.Dirs_Selectable = true;
|
|
filebrowser.Filter = &audiofilefilter;
|
|
|
|
hide();
|
|
|
|
if (filebrowser.exec(m_Path.c_str()))
|
|
{
|
|
#ifdef AUDIOPLAYER_TIME_DEBUG
|
|
timeval start;
|
|
gettimeofday(&start,NULL);
|
|
#endif
|
|
CProgressWindow progress;
|
|
long maxProgress = (filebrowser.getSelectedFiles().size() > 1) ? filebrowser.getSelectedFiles().size() - 1 : 1;
|
|
long currentProgress = -1;
|
|
if (maxProgress > SHOW_FILE_LOAD_LIMIT)
|
|
{
|
|
progress.setTitle(LOCALE_AUDIOPLAYER_READING_FILES);
|
|
progress.exec(this,"");
|
|
}
|
|
|
|
m_Path = filebrowser.getCurrentDir();
|
|
CFileList::const_iterator files = filebrowser.getSelectedFiles().begin();
|
|
for (; files != filebrowser.getSelectedFiles().end(); files++)
|
|
{
|
|
if (maxProgress > SHOW_FILE_LOAD_LIMIT)
|
|
{
|
|
currentProgress++;
|
|
// show status
|
|
int global = 100*currentProgress/maxProgress;
|
|
progress.showGlobalStatus(global);
|
|
progress.showStatusMessageUTF(files->Name);
|
|
#ifdef LCD_UPDATE
|
|
CVFD::getInstance()->showProgressBar(global, "read metadata...");
|
|
CVFD::getInstance()->setMode(CVFD::MODE_PROGRESSBAR);
|
|
#endif // LCD_UPDATE
|
|
}
|
|
if ((files->getType() == CFile::FILE_CDR)
|
|
|| (files->getType() == CFile::FILE_OGG)
|
|
|| (files->getType() == CFile::FILE_MP3)
|
|
|| (files->getType() == CFile::FILE_WAV)
|
|
#ifdef ENABLE_FLAC
|
|
|| (files->getType() == CFile::FILE_FLAC)
|
|
#endif
|
|
)
|
|
{
|
|
CAudiofileExt audiofile(files->Name,
|
|
files->getType());
|
|
addToPlaylist(audiofile);
|
|
}
|
|
if (files->getType() == CFile::STREAM_AUDIO)
|
|
{
|
|
std::string filename = files->Name;
|
|
FILE *fd = fopen(filename.c_str(), "r");
|
|
if (fd)
|
|
{
|
|
char buf[512];
|
|
unsigned int len = fread(buf, sizeof(char), 512, fd);
|
|
fclose(fd);
|
|
|
|
if (len && (strstr(buf, ".m3u") || strstr(buf, ".pls")))
|
|
{
|
|
printf("m3u/pls Playlist found: %s\n", buf);
|
|
filename = buf;
|
|
processPlaylistUrl(buf);
|
|
}
|
|
else
|
|
{
|
|
addUrl2Playlist(filename.c_str());
|
|
}
|
|
}
|
|
}
|
|
else if (files->getType() == CFile::FILE_PLAYLIST)
|
|
{
|
|
std::string sPath = files->Name.substr(0, files->Name.rfind('/'));
|
|
std::ifstream infile;
|
|
char cLine[256];
|
|
infile.open(files->Name.c_str(), std::ifstream::in);
|
|
while (infile.good())
|
|
{
|
|
infile.getline(cLine, 255);
|
|
// remove CR
|
|
if (cLine[strlen(cLine)-1]=='\r')
|
|
cLine[strlen(cLine)-1]=0;
|
|
if (strlen(cLine) > 0 && cLine[0]!='#')
|
|
{
|
|
char *url = strstr(cLine, "http://");
|
|
if (url != NULL) {
|
|
if (strstr(url, ".m3u") || strstr(url, ".pls"))
|
|
processPlaylistUrl(url);
|
|
} else if ((url = strstr(cLine, "icy://")) != NULL) {
|
|
addUrl2Playlist(url);
|
|
} else if ((url = strstr(cLine, "scast:://")) != NULL) {
|
|
addUrl2Playlist(url);
|
|
}
|
|
else
|
|
{
|
|
std::string filename = sPath + '/' + cLine;
|
|
|
|
std::string::size_type pos;
|
|
while ((pos=filename.find('\\'))!=std::string::npos)
|
|
filename[pos]='/';
|
|
|
|
std::ifstream testfile;
|
|
testfile.open(filename.c_str(), std::ifstream::in);
|
|
if (testfile.good())
|
|
{
|
|
#ifdef AUDIOPLAYER_CHECK_FOR_DUPLICATES
|
|
// Check for duplicates and remove (new entry has higher prio)
|
|
// this really needs some time :(
|
|
for (unsigned long i=0; i<m_playlist.size(); i++)
|
|
{
|
|
if (m_playlist[i].Filename == filename)
|
|
removeFromPlaylist(i);
|
|
}
|
|
#endif
|
|
if (strcasecmp(filename.substr(filename.length()-3,3).c_str(), "url")==0)
|
|
{
|
|
addUrl2Playlist(filename.c_str());
|
|
}
|
|
else
|
|
{
|
|
CFile playlistItem;
|
|
playlistItem.Name = filename;
|
|
CFile::FileType fileType = playlistItem.getType();
|
|
if (fileType == CFile::FILE_CDR
|
|
|| fileType == CFile::FILE_MP3
|
|
|| fileType == CFile::FILE_OGG
|
|
|| fileType == CFile::FILE_WAV
|
|
#ifdef ENABLE_FLAC
|
|
|| fileType == CFile::FILE_FLAC
|
|
#endif
|
|
)
|
|
{
|
|
CAudiofileExt audioFile(filename,fileType);
|
|
addToPlaylist(audioFile);
|
|
} else
|
|
{
|
|
printf("Audioplayer: file type (%d) is *not* supported in playlists\n(%s)\n",
|
|
fileType, filename.c_str());
|
|
}
|
|
}
|
|
}
|
|
testfile.close();
|
|
}
|
|
}
|
|
}
|
|
infile.close();
|
|
}
|
|
else if (files->getType() == CFile::FILE_XML)
|
|
{
|
|
if (!files->Name.empty())
|
|
{
|
|
scanXmlFile(files->Name);
|
|
}
|
|
}
|
|
}
|
|
if (m_select_title_by_name)
|
|
{
|
|
buildSearchTree();
|
|
}
|
|
#ifdef AUDIOPLAYER_TIME_DEBUG
|
|
timeval end;
|
|
gettimeofday(&end,NULL);
|
|
printf("adding %ld files took: ",maxProgress+1);
|
|
printTimevalDiff(start,end);
|
|
#endif
|
|
result = true;
|
|
}
|
|
CVFD::getInstance()->setMode(CVFD::MODE_AUDIO);
|
|
paintLCD();
|
|
// if playlist is turned off -> start playing immediately
|
|
if (!m_show_playlist && !m_playlist.empty())
|
|
play(m_selected);
|
|
|
|
return ( result);
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
#define SC_BASE_DIR "http://www.shoutcast.com"
|
|
#define SC_INIT_DIR "/sbin/newxml.phtml"
|
|
bool CAudioPlayerGui::openSCbrowser(void)
|
|
{
|
|
bool result = false;
|
|
CFileBrowser filebrowser(SC_BASE_DIR, CFileBrowser::ModeSC);
|
|
|
|
filebrowser.Multi_Select = true;
|
|
filebrowser.Dirs_Selectable = true;
|
|
filebrowser.Filter = NULL;//&audiofilefilter;
|
|
|
|
hide();
|
|
|
|
if (filebrowser.exec(SC_INIT_DIR))
|
|
{
|
|
#ifdef AUDIOPLAYER_TIME_DEBUG
|
|
timeval start;
|
|
gettimeofday(&start,NULL);
|
|
#endif
|
|
CProgressWindow progress;
|
|
long maxProgress = (filebrowser.getSelectedFiles().size() > 1) ? filebrowser.getSelectedFiles().size() - 1: 1;
|
|
long currentProgress = -1;
|
|
//if (maxProgress > SHOW_FILE_LOAD_LIMIT)
|
|
{
|
|
progress.setTitle(LOCALE_AUDIOPLAYER_READING_FILES);
|
|
progress.exec(this,"");
|
|
}
|
|
|
|
m_Path = filebrowser.getCurrentDir();
|
|
CFileList::const_iterator files = filebrowser.getSelectedFiles().begin();
|
|
neutrino_msg_t msg;
|
|
neutrino_msg_data_t data;
|
|
g_RCInput->getMsg(&msg, &data, 0);
|
|
for (; (files != filebrowser.getSelectedFiles().end()) && (msg != CRCInput::RC_home); files++)
|
|
{
|
|
//if (maxProgress > SHOW_FILE_LOAD_LIMIT)
|
|
{
|
|
currentProgress++;
|
|
// show progress
|
|
int global = 100*currentProgress/maxProgress;
|
|
progress.showGlobalStatus(global);
|
|
progress.showStatusMessageUTF(files->Name);
|
|
#ifdef LCD_UPDATE
|
|
CVFD::getInstance()->showProgressBar(global, "read metadata...");
|
|
CVFD::getInstance()->setMode(CVFD::MODE_PROGRESSBAR);
|
|
#endif // LCD_UPDATE
|
|
}
|
|
//printf("processPlaylistUrl(%s, %s)\n", files->Url.c_str(), files->Name.c_str());
|
|
processPlaylistUrl(files->Url.c_str(), files->Name.c_str(), files->Time);
|
|
g_RCInput->getMsg(&msg, &data, 0);
|
|
}
|
|
if (m_select_title_by_name)
|
|
{
|
|
buildSearchTree();
|
|
}
|
|
#ifdef AUDIOPLAYER_TIME_DEBUG
|
|
timeval end;
|
|
gettimeofday(&end,NULL);
|
|
printf("adding %ld files took: ",maxProgress+1);
|
|
printTimevalDiff(start,end);
|
|
#endif
|
|
result = true;
|
|
}
|
|
CVFD::getInstance()->setMode(CVFD::MODE_AUDIO);
|
|
paintLCD();
|
|
// if playlist is turned off -> start playing immediately
|
|
if (!m_show_playlist && !m_playlist.empty())
|
|
play(m_selected);
|
|
|
|
return ( result);
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
|
|
|
|
void CAudioPlayerGui::hide()
|
|
{
|
|
// printf("hide(){\n");
|
|
if (m_visible)
|
|
{
|
|
m_frameBuffer->paintBackgroundBoxRel(m_x - ConnectLineBox_Width-1, m_y + m_title_height - 1,
|
|
m_width + ConnectLineBox_Width+2, m_height + 2 - m_title_height);
|
|
clearItemID3DetailsLine();
|
|
m_frameBuffer->paintBackgroundBoxRel(m_x, m_y, m_width, m_title_height);
|
|
m_visible = false;
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
|
|
void CAudioPlayerGui::paintItem(int pos)
|
|
{
|
|
if (!m_show_playlist)
|
|
return;
|
|
|
|
int ypos = m_y + m_title_height + m_theight + pos*m_fheight;
|
|
int c_rad_small;
|
|
uint8_t color;
|
|
fb_pixel_t bgcolor;
|
|
|
|
if ((pos + m_liststart) == m_selected)
|
|
{
|
|
if ((pos + m_liststart) == (unsigned)m_current)
|
|
{
|
|
color = COL_MENUCONTENTSELECTED + 2;
|
|
bgcolor = COL_MENUCONTENTSELECTED_PLUS_2;
|
|
}
|
|
else
|
|
{
|
|
color = COL_MENUCONTENTSELECTED;
|
|
bgcolor = COL_MENUCONTENTSELECTED_PLUS_0;
|
|
}
|
|
paintItemID3DetailsLine(pos);
|
|
c_rad_small = RADIUS_SMALL;
|
|
}
|
|
else
|
|
{
|
|
if (((pos + m_liststart) < m_playlist.size()) && (pos & 1))
|
|
{
|
|
if ((pos + m_liststart) == (unsigned)m_current)
|
|
{
|
|
color = COL_MENUCONTENTDARK + 2;
|
|
bgcolor = COL_MENUCONTENTDARK_PLUS_2;
|
|
}
|
|
else
|
|
{
|
|
color = COL_MENUCONTENTDARK;
|
|
bgcolor = COL_MENUCONTENTDARK_PLUS_0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ((pos + m_liststart) == (unsigned)m_current)
|
|
{
|
|
color = COL_MENUCONTENT + 2;
|
|
bgcolor = COL_MENUCONTENT_PLUS_2;
|
|
}
|
|
else
|
|
{
|
|
color = COL_MENUCONTENT;
|
|
bgcolor = COL_MENUCONTENT_PLUS_0;
|
|
}
|
|
}
|
|
c_rad_small = 0;
|
|
}
|
|
|
|
m_frameBuffer->paintBoxRel(m_x, ypos, m_width - 15, m_fheight, bgcolor, c_rad_small);
|
|
|
|
if ((pos + m_liststart) < m_playlist.size())
|
|
{
|
|
if (m_playlist[pos + m_liststart].FileType != CFile::STREAM_AUDIO &&
|
|
!m_playlist[pos + m_liststart].MetaData.bitrate)
|
|
{
|
|
// id3tag noch nicht geholt
|
|
GetMetaData(m_playlist[pos + m_liststart]);
|
|
if (m_state != CAudioPlayerGui::STOP && !g_settings.audioplayer_highprio)
|
|
usleep(100*1000);
|
|
}
|
|
char sNr[20];
|
|
sprintf(sNr, "%2d : ", pos + m_liststart + 1);
|
|
std::string tmp = sNr;
|
|
getFileInfoToDisplay(tmp, m_playlist[pos + m_liststart]);
|
|
|
|
char dura[9];
|
|
if (m_inetmode)
|
|
snprintf(dura, 8, "%ldk", m_playlist[pos + m_liststart].MetaData.total_time);
|
|
else
|
|
snprintf(dura, 8, "%ld:%02ld", m_playlist[pos + m_liststart].MetaData.total_time / 60,
|
|
m_playlist[pos + m_liststart].MetaData.total_time % 60);
|
|
int w = g_Font[SNeutrinoSettings::FONT_TYPE_MENU]->getRenderWidth(dura) + 5;
|
|
g_Font[SNeutrinoSettings::FONT_TYPE_MENU]->RenderString(m_x + 10, ypos + m_fheight, m_width - 30 - w,
|
|
tmp, color, m_fheight, true); // UTF-8
|
|
g_Font[SNeutrinoSettings::FONT_TYPE_MENU]->RenderString(m_x + m_width - 15 - w, ypos + m_fheight,
|
|
w, dura, color, m_fheight);
|
|
if ((pos + m_liststart) == m_selected)
|
|
{
|
|
if (m_state == CAudioPlayerGui::STOP)
|
|
{
|
|
CVFD::getInstance()->showAudioTrack(m_playlist[pos + m_liststart].MetaData.artist,
|
|
m_playlist[pos + m_liststart].MetaData.title,
|
|
m_playlist[pos + m_liststart].MetaData.album);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//--------------playlist----------------------------------------------------------
|
|
|
|
void CAudioPlayerGui::paintHead()
|
|
{
|
|
if (!m_show_playlist)
|
|
return;
|
|
|
|
int c_rad_mid = RADIUS_MID;
|
|
std::string strCaption;
|
|
if (m_inetmode)
|
|
strCaption = g_Locale->getText(LOCALE_INETRADIO_NAME);
|
|
else
|
|
strCaption = g_Locale->getText(LOCALE_AUDIOPLAYER_HEAD);
|
|
m_frameBuffer->paintBoxRel(m_x, m_y + m_title_height, m_width, m_theight, COL_MENUHEAD_PLUS_0, c_rad_mid, CORNER_TOP);
|
|
m_frameBuffer->paintIcon(NEUTRINO_ICON_MP3,m_x + 7, m_y + m_title_height + 10);
|
|
g_Font[SNeutrinoSettings::FONT_TYPE_MENU_TITLE]->RenderString(m_x + 35, m_y + m_theight + m_title_height + 0,
|
|
m_width - 45, strCaption, COL_MENUHEAD, 0, true); // UTF-8
|
|
int ypos = m_y + m_title_height;
|
|
if (m_theight > 26)
|
|
ypos = (m_theight - 26) / 2 + m_y + m_title_height;
|
|
#ifdef ENABLE_GUI_MOUNT
|
|
if (!m_inetmode)
|
|
m_frameBuffer->paintIcon(NEUTRINO_ICON_BUTTON_DBOX, m_x + m_width - 30, ypos);
|
|
#endif
|
|
#if 1
|
|
if ( CNeutrinoApp::getInstance()->isMuted() )
|
|
{
|
|
int xpos = m_x + m_width - 75;
|
|
ypos = m_y + m_title_height;
|
|
if (m_theight > 32)
|
|
ypos = (m_theight - 32) / 2 + m_y + m_title_height;
|
|
m_frameBuffer->paintIcon(NEUTRINO_ICON_BUTTON_MUTE, xpos, ypos);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
const struct button_label AudioPlayerButtons[][4] =
|
|
{
|
|
{
|
|
{ NEUTRINO_ICON_BUTTON_RED , LOCALE_AUDIOPLAYER_STOP },
|
|
{ NEUTRINO_ICON_BUTTON_GREEN , LOCALE_AUDIOPLAYER_REWIND },
|
|
{ NEUTRINO_ICON_BUTTON_YELLOW, LOCALE_AUDIOPLAYER_PAUSE },
|
|
{ NEUTRINO_ICON_BUTTON_BLUE , LOCALE_AUDIOPLAYER_FASTFORWARD },
|
|
},
|
|
{
|
|
{ NEUTRINO_ICON_BUTTON_RED , LOCALE_AUDIOPLAYER_DELETE },
|
|
{ NEUTRINO_ICON_BUTTON_GREEN , LOCALE_AUDIOPLAYER_ADD },
|
|
{ NEUTRINO_ICON_BUTTON_YELLOW, LOCALE_AUDIOPLAYER_DELETEALL },
|
|
{ NEUTRINO_ICON_BUTTON_BLUE , LOCALE_AUDIOPLAYER_SHUFFLE },
|
|
},
|
|
{
|
|
{ NEUTRINO_ICON_BUTTON_GREEN , LOCALE_AUDIOPLAYER_JUMP_BACKWARDS },
|
|
{ NEUTRINO_ICON_BUTTON_BLUE , LOCALE_AUDIOPLAYER_JUMP_FORWARDS },
|
|
},
|
|
{
|
|
{ NEUTRINO_ICON_BUTTON_GREEN , LOCALE_AUDIOPLAYER_JUMP_BACKWARDS },
|
|
{ NEUTRINO_ICON_BUTTON_BLUE , LOCALE_AUDIOPLAYER_JUMP_FORWARDS },
|
|
},
|
|
{
|
|
{ NEUTRINO_ICON_BUTTON_GREEN , LOCALE_AUDIOPLAYER_SAVE_PLAYLIST },
|
|
{ NEUTRINO_ICON_BUTTON_YELLOW, LOCALE_AUDIOPLAYER_BUTTON_SELECT_TITLE_BY_ID },
|
|
},
|
|
{
|
|
{ NEUTRINO_ICON_BUTTON_GREEN , LOCALE_AUDIOPLAYER_SAVE_PLAYLIST },
|
|
{ NEUTRINO_ICON_BUTTON_YELLOW, LOCALE_AUDIOPLAYER_BUTTON_SELECT_TITLE_BY_NAME },
|
|
},
|
|
{
|
|
{ NEUTRINO_ICON_BUTTON_RED , LOCALE_AUDIOPLAYER_STOP },
|
|
{ NEUTRINO_ICON_BUTTON_YELLOW, LOCALE_AUDIOPLAYER_PAUSE },
|
|
},
|
|
{
|
|
{ NEUTRINO_ICON_BUTTON_GREEN , LOCALE_AUDIOPLAYER_ADD },
|
|
{ NEUTRINO_ICON_BUTTON_BLUE , LOCALE_INETRADIO_NAME },
|
|
},
|
|
{
|
|
{ NEUTRINO_ICON_BUTTON_RED , LOCALE_AUDIOPLAYER_DELETE },
|
|
{ NEUTRINO_ICON_BUTTON_GREEN , LOCALE_AUDIOPLAYER_ADD },
|
|
{ NEUTRINO_ICON_BUTTON_YELLOW, LOCALE_AUDIOPLAYER_DELETEALL },
|
|
{ NEUTRINO_ICON_BUTTON_BLUE , LOCALE_INETRADIO_NAME },
|
|
},
|
|
};
|
|
//------------------------------------------------------------------------
|
|
|
|
void CAudioPlayerGui::paintFoot()
|
|
{
|
|
// printf("paintFoot{\n");
|
|
int top;
|
|
int c_rad_mid = RADIUS_MID;
|
|
if (m_show_playlist)
|
|
top = m_y + (m_height - m_info_height - 2 * m_buttonHeight);
|
|
else
|
|
top = m_y + (m_height - 2 * m_buttonHeight);
|
|
|
|
int ButtonWidth = (m_width - 20) / 4;
|
|
int ButtonWidth2 = (m_width - 50) / 2;
|
|
m_frameBuffer->paintBoxRel(m_x, top, m_width, 2 * m_buttonHeight, COL_INFOBAR_SHADOW_PLUS_1, c_rad_mid, CORNER_BOTTOM);
|
|
m_frameBuffer->paintHLine(m_x, m_x + m_width, top, COL_INFOBAR_SHADOW_PLUS_1);
|
|
|
|
if (!m_playlist.empty())
|
|
{
|
|
// play
|
|
m_frameBuffer->paintIcon(NEUTRINO_ICON_BUTTON_OKAY, m_x + 1 * ButtonWidth2 + 25, top + m_buttonHeight - 3);
|
|
g_Font[SNeutrinoSettings::FONT_TYPE_INFOBAR_SMALL]
|
|
->RenderString(m_x + 1 * ButtonWidth2 + 53, top + m_buttonHeight + 24 - 4, ButtonWidth2 - 28,
|
|
g_Locale->getText(LOCALE_AUDIOPLAYER_PLAY), COL_INFOBAR /*_SHADOW_PLUS_1*/, 0, true); // UTF-8
|
|
// keylevel switch
|
|
m_frameBuffer->paintIcon(NEUTRINO_ICON_BUTTON_HELP, m_x + 0 * ButtonWidth + 25, top + m_buttonHeight - 3);
|
|
g_Font[SNeutrinoSettings::FONT_TYPE_INFOBAR_SMALL]
|
|
->RenderString(m_x + 0 * ButtonWidth + 53 , top + m_buttonHeight + 24 - 4, ButtonWidth2 - 28,
|
|
g_Locale->getText(LOCALE_AUDIOPLAYER_KEYLEVEL), COL_INFOBAR /*_SHADOW_PLUS_1*/, 0, true); // UTF-8
|
|
}
|
|
|
|
if (m_key_level == 0)
|
|
{
|
|
if (m_playlist.empty()) {
|
|
if (m_inetmode)
|
|
::paintButtons(m_frameBuffer, g_Font[SNeutrinoSettings::FONT_TYPE_INFOBAR_SMALL], g_Locale,
|
|
m_x + 10, top + 4, ButtonWidth, 2, AudioPlayerButtons[7]);
|
|
else
|
|
::paintButtons(m_frameBuffer, g_Font[SNeutrinoSettings::FONT_TYPE_INFOBAR_SMALL], g_Locale,
|
|
m_x + 10, top + 4, ButtonWidth, 1, &(AudioPlayerButtons[7][0]));
|
|
} else if (m_inetmode)
|
|
::paintButtons(m_frameBuffer, g_Font[SNeutrinoSettings::FONT_TYPE_INFOBAR_SMALL], g_Locale,
|
|
m_x + 10, top + 4, ButtonWidth, 4, AudioPlayerButtons[8]);
|
|
else
|
|
::paintButtons(m_frameBuffer, g_Font[SNeutrinoSettings::FONT_TYPE_INFOBAR_SMALL], g_Locale,
|
|
m_x + 10, top + 4, ButtonWidth, 4, AudioPlayerButtons[1]);
|
|
}
|
|
else if (m_key_level == 1)
|
|
{
|
|
if (m_curr_audiofile.FileType != CFile::STREAM_AUDIO)
|
|
{
|
|
::paintButtons(m_frameBuffer, g_Font[SNeutrinoSettings::FONT_TYPE_INFOBAR_SMALL], g_Locale, m_x + 10, top + 4, ButtonWidth, 4, AudioPlayerButtons[0]);
|
|
}
|
|
else
|
|
{
|
|
::paintButtons(m_frameBuffer, g_Font[SNeutrinoSettings::FONT_TYPE_INFOBAR_SMALL], g_Locale, m_x + 10, top + 4, ButtonWidth*2, 2, AudioPlayerButtons[6]);
|
|
}
|
|
}
|
|
else
|
|
{ // key_level == 2
|
|
if (m_state == CAudioPlayerGui::STOP)
|
|
{
|
|
if (m_select_title_by_name)
|
|
{
|
|
::paintButtons(m_frameBuffer, g_Font[SNeutrinoSettings::FONT_TYPE_INFOBAR_SMALL], g_Locale,
|
|
m_x + ButtonWidth + 10, top + 4, ButtonWidth, 2, AudioPlayerButtons[5]);
|
|
}
|
|
else
|
|
{
|
|
::paintButtons(m_frameBuffer, g_Font[SNeutrinoSettings::FONT_TYPE_INFOBAR_SMALL], g_Locale,
|
|
m_x + ButtonWidth + 10, top + 4, ButtonWidth, 2, AudioPlayerButtons[4]);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (m_select_title_by_name)
|
|
{
|
|
::paintButtons(m_frameBuffer, g_Font[SNeutrinoSettings::FONT_TYPE_INFOBAR_SMALL], g_Locale,
|
|
m_x + ButtonWidth + 10, top + 4, ButtonWidth*2, 2, AudioPlayerButtons[3]);
|
|
}
|
|
else
|
|
{
|
|
::paintButtons(m_frameBuffer, g_Font[SNeutrinoSettings::FONT_TYPE_INFOBAR_SMALL], g_Locale,
|
|
m_x + ButtonWidth + 10, top + 4, ButtonWidth*2, 2, AudioPlayerButtons[2]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
//------------------------------------------------------------------------
|
|
void CAudioPlayerGui::paintInfo()
|
|
{
|
|
int c_rad_mid = RADIUS_MID;
|
|
if (m_state == CAudioPlayerGui::STOP && m_show_playlist)
|
|
m_frameBuffer->paintBackgroundBoxRel(m_x, m_y, m_width, m_title_height);
|
|
else
|
|
{
|
|
if (!m_show_playlist)
|
|
{
|
|
// no playlist -> smaller Info-Box
|
|
m_frameBuffer->paintBoxRel(m_x, m_y, m_width, m_title_height - 10 - m_fheight, COL_MENUCONTENT_PLUS_6, c_rad_mid);
|
|
m_frameBuffer->paintBoxRel(m_x + 2, m_y + 2 , m_width - 4, m_title_height - 14 - m_fheight, COL_MENUCONTENTSELECTED_PLUS_0, c_rad_mid);
|
|
}
|
|
else
|
|
{
|
|
m_frameBuffer->paintBoxRel(m_x, m_y, m_width, m_title_height - 10, COL_MENUCONTENT_PLUS_6, c_rad_mid);
|
|
m_frameBuffer->paintBoxRel(m_x + 2, m_y + 2 , m_width - 4, m_title_height - 14, COL_MENUCONTENTSELECTED_PLUS_0, c_rad_mid);
|
|
}
|
|
|
|
// first line (Track number)
|
|
std::string tmp;
|
|
if (m_inetmode) {
|
|
tmp = m_curr_audiofile.MetaData.album;
|
|
} else {
|
|
char sNr[20];
|
|
sprintf(sNr, ": %2d", m_current + 1);
|
|
tmp = g_Locale->getText(LOCALE_AUDIOPLAYER_PLAYING);
|
|
tmp += sNr ;
|
|
}
|
|
|
|
int w = g_Font[SNeutrinoSettings::FONT_TYPE_MENU]->getRenderWidth(tmp, true); // UTF-8
|
|
int xstart = (m_width - w) / 2;
|
|
if (xstart < 10)
|
|
xstart = 10;
|
|
g_Font[SNeutrinoSettings::FONT_TYPE_MENU]->RenderString(m_x + xstart, m_y + 4 + 1*m_fheight, m_width - 20,
|
|
tmp, COL_MENUCONTENTSELECTED, 0, true); // UTF-8
|
|
|
|
// second line (Artist/Title...)
|
|
if (m_curr_audiofile.FileType != CFile::STREAM_AUDIO &&
|
|
!m_curr_audiofile.MetaData.bitrate)
|
|
{
|
|
GetMetaData(m_curr_audiofile);
|
|
}
|
|
|
|
if (m_curr_audiofile.MetaData.title.empty())
|
|
tmp = m_curr_audiofile.MetaData.artist;
|
|
else if (m_curr_audiofile.MetaData.artist.empty())
|
|
tmp = m_curr_audiofile.MetaData.title;
|
|
else if (g_settings.audioplayer_display == TITLE_ARTIST)
|
|
{
|
|
tmp = m_curr_audiofile.MetaData.title;
|
|
tmp += " / ";
|
|
tmp += m_curr_audiofile.MetaData.artist;
|
|
}
|
|
else //if(g_settings.audioplayer_display == ARTIST_TITLE)
|
|
{
|
|
tmp = m_curr_audiofile.MetaData.artist;
|
|
tmp += " / ";
|
|
tmp += m_curr_audiofile.MetaData.title;
|
|
}
|
|
w = g_Font[SNeutrinoSettings::FONT_TYPE_MENU]->getRenderWidth(tmp, true); // UTF-8
|
|
xstart=(m_width-w)/2;
|
|
if (xstart < 10)
|
|
xstart=10;
|
|
g_Font[SNeutrinoSettings::FONT_TYPE_MENU]->RenderString(m_x+xstart, m_y +4+ 2*m_fheight, m_width- 20, tmp, COL_MENUCONTENTSELECTED, 0, true); // UTF-8
|
|
|
|
// reset so fields get painted always
|
|
m_metainfo.clear();
|
|
m_time_total = 0;
|
|
m_time_played = 0;
|
|
updateMetaData();
|
|
|
|
updateTimes(true);
|
|
}
|
|
}
|
|
//------------------------------------------------------------------------
|
|
|
|
void CAudioPlayerGui::paint()
|
|
{
|
|
if (m_show_playlist)
|
|
{
|
|
m_liststart = (m_selected / m_listmaxshow) * m_listmaxshow;
|
|
paintHead();
|
|
for (unsigned int count=0; count<m_listmaxshow; count++)
|
|
{
|
|
paintItem(count);
|
|
}
|
|
|
|
int ypos = m_y + m_title_height + m_theight;
|
|
int sb = m_fheight * m_listmaxshow;
|
|
m_frameBuffer->paintBoxRel(m_x + m_width - 15, ypos, 15, sb, COL_MENUCONTENT_PLUS_1);
|
|
|
|
int sbc = ((m_playlist.size() - 1) / m_listmaxshow) + 1;
|
|
int sbs = (m_selected / m_listmaxshow);
|
|
|
|
m_frameBuffer->paintBoxRel(m_x + m_width - 13, ypos + 2 + sbs*(sb-4)/sbc , 11, (sb-4)/sbc, COL_MENUCONTENT_PLUS_3, RADIUS_SMALL);
|
|
}
|
|
|
|
paintFoot();
|
|
paintInfo();
|
|
m_visible = true;
|
|
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
|
|
void CAudioPlayerGui::clearItemID3DetailsLine ()
|
|
{
|
|
paintItemID3DetailsLine(-1);
|
|
}
|
|
//------------------------------------------------------------------------
|
|
|
|
void CAudioPlayerGui::paintItemID3DetailsLine (int pos)
|
|
{
|
|
int xpos = m_x - ConnectLineBox_Width;
|
|
int ypos1 = m_y + m_title_height + m_theight+ 0 + pos*m_fheight;
|
|
int ypos2 = m_y + (m_height - m_info_height);
|
|
int ypos1a = ypos1 + (m_fheight / 2) - 2;
|
|
int ypos2a = ypos2 + (m_info_height / 2) - 2;
|
|
fb_pixel_t col1 = COL_MENUCONTENT_PLUS_6;
|
|
fb_pixel_t col2 = COL_MENUCONTENT_PLUS_1;
|
|
int c_rad_small = RADIUS_SMALL;
|
|
|
|
|
|
// Clear
|
|
m_frameBuffer->paintBackgroundBoxRel(xpos - 1, m_y + m_title_height, ConnectLineBox_Width + 1,
|
|
m_height - m_title_height);
|
|
|
|
// paint Line if detail info (and not valid list pos)
|
|
if (!m_playlist.empty() && (pos >= 0))
|
|
{
|
|
// 1. col thick line
|
|
m_frameBuffer->paintBoxRel(xpos + ConnectLineBox_Width - 4, ypos1, 4, m_fheight, col2, c_rad_small, CORNER_LEFT);
|
|
m_frameBuffer->paintBoxRel(xpos + ConnectLineBox_Width - 3, ypos1, 8, m_fheight, col1, c_rad_small, CORNER_LEFT); // item marker
|
|
|
|
m_frameBuffer->paintBoxRel(xpos + ConnectLineBox_Width - 4, ypos2, 4, m_info_height, col1);
|
|
|
|
m_frameBuffer->paintBoxRel(xpos + ConnectLineBox_Width - 16, ypos1a, 4, ypos2a - ypos1a, col1);
|
|
|
|
m_frameBuffer->paintBoxRel(xpos + ConnectLineBox_Width - 16, ypos1a, 12, 4, col1);
|
|
m_frameBuffer->paintBoxRel(xpos + ConnectLineBox_Width - 16, ypos2a, 12, 4, col1);
|
|
|
|
// 2. col small line
|
|
m_frameBuffer->paintBoxRel(xpos + ConnectLineBox_Width - 4, ypos2, 1, m_info_height, col2);
|
|
|
|
m_frameBuffer->paintBoxRel(xpos + ConnectLineBox_Width - 16, ypos1a, 1, ypos2a - ypos1a + 4, col2);
|
|
|
|
m_frameBuffer->paintBoxRel(xpos + ConnectLineBox_Width - 16, ypos1a, 12, 1, col2);
|
|
m_frameBuffer->paintBoxRel(xpos + ConnectLineBox_Width - 12, ypos2a, 8, 1, col2);
|
|
|
|
// -- small Frame around infobox
|
|
m_frameBuffer->paintBoxRel(m_x, ypos2 , 2 , m_info_height , col1);
|
|
m_frameBuffer->paintBoxRel(m_x + m_width - 2, ypos2 , 2 , m_info_height , col1);
|
|
m_frameBuffer->paintBoxRel(m_x, ypos2 , m_width -2 , 2 , col1);
|
|
m_frameBuffer->paintBoxRel(m_x, ypos2 + m_info_height -2, m_width -2 , 2 , col1);
|
|
// m_frameBuffer->paintBoxRel(m_x, ypos2, m_width, m_info_height, col1);
|
|
|
|
// paint id3 infobox
|
|
m_frameBuffer->paintBoxRel(m_x + 2, ypos2 + 2 , m_width - 4, m_info_height - 4, COL_MENUCONTENTDARK_PLUS_0);
|
|
g_Font[SNeutrinoSettings::FONT_TYPE_MENU]->RenderString(m_x + 10, ypos2 + 2 + 1*m_fheight, m_width- 80,
|
|
m_playlist[m_selected].MetaData.title, COL_MENUCONTENTDARK, 0, true); // UTF-8
|
|
std::string tmp;
|
|
if (m_playlist[m_selected].MetaData.genre.empty())
|
|
tmp = m_playlist[m_selected].MetaData.date;
|
|
else if (m_playlist[m_selected].MetaData.date.empty())
|
|
tmp = m_playlist[m_selected].MetaData.genre;
|
|
else
|
|
{
|
|
tmp = m_playlist[m_selected].MetaData.genre;
|
|
tmp += " / ";
|
|
tmp += m_playlist[m_selected].MetaData.date;
|
|
}
|
|
int w = g_Font[SNeutrinoSettings::FONT_TYPE_MENU]->getRenderWidth(tmp, true) + 10; // UTF-8
|
|
g_Font[SNeutrinoSettings::FONT_TYPE_MENU]->RenderString(m_x + m_width - w - 5, ypos2 + 2 + 1*m_fheight,
|
|
w, tmp, COL_MENUCONTENTDARK, 0, true); // UTF-8
|
|
tmp = m_playlist[m_selected].MetaData.artist;
|
|
if (!(m_playlist[m_selected].MetaData.album.empty()))
|
|
{
|
|
tmp += " (";
|
|
tmp += m_playlist[m_selected].MetaData.album;
|
|
tmp += ')';
|
|
}
|
|
g_Font[SNeutrinoSettings::FONT_TYPE_MENU]->RenderString(m_x + 10, ypos2 + 2*m_fheight - 2, m_width - 20,
|
|
tmp, COL_MENUCONTENTDARK, 0, true); // UTF-8
|
|
}
|
|
else
|
|
{
|
|
m_frameBuffer->paintBackgroundBoxRel(m_x, ypos2, m_width, m_info_height);
|
|
}
|
|
}
|
|
//------------------------------------------------------------------------
|
|
|
|
void CAudioPlayerGui::stop()
|
|
{
|
|
m_state = CAudioPlayerGui::STOP;
|
|
m_current = 0;
|
|
//LCD
|
|
paintLCD();
|
|
//Display
|
|
paintInfo();
|
|
m_key_level = 0;
|
|
paintFoot();
|
|
|
|
if (CAudioPlayer::getInstance()->getState() != CBaseDec::STOP)
|
|
CAudioPlayer::getInstance()->stop();
|
|
}
|
|
//------------------------------------------------------------------------
|
|
|
|
void CAudioPlayerGui::pause()
|
|
{
|
|
if (m_state == CAudioPlayerGui::PLAY
|
|
|| m_state == CAudioPlayerGui::FF
|
|
|| m_state == CAudioPlayerGui::REV)
|
|
{
|
|
m_state = CAudioPlayerGui::PAUSE;
|
|
CAudioPlayer::getInstance()->pause();
|
|
}
|
|
else if (m_state == CAudioPlayerGui::PAUSE)
|
|
{
|
|
m_state = CAudioPlayerGui::PLAY;
|
|
CAudioPlayer::getInstance()->pause();
|
|
}
|
|
paintLCD();
|
|
}
|
|
//------------------------------------------------------------------------
|
|
|
|
void CAudioPlayerGui::ff(unsigned int seconds)
|
|
{
|
|
if (m_state == CAudioPlayerGui::FF)
|
|
{
|
|
m_state = CAudioPlayerGui::PLAY;
|
|
CAudioPlayer::getInstance()->ff(seconds);
|
|
}
|
|
else if (m_state == CAudioPlayerGui::PLAY
|
|
|| m_state == CAudioPlayerGui::PAUSE
|
|
|| m_state == CAudioPlayerGui::REV)
|
|
{
|
|
m_state = CAudioPlayerGui::FF;
|
|
CAudioPlayer::getInstance()->ff(seconds);
|
|
}
|
|
paintLCD();
|
|
}
|
|
//------------------------------------------------------------------------
|
|
|
|
void CAudioPlayerGui::rev(unsigned int seconds)
|
|
{
|
|
if (m_state == CAudioPlayerGui::REV)
|
|
{
|
|
m_state = CAudioPlayerGui::PLAY;
|
|
CAudioPlayer::getInstance()->rev(seconds);
|
|
}
|
|
else if (m_state == CAudioPlayerGui::PLAY
|
|
|| m_state == CAudioPlayerGui::PAUSE
|
|
|| m_state == CAudioPlayerGui::FF)
|
|
{
|
|
m_state = CAudioPlayerGui::REV;
|
|
CAudioPlayer::getInstance()->rev(seconds);
|
|
}
|
|
paintLCD();
|
|
}
|
|
//------------------------------------------------------------------------
|
|
|
|
void CAudioPlayerGui::play(unsigned int pos)
|
|
{
|
|
//printf("AudioPlaylist: play %d/%d\n",pos,playlist.size());
|
|
unsigned int old_current = m_current;
|
|
unsigned int old_selected = m_selected;
|
|
|
|
m_current = pos;
|
|
if (g_settings.audioplayer_follow)
|
|
m_selected = pos;
|
|
|
|
if (m_selected - m_liststart >= m_listmaxshow && g_settings.audioplayer_follow)
|
|
{
|
|
m_liststart = m_selected;
|
|
if (!m_screensaver)
|
|
paint();
|
|
}
|
|
else if (m_liststart < m_selected && g_settings.audioplayer_follow)
|
|
{
|
|
m_liststart = m_selected - m_listmaxshow + 1;
|
|
if (!m_screensaver)
|
|
paint();
|
|
}
|
|
else
|
|
{
|
|
if (old_current >= m_liststart && old_current - m_liststart < m_listmaxshow)
|
|
{
|
|
if (!m_screensaver)
|
|
paintItem(old_current - m_liststart);
|
|
}
|
|
if (pos >= m_liststart && pos - m_liststart < m_listmaxshow)
|
|
{
|
|
if (!m_screensaver)
|
|
paintItem(pos - m_liststart);
|
|
}
|
|
if (g_settings.audioplayer_follow)
|
|
{
|
|
if (old_selected >= m_liststart && old_selected - m_liststart < m_listmaxshow)
|
|
if (!m_screensaver)
|
|
paintItem(old_selected - m_liststart);
|
|
}
|
|
}
|
|
|
|
if (m_playlist[pos].FileType != CFile::STREAM_AUDIO &&
|
|
!m_playlist[pos].MetaData.bitrate)
|
|
{
|
|
// id3tag noch nicht geholt
|
|
//printf("play: need getMetaData\n");
|
|
GetMetaData(m_playlist[pos]);
|
|
}
|
|
m_metainfo.clear();
|
|
m_time_played = 0;
|
|
m_time_total = m_playlist[m_current].MetaData.total_time;
|
|
m_state = CAudioPlayerGui::PLAY;
|
|
m_curr_audiofile = m_playlist[m_current];
|
|
// Play
|
|
CAudioPlayer::getInstance()->play(&m_curr_audiofile, g_settings.audioplayer_highprio == 1);
|
|
//LCD
|
|
paintLCD();
|
|
// Display
|
|
if (!m_screensaver)
|
|
paintInfo();
|
|
m_key_level = 1;
|
|
if (!m_screensaver)
|
|
paintFoot();
|
|
}
|
|
//------------------------------------------------------------------------
|
|
|
|
int CAudioPlayerGui::getNext()
|
|
{
|
|
int ret= m_current + 1;
|
|
if (m_playlist.empty())
|
|
return -1;
|
|
if ((unsigned)ret >= m_playlist.size())
|
|
{
|
|
if (g_settings.audioplayer_repeat_on == 1)
|
|
ret = 0;
|
|
else
|
|
ret = -1;
|
|
}
|
|
return ret;
|
|
}
|
|
//------------------------------------------------------------------------
|
|
|
|
void CAudioPlayerGui::updateMetaData()
|
|
{
|
|
bool updateMeta = false;
|
|
bool updateLcd = false;
|
|
bool updateScreen = false;
|
|
|
|
if (m_state == CAudioPlayerGui::STOP || !m_show_playlist)
|
|
return;
|
|
|
|
if ( CAudioPlayer::getInstance()->hasMetaDataChanged()
|
|
|| m_metainfo.empty() )
|
|
{
|
|
const CAudioMetaData meta =
|
|
CAudioPlayer::getInstance()->getMetaData();
|
|
|
|
std::stringstream info;
|
|
info.precision(3);
|
|
|
|
if ( meta.bitrate > 0 )
|
|
{
|
|
info << " / ";
|
|
if ( meta.vbr )
|
|
{
|
|
info << "VBR ";
|
|
}
|
|
info << meta.bitrate/1000 << "kbps";
|
|
}
|
|
|
|
if ( meta.samplerate > 0 )
|
|
{
|
|
info << " / " << meta.samplerate/1000 << "." << (meta.samplerate/100)%10 <<"kHz";
|
|
}
|
|
|
|
m_metainfo = meta.type_info + info.str();
|
|
updateMeta = true;
|
|
|
|
if (!meta.artist.empty() &&
|
|
meta.artist != m_curr_audiofile.MetaData.artist)
|
|
{
|
|
m_curr_audiofile.MetaData.artist = meta.artist;
|
|
updateScreen = true;
|
|
updateLcd = true;
|
|
}
|
|
if (!meta.title.empty() &&
|
|
meta.title != m_curr_audiofile.MetaData.title)
|
|
{
|
|
m_curr_audiofile.MetaData.title = meta.title;
|
|
updateScreen = true;
|
|
updateLcd = true;
|
|
}
|
|
if (!meta.sc_station.empty() &&
|
|
meta.sc_station != m_curr_audiofile.MetaData.album)
|
|
{
|
|
m_curr_audiofile.MetaData.album = meta.sc_station;
|
|
updateLcd = true;
|
|
}
|
|
}
|
|
//if (CAudioPlayer::getInstance()->getScBuffered() != 0)
|
|
if (CAudioPlayer::getInstance()->hasMetaDataChanged() != 0)
|
|
{
|
|
updateLcd = true;
|
|
}
|
|
//printf("CAudioPlayerGui::updateMetaData: updateLcd %d\n", updateLcd);
|
|
if (updateLcd)
|
|
paintLCD();
|
|
if (updateScreen)
|
|
paintInfo();
|
|
if (updateMeta || updateScreen)
|
|
{
|
|
m_frameBuffer->paintBoxRel(m_x + 10, m_y + 4 + 2*m_fheight, m_width - 20,
|
|
m_sheight, COL_MENUCONTENTSELECTED_PLUS_0);
|
|
int xstart = ((m_width - 20 - g_Font[SNeutrinoSettings::FONT_TYPE_INFOBAR_SMALL]->getRenderWidth(m_metainfo))/2)+10;
|
|
g_Font[SNeutrinoSettings::FONT_TYPE_INFOBAR_SMALL]
|
|
->RenderString(m_x + xstart, m_y + 4 + 2*m_fheight + m_sheight,
|
|
m_width- 2*xstart, m_metainfo, COL_MENUCONTENTSELECTED);
|
|
}
|
|
}
|
|
//------------------------------------------------------------------------
|
|
|
|
void CAudioPlayerGui::updateTimes(const bool force)
|
|
{
|
|
if (m_state != CAudioPlayerGui::STOP)
|
|
{
|
|
bool updateTotal = force;
|
|
bool updatePlayed = force;
|
|
|
|
if (m_time_total != CAudioPlayer::getInstance()->getTimeTotal())
|
|
{
|
|
m_time_total = CAudioPlayer::getInstance()->getTimeTotal();
|
|
if (m_curr_audiofile.MetaData.total_time != CAudioPlayer::getInstance()->getTimeTotal())
|
|
{
|
|
m_curr_audiofile.MetaData.total_time = CAudioPlayer::getInstance()->getTimeTotal();
|
|
if (m_current >= 0)
|
|
m_playlist[m_current].MetaData.total_time = CAudioPlayer::getInstance()->getTimeTotal();
|
|
}
|
|
updateTotal = true;
|
|
}
|
|
if ((m_time_played != CAudioPlayer::getInstance()->getTimePlayed()))
|
|
{
|
|
m_time_played = CAudioPlayer::getInstance()->getTimePlayed();
|
|
updatePlayed = true;
|
|
}
|
|
if (!m_screensaver)
|
|
{
|
|
char tot_time[11];
|
|
snprintf(tot_time, 10, " / %ld:%02ld", m_time_total / 60, m_time_total % 60);
|
|
char tmp_time[8];
|
|
snprintf(tmp_time, 7, "%ld:00", m_time_total / 60);
|
|
char play_time[8];
|
|
snprintf(play_time, 7, "%ld:%02ld", m_time_played / 60, m_time_played % 60);
|
|
|
|
int w1 = g_Font[SNeutrinoSettings::FONT_TYPE_MENU]->getRenderWidth(tot_time);
|
|
int w2 = g_Font[SNeutrinoSettings::FONT_TYPE_MENU]->getRenderWidth(tmp_time);
|
|
|
|
if (updateTotal)
|
|
{
|
|
m_frameBuffer->paintBoxRel(m_x + m_width - w1 - 10, m_y + 4, w1 + 4,
|
|
m_fheight, COL_MENUCONTENTSELECTED_PLUS_0);
|
|
if (m_time_total > 0)
|
|
g_Font[SNeutrinoSettings::FONT_TYPE_MENU]->RenderString(m_x + m_width - w1 - 10, m_y + 4 + m_fheight,
|
|
w1, tot_time, COL_MENUCONTENTSELECTED);
|
|
}
|
|
if (updatePlayed || (m_state == CAudioPlayerGui::PAUSE))
|
|
{
|
|
//m_frameBuffer->paintBoxRel(m_x + m_width - w1 - w2 - 15, m_y + 4, w2 + 4, m_fheight,
|
|
m_frameBuffer->paintBoxRel(m_x + m_width - w1 - w2 - 16, m_y + 4, w2 + 5, m_fheight,
|
|
COL_MENUCONTENTSELECTED_PLUS_0);
|
|
struct timeval tv;
|
|
gettimeofday(&tv, NULL);
|
|
if ((m_state != CAudioPlayerGui::PAUSE) || (tv.tv_sec & 1))
|
|
{
|
|
g_Font[SNeutrinoSettings::FONT_TYPE_MENU]->RenderString(m_x + m_width - w1 - w2 - 11, m_y + 4 + m_fheight,
|
|
w2+4, play_time, COL_MENUCONTENTSELECTED);
|
|
}
|
|
}
|
|
}
|
|
if ((updatePlayed || updateTotal) && m_time_total != 0)
|
|
{
|
|
CVFD::getInstance()->showAudioProgress(100 * m_time_played / m_time_total, CNeutrinoApp::getInstance()->isMuted());
|
|
}
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
|
|
void CAudioPlayerGui::paintLCD()
|
|
{
|
|
switch (m_state)
|
|
{
|
|
case CAudioPlayerGui::STOP:
|
|
CVFD::getInstance()->showAudioPlayMode(CVFD::AUDIO_MODE_STOP);
|
|
CVFD::getInstance()->showAudioProgress(0, CNeutrinoApp::getInstance()->isMuted());
|
|
break;
|
|
case CAudioPlayerGui::PLAY:
|
|
CVFD::getInstance()->showAudioPlayMode(CVFD::AUDIO_MODE_PLAY);
|
|
|
|
CVFD::getInstance()->showAudioTrack(m_curr_audiofile.MetaData.artist, m_curr_audiofile.MetaData.title,
|
|
m_curr_audiofile.MetaData.album);
|
|
if (m_curr_audiofile.FileType != CFile::STREAM_AUDIO && m_time_total != 0)
|
|
CVFD::getInstance()->showAudioProgress(100 * m_time_played / m_time_total, CNeutrinoApp::getInstance()->isMuted());
|
|
|
|
#ifdef INCLUDE_UNUSED_STUFF
|
|
else
|
|
CVFD::getInstance()->showAudioProgress(100 * CAudioPlayer::getInstance()->getScBuffered() / 65536, CNeutrinoApp::getInstance()->isMuted());
|
|
#endif /* INCLUDE_UNUSED_STUFF */
|
|
break;
|
|
case CAudioPlayerGui::PAUSE:
|
|
CVFD::getInstance()->showAudioPlayMode(CVFD::AUDIO_MODE_PAUSE);
|
|
CVFD::getInstance()->showAudioTrack(m_curr_audiofile.MetaData.artist, m_curr_audiofile.MetaData.title,
|
|
m_curr_audiofile.MetaData.album);
|
|
break;
|
|
case CAudioPlayerGui::FF:
|
|
CVFD::getInstance()->showAudioPlayMode(CVFD::AUDIO_MODE_FF);
|
|
CVFD::getInstance()->showAudioTrack(m_curr_audiofile.MetaData.artist, m_curr_audiofile.MetaData.title,
|
|
m_curr_audiofile.MetaData.album);
|
|
break;
|
|
case CAudioPlayerGui::REV:
|
|
CVFD::getInstance()->showAudioPlayMode(CVFD::AUDIO_MODE_REV);
|
|
CVFD::getInstance()->showAudioTrack(m_curr_audiofile.MetaData.artist, m_curr_audiofile.MetaData.title,
|
|
m_curr_audiofile.MetaData.album);
|
|
break;
|
|
}
|
|
}
|
|
//------------------------------------------------------------------------
|
|
|
|
void CAudioPlayerGui::screensaver(bool on)
|
|
{
|
|
if (on)
|
|
{
|
|
m_screensaver = true;
|
|
m_frameBuffer->ClearFrameBuffer();
|
|
stimer = g_RCInput->addTimer(10*1000*1000, false);
|
|
}
|
|
else
|
|
{
|
|
if (stimer)
|
|
g_RCInput->killTimer(stimer);
|
|
stimer = 0;
|
|
m_screensaver = false;
|
|
#if 0
|
|
m_frameBuffer->loadPal("radiomode.pal", 18, COL_MAXFREE);
|
|
m_frameBuffer->useBackground(m_frameBuffer->loadBackground(NEUTRINO_ICON_RADIOMODE));// set useBackground true or false
|
|
m_frameBuffer->paintBackground();
|
|
#endif
|
|
paint();
|
|
m_idletime = time(NULL);
|
|
}
|
|
}
|
|
//------------------------------------------------------------------------
|
|
|
|
void CAudioPlayerGui::GetMetaData(CAudiofileExt &File)
|
|
{
|
|
// printf("GetMetaData\n");
|
|
bool ret = 1;
|
|
|
|
if (CFile::STREAM_AUDIO != File.FileType)
|
|
ret = CAudioPlayer::getInstance()->readMetaData( &File,
|
|
m_state != CAudioPlayerGui::STOP &&
|
|
!g_settings.audioplayer_highprio);
|
|
|
|
if (!ret || (File.MetaData.artist.empty() && File.MetaData.title.empty() ))
|
|
{
|
|
//Set from Filename
|
|
std::string tmp = File.Filename.substr(File.Filename.rfind('/') + 1);
|
|
tmp = tmp.substr(0,tmp.length()-4); //remove extension (.mp3)
|
|
std::string::size_type i = tmp.rfind(" - ");
|
|
if (i != std::string::npos)
|
|
{ // Trennzeichen " - " gefunden
|
|
File.MetaData.artist = tmp.substr(0, i);
|
|
File.MetaData.title = tmp.substr(i + 3);
|
|
}
|
|
else
|
|
{
|
|
i = tmp.rfind('-');
|
|
if (i != std::string::npos)
|
|
{ //Trennzeichen "-"
|
|
File.MetaData.artist = tmp.substr(0, i);
|
|
File.MetaData.title = tmp.substr(i + 1);
|
|
}
|
|
else
|
|
File.MetaData.title = tmp;
|
|
}
|
|
File.MetaData.artist = FILESYSTEM_ENCODING_TO_UTF8_STRING(File.MetaData.artist);
|
|
File.MetaData.title = FILESYSTEM_ENCODING_TO_UTF8_STRING(File.MetaData.title );
|
|
}
|
|
}
|
|
//------------------------------------------------------------------------
|
|
|
|
bool CAudioPlayerGui::getNumericInput(neutrino_msg_t& msg, int& val) {
|
|
|
|
neutrino_msg_data_t data;
|
|
int x1 = (g_settings.screen_EndX - g_settings.screen_StartX) / 2 + g_settings.screen_StartX - 50;
|
|
int y1 = (g_settings.screen_EndY - g_settings.screen_StartY) / 2 + g_settings.screen_StartY;
|
|
char str[11];
|
|
do
|
|
{
|
|
val = val * 10 + CRCInput::getNumericValue(msg);
|
|
sprintf(str, "%d", val);
|
|
int w = g_Font[SNeutrinoSettings::FONT_TYPE_CHANNEL_NUM_ZAP]->getRenderWidth(str);
|
|
int h = g_Font[SNeutrinoSettings::FONT_TYPE_CHANNEL_NUM_ZAP]->getHeight();
|
|
m_frameBuffer->paintBoxRel(x1 - 7, y1 - h - 5, w + 14, h + 10, COL_MENUCONTENT_PLUS_6);
|
|
m_frameBuffer->paintBoxRel(x1 - 4, y1 - h - 3, w + 8, h + 6, COL_MENUCONTENTSELECTED_PLUS_0);
|
|
g_Font[SNeutrinoSettings::FONT_TYPE_CHANNEL_NUM_ZAP]->RenderString(x1, y1, w + 1, str, COL_MENUCONTENTSELECTED, 0);
|
|
while (true)
|
|
{
|
|
g_RCInput->getMsg(&msg, &data, 100);
|
|
if (msg > CRCInput::RC_MaxRC && msg != CRCInput::RC_timeout)
|
|
{ // not a key event
|
|
CNeutrinoApp::getInstance()->handleMsg(msg, data);
|
|
continue;
|
|
}
|
|
if (msg & (CRCInput::RC_Repeat|CRCInput::RC_Release)) // repeat / release
|
|
continue;
|
|
break;
|
|
}
|
|
} while (g_RCInput->isNumeric(msg) && val < 1000000);
|
|
return (msg == CRCInput::RC_ok);
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
|
|
|
|
void CAudioPlayerGui::getFileInfoToDisplay(std::string &info, CAudiofileExt &file)
|
|
{
|
|
std::string fileInfo;
|
|
std::string artist;
|
|
std::string title;
|
|
|
|
if (!m_inetmode) {
|
|
artist ="Artist?";
|
|
title = "Title?";
|
|
}
|
|
|
|
if (!file.MetaData.bitrate)
|
|
{
|
|
GetMetaData(file);
|
|
}
|
|
|
|
if (!file.MetaData.artist.empty())
|
|
artist = file.MetaData.artist;
|
|
|
|
if (!file.MetaData.title.empty())
|
|
title = file.MetaData.title;
|
|
|
|
if (g_settings.audioplayer_display == TITLE_ARTIST)
|
|
{
|
|
fileInfo += title;
|
|
if (!title.empty() && !artist.empty()) fileInfo += ", ";
|
|
fileInfo += artist;
|
|
}
|
|
else //if(g_settings.audioplayer_display == ARTIST_TITLE)
|
|
{
|
|
fileInfo += artist;
|
|
if (!title.empty() && !artist.empty()) fileInfo += ", ";
|
|
fileInfo += title;
|
|
}
|
|
|
|
if (!file.MetaData.album.empty())
|
|
{
|
|
fileInfo += " (";
|
|
fileInfo += file.MetaData.album;
|
|
fileInfo += ')';
|
|
}
|
|
if (fileInfo.empty())
|
|
{
|
|
fileInfo += "Unknown";
|
|
}
|
|
file.firstChar = tolower(fileInfo[0]);
|
|
info += fileInfo;
|
|
}
|
|
//------------------------------------------------------------------------
|
|
|
|
void CAudioPlayerGui::addToPlaylist(CAudiofileExt &file)
|
|
{
|
|
//printf("add2Playlist: %s\n", file.Filename.c_str());
|
|
if (m_select_title_by_name)
|
|
{
|
|
if (!file.MetaData.bitrate)
|
|
{
|
|
std::string t = "";
|
|
getFileInfoToDisplay(t,file);
|
|
}
|
|
}
|
|
m_playlist.push_back(file);
|
|
m_playlistHasChanged = true;
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
void CAudioPlayerGui::removeFromPlaylist(long pos)
|
|
{
|
|
unsigned char firstChar = ' ';
|
|
if (m_select_title_by_name)
|
|
{
|
|
// must be called before m_playlist.erase()
|
|
firstChar = getFirstChar(m_playlist[pos]);
|
|
}
|
|
|
|
m_playlist.erase(m_playlist.begin() + pos);
|
|
m_playlistHasChanged = true;
|
|
|
|
if (m_select_title_by_name)
|
|
{
|
|
|
|
#ifdef AUDIOPLAYER_TIME_DEBUG
|
|
timeval start;
|
|
gettimeofday(&start,NULL);
|
|
#endif
|
|
//printf("searching for key: %c val: %ld\n",firstChar,pos);
|
|
|
|
CTitle2Pos::iterator item = m_title2Pos.find(firstChar);
|
|
if (item != m_title2Pos.end())
|
|
{
|
|
//const CPosList::size_type del =
|
|
item->second.erase(pos);
|
|
|
|
// delete empty entries
|
|
if (item->second.size() == 0)
|
|
{
|
|
m_title2Pos.erase(item);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
printf("could not find key: %c pos: %ld\n",firstChar,pos);
|
|
}
|
|
// decrease position information for all titles with a position
|
|
// behind item to delete
|
|
long p = 0;
|
|
for (CTitle2Pos::iterator title=m_title2Pos.begin();
|
|
title!=m_title2Pos.end(); title++)
|
|
{
|
|
CPosList newList;
|
|
for (CPosList::iterator posIt=title->second.begin();
|
|
posIt!=title->second.end(); posIt++)
|
|
{
|
|
p = *(posIt);
|
|
if (*posIt > pos)
|
|
p--;
|
|
// old list is sorted so we can give a hint to insert at the end
|
|
newList.insert(newList.end(), p);
|
|
}
|
|
//title->second.clear();
|
|
title->second = newList;
|
|
}
|
|
#ifdef AUDIOPLAYER_TIME_DEBUG
|
|
timeval end;
|
|
gettimeofday(&end,NULL);
|
|
printf("delete took: ");
|
|
printTimevalDiff(start,end);
|
|
#endif
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------
|
|
|
|
void CAudioPlayerGui::selectTitle(unsigned char selectionChar)
|
|
{
|
|
unsigned long i;
|
|
|
|
//printf("fastLookup: key %c\n",selectionChar);
|
|
CTitle2Pos::iterator it = m_title2Pos.find(selectionChar);
|
|
if (it!=m_title2Pos.end())
|
|
{
|
|
// search for the next greater id
|
|
// if nothing found take the first
|
|
CPosList::iterator posIt = it->second.upper_bound(m_selected);
|
|
if (posIt != it->second.end())
|
|
{
|
|
i = *posIt;
|
|
//printf("upper bound i: %ld\n",i);
|
|
}
|
|
else
|
|
{
|
|
if (it->second.size() > 0)
|
|
{
|
|
i = *(it->second.begin());
|
|
//printf("using begin i: %ld\n",i);
|
|
}
|
|
else
|
|
{
|
|
//printf("no title with that key\n");
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//printf("no title with that key\n");
|
|
return;
|
|
}
|
|
|
|
int prevselected = m_selected;
|
|
m_selected = i;
|
|
|
|
paintItem(prevselected - m_liststart);
|
|
unsigned int oldliststart = m_liststart;
|
|
m_liststart = (m_selected / m_listmaxshow)*m_listmaxshow;
|
|
//printf("before paint\n");
|
|
if (oldliststart != m_liststart)
|
|
{
|
|
paint();
|
|
}
|
|
else
|
|
{
|
|
paintItem(m_selected - m_liststart);
|
|
}
|
|
}
|
|
//------------------------------------------------------------------------
|
|
|
|
void CAudioPlayerGui::printSearchTree()
|
|
{
|
|
for (CTitle2Pos::iterator it=m_title2Pos.begin();
|
|
it!=m_title2Pos.end(); it++)
|
|
{
|
|
printf("key: %c\n",it->first);
|
|
long pos=-1;
|
|
for (CPosList::iterator it2=it->second.begin();
|
|
it2!=it->second.end(); it2++)
|
|
{
|
|
pos++;
|
|
printf(" val: %ld ",*it2);
|
|
if (pos % 5 == 4)
|
|
printf("\n");
|
|
}
|
|
printf("\n");
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
|
|
void CAudioPlayerGui::buildSearchTree()
|
|
{
|
|
|
|
// printf("before\n");
|
|
// printSearchTree();
|
|
|
|
#ifdef AUDIOPLAYER_TIME_DEBUG
|
|
timeval start;
|
|
gettimeofday(&start,NULL);
|
|
#endif
|
|
|
|
CProgressWindow progress;
|
|
progress.setTitle(LOCALE_AUDIOPLAYER_BUILDING_SEARCH_INDEX);
|
|
progress.exec(this, "");
|
|
|
|
long maxProgress = (m_playlist.size() > 1) ? m_playlist.size() - 1 : 1;
|
|
|
|
m_title2Pos.clear();
|
|
long listPos = -1;
|
|
|
|
for (CAudioPlayList::iterator it=m_playlist.begin();
|
|
it!=m_playlist.end(); it++)
|
|
{
|
|
// if (m_state == CAudioPlayerGui::PLAY)
|
|
// usleep(10*1000);
|
|
listPos++;
|
|
progress.showGlobalStatus(100*listPos / maxProgress);
|
|
//std::string info;
|
|
progress.showStatusMessageUTF(it->Filename);
|
|
unsigned char firstChar = getFirstChar(*it);
|
|
const std::pair<CTitle2Pos::iterator,bool> item =
|
|
m_title2Pos.insert(CTitle2PosItem(firstChar,CPosList()));
|
|
item.first->second.insert(listPos);
|
|
}
|
|
progress.hide();
|
|
m_playlistHasChanged = false;
|
|
|
|
#ifdef AUDIOPLAYER_TIME_DEBUG
|
|
timeval end;
|
|
gettimeofday(&end,NULL);
|
|
printf("searchtree took: ");
|
|
printTimevalDiff(start,end);
|
|
#endif
|
|
// printf("after:\n");
|
|
//printSearchTree();
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
|
|
unsigned char CAudioPlayerGui::getFirstChar(CAudiofileExt &file)
|
|
{
|
|
if (file.firstChar == '\0')
|
|
{
|
|
std::string info;
|
|
getFileInfoToDisplay(info,file);
|
|
}
|
|
//printf("getFirstChar: %c\n",file.firstChar);
|
|
return file.firstChar;
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------
|
|
#ifdef AUDIOPLAYER_TIME_DEBUG
|
|
void CAudioPlayerGui::printTimevalDiff(timeval &start, timeval &end)
|
|
{
|
|
|
|
long secs = end.tv_sec - start.tv_sec;
|
|
long usecs = end.tv_usec -start.tv_usec;
|
|
if (usecs < 0)
|
|
{
|
|
usecs = 1000000 + usecs;
|
|
secs--;
|
|
}
|
|
printf("%ld:%ld\n",secs,usecs);
|
|
}
|
|
#endif
|
|
|
|
//------------------------------------------------------------------------
|
|
|
|
void CAudioPlayerGui::savePlaylist()
|
|
{
|
|
const char *path;
|
|
|
|
// .m3u playlist
|
|
// http://hanna.pyxidis.org/tech/m3u.html
|
|
|
|
CFileBrowser browser;
|
|
browser.Multi_Select = false;
|
|
browser.Dir_Mode = true;
|
|
CFileFilter dirFilter;
|
|
dirFilter.addFilter("m3u");
|
|
browser.Filter = &dirFilter;
|
|
// select preferred directory if exists
|
|
if (strlen(g_settings.network_nfs_audioplayerdir) != 0)
|
|
path = g_settings.network_nfs_audioplayerdir;
|
|
else
|
|
path = "/";
|
|
|
|
// let user select target directory
|
|
this->hide();
|
|
if (browser.exec(path))
|
|
{
|
|
// refresh view
|
|
this->paint();
|
|
CFile *file = browser.getSelectedFile();
|
|
std::string absPlaylistDir = file->getPath();
|
|
|
|
// add a trailing slash if necessary
|
|
if ((absPlaylistDir.empty()) || ((*(absPlaylistDir.rbegin()) != '/')))
|
|
{
|
|
absPlaylistDir += '/';
|
|
}
|
|
absPlaylistDir += file->getFileName();
|
|
|
|
const int filenamesize = 30;
|
|
char filename[filenamesize + 1] = "";
|
|
|
|
if (file->getType() == CFile::FILE_PLAYLIST)
|
|
{
|
|
// file is playlist so we should ask if we can overwrite it
|
|
std::string name = file->getPath();
|
|
name += '/';
|
|
name += file->getFileName();
|
|
bool overwrite = askToOverwriteFile(name);
|
|
if (!overwrite)
|
|
{
|
|
return;
|
|
}
|
|
snprintf(filename, name.size(), "%s", name.c_str());
|
|
}
|
|
else if (file->getType() == CFile::FILE_DIR)
|
|
{
|
|
// query for filename
|
|
this->hide();
|
|
CStringInputSMS filenameInput(LOCALE_AUDIOPLAYER_PLAYLIST_NAME,
|
|
filename,
|
|
filenamesize - 1,
|
|
LOCALE_AUDIOPLAYER_PLAYLIST_NAME_HINT1,
|
|
LOCALE_AUDIOPLAYER_PLAYLIST_NAME_HINT2,
|
|
"abcdefghijklmnopqrstuvwxyz0123456789-.,:!?/ ");
|
|
filenameInput.exec(NULL, "");
|
|
// refresh view
|
|
this->paint();
|
|
std::string name = absPlaylistDir;
|
|
name += '/';
|
|
name += filename;
|
|
name += ".m3u";
|
|
std::ifstream input(name.c_str());
|
|
|
|
// test if file exists and query for overwriting it or not
|
|
if (input.is_open())
|
|
{
|
|
bool overwrite = askToOverwriteFile(name);
|
|
if (!overwrite)
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
input.close();
|
|
}
|
|
else
|
|
{
|
|
std::cout << "CAudioPlayerGui: neither .m3u nor directory selected, abort" << std::endl;
|
|
return;
|
|
}
|
|
std::string absPlaylistFilename = absPlaylistDir;
|
|
absPlaylistFilename += '/';
|
|
absPlaylistFilename += filename;
|
|
absPlaylistFilename += ".m3u";
|
|
std::ofstream playlistFile(absPlaylistFilename.c_str());
|
|
std::cout << "CAudioPlayerGui: writing playlist to " << absPlaylistFilename << std::endl;
|
|
if (!playlistFile)
|
|
{
|
|
// an error occured
|
|
const int msgsize = 255;
|
|
char msg[msgsize] = "";
|
|
snprintf(msg,
|
|
msgsize,
|
|
"%s\n%s",
|
|
g_Locale->getText(LOCALE_AUDIOPLAYER_PLAYLIST_FILEERROR_MSG),
|
|
absPlaylistFilename.c_str());
|
|
|
|
DisplayErrorMessage(msg);
|
|
// refresh view
|
|
this->paint();
|
|
std::cout << "CAudioPlayerGui: could not create play list file "
|
|
<< absPlaylistFilename << std::endl;
|
|
return;
|
|
}
|
|
// writing .m3u file
|
|
playlistFile << "#EXTM3U" << std::endl;
|
|
|
|
CAudioPlayList::const_iterator it;
|
|
for (it = m_playlist.begin(); it!=m_playlist.end(); it++)
|
|
{
|
|
playlistFile << "#EXTINF:" << it->MetaData.total_time << ","
|
|
<< it->MetaData.artist << " - " << it->MetaData.title << std::endl;
|
|
if (m_inetmode)
|
|
playlistFile << it->Filename << std::endl;
|
|
else
|
|
playlistFile << absPath2Rel(absPlaylistDir, it->Filename) << std::endl;
|
|
}
|
|
playlistFile.close();
|
|
}
|
|
this->paint();
|
|
}
|
|
//------------------------------------------------------------------------
|
|
|
|
bool CAudioPlayerGui::askToOverwriteFile(const std::string& filename) {
|
|
|
|
char msg[filename.length() + 127];
|
|
snprintf(msg,
|
|
filename.length() + 126,
|
|
"%s\n%s",
|
|
g_Locale->getText(LOCALE_AUDIOPLAYER_PLAYLIST_FILEOVERWRITE_MSG),
|
|
filename.c_str());
|
|
bool res = (ShowMsgUTF(LOCALE_AUDIOPLAYER_PLAYLIST_FILEOVERWRITE_TITLE,
|
|
msg,CMessageBox::mbrYes, CMessageBox::mbYes | CMessageBox::mbNo)
|
|
== CMessageBox::mbrYes);
|
|
this->paint();
|
|
return res;
|
|
}
|
|
//------------------------------------------------------------------------
|
|
|
|
std::string CAudioPlayerGui::absPath2Rel(const std::string& fromDir,
|
|
const std::string& absFilename) {
|
|
std::string res = "";
|
|
|
|
int length = fromDir.length() < absFilename.length() ? fromDir.length() : absFilename.length();
|
|
int lastSlash = 0;
|
|
// find common prefix for both paths
|
|
// fromDir: /foo/bar/angle/1 (length: 16)
|
|
// absFilename: /foo/bar/devil/2/fire.mp3 (length: 19)
|
|
// -> /foo/bar/ is prefix, lastSlash will be 8
|
|
for (int i=0; i<length; i++)
|
|
{
|
|
if (fromDir[i] == absFilename[i])
|
|
{
|
|
if (fromDir[i] == '/')
|
|
{
|
|
lastSlash = i;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
// cut common prefix
|
|
std::string relFilepath = absFilename.substr(lastSlash + 1, absFilename.length() - lastSlash + 1);
|
|
// relFilepath is now devil/2/fire.mp3
|
|
|
|
// First slash is not removed because we have to go up each directory.
|
|
// Since the slashes are counted later we make sure for each directory one slash is present
|
|
std::string relFromDir = fromDir.substr(lastSlash, fromDir.length() - lastSlash);
|
|
// relFromDir is now /angle/1
|
|
|
|
// go up as many directories as neccessary
|
|
for (unsigned int i=0; i<relFromDir.size(); i++)
|
|
{
|
|
if (relFromDir[i] == '/')
|
|
{
|
|
res = res + "../";
|
|
}
|
|
}
|
|
|
|
res = res + relFilepath;
|
|
return res;
|
|
}
|