You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1678 lines
46 KiB
1678 lines
46 KiB
/*
|
|
* Kscd - A simple cd player for the KDE Project
|
|
*
|
|
* Copyright (c) 1997 Bernd Johannes wuebben@math.cornell.edu
|
|
* Copyright (c) 2002-2003 Aaron J. Seigo <aseigo@kde.org>
|
|
* Copyright (c) 2004 Alexander Kern <alex.kern@gmx.de>
|
|
* Copyright (c) 2003-2006 Richard Lärkäng <nouseforaname@home.se>
|
|
*
|
|
* 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, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*
|
|
*/
|
|
|
|
#include <tqdir.h>
|
|
#include <tqregexp.h>
|
|
#include <tqtextstream.h>
|
|
#include <tqlayout.h>
|
|
#include <tqhbox.h>
|
|
#include <tqvbox.h>
|
|
#include <tqapplication.h>
|
|
#include <tqgroupbox.h>
|
|
#include <tqsqlpropertymap.h>
|
|
|
|
#include <dcopclient.h>
|
|
#include <tdeaboutdata.h>
|
|
#include <tdeaccel.h>
|
|
#include <tdeaction.h>
|
|
#include <dcopref.h>
|
|
#include <kcharsets.h>
|
|
#include <tdecmdlineargs.h>
|
|
#include <tdeconfig.h>
|
|
#include <kdebug.h>
|
|
#include <kdialogbase.h>
|
|
#include <tdeemailsettings.h>
|
|
#include <tdeglobal.h>
|
|
#include <khelpmenu.h>
|
|
#include <kkeydialog.h>
|
|
#include <kiconloader.h>
|
|
#include <kinputdialog.h>
|
|
#include <tdelocale.h>
|
|
#include <tdemainwindow.h>
|
|
#include <tdemessagebox.h>
|
|
#include <tdepopupmenu.h>
|
|
#include <tdeprotocolmanager.h>
|
|
#include <krun.h>
|
|
#include <kstandarddirs.h>
|
|
#include <kstdaction.h>
|
|
#include <kstringhandler.h>
|
|
#include <kurl.h>
|
|
#include <kuniqueapplication.h>
|
|
#include <tdeglobalsettings.h>
|
|
#include <tdecmoduleloader.h>
|
|
#include <tdeconfigdialog.h>
|
|
|
|
#include "docking.h"
|
|
#include "kscd.h"
|
|
#include "version.h"
|
|
#include "prefs.h"
|
|
|
|
#include <twin.h>
|
|
#include <netwm.h>
|
|
#include <stdlib.h>
|
|
|
|
#include <config.h>
|
|
|
|
#include "cddbdlg.h"
|
|
#include "configWidget.h"
|
|
#include <tqtextcodec.h>
|
|
#include <kcompactdisc.h>
|
|
#include <fixx11h.h>
|
|
|
|
static const char description[] = I18N_NOOP("TDE CD player");
|
|
|
|
bool stoppedByUser = false;
|
|
|
|
|
|
/****************************************************************************
|
|
The GUI part
|
|
*****************************************************************************/
|
|
|
|
KSCD::KSCD( TQWidget *parent, const char *name )
|
|
: DCOPObject("CDPlayer"),
|
|
kscdPanelDlg( parent, name, TQt::WDestructiveClose ),
|
|
configDialog(0L),
|
|
cddialog(0L), //!!!!
|
|
jumpToTrack(0L),
|
|
updateTime(true),
|
|
m_dockWidget(0)
|
|
{
|
|
m_cd = new TDECompactDisc();
|
|
cddbInfo.clear(); // The first freedb revision is "0" //!!!!
|
|
random_current = random_list.begin();
|
|
|
|
cddb = new KCDDB::Client();
|
|
connect(cddb, TQT_SIGNAL(finished(CDDB::Result)), TQT_TQOBJECT(this), TQT_SLOT(lookupCDDBDone(CDDB::Result)));
|
|
|
|
#if defined(BUILD_CDDA)
|
|
audio_systems_list
|
|
<< "arts"
|
|
#if defined(HAVE_ARTS_LIBASOUND2)
|
|
<< "alsa"
|
|
#endif
|
|
#ifdef USE_SUN_AUDIO
|
|
<< "sun"
|
|
#endif
|
|
;
|
|
#endif
|
|
|
|
readSettings();
|
|
initFont();
|
|
drawPanel();
|
|
setColors();
|
|
|
|
// the time slider
|
|
timeIcon->setPixmap(SmallIcon("player_time"));
|
|
connect(timeSlider, TQT_SIGNAL(sliderPressed()), TQT_SLOT(timeSliderPressed()));
|
|
connect(timeSlider, TQT_SIGNAL(sliderReleased()), TQT_SLOT(timeSliderReleased()));
|
|
connect(timeSlider, TQT_SIGNAL(sliderMoved(int)), TQT_SLOT(timeSliderMoved(int)));
|
|
connect(timeSlider, TQT_SIGNAL(valueChanged(int)), TQT_SLOT(jumpToTime(int)));
|
|
|
|
// the volume slider
|
|
volumeIcon->setPixmap(SmallIcon("player_volume"));
|
|
volumeSlider->setValue(Prefs::volume());
|
|
TQString str;
|
|
str = TQString::fromUtf8( TQCString().sprintf(i18n("Vol: %02d%%").utf8(), Prefs::volume()) );
|
|
volumelabel->setText(str);
|
|
connect(volumeSlider, TQT_SIGNAL(valueChanged(int)), TQT_SLOT(volChanged(int)));
|
|
|
|
/* FIXME check for return value */
|
|
setDevicePaths(/*Prefs::cdDevice(), Prefs::audioSystem(), Prefs::audioDevice()*/);
|
|
connect(m_cd, TQT_SIGNAL(trackPlaying(unsigned, unsigned)), TQT_TQOBJECT(this), TQT_SLOT(trackUpdate(unsigned, unsigned)));
|
|
connect(m_cd, TQT_SIGNAL(trackPaused(unsigned, unsigned)), TQT_TQOBJECT(this), TQT_SLOT(trackUpdate(unsigned, unsigned)));
|
|
connect(m_cd, TQT_SIGNAL(trackChanged(unsigned, unsigned)), TQT_TQOBJECT(this), TQT_SLOT(trackChanged(unsigned, unsigned)));
|
|
connect(m_cd, TQT_SIGNAL(discStopped()), TQT_TQOBJECT(this), TQT_SLOT(discStopped()));
|
|
connect(m_cd, TQT_SIGNAL(discChanged(unsigned)), TQT_TQOBJECT(this), TQT_SLOT(discChanged(unsigned)));
|
|
connect( &queryledtimer, TQT_SIGNAL(timeout()), TQT_SLOT(togglequeryled()) );
|
|
connect( &titlelabeltimer, TQT_SIGNAL(timeout()), TQT_SLOT(titlelabeltimeout()) );
|
|
connect( &cycletimer, TQT_SIGNAL(timeout()), TQT_SLOT(cycletimeout()) );
|
|
connect( &jumpTrackTimer, TQT_SIGNAL(timeout()), TQT_SLOT(jumpTracks()) );
|
|
/*
|
|
these are always connected in base class
|
|
connect( playPB, TQT_SIGNAL(clicked()), TQT_SLOT(playClicked()) );
|
|
connect( nextPB, TQT_SIGNAL(clicked()), TQT_SLOT(nextClicked()) );
|
|
connect( prevPB, TQT_SIGNAL(clicked()), TQT_SLOT(prevClicked()) );
|
|
connect( stopPB, TQT_SIGNAL(clicked()), TQT_SLOT(stopClicked()) );
|
|
connect( ejectPB, TQT_SIGNAL(clicked()), TQT_SLOT(ejectClicked()) );
|
|
*/
|
|
connect( repeatPB, TQT_SIGNAL(clicked()), TQT_SLOT(loopClicked()) );
|
|
connect( songListCB, TQT_SIGNAL(activated(int)), TQT_SLOT(trackSelected(int)));
|
|
connect( shufflePB, TQT_SIGNAL(clicked()), TQT_SLOT(randomSelected()));
|
|
connect( cddbPB, TQT_SIGNAL(clicked()), TQT_SLOT(CDDialogSelected()));
|
|
connect(kapp, TQT_SIGNAL(tdedisplayPaletteChanged()), TQT_TQOBJECT(this), TQT_SLOT(setColors()));
|
|
connect(kapp, TQT_SIGNAL(iconChanged(int)), TQT_TQOBJECT(this), TQT_SLOT(setIcons()));
|
|
TQToolTip::remove(songListCB);
|
|
TQToolTip::add(songListCB, i18n("Track list"));
|
|
|
|
|
|
// set up the actions and keyboard accels
|
|
m_actions = new TDEActionCollection(this);
|
|
|
|
TDEAction* action;
|
|
action = new TDEAction(i18n("Play/Pause"), Key_P, TQT_TQOBJECT(this), TQT_SLOT(playClicked()), m_actions, "Play/Pause");
|
|
action = new TDEAction(i18n("Stop"), Key_S, TQT_TQOBJECT(this), TQT_SLOT(stopClicked()), m_actions, "Stop");
|
|
action = new TDEAction(i18n("Previous"), Key_B, TQT_TQOBJECT(this), TQT_SLOT(prevClicked()), m_actions, "Previous");
|
|
action = new TDEAction(i18n("Next"), Key_N, TQT_TQOBJECT(this), TQT_SLOT(nextClicked()), m_actions, "Next");
|
|
action = KStdAction::quit(TQT_TQOBJECT(this), TQT_SLOT(quitClicked()), m_actions);
|
|
action = KStdAction::keyBindings(TQT_TQOBJECT(this), TQT_SLOT(configureKeys()), m_actions, "options_configure_shortcuts");
|
|
action = KStdAction::keyBindings(TQT_TQOBJECT(this), TQT_SLOT(configureGlobalKeys()), m_actions, "options_configure_globals");
|
|
action = KStdAction::preferences(TQT_TQOBJECT(this), TQT_SLOT(showConfig()), m_actions);
|
|
action = new TDEAction(i18n("Loop"), Key_L, TQT_TQOBJECT(this), TQT_SLOT(loopClicked()), m_actions, "Loop");
|
|
action = new TDEAction(i18n("Eject"), CTRL + Key_E, TQT_TQOBJECT(this), TQT_SLOT(ejectClicked()), m_actions, "Eject");
|
|
action = new TDEAction(i18n("Increase Volume"), Key_Plus, TQT_TQOBJECT(this), TQT_SLOT(incVolume()), m_actions, "IncVolume");
|
|
TDEShortcut increaseVolume = action->shortcut();
|
|
increaseVolume.append( KKey( Key_Equal ) );
|
|
action->setShortcut( increaseVolume );
|
|
action = new TDEAction(i18n("Decrease Volume"), Key_Minus, TQT_TQOBJECT(this), TQT_SLOT(decVolume()), m_actions, "DecVolume");
|
|
action = new TDEAction(i18n("Options"), CTRL + Key_T, TQT_TQOBJECT(this), TQT_SLOT(showConfig()), m_actions, "Options");
|
|
action = new TDEAction(i18n("Shuffle"), Key_R, TQT_TQOBJECT(this), TQT_SLOT(randomSelected()), m_actions, "Shuffle");
|
|
action = new TDEAction(i18n("CDDB"), CTRL + Key_D, TQT_TQOBJECT(this), TQT_SLOT(CDDialogSelected()), m_actions, "CDDB");
|
|
|
|
m_actions->readShortcutSettings("Shortcuts");
|
|
|
|
m_actions->action( "options_configure_globals" )->setText( i18n( "Configure &Global Shortcuts..." ) );
|
|
|
|
kapp->installKDEPropertyMap();
|
|
TQSqlPropertyMap *map = TQSqlPropertyMap::defaultMap();
|
|
map->insert("KComboBox", "currentText");
|
|
|
|
initGlobalShortcuts();
|
|
|
|
setupPopups();
|
|
|
|
if (Prefs::looping())
|
|
{
|
|
loopled->on();
|
|
loopled->show();
|
|
repeatPB->setOn(true);
|
|
}
|
|
|
|
setDocking(Prefs::docking());
|
|
|
|
setFocusPolicy(TQ_NoFocus);
|
|
|
|
songListCB->setSizePolicy(TQSizePolicy::Ignored, TQSizePolicy::Fixed);
|
|
adjustSize();
|
|
setFixedHeight(this->height());
|
|
} // KSCD
|
|
|
|
|
|
KSCD::~KSCD()
|
|
{
|
|
delete cddb;
|
|
delete m_cd;
|
|
} // ~KSCD
|
|
|
|
|
|
void KSCD::initGlobalShortcuts() {
|
|
|
|
m_globalAccel = new TDEGlobalAccel( TQT_TQOBJECT(this) );
|
|
|
|
//Definition of global shortcuts is based on 'local' shortcuts which follow
|
|
//the WIN key.
|
|
m_globalAccel->insert("Next", i18n("Next"), 0, KKey("WIN+N"), KKey("WIN+Right"),
|
|
TQT_TQOBJECT(this), TQT_SLOT(nextClicked()));
|
|
//NOTE: WIN+B collidates with amarok's default global shortcut.
|
|
m_globalAccel->insert("Previous", i18n("Previous"), 0, KKey("WIN+B"), KKey("WIN+Left"),
|
|
TQT_TQOBJECT(this), TQT_SLOT(prevClicked()));
|
|
m_globalAccel->insert("Play/Pause", i18n("Play/Pause"), 0, KKey("WIN+P"), 0,
|
|
TQT_TQOBJECT(this), TQT_SLOT(playClicked()));
|
|
m_globalAccel->insert("Stop", i18n("Stop"), 0, KKey("WIN+S"), 0,
|
|
TQT_TQOBJECT(this), TQT_SLOT(stopClicked()));
|
|
m_globalAccel->insert("IncVolume", i18n("Increase Volume"), 0, KKey("WIN+Plus"), KKey("WIN+Up"),
|
|
TQT_TQOBJECT(this), TQT_SLOT(incVolume()));
|
|
m_globalAccel->insert("DecVolume", i18n("Decrease Volume"), 0, KKey("WIN+Minus"), KKey("WIN+Down"),
|
|
TQT_TQOBJECT(this), TQT_SLOT(decVolume()));
|
|
m_globalAccel->insert("Shuffle", i18n("Shuffle"), 0, KKey("WIN+R"), 0,
|
|
TQT_TQOBJECT(this), TQT_SLOT(incVolume()));
|
|
|
|
m_globalAccel->setConfigGroup( "GlobalShortcuts" );
|
|
m_globalAccel->readSettings( kapp->config() );
|
|
m_globalAccel->updateConnections();
|
|
}
|
|
|
|
bool KSCD::digitalPlayback() {
|
|
#if defined(BUILD_CDDA)
|
|
return !(Prefs::audioSystem().isEmpty());
|
|
#else
|
|
return false;
|
|
#endif
|
|
}
|
|
|
|
void KSCD::setVolume(int v)
|
|
{
|
|
volChanged(v);
|
|
volumeSlider->setValue(v);
|
|
}
|
|
|
|
void KSCD::setDevice(const TQString& dev)
|
|
{
|
|
Prefs::self()->setCdDevice(dev);
|
|
setDevicePaths();
|
|
}
|
|
|
|
/**
|
|
* Initialize smallfont which fits into the 13 and 14 pixel widgets.
|
|
*/
|
|
void KSCD::initFont()
|
|
{
|
|
/* int theSmallPtSize = 10;
|
|
|
|
// Find a font that fits the 13 and 14 pixel widgets
|
|
TQFont fn( TDEGlobalSettings::generalFont().family(), theSmallPtSize, TQFont::Bold );
|
|
bool fits = false;
|
|
while (!fits && theSmallPtSize > 1)
|
|
{
|
|
TQFontMetrics metrics(fn);
|
|
if(metrics.height() > 13)
|
|
{
|
|
--theSmallPtSize;
|
|
fn.setPointSize(theSmallPtSize);
|
|
} else {
|
|
fits = true;
|
|
}
|
|
}
|
|
smallfont = TQFont(TDEGlobalSettings::generalFont().family(), theSmallPtSize, TQFont::Bold);
|
|
*/
|
|
} // initFont()
|
|
|
|
/**
|
|
* drawPanel() constructs KSCD's little black LED area
|
|
* all settings are made via panel.ui
|
|
*/
|
|
void KSCD::drawPanel()
|
|
{
|
|
setIcons();
|
|
adjustSize();
|
|
|
|
const int D = 6;
|
|
for (int u = 0; u < 5; u++) {
|
|
trackTimeLED[u] = new BW_LED_Number(frameleds);
|
|
trackTimeLED[u]->setLEDoffColor(Prefs::backColor());
|
|
trackTimeLED[u]->setLEDColor(Prefs::ledColor(), Prefs::backColor());
|
|
trackTimeLED[u]->setGeometry(2 + u * 18, D, 23, 30);
|
|
connect(trackTimeLED[u], TQT_SIGNAL(clicked()), TQT_TQOBJECT(this), TQT_SLOT(cycleplaytimemode()));
|
|
}
|
|
|
|
setLEDs(-1);
|
|
|
|
queryled = new LedLamp(symbols);
|
|
queryled->move(+10, D + 1);
|
|
queryled->off();
|
|
queryled->hide();
|
|
|
|
loopled = new LedLamp(symbols, LedLamp::Loop);
|
|
loopled->move(+10, D + 18);
|
|
loopled->off();
|
|
|
|
totaltimelabel->hide();
|
|
} // drawPanel
|
|
|
|
void KSCD::setIcons()
|
|
{
|
|
playPB->setIconSet(SmallIconSet("media-playback-start"));
|
|
stopPB->setIconSet(SmallIconSet("media-playback-stop"));
|
|
ejectPB->setIconSet(SmallIconSet("player_eject"));
|
|
prevPB->setIconSet(SmallIconSet("media-skip-backward"));
|
|
nextPB->setIconSet(SmallIconSet("media-skip-forward"));
|
|
cddbPB->setIconSet(SmallIconSet("view_text"));
|
|
infoPB->setIconSet(SmallIconSet("system-run"));
|
|
}
|
|
|
|
void KSCD::setupPopups()
|
|
{
|
|
TQPopupMenu* mainPopup = new TQPopupMenu(this);
|
|
infoPB->setPopup(mainPopup);
|
|
infoPopup = new TQPopupMenu (this);
|
|
|
|
|
|
infoPopup->insertItem("MusicMoz", 0);
|
|
infoPopup->insertItem("Ultimate Bandlist", 1);
|
|
infoPopup->insertItem("CD Universe", 2);
|
|
infoPopup->insertSeparator();
|
|
infoPopup->insertItem("AlltheWeb", 3);
|
|
infoPopup->insertItem("Altavista", 4);
|
|
infoPopup->insertItem("Excite", 5);
|
|
infoPopup->insertItem("Google", 6);
|
|
infoPopup->insertItem("Google Groups", 7);
|
|
infoPopup->insertItem("HotBot", 8);
|
|
infoPopup->insertItem("Lycos", 9);
|
|
infoPopup->insertItem("Open Directory", 10);
|
|
infoPopup->insertItem("Yahoo!", 11);
|
|
|
|
m_actions->action(KStdAction::name(KStdAction::Preferences))->plug(mainPopup);
|
|
//NEW add the shortcut dialogs
|
|
m_actions->action("options_configure_globals")->plug(mainPopup);
|
|
m_actions->action("options_configure_shortcuts")->plug(mainPopup);
|
|
mainPopup->insertSeparator();
|
|
|
|
mainPopup->insertItem(i18n("Artist Information"), infoPopup);
|
|
|
|
connect( infoPopup, TQT_SIGNAL(activated(int)), TQT_SLOT(information(int)) );
|
|
|
|
KHelpMenu* helpMenu = new KHelpMenu(this, TDEGlobal::instance()->aboutData(), false);
|
|
mainPopup->insertItem(SmallIcon("help"),i18n("&Help"), helpMenu->menu());
|
|
mainPopup->insertSeparator();
|
|
m_actions->action(KStdAction::name(KStdAction::Quit))->plug(mainPopup);
|
|
} // setupPopups
|
|
|
|
void KSCD::playClicked()
|
|
{
|
|
if (m_cd->discId() == TDECompactDisc::missingDisc)
|
|
return;
|
|
|
|
kapp->processEvents();
|
|
kapp->flushX();
|
|
|
|
if (!m_cd->isPlaying())
|
|
{
|
|
kapp->processEvents();
|
|
kapp->flushX();
|
|
|
|
if (m_cd->isPaused())
|
|
{
|
|
// Unpause (!!).
|
|
m_cd->pause();
|
|
}
|
|
else
|
|
{
|
|
setLEDs(0);
|
|
resetTimeSlider(true);
|
|
|
|
if(Prefs::randomPlay())
|
|
{
|
|
make_random_list();
|
|
// next clicked handles updating the play button, etc.
|
|
nextClicked();
|
|
}
|
|
else
|
|
{
|
|
m_cd->play(0, 0, playlist.isEmpty() ? 0 : 1);
|
|
}
|
|
}
|
|
|
|
// Update UI to allow a subsequent pause.
|
|
statuslabel->setText(i18n("Play"));
|
|
playPB->setIconSet(SmallIconSet("media-playback-pause"));
|
|
playPB->setText(i18n("Pause"));
|
|
}
|
|
else
|
|
{
|
|
m_cd->pause();
|
|
|
|
// Update UI to allow a subsequent play.
|
|
statuslabel->setText(i18n("Pause"));
|
|
playPB->setIconSet(SmallIconSet("media-playback-start"));
|
|
playPB->setText(i18n("Play"));
|
|
}
|
|
|
|
kapp->processEvents();
|
|
kapp->flushX();
|
|
} // playClicked()
|
|
|
|
void KSCD::setShuffle(int shuffle)
|
|
{
|
|
if (shuffle == 2) {
|
|
if(Prefs::randomPlay() && m_cd->tracks() > 0) {
|
|
shufflePB->blockSignals(true);
|
|
shufflePB->setOn(true);
|
|
shufflePB->blockSignals(false);
|
|
make_random_list(); /* koz: Build a unique, once, random list */
|
|
if(m_cd->isPlaying())
|
|
nextClicked();
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
Prefs::setRandomPlay(shuffle);
|
|
shufflePB->blockSignals(true);
|
|
shufflePB->setOn(shuffle);
|
|
shufflePB->blockSignals(false);
|
|
|
|
if (Prefs::randomPlay() && m_cd->tracks() > 0) {
|
|
make_random_list(); /* koz: Build a unique, once, random list */
|
|
if(m_cd->isPlaying())
|
|
nextClicked();
|
|
}
|
|
}
|
|
|
|
void KSCD::stopClicked()
|
|
{
|
|
stoppedByUser = true;
|
|
|
|
kapp->processEvents();
|
|
kapp->flushX();
|
|
m_cd->stop();
|
|
} // stopClicked()
|
|
|
|
void KSCD::prevClicked()
|
|
{
|
|
int track = m_cd->track();
|
|
|
|
if (Prefs::randomPlay()) {
|
|
track = prev_randomtrack();
|
|
if (track == -1) {
|
|
return;
|
|
}
|
|
} else {
|
|
if (track <= 1) {
|
|
if (Prefs::looping()) {
|
|
track = m_cd->tracks();
|
|
} else {
|
|
return;
|
|
}
|
|
} else {
|
|
track--;
|
|
}
|
|
}
|
|
|
|
kapp->processEvents();
|
|
kapp->flushX();
|
|
m_cd->play(track, 0, playlist.isEmpty() ? 0 : track);
|
|
} // prevClicked()
|
|
|
|
bool KSCD::nextClicked()
|
|
{
|
|
unsigned track = m_cd->track();
|
|
|
|
if (Prefs::randomPlay()) {
|
|
track = next_randomtrack();
|
|
if(track == 0) {
|
|
return false;
|
|
}
|
|
} else {
|
|
if(track < 1) {
|
|
track = 1;
|
|
} else if (track >= m_cd->tracks()) {
|
|
if (Prefs::looping()) {
|
|
track = 1;
|
|
} else {
|
|
return true;
|
|
}
|
|
} else {
|
|
track++;
|
|
}
|
|
}
|
|
|
|
kapp->processEvents();
|
|
kapp->flushX();
|
|
m_cd->play(track, 0, Prefs::randomPlay() || !playlist.isEmpty() ? track + 1 : 0);
|
|
return true;
|
|
} // nextClicked()
|
|
|
|
void KSCD::trackChanged(unsigned track, unsigned trackLength)
|
|
{
|
|
TQString tooltip = artistlabel->text();
|
|
if (track < 1)
|
|
{
|
|
setLEDs(-1);
|
|
resetTimeSlider(true);
|
|
tracklabel->setText("--/--");
|
|
titlelabel->clear();
|
|
}
|
|
else
|
|
{
|
|
// if (!nextClicked())
|
|
// {
|
|
// statuslabel->setText(i18n("Disc Finished"));
|
|
// m_cd->stop();
|
|
// }
|
|
// break;
|
|
|
|
if (songListCB->count())
|
|
{
|
|
songListCB->setCurrentItem(track - 1);
|
|
// drop the number.
|
|
// for Mahlah, a picky though otherwise wonderful person - AJS
|
|
TQString justTheName = songListCB->currentText();
|
|
justTheName = justTheName.right(justTheName.length() - 4);
|
|
|
|
TQToolTip::remove(songListCB);
|
|
TQToolTip::add(songListCB, i18n("Current track: %1").arg(justTheName));
|
|
}
|
|
timeSlider->blockSignals(true);
|
|
timeSlider->setRange(0, trackLength ? trackLength - 1 : 0);
|
|
timeSlider->blockSignals(false);
|
|
TQString str;
|
|
str.sprintf("%02d/%02d", track, m_cd->tracks());
|
|
tracklabel->setText(str);
|
|
|
|
TQString title = cddbInfo.trackInfoList[track-1].title;
|
|
titlelabel->setText(title);
|
|
tooltip += "/";
|
|
tooltip += KStringHandler::rsqueeze(title, 30);
|
|
}
|
|
emit trackChanged(tooltip);
|
|
} //trackChanged(int track)
|
|
|
|
|
|
void KSCD::jumpToTime(int ms, bool forcePlay)
|
|
{
|
|
kapp->processEvents();
|
|
kapp->flushX();
|
|
|
|
int track = m_cd->track();
|
|
if ((m_cd->isPlaying() || forcePlay) &&
|
|
ms < (int)m_cd->trackLength())
|
|
{
|
|
if(Prefs::randomPlay() || !playlist.isEmpty())
|
|
{
|
|
m_cd->play(track, ms, track + 1);
|
|
}
|
|
else
|
|
{
|
|
m_cd->play(track, ms);
|
|
}
|
|
}
|
|
} // jumpToTime(int ms)
|
|
|
|
void KSCD::timeSliderPressed()
|
|
{
|
|
updateTime = false;
|
|
} // timeSliderPressed()
|
|
|
|
void KSCD::timeSliderMoved(int milliseconds)
|
|
{
|
|
setLEDs(milliseconds);
|
|
} // timeSliderMoved(int seconds)
|
|
|
|
void KSCD::timeSliderReleased()
|
|
{
|
|
updateTime = true;
|
|
} // timeSliderReleased()
|
|
|
|
void KSCD::quitClicked()
|
|
{
|
|
// ensure nothing else starts happening
|
|
queryledtimer.stop();
|
|
titlelabeltimer.stop();
|
|
cycletimer.stop();
|
|
jumpTrackTimer.stop();
|
|
|
|
writeSettings();
|
|
//setShuffle(0);
|
|
statuslabel->clear();
|
|
setLEDs(-1);
|
|
|
|
// Good GOD this is evil
|
|
kapp->processEvents();
|
|
kapp->flushX();
|
|
|
|
if(Prefs::stopExit())
|
|
m_cd->stop();
|
|
|
|
delete m_cd;
|
|
|
|
kapp->quit();
|
|
} // quitClicked()
|
|
|
|
bool KSCD::event( TQEvent *e )
|
|
{
|
|
return TQWidget::event(e);
|
|
} // event
|
|
|
|
|
|
void KSCD::loopOn()
|
|
{
|
|
Prefs::setLooping(true);
|
|
loopled->on();
|
|
loopled->show();
|
|
kapp->processEvents();
|
|
kapp->flushX();
|
|
} // loopOn;
|
|
|
|
void KSCD::loopOff()
|
|
{
|
|
Prefs::setLooping(false);
|
|
loopled->off();
|
|
loopled->show();
|
|
kapp->processEvents();
|
|
kapp->flushX();
|
|
} // loopOff;
|
|
|
|
void KSCD::loopClicked()
|
|
{
|
|
if(Prefs::looping())
|
|
{
|
|
loopOff();
|
|
}
|
|
else
|
|
{
|
|
loopOn();
|
|
}
|
|
} // loopClicked
|
|
|
|
/**
|
|
* Do everything needed if the user requested to eject the disc.
|
|
*
|
|
*/
|
|
void KSCD::ejectClicked()
|
|
{
|
|
m_cd->eject();
|
|
} // ejectClicked
|
|
|
|
void KSCD::closeEvent(TQCloseEvent *e)
|
|
{
|
|
if (Prefs::docking() && !kapp->sessionSaving())
|
|
{
|
|
hide();
|
|
e->ignore();
|
|
return;
|
|
}
|
|
e->accept();
|
|
}
|
|
|
|
void KSCD::randomSelected()
|
|
{
|
|
setShuffle(Prefs::randomPlay()?0:1);
|
|
|
|
/* FIXME this helps us to display "Random" in Status line
|
|
should it maybe to be replaced with symbol "RAND" or something others */
|
|
statuslabel->setText(Prefs::randomPlay()?i18n("Random"):i18n("Play"));
|
|
} // randomSelected
|
|
|
|
/**
|
|
* A Track was selected for playback from the drop down box.
|
|
*
|
|
*/
|
|
void KSCD::trackSelected( int cb_index )
|
|
{
|
|
if (cb_index < 0)
|
|
return;
|
|
|
|
unsigned int track = cb_index + 1;
|
|
setShuffle(0);
|
|
|
|
m_cd->play(track, 0);
|
|
} // trackSelected
|
|
|
|
void KSCD::updateConfigDialog(configWidget* widget)
|
|
{
|
|
if(!widget)
|
|
return;
|
|
|
|
static TQString originalTitleOfGroupBox = widget->groupBox3->title();
|
|
if(m_cd->isPlaying()) {
|
|
widget->groupBox3->setEnabled(false);
|
|
widget->groupBox3->setTitle( i18n( "CD Drive (you must stop playing to change this)" ) );
|
|
} else {
|
|
widget->groupBox3->setEnabled(true);
|
|
widget->groupBox3->setTitle(originalTitleOfGroupBox);
|
|
}
|
|
}
|
|
|
|
void KSCD::showConfig()
|
|
{
|
|
static configWidget* confWidget = 0;
|
|
|
|
if (TDEConfigDialog::showDialog("settings")) {
|
|
updateConfigDialog(confWidget);
|
|
return;
|
|
}
|
|
|
|
configDialog = new TDEConfigDialog(this, "settings", Prefs::self());
|
|
|
|
configDialog->setHelp(TQString());
|
|
|
|
confWidget = new configWidget(this, 0, "Kscd");
|
|
|
|
// kscd config page
|
|
configDialog->addPage(confWidget, i18n("CD Player"), "kscd", i18n("Settings & Behavior"));
|
|
|
|
// libkcddb page
|
|
KService::Ptr libkcddb = KService::serviceByDesktopName("libkcddb");
|
|
if (libkcddb && libkcddb->isValid())
|
|
{
|
|
TDECModuleInfo info(libkcddb->desktopEntryPath());
|
|
if (info.service()->isValid())
|
|
{
|
|
TDECModule *m = TDECModuleLoader::loadModule(info, TDECModuleLoader::Inline);
|
|
if (m)
|
|
{
|
|
m->load();
|
|
KCDDB::Config* cfg = new KCDDB::Config();
|
|
cfg->readConfig();
|
|
configDialog -> addPage(m, cfg, TQString("CDDB"), "application-x-cda", i18n("Configure Fetching Items"));
|
|
|
|
connect(configDialog, TQT_SIGNAL(okClicked()), m, TQT_SLOT(save()));
|
|
connect(configDialog, TQT_SIGNAL(applyClicked()), m, TQT_SLOT(save()));
|
|
connect(configDialog, TQT_SIGNAL(defaultClicked()), m, TQT_SLOT(defaults()));
|
|
}
|
|
}
|
|
}
|
|
|
|
updateConfigDialog(confWidget);
|
|
|
|
connect(configDialog, TQT_SIGNAL(settingsChanged()), TQT_TQOBJECT(this), TQT_SLOT(configDone()));
|
|
configDialog -> show();
|
|
} // showConfig()
|
|
|
|
void KSCD::configDone()
|
|
{
|
|
setColors();
|
|
setDocking(Prefs::docking());
|
|
|
|
setDevicePaths();
|
|
|
|
volumeIcon->setEnabled(!Prefs::digitalPlayback());
|
|
volumeSlider->setEnabled(!Prefs::digitalPlayback());
|
|
|
|
// dialog deletes itself
|
|
configDialog = 0L;
|
|
}
|
|
|
|
void KSCD::configureKeys()
|
|
{
|
|
KKeyDialog::configure(m_actions, this);
|
|
}
|
|
|
|
void KSCD::configureGlobalKeys()
|
|
{
|
|
KKeyDialog::configure(m_globalAccel, true, this, true);
|
|
}
|
|
|
|
void KSCD::setDevicePaths()
|
|
{
|
|
if (!m_cd->setDevice(Prefs::cdDevice(), Prefs::volume(), Prefs::digitalPlayback(),
|
|
Prefs::audioSystem(), Prefs::audioDevice()))
|
|
{
|
|
// This device did not seem usable.
|
|
TQString str = i18n("CD-ROM read or access error (or no audio disc in drive).\n"\
|
|
"Please make sure you have access permissions to:\n%1").arg(
|
|
TDECompactDisc::urlToDevice(Prefs::cdDevice()));
|
|
KMessageBox::error(this, str, i18n("Error"));
|
|
}
|
|
} // setDevicePath()
|
|
|
|
void KSCD::setDocking(bool dock)
|
|
{
|
|
Prefs::setDocking(dock);
|
|
if (Prefs::docking())
|
|
{
|
|
if (!m_dockWidget)
|
|
{
|
|
m_dockWidget = new DockWidget(this, "dockw");
|
|
connect(m_dockWidget, TQT_SIGNAL(quitSelected()), TQT_TQOBJECT(this), TQT_SLOT(quitClicked()));
|
|
}
|
|
|
|
m_dockWidget->show();
|
|
connect(this, TQT_SIGNAL(trackChanged(const TQString&)),
|
|
m_dockWidget, TQT_SLOT(setToolTip(const TQString&)));
|
|
connect(this, TQT_SIGNAL(trackChanged(const TQString&)),
|
|
m_dockWidget, TQT_SLOT(createPopup(const TQString&)));
|
|
}
|
|
else
|
|
{
|
|
show();
|
|
delete m_dockWidget;
|
|
m_dockWidget = 0;
|
|
}
|
|
}
|
|
|
|
void KSCD::incVolume()
|
|
{
|
|
int v = Prefs::volume() + 5;
|
|
|
|
if (v > 100)
|
|
{
|
|
v = 100;
|
|
}
|
|
|
|
volChanged(v);
|
|
volumeSlider->setValue(v);
|
|
} // incVolume
|
|
|
|
void KSCD::decVolume()
|
|
{
|
|
int v = Prefs::volume() - 5;
|
|
|
|
if (v < 0)
|
|
{
|
|
v = 0;
|
|
}
|
|
|
|
volChanged(v);
|
|
volumeSlider->setValue(v);
|
|
} // decVolume
|
|
|
|
void KSCD::volChanged( int vol )
|
|
{
|
|
TQString str;
|
|
str = TQString::fromUtf8( TQCString().sprintf(i18n("Vol: %02d%%").utf8(), vol) );
|
|
volumelabel->setText(str);
|
|
m_cd->setVolume(vol);
|
|
Prefs::setVolume(vol);
|
|
} // volChanged
|
|
|
|
void KSCD::make_random_list()
|
|
{
|
|
/* koz: 15/01/00. I want a random list that does not repeat tracks. Ie, */
|
|
/* a list is created in which each track is listed only once. The tracks */
|
|
/* are picked off one by one until the end of the list */
|
|
|
|
int selected = 0;
|
|
bool rejected = false;
|
|
|
|
//kdDebug(67000) << "Playlist has " << size << " entries\n" << endl;
|
|
random_list.clear();
|
|
for(unsigned i = 0; i < m_cd->tracks(); i++)
|
|
{
|
|
do {
|
|
selected = 1 + (int) randSequence.getLong(m_cd->tracks());
|
|
rejected = (random_list.find(selected) != random_list.end());
|
|
} while(rejected == true);
|
|
random_list.append(selected);
|
|
}
|
|
/*
|
|
printf("debug: dump random list\n");
|
|
RandomList::iterator it;
|
|
for(it = random_list.begin(); it != random_list.end(); it++) {
|
|
printf("%i ", *it);
|
|
}
|
|
printf("\n");
|
|
*/
|
|
random_current = random_list.end();
|
|
} // make_random_list()
|
|
|
|
int KSCD::next_randomtrack()
|
|
{
|
|
/* Check to see if we are at invalid state */
|
|
if(random_current == random_list.end())
|
|
{
|
|
random_current = random_list.begin();
|
|
}
|
|
else if(random_current == random_list.fromLast())
|
|
{
|
|
if(!Prefs::looping())
|
|
{
|
|
m_cd->stop();
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
// playing the same random list isn't very random, is it?
|
|
make_random_list();
|
|
return next_randomtrack();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
++random_current;
|
|
}
|
|
|
|
return *random_current;
|
|
} // next_randomtrack
|
|
|
|
int KSCD::prev_randomtrack()
|
|
{
|
|
/* Check to see if we are at invalid state */
|
|
if(random_current == random_list.end())
|
|
{
|
|
random_current = random_list.fromLast();
|
|
}
|
|
else if(random_current == random_list.begin())
|
|
{
|
|
if(!Prefs::looping())
|
|
{
|
|
return -1;
|
|
}
|
|
else
|
|
{
|
|
// playing the same random list isn't very random, is it?
|
|
make_random_list();
|
|
return prev_randomtrack();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
--random_current;
|
|
}
|
|
|
|
return *random_current;
|
|
} // prev_randomtrack
|
|
|
|
void KSCD::discChanged(unsigned discId)
|
|
{
|
|
cddbInfo.clear();
|
|
if (discId == TDECompactDisc::missingDisc)
|
|
{
|
|
statuslabel->setText(i18n("No disc"));
|
|
}
|
|
else
|
|
{
|
|
cddbInfo.id = TQString::number(discId, 16).rightJustify(8,'0');
|
|
cddbInfo.length = m_cd->discLength() / 1000;
|
|
cddbInfo.artist = m_cd->discArtist();
|
|
cddbInfo.title = m_cd->discTitle();
|
|
|
|
// If it's a sampler, we'll do artist/title.
|
|
bool isSampler = (cddbInfo.title.compare("Various") == 0);
|
|
KCDDB::TrackInfo track;
|
|
for (unsigned i = 1; i <= m_cd->tracks(); i++)
|
|
{
|
|
if (isSampler)
|
|
{
|
|
track.title = m_cd->trackArtist(i);
|
|
track.title.append("/");
|
|
track.title.append(m_cd->trackTitle(i));
|
|
}
|
|
else
|
|
{
|
|
track.title = m_cd->trackTitle(i);
|
|
}
|
|
|
|
// FIXME: KDE4
|
|
// track.length = cd->trk[i - 1].length;
|
|
cddbInfo.trackInfoList.append(track);
|
|
}
|
|
}
|
|
|
|
// Set the total time.
|
|
TQTime dml;
|
|
dml = dml.addSecs(m_cd->discLength() / 1000);
|
|
|
|
TQString fmt;
|
|
if(dml.hour() > 0)
|
|
fmt.sprintf("%02d:%02d:%02d",dml.hour(),dml.minute(),dml.second());
|
|
else
|
|
fmt.sprintf("%02d:%02d",dml.minute(),dml.second());
|
|
totaltimelabel->setText(fmt);
|
|
|
|
trackChanged(0, 0);
|
|
populateSongList("");
|
|
//totaltimelabel->clear();
|
|
totaltimelabel->lower();
|
|
|
|
if ((Prefs::autoplay() || TDECmdLineArgs::parsedArgs()->isSet("start"))
|
|
&& !m_cd->isPlaying())
|
|
{
|
|
playClicked();
|
|
}
|
|
|
|
// We just populated the GUI with what we got from the CD. Now look for
|
|
// more from the Internet...
|
|
lookupCDDB();
|
|
}
|
|
|
|
void KSCD::discStopped()
|
|
{
|
|
if (Prefs::ejectOnFinish() && !stoppedByUser && (m_cd->discId() != TDECompactDisc::missingDisc))
|
|
{
|
|
ejectClicked();
|
|
}
|
|
|
|
if (!stoppedByUser)
|
|
{
|
|
if (Prefs::randomPlay())
|
|
{
|
|
// If nextClicked returns false, it was the last
|
|
// random track, and the player should be stopped
|
|
if (nextClicked())
|
|
return;
|
|
}
|
|
else if (Prefs::looping())
|
|
{
|
|
playClicked();
|
|
return;
|
|
}
|
|
}
|
|
|
|
statuslabel->setText(i18n("Stopped"));
|
|
playPB->setText(i18n("Play"));
|
|
playPB->setIconSet(SmallIconSet("media-playback-start"));
|
|
|
|
/* reset to initial value, only stopclicked() sets this to true */
|
|
stoppedByUser = false;
|
|
|
|
trackChanged(0, 0);
|
|
populateSongList("");
|
|
totaltimelabel->clear();
|
|
totaltimelabel->lower();
|
|
}
|
|
|
|
void KSCD::setLEDs(int milliseconds)
|
|
{
|
|
TQString symbols;
|
|
|
|
if (milliseconds < 0)
|
|
{
|
|
symbols = "--:--";
|
|
}
|
|
else
|
|
{
|
|
unsigned mymin;
|
|
unsigned mysec;
|
|
mymin = milliseconds / 60000;
|
|
mysec = (milliseconds % 60000) / 1000;
|
|
symbols.sprintf("%02d:%02d", mymin, mysec);
|
|
}
|
|
|
|
for (int i = 0; i < 5; i++)
|
|
{
|
|
trackTimeLED[i]->display((char)symbols.local8Bit().at(i));
|
|
}
|
|
}
|
|
|
|
void KSCD::resetTimeSlider(bool enabled)
|
|
{
|
|
timeSlider->setEnabled(enabled);
|
|
timeSlider->blockSignals(true);
|
|
timeSlider->setValue(0);
|
|
timeSlider->blockSignals(false);
|
|
} // resetTimeSlider(bool enabled);
|
|
|
|
void KSCD::setColors()
|
|
{
|
|
TQColor led_color = Prefs::ledColor();
|
|
TQColor background_color = Prefs::backColor();
|
|
|
|
backdrop->setBackgroundColor(background_color);
|
|
|
|
TQColorGroup colgrp( led_color, background_color, led_color,led_color , led_color,
|
|
led_color, white );
|
|
|
|
titlelabel ->setPalette( TQPalette(colgrp,colgrp,colgrp) );
|
|
artistlabel->setPalette( TQPalette(colgrp,colgrp,colgrp) );
|
|
volumelabel->setPalette( TQPalette(colgrp,colgrp,colgrp) );
|
|
statuslabel->setPalette( TQPalette(colgrp,colgrp,colgrp) );
|
|
tracklabel ->setPalette( TQPalette(colgrp,colgrp,colgrp) );
|
|
totaltimelabel->setPalette( TQPalette(colgrp,colgrp,colgrp) );
|
|
|
|
queryled->setPalette( TQPalette(colgrp,colgrp,colgrp) );
|
|
loopled->setPalette( TQPalette(colgrp,colgrp,colgrp) );
|
|
|
|
for (int u = 0; u< 5;u++){
|
|
trackTimeLED[u]->setLEDoffColor(background_color);
|
|
trackTimeLED[u]->setLEDColor(led_color,background_color);
|
|
}
|
|
|
|
titlelabel ->setFont( Prefs::ledFont() );
|
|
artistlabel->setFont( Prefs::ledFont() );
|
|
volumelabel->setFont( Prefs::ledFont() );
|
|
statuslabel->setFont( Prefs::ledFont() );
|
|
tracklabel ->setFont( Prefs::ledFont() );
|
|
totaltimelabel->setFont( Prefs::ledFont() );
|
|
}
|
|
|
|
void KSCD::readSettings()
|
|
{
|
|
/*
|
|
time_display_mode = config->readNumEntry("TimeDisplay", TRACK_SEC);
|
|
*/
|
|
|
|
#ifndef DEFAULT_CD_DEVICE
|
|
#define DEFAULT_CD_DEVICE "/dev/cdrom"
|
|
// sun ultrix etc have a canonical cd rom device specified in the
|
|
// respective plat_xxx.c file. On those platforms you need nnot
|
|
// specify the cd rom device and DEFAULT_CD_DEVICE is not defined
|
|
// in config.h
|
|
#endif
|
|
|
|
if (Prefs::cdDevice().isEmpty())
|
|
{
|
|
Prefs::setCdDevice(DEFAULT_CD_DEVICE);
|
|
}
|
|
|
|
volumeIcon->setEnabled(!Prefs::digitalPlayback());
|
|
volumeSlider->setEnabled(!Prefs::digitalPlayback());
|
|
}
|
|
|
|
/**
|
|
* Write KSCD's Configuration into the kderc file.
|
|
*
|
|
*/
|
|
void KSCD::writeSettings()
|
|
{
|
|
Prefs::writeConfig();
|
|
} // writeSettings()
|
|
|
|
void KSCD::CDDialogSelected()
|
|
{
|
|
if (!cddialog)
|
|
{
|
|
cddialog = new CDDBDlg(this);
|
|
|
|
cddialog->setData(cddbInfo, m_cd->discSignature(), playlist);
|
|
connect(cddialog,TQT_SIGNAL(cddbQuery()),TQT_SLOT(lookupCDDB()));
|
|
connect(cddialog,TQT_SIGNAL(newCDInfoStored(KCDDB::CDInfo)),
|
|
TQT_SLOT(setCDInfo(KCDDB::CDInfo)));
|
|
connect(cddialog,TQT_SIGNAL(finished()),TQT_SLOT(CDDialogDone()));
|
|
connect(cddialog,TQT_SIGNAL(play(int)),TQT_SLOT(trackSelected(int)));
|
|
}
|
|
|
|
cddialog->show();
|
|
cddialog->raise();
|
|
}
|
|
|
|
void KSCD::CDDialogDone()
|
|
{
|
|
cddialog->delayedDestruct();
|
|
cddialog = 0L;
|
|
}
|
|
|
|
void KSCD::lookupCDDB()
|
|
{
|
|
if (m_cd->discId() == TDECompactDisc::missingDisc)
|
|
return;
|
|
kdDebug(67000) << "lookupCDDB() called" << endl;
|
|
|
|
populateSongList(i18n("Start freedb lookup."));
|
|
|
|
setShuffle(2);
|
|
|
|
led_on();
|
|
|
|
cddb->config().reparse();
|
|
cddb->setBlockingMode(false);
|
|
cddb->lookup(m_cd->discSignature());
|
|
} // lookupCDDB
|
|
|
|
void KSCD::lookupCDDBDone(CDDB::Result result)
|
|
{
|
|
led_off();
|
|
if ((result != KCDDB::CDDB::Success) &&
|
|
(result != KCDDB::CDDB::MultipleRecordFound))
|
|
{
|
|
populateSongList(result == CDDB::NoRecordFound ? i18n("No matching freedb entry found.") : i18n("Error getting freedb entry."));
|
|
return;
|
|
}
|
|
|
|
// The intent of the original code here seems to have been to perform the
|
|
// lookup, and then to convert all the string data within the CDDB response
|
|
// using the use Prefs::selectedEncoding() and a TQTextCodec. However, that
|
|
// seems to be irrelevant these days.
|
|
KCDDB::CDInfo info = cddb->bestLookupResponse();
|
|
// TODO Why doesn't libcddb not return MultipleRecordFound?
|
|
//if( result == KCDDB::CDDB::MultipleRecordFound ) {
|
|
if( cddb->lookupResponse().count() > 1 ) {
|
|
CDInfoList cddb_info = cddb->lookupResponse();
|
|
CDInfoList::iterator it;
|
|
TQStringList list;
|
|
for ( it = cddb_info.begin(); it != cddb_info.end(); ++it ) {
|
|
list.append( TQString("%1, %2, %3").arg((*it).artist).arg((*it).title)
|
|
.arg((*it).genre));
|
|
}
|
|
|
|
bool ok(false);
|
|
TQString res = KInputDialog::getItem(
|
|
i18n("Select CDDB Entry"),
|
|
i18n("Select a CDDB entry:"), list, 0, false, &ok,
|
|
this );
|
|
if ( ok ) {
|
|
// The user selected and item and pressed OK
|
|
uint c = 0;
|
|
for ( TQStringList::Iterator it = list.begin(); it != list.end(); ++it ) {
|
|
if( *it == res) break;
|
|
c++;
|
|
}
|
|
if( c < cddb_info.size() )
|
|
info = cddb_info[c];
|
|
} else {
|
|
return;
|
|
// user pressed Cancel
|
|
}
|
|
}
|
|
|
|
setCDInfo(info);
|
|
|
|
// In case the cddb dialog is open, update it
|
|
if (cddialog)
|
|
cddialog->setData(cddbInfo, m_cd->discSignature(), playlist);
|
|
} // lookupCDDBDone
|
|
|
|
void KSCD::setCDInfo(KCDDB::CDInfo info)
|
|
{
|
|
// Some sanity provisions to ensure that the number of records matches what
|
|
// the CD actually contains.
|
|
while (info.trackInfoList.count() < cddbInfo.trackInfoList.count())
|
|
{
|
|
info.trackInfoList.append(KCDDB::TrackInfo());
|
|
}
|
|
while (info.trackInfoList.count() > cddbInfo.trackInfoList.count())
|
|
{
|
|
info.trackInfoList.pop_back();
|
|
}
|
|
cddbInfo = info;
|
|
populateSongList("");
|
|
}
|
|
|
|
void KSCD::led_off()
|
|
{
|
|
queryledtimer.stop();
|
|
queryled->off();
|
|
queryled->hide();
|
|
totaltimelabel->raise();
|
|
totaltimelabel->show();
|
|
} // led_off
|
|
|
|
void KSCD::led_on()
|
|
{
|
|
totaltimelabel->hide();
|
|
totaltimelabel->lower();
|
|
queryledtimer.start(800);
|
|
queryled->off();
|
|
queryled->show();
|
|
kapp->processEvents();
|
|
kapp->flushX();
|
|
} // led_on
|
|
|
|
void KSCD::togglequeryled()
|
|
{
|
|
queryled->show();
|
|
queryled->toggle();
|
|
} // togglequeryled
|
|
|
|
void KSCD::titlelabeltimeout()
|
|
{
|
|
// clear the cddb error message on the title label.
|
|
titlelabeltimer.stop();
|
|
titlelabel->clear();
|
|
|
|
} // titlelabeltimeout
|
|
|
|
void KSCD::trayOpening()
|
|
{
|
|
statuslabel->setText(i18n("Ejected"));
|
|
trackChanged(0, 0);
|
|
}
|
|
|
|
int KSCD::currentTrack()
|
|
{
|
|
return m_cd->track();
|
|
}
|
|
|
|
int KSCD::currentTrackLength()
|
|
{
|
|
return m_cd->trackLength();
|
|
}
|
|
|
|
int KSCD::currentPosition()
|
|
{
|
|
return m_cd->trackPosition();
|
|
}
|
|
|
|
int KSCD::getStatus()
|
|
{
|
|
if (m_cd->isPlaying())
|
|
return 2;
|
|
else if (m_cd->isPaused())
|
|
return 4;
|
|
else if (m_cd->discId() != TDECompactDisc::missingDisc)
|
|
return 5;
|
|
else
|
|
return 6;
|
|
}
|
|
|
|
bool KSCD::playing()
|
|
{
|
|
return m_cd->isPlaying();
|
|
}
|
|
|
|
void KSCD::trackUpdate(unsigned /*track*/, unsigned trackPosition)
|
|
{
|
|
unsigned tmp;
|
|
|
|
switch (Prefs::timeDisplayMode())
|
|
{
|
|
case TRACK_REM:
|
|
tmp = m_cd->trackLength() - trackPosition;
|
|
break;
|
|
|
|
case TOTAL_SEC:
|
|
tmp = m_cd->discPosition();
|
|
break;
|
|
|
|
case TOTAL_REM:
|
|
tmp = m_cd->discLength() - m_cd->discPosition();
|
|
break;
|
|
|
|
case TRACK_SEC:
|
|
default:
|
|
tmp = trackPosition;
|
|
break;
|
|
}
|
|
if (updateTime)
|
|
{
|
|
setLEDs(tmp);
|
|
timeSlider->blockSignals(true);
|
|
timeSlider->setValue(trackPosition);
|
|
timeSlider->blockSignals(false);
|
|
}
|
|
}
|
|
|
|
void KSCD::cycleplaytimemode()
|
|
{
|
|
cycletimer.stop();
|
|
|
|
if (Prefs::timeDisplayMode() > 2) {
|
|
Prefs::setTimeDisplayMode(TRACK_SEC);
|
|
} else {
|
|
Prefs::setTimeDisplayMode(Prefs::timeDisplayMode() + 1);
|
|
}
|
|
|
|
switch(Prefs::timeDisplayMode()) {
|
|
|
|
case TRACK_REM:
|
|
volumelabel->setText(i18n("Tra Rem"));
|
|
break;
|
|
|
|
case TOTAL_SEC:
|
|
volumelabel->setText(i18n("Tot Sec"));
|
|
break;
|
|
|
|
case TOTAL_REM:
|
|
volumelabel->setText(i18n("Tot Rem"));
|
|
break;
|
|
|
|
case TRACK_SEC:
|
|
default:
|
|
volumelabel->setText(i18n("Tra Sec"));
|
|
break;
|
|
}
|
|
|
|
cycletimer.start(3000, true);
|
|
} // cycleplaymode
|
|
|
|
void KSCD::cycletimeout()
|
|
{
|
|
cycletimer.stop();
|
|
TQString str;
|
|
str = TQString::fromUtf8( TQCString().sprintf(i18n("Vol: %02d%%").utf8(), Prefs::volume()) );
|
|
volumelabel->setText(str);
|
|
} // cycletimeout
|
|
|
|
|
|
void KSCD::information(int i)
|
|
{
|
|
//kdDebug(67000) << "Information " << i << "\n" << endl;
|
|
|
|
if(cddbInfo.artist.isEmpty())
|
|
return;
|
|
|
|
TQString encodedArtist = KURL::encode_string_no_slash(cddbInfo.artist);
|
|
|
|
TQString str;
|
|
|
|
switch(i)
|
|
{
|
|
case 0:
|
|
str = TQString("http://musicmoz.org/cgi-bin/ext.cgi?artist=%1")
|
|
.arg(encodedArtist);
|
|
break;
|
|
|
|
case 1:
|
|
str = TQString("http://ubl.artistdirect.com/cgi-bin/gx.cgi/AppLogic+Search?select=MusicArtist&searchstr=%1&searchtype=NormalSearch")
|
|
.arg(encodedArtist);
|
|
break;
|
|
|
|
case 2:
|
|
str = TQString("http://www.cduniverse.com/cgi-bin/cdubin.exe/rlinka/ean=%1")
|
|
.arg(encodedArtist);
|
|
break;
|
|
|
|
case 3:
|
|
str = TQString("http://www.alltheweb.com/search?cat=web&q=%1")
|
|
.arg(encodedArtist);
|
|
break;
|
|
|
|
case 4:
|
|
str = TQString("http://altavista.com/web/results?q=%1&kgs=0&kls=1&avkw=xytx")
|
|
.arg(encodedArtist);
|
|
break;
|
|
|
|
case 5:
|
|
str = TQString("http://msxml.excite.com/_1_2UDOUB70SVHVHR__info.xcite/dog/results?otmpl=dog/webresults.htm&qkw=%1&qcat=web&qk=20&top=1&start=&ver=14060")
|
|
.arg(encodedArtist);
|
|
break;
|
|
|
|
case 6:
|
|
str = TQString("http://www.google.com/search?q=%1")
|
|
.arg(encodedArtist);
|
|
break;
|
|
|
|
case 7:
|
|
str = TQString("http://groups.google.com/groups?oi=djq&as_q=%1&num=20")
|
|
.arg(encodedArtist);
|
|
break;
|
|
|
|
case 8:
|
|
str = TQString("http://www.hotbot.com/default.asp?prov=Inktomi&query=%1&ps=&loc=searchbox&tab=web")
|
|
.arg(encodedArtist);
|
|
break;
|
|
|
|
case 9:
|
|
str = TQString("http://search.lycos.com/default.asp?lpv=1&loc=searchhp&tab=web&query=%1")
|
|
.arg(encodedArtist);
|
|
break;
|
|
|
|
case 10:
|
|
str = TQString("http://search.dmoz.org/cgi-bin/search?search=%1")
|
|
.arg(encodedArtist);
|
|
break;
|
|
|
|
case 11:
|
|
str = TQString("http://search.yahoo.com/bin/search?p=%1")
|
|
.arg(encodedArtist);
|
|
break;
|
|
|
|
default:
|
|
return;
|
|
break;
|
|
} // switch()
|
|
|
|
KRun::runURL(KURL( str ), "text/html");
|
|
} // information
|
|
|
|
/**
|
|
* Save state on session termination
|
|
*/
|
|
bool KSCD::saveState(TQSessionManager& /*sm*/)
|
|
{
|
|
writeSettings();
|
|
TDEConfig* config = TDEApplication::kApplication()->sessionConfig();
|
|
config->setGroup("General");
|
|
config->writeEntry("Show", isVisible());
|
|
return true;
|
|
} // saveState
|
|
|
|
|
|
/**
|
|
* Allow the user to type in the number of the track
|
|
*/
|
|
void KSCD::keyPressEvent(TQKeyEvent* e)
|
|
{
|
|
bool isNum;
|
|
int value = e->text().toInt(&isNum);
|
|
|
|
if (e->key() == TQt::Key_F1)
|
|
{
|
|
kapp->invokeHelp();
|
|
}
|
|
else if (isNum)
|
|
{
|
|
value = (jumpToTrack * 10) + value;
|
|
|
|
if (value <= (int)cddbInfo.trackInfoList.count())
|
|
{
|
|
jumpToTrack = value;
|
|
jumpTrackTimer.stop();
|
|
jumpTrackTimer.start(333);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
TQWidget::keyPressEvent(e);
|
|
}
|
|
} //keyPressEvent
|
|
|
|
void KSCD::jumpTracks()
|
|
{
|
|
if (jumpToTrack > 0 && jumpToTrack <= (int)cddbInfo.trackInfoList.count())
|
|
{
|
|
m_cd->play(jumpToTrack, 0, jumpToTrack + 1);
|
|
}
|
|
|
|
jumpToTrack = 0;
|
|
} // jumpTracks
|
|
|
|
TQString KSCD::currentTrackTitle()
|
|
{
|
|
int track = m_cd->track();
|
|
return (track > -1) ? cddbInfo.trackInfoList[track-1].title : TQString();
|
|
}
|
|
|
|
TQString KSCD::currentAlbum()
|
|
{
|
|
return cddbInfo.title;
|
|
}
|
|
|
|
TQString KSCD::currentArtist()
|
|
{
|
|
return cddbInfo.artist;
|
|
}
|
|
|
|
TQStringList KSCD::trackList()
|
|
{
|
|
TQStringList tracks;
|
|
for (TrackInfoList::const_iterator it = cddbInfo.trackInfoList.begin();
|
|
it != cddbInfo.trackInfoList.end(); ++it)
|
|
tracks << (*it).title;
|
|
|
|
return tracks;
|
|
}
|
|
|
|
void KSCD::populateSongList(TQString infoStatus)
|
|
{
|
|
// set the artist and title labels as well as the dock tooltip.
|
|
if (!infoStatus.isEmpty())
|
|
artistlabel->setText(infoStatus);
|
|
else
|
|
artistlabel->setText(TQString("%1 - %2").arg(cddbInfo.artist, cddbInfo.title));
|
|
|
|
songListCB->clear();
|
|
for (unsigned i = 0; i < cddbInfo.trackInfoList.count(); i++)
|
|
{
|
|
unsigned tmp = m_cd->trackLength(i + 1);
|
|
unsigned mymin;
|
|
unsigned mysec;
|
|
mymin = tmp / 60000;
|
|
mysec = (tmp % 60000) / 1000;
|
|
TQString str1;
|
|
str1.sprintf("%02d: ", i + 1);
|
|
TQString str2;
|
|
str2.sprintf(" (%02d:%02d) ", mymin, mysec);
|
|
str1.append(cddbInfo.trackInfoList[i].title);
|
|
str1.append(str2);
|
|
songListCB->insertItem(str1);
|
|
}
|
|
|
|
emit trackChanged(m_cd->track(), m_cd->trackLength());
|
|
}
|
|
|
|
static const TDECmdLineOptions options[] =
|
|
{
|
|
{"s",0,0},
|
|
{"start",I18N_NOOP("Start playing"),0},
|
|
{"+[device]",I18N_NOOP("CD device, can be a path or a media:/ URL"),0},
|
|
TDECmdLineLastOption
|
|
};
|
|
|
|
|
|
/**
|
|
* main()
|
|
*/
|
|
int main( int argc, char *argv[] )
|
|
{
|
|
TDEAboutData aboutData("kscd", I18N_NOOP("KsCD"),
|
|
KSCDVERSION, description,
|
|
TDEAboutData::License_GPL,
|
|
"(c) 2001, Dirk Försterling\n(c) 2003, Aaron J. Seigo");
|
|
aboutData.addAuthor("Aaron J. Seigo", I18N_NOOP("Current maintainer"), "aseigo@kde.org");
|
|
aboutData.addAuthor("Alexander Kern",I18N_NOOP("Workman library update, CDTEXT, CDDA"), "kernalex@kde.org");
|
|
aboutData.addAuthor("Bernd Johannes Wuebben",0, "wuebben@kde.org");
|
|
aboutData.addAuthor("Dirk Försterling", I18N_NOOP("Workman library, previous maintainer"), "milliByte@gmx.net");
|
|
aboutData.addCredit("Wilfried Huss", I18N_NOOP("Patches galore"));
|
|
aboutData.addCredit("Steven Grimm", I18N_NOOP("Workman library"));
|
|
aboutData.addCredit("Sven Lueppken", I18N_NOOP("UI Work"));
|
|
aboutData.addCredit("freedb.org", I18N_NOOP("Special thanks to freedb.org for providing a free CDDB-like CD database"), 0, "http://freedb.org");
|
|
|
|
TDECmdLineArgs::init( argc, argv, &aboutData );
|
|
TDECmdLineArgs::addCmdLineOptions(options);
|
|
KUniqueApplication::addCmdLineOptions();
|
|
|
|
TDECmdLineArgs* args = TDECmdLineArgs::parsedArgs();
|
|
if (!KUniqueApplication::start())
|
|
{
|
|
fprintf(stderr, "kscd is already running\n");
|
|
if (args->count()>0 || args->isSet("start"))
|
|
{
|
|
DCOPClient client;
|
|
if (client.attach())
|
|
{
|
|
// Forward the command line args to the running instance.
|
|
DCOPRef ref("kscd", "CDPlayer");
|
|
if (args->count() > 0)
|
|
{
|
|
ref.send("setDevice(TQString)", TQString(args->arg(0)));
|
|
}
|
|
if (args->isSet("start"))
|
|
{
|
|
ref.send("play()");
|
|
}
|
|
}
|
|
}
|
|
exit(0);
|
|
}
|
|
|
|
KUniqueApplication a;
|
|
|
|
kapp->dcopClient()->setDefaultObject("CDPlayer");
|
|
|
|
KSCD *k = new KSCD();
|
|
|
|
a.setTopWidget( k );
|
|
a.setMainWidget( k );
|
|
|
|
k->setCaption(a.caption());
|
|
|
|
if (kapp->isRestored())
|
|
{
|
|
TDEConfig* config = TDEApplication::kApplication()->sessionConfig();
|
|
config->setGroup("General");
|
|
if (config->readBoolEntry("Show"))
|
|
k->show();
|
|
}
|
|
else
|
|
{
|
|
k->show();
|
|
}
|
|
|
|
if (args->count()>0) Prefs::self()->setCdDevice(args->arg(0));
|
|
|
|
return a.exec();
|
|
}
|
|
|
|
#include "kscd.moc"
|