kill dead code
[kdemultimedia.git] / kscd / kscd.cpp
blobb911af177a89243a98269998e74d91d7a137f6d3
1 /*
2 * Kscd - A simple cd player for the KDE Project
4 * Copyright (c) 1997 Bernd Johannes wuebben@math.cornell.edu
5 * Copyright (c) 2002-2003 Aaron J. Seigo <aseigo@kde.org>
6 * Copyright (c) 2004 Alexander Kern <alex.kern@gmx.de>
7 * Copyright (c) 2003-2006 Richard Lärkäng <nouseforaname@home.se>
8 * Copyright (c) 2007 Benjamin K. Stuhl <benjamin.stuhl@colorado.edu>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2, or (at your option)
13 * any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
25 #include "docking.h"
26 #include "kscd.h"
27 #include "prefs.h"
28 #include "cddbdlg.h"
29 #include "configWidget.h"
30 #include "kcompactdisc.h"
32 #include <config-alsa.h>
34 #include <QCloseEvent>
35 #include <QKeyEvent>
36 #include <QEvent>
37 #include <QMenu>
38 #include <QtDBus>
40 #include <kaboutdata.h>
41 #include <kactioncollection.h>
42 #include <kcmdlineargs.h>
43 #include <khelpmenu.h>
44 #include <kshortcutsdialog.h>
45 #include <kiconloader.h>
46 #include <kinputdialog.h>
47 #include <kmessagebox.h>
48 #include <kmenu.h>
49 #include <krun.h>
50 #include <kstandardaction.h>
51 #include <kstringhandler.h>
52 #include <kuniqueapplication.h>
53 #include <kcmoduleloader.h>
54 #include <ktoolinvocation.h>
56 using namespace KCDDB;
58 static const char description[] = I18N_NOOP("KDE CD player");
60 bool stoppedByUser = true;
63 /****************************************************************************
64 The GUI part
65 *****************************************************************************/
67 KSCD::KSCD( QWidget *parent )
68 : QWidget( parent ),
69 kscdPanelDlg( ),
70 configDialog(0L),
71 cddialog(0L), //!!!!
72 updateTime(true),
73 m_dockWidget(0)
75 QDBusConnection::sessionBus().registerObject("/CDPlayer", this, QDBusConnection::ExportScriptableSlots);
76 setupUi(this);
77 m_cd = new KCompactDisc();
78 cddbInfo.clear(); // The first freedb revision is "0" //!!!!
79 cddb = new KCDDB::Client();
80 connect(cddb, SIGNAL(finished(KCDDB::Result)), this, SLOT(lookupCDDBDone(KCDDB::Result)));
82 readSettings();
83 drawPanel();
84 setColors();
86 // the time slider
87 timeIcon->setPixmap(SmallIcon("player-time"));
88 connect(timeSlider, SIGNAL(sliderPressed()), SLOT(timeSliderPressed()));
89 connect(timeSlider, SIGNAL(sliderReleased()), SLOT(timeSliderReleased()));
90 connect(timeSlider, SIGNAL(sliderMoved(int)), SLOT(timeSliderMoved(int)));
91 connect(timeSlider, SIGNAL(valueChanged(int)), SLOT(jumpToTime(int)));
93 // the volume slider
94 volumeIcon->setPixmap(SmallIcon("player-volume"));
95 volumeSlider->setValue(Prefs::volume());
96 showVolumeInLabel();
97 connect(volumeSlider, SIGNAL(valueChanged(int)), SLOT(volChanged(int)));
99 connect(m_cd, SIGNAL(discChanged(unsigned int)), this, SLOT(discChanged(unsigned int)));
100 connect(m_cd, SIGNAL(discInformation(KCompactDisc::DiscInfo)), this, SLOT(discInformation(KCompactDisc::DiscInfo)));
101 connect(m_cd, SIGNAL(discStatusChanged(KCompactDisc::DiscStatus)), this,
102 SLOT(discStatusChanged(KCompactDisc::DiscStatus)));
104 connect(m_cd, SIGNAL(playoutTrackChanged(unsigned int)), this, SLOT(trackChanged(unsigned int)));
105 connect(m_cd, SIGNAL(playoutPositionChanged(unsigned int)), this, SLOT(trackPosition(unsigned int)));
107 connect(&queryledtimer, SIGNAL(timeout()), SLOT(togglequeryled()) );
108 connect(&titlelabeltimer, SIGNAL(timeout()), SLOT(titlelabeltimeout()) );
110 connect(playPB, SIGNAL(clicked()), SLOT(playClicked()) );
111 connect(nextPB, SIGNAL(clicked()), SLOT(nextClicked()) );
112 connect(prevPB, SIGNAL(clicked()), SLOT(prevClicked()) );
113 connect(stopPB, SIGNAL(clicked()), SLOT(stopClicked()) );
114 connect(ejectPB, SIGNAL(clicked()), SLOT(ejectClicked()) );
115 connect(songListCB, SIGNAL(activated(int)), SLOT(trackSelected(int)));
117 connect(shufflePB, SIGNAL(clicked()), SLOT(randomClicked()));
118 connect(repeatPB, SIGNAL(clicked()), SLOT(loopClicked()) );
119 connect(m_cd, SIGNAL(randomPlaylistChanged(bool)), this, SLOT(randomChanged(bool)));
120 connect(m_cd, SIGNAL(loopPlaylistChanged(bool)), this, SLOT(loopChanged(bool)));
122 connect(cddbPB, SIGNAL(clicked()), SLOT(CDDialogSelected()));
123 connect(KGlobalSettings::self(), SIGNAL(kdisplayPaletteChanged()), this, SLOT(setColors()));
124 connect(KGlobalSettings::self(), SIGNAL(iconChanged(int)), this, SLOT(setIcons()));
125 songListCB->setToolTip(i18n("Track list"));
128 // set up the actions and keyboard accels
129 m_actions = new KActionCollection(this);
130 m_actions->setConfigGroup("Shortcuts");
132 QAction* action;
133 action = m_actions->addAction(i18n("Play/Pause"), this, SLOT(playClicked()));
134 action->setShortcut(Qt::Key_P);
135 qobject_cast<KAction*>(action)->setGlobalShortcut(KShortcut(Qt::META + Qt::Key_P));
137 action = m_actions->addAction(i18n("Stop"), this, SLOT(stopClicked()));
138 action->setShortcut(Qt::Key_S);
139 qobject_cast<KAction*>(action)->setGlobalShortcut(KShortcut(Qt::META + Qt::Key_S));
141 action = m_actions->addAction(i18n("Previous"), this, SLOT(prevClicked()));
142 action->setShortcut(Qt::Key_B);
143 //NOTE: WIN+B collidates with amarok's default global shortcut.
144 qobject_cast<KAction*>(action)->setGlobalShortcut(KShortcut(Qt::META + Qt::Key_B));
146 action = m_actions->addAction(i18n("Next"), this, SLOT(nextClicked()));
147 action->setShortcut(Qt::Key_N);
148 qobject_cast<KAction*>(action)->setGlobalShortcut(KShortcut(Qt::META + Qt::Key_N));
150 action = m_actions->addAction(KStandardAction::Quit, this, SLOT(quitClicked()));
152 action = m_actions->addAction(KStandardAction::KeyBindings, this, SLOT(configureKeys()));
154 action = m_actions->addAction(KStandardAction::Preferences, this, SLOT(showConfig()));
156 action = m_actions->addAction(i18n("Loop"), this, SLOT(loopClicked()));
157 action->setShortcut(Qt::Key_L);
158 action = m_actions->addAction(i18n("Eject"), this, SLOT(ejectClicked()));
159 action->setShortcut(Qt::CTRL + Qt::Key_E);
160 action = m_actions->addAction(i18n("Increase Volume"), this, SLOT(incVolume()));
161 action->setShortcuts(KShortcut(QKeySequence(Qt::Key_Plus), QKeySequence(Qt::Key_Equal)));
162 qobject_cast<KAction*>(action)->setGlobalShortcut(KShortcut(Qt::META + Qt::Key_Plus));
164 action = m_actions->addAction(i18n("Decrease Volume"), this, SLOT(decVolume()));
165 action->setShortcut(Qt::Key_Minus);
166 qobject_cast<KAction*>(action)->setGlobalShortcut(KShortcut(Qt::META + Qt::Key_Minus));
168 action = m_actions->addAction(i18n("Options"), this, SLOT(showConfig()));
169 action->setShortcut(Qt::CTRL + Qt::Key_T);
170 action = m_actions->addAction(i18n("Shuffle"), this, SLOT(randomClicked()));
171 action->setShortcut(Qt::Key_R);
172 qobject_cast<KAction*>(action)->setGlobalShortcut(KShortcut(Qt::META + Qt::Key_R));
174 action = m_actions->addAction(i18n("CDDB"), this, SLOT(CDDialogSelected()));
175 action->setShortcut(Qt::CTRL + Qt::Key_D);
177 m_actions->readSettings();
179 setupPopups();
181 m_cd->setLoopPlaylist(Prefs::looping());
182 m_cd->setRandomPlaylist(Prefs::randomPlay());
184 setDocking(Prefs::docking());
185 setFocusPolicy(Qt::NoFocus);
187 songListCB->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed);
188 adjustSize();
189 setFixedHeight(this->height());
191 /* FIXME check for return value */
192 setDevicePaths();
195 KSCD::~KSCD()
197 delete cddb;
198 delete m_cd;
201 void KSCD::setVolume(int v)
203 volChanged(v);
204 volumeSlider->setValue(v);
207 void KSCD::setDevice(const QString& dev)
209 Prefs::setCdDevice(dev);
210 setDevicePaths();
214 * drawPanel() constructs KSCD's little black LED area
215 * all settings are made via panel.ui
217 void KSCD::drawPanel()
219 setIcons();
220 adjustSize();
222 connect(lcdNumber, SIGNAL(clicked()), this, SLOT(cycleplaytimemode()));
224 setLEDs(-1);
226 queryled->setVisible(false);
227 totaltimelabel->hide();
230 void KSCD::setIcons()
232 playPB->setIcon(KIcon(SmallIcon("media-playback-start")));
233 stopPB->setIcon(KIcon(SmallIcon("media-playback-stop")));
234 ejectPB->setIcon(KIcon(SmallIcon("media-eject")));
235 prevPB->setIcon(KIcon(SmallIcon("media-skip-backward")));
236 nextPB->setIcon(KIcon(SmallIcon("media-skip-forward")));
237 cddbPB->setIcon(KIcon(SmallIcon("fileview-text")));
238 infoPB->setIcon(KIcon(SmallIcon("system-run")));
241 void KSCD::setupPopups()
243 QMenu *infoPopup, *mainPopup;
245 mainPopup = new QMenu(this);
246 infoPB->setMenu(mainPopup);
247 infoPopup = mainPopup->addMenu(i18n("Artist Information"));
249 connect(infoPopup, SIGNAL(triggered(QAction *)), SLOT(information(QAction *)));
251 infoPopup->addAction("MusicMoz");
252 infoPopup->addAction("Ultimate Bandlist");
253 infoPopup->addAction("CD Universe");
254 infoPopup->addSeparator();
255 infoPopup->addAction("AlltheWeb");
256 infoPopup->addAction("Altavista");
257 infoPopup->addAction("Excite");
258 infoPopup->addAction("Google");
259 infoPopup->addAction("Google Groups");
260 infoPopup->addAction("HotBot");
261 infoPopup->addAction("Lycos");
262 infoPopup->addAction("Open Directory");
263 infoPopup->addAction("Yahoo!");
265 mainPopup->addAction(m_actions->action(KStandardAction::name(KStandardAction::Preferences)));
266 mainPopup->addAction(m_actions->action(KStandardAction::name(KStandardAction::KeyBindings)));
267 mainPopup->addSeparator();
269 KHelpMenu* helpMenu = new KHelpMenu(this, KGlobal::mainComponent().aboutData(), false);
270 mainPopup->addMenu(helpMenu->menu());
271 mainPopup->addSeparator();
272 mainPopup->addAction(m_actions->action(KStandardAction::name(KStandardAction::Quit)));
275 void KSCD::playClicked()
277 if (m_cd->isPlaying() || m_cd->isPaused())
278 m_cd->pause();
279 else
280 m_cd->play();
283 void KSCD::stopClicked()
285 stoppedByUser = true;
287 m_cd->stop();
290 void KSCD::prevClicked()
292 m_cd->prev();
295 void KSCD::nextClicked()
297 m_cd->next();
300 void KSCD::jumpToTime(int seconds)
302 m_cd->playPosition(seconds);
305 void KSCD::timeSliderPressed()
307 updateTime = false;
310 void KSCD::timeSliderMoved(int seconds)
312 setLEDs(seconds);
313 jumpToTime(seconds);
316 void KSCD::timeSliderReleased()
318 updateTime = true;
321 void KSCD::quitClicked()
323 // ensure nothing else starts happening
324 queryledtimer.stop();
325 titlelabeltimer.stop();
327 writeSettings();
329 m_cd->stop();
331 delete m_cd;
333 kapp->quit();
336 bool KSCD::event( QEvent *e )
338 return QWidget::event(e);
342 * Do everything needed if the user requested to eject the disc.
345 void KSCD::ejectClicked()
347 m_cd->eject();
350 void KSCD::closeEvent(QCloseEvent *e)
352 if (Prefs::docking() && !kapp->sessionSaving())
354 hide();
355 e->ignore();
356 return;
358 e->accept();
361 void KSCD::randomClicked()
363 Prefs::setRandomPlay(!Prefs::randomPlay());
364 m_cd->setRandomPlaylist(Prefs::randomPlay());
367 void KSCD::randomChanged(bool on)
369 randomled->setVisible(on);
370 shufflePB->setChecked(on);
373 void KSCD::loopClicked()
375 Prefs::setLooping(!Prefs::looping()) ;
376 m_cd->setLoopPlaylist(Prefs::looping());
379 void KSCD::loopChanged(bool on)
381 loopled->setVisible(on);
382 repeatPB->setChecked(on);
386 * A Track was selected for playback from the drop down box.
389 void KSCD::trackSelected(int cb_index)
391 m_cd->playTrack(cb_index + 1);
394 void KSCD::updateConfigDialog(configWidget* widget)
396 if(!widget)
397 return;
399 static QString originalTitleOfGroupBox = widget->groupBox3->title();
400 if(m_cd->isPlaying()) {
401 widget->groupBox3->setEnabled(false);
402 widget->groupBox3->setTitle( i18n( "CD Drive (you must stop playing to change this)" ) );
403 } else {
404 widget->groupBox3->setEnabled(true);
405 widget->groupBox3->setTitle(originalTitleOfGroupBox);
409 void KSCD::showConfig()
411 static configWidget* confWidget = 0;
413 if (KConfigDialog::showDialog("settings")) {
414 updateConfigDialog(confWidget);
415 return;
418 configDialog = new KConfigDialog(this, "settings", Prefs::self());
420 configDialog->setHelp(QString());
422 confWidget = new configWidget(this, 0);
424 // kscd config page
425 configDialog->addPage(confWidget, i18n("CD Player"), "kscd", i18n("Settings & Behavior"));
427 // libkcddb page
428 KService::Ptr libkcddb = KService::serviceByDesktopName("libkcddb");
429 if (libkcddb && libkcddb->isValid())
431 KCModuleInfo info(libkcddb->entryPath());
432 if (info.service()->isValid())
434 KCModule *m = KCModuleLoader::loadModule(info, KCModuleLoader::Inline);
435 if (m)
437 m->load();
438 KCDDB::Config* cfg = new KCDDB::Config();
439 cfg->readConfig();
440 configDialog -> addPage(m, cfg, QString("CDDB"), "text-xmcd", i18n("Configure Fetching Items"));
442 connect(configDialog, SIGNAL(okClicked()), m, SLOT(save()));
443 connect(configDialog, SIGNAL(applyClicked()), m, SLOT(save()));
444 connect(configDialog, SIGNAL(defaultClicked()), m, SLOT(defaults()));
449 updateConfigDialog(confWidget);
451 connect(configDialog, SIGNAL(settingsChanged(const QString&)), this, SLOT(configDone()));
452 configDialog -> show();
455 void KSCD::configDone()
457 Prefs::self()->writeConfig();
459 setColors();
460 setDocking(Prefs::docking());
462 setDevicePaths();
463 // dialog deletes itself
464 configDialog = 0L;
467 void KSCD::configureKeys()
469 KShortcutsDialog::configure(m_actions, KShortcutsEditor::LetterShortcutsAllowed, this);
472 void KSCD::setDevicePaths()
474 QString audioSystem;
475 if(!Prefs::digitalPlayback()) {
476 audioSystem = QString("cdin");
477 } else {
478 switch(Prefs::audioSystem())
480 case Prefs::EnumAudioSystem::phonon:
481 audioSystem = QString("phonon");
482 break;
483 case Prefs::EnumAudioSystem::arts:
484 audioSystem = QString("arts");
485 break;
486 case Prefs::EnumAudioSystem::alsa:
487 audioSystem = QString("alsa");
488 break;
489 case Prefs::EnumAudioSystem::sun:
490 audioSystem = QString("sun");
491 break;
492 default:
493 return;
497 if (!m_cd->setDevice(Prefs::cdDevice(), Prefs::volume(), Prefs::digitalPlayback(),
498 audioSystem, Prefs::audioDevice()))
500 // This device did not seem usable.
501 QString str = i18n("CD-ROM access error (or error in startup of audio system).\n"\
502 "Please make sure you have access permissions to cdrom device:\n"\
503 "device '%1'(%2), audio system '%3'",
504 Prefs::cdDevice(), KCompactDisc::urlToDevice(Prefs::cdDevice()), audioSystem);
505 KMessageBox::error(this, str, i18n("Error"));
507 } else {
508 kDebug(67000) << "Vendor: " << m_cd->deviceVendor();
509 kDebug(67000) << "Model: " << m_cd->deviceModel();
510 kDebug(67000) << "Revision: " << m_cd->deviceRevision();
513 m_cd->setRandomPlaylist(Prefs::randomPlay());
514 m_cd->setLoopPlaylist(Prefs::looping());
517 void KSCD::setDocking(bool dock)
519 Prefs::setDocking(dock);
520 if (Prefs::docking())
522 if (!m_dockWidget)
524 m_dockWidget = new DockWidget(this, "dockw");
525 connect(m_dockWidget, SIGNAL(quitSelected()), this, SLOT(quitClicked()));
528 m_dockWidget->show();
529 connect(this, SIGNAL(tooltipCurrentTrackChanged(const QString&)),
530 m_dockWidget, SLOT(setToolTip(const QString&)));
531 connect(this, SIGNAL(tooltipCurrentTrackChanged(const QString&)),
532 m_dockWidget, SLOT(createPopup(const QString&)));
534 else
536 show();
537 delete m_dockWidget;
538 m_dockWidget = 0;
542 void KSCD::incVolume()
544 int v = Prefs::volume() + 5;
546 if (v > 100)
548 v = 100;
551 volChanged(v);
552 volumeSlider->setValue(v);
555 void KSCD::decVolume()
557 int v = Prefs::volume() - 5;
559 if (v < 0)
561 v = 0;
564 volChanged(v);
565 volumeSlider->setValue(v);
568 void KSCD::volChanged(int vol)
570 m_cd->setVolume(vol);
571 Prefs::setVolume(vol);
572 showVolumeInLabel();
575 void KSCD::setLEDs(int seconds)
577 QString symbols;
579 if (seconds < 0)
581 symbols = "--:--";
583 else
585 unsigned mymin;
586 unsigned mysec;
587 mymin = seconds / 60;
588 mysec = (seconds % 60);
589 symbols.sprintf("%02d:%02d", mymin, mysec);
592 lcdNumber->display(symbols);
595 void KSCD::resetTimeSlider(bool enabled)
597 timeSlider->setEnabled(enabled);
598 timeSlider->blockSignals(true);
599 timeSlider->setValue(0);
600 timeSlider->blockSignals(false);
603 void KSCD::setColors()
605 QColor led_color = Prefs::ledColor();
606 QColor background_color = Prefs::backColor();
607 QPalette pal(led_color, background_color,
608 led_color, led_color,
609 led_color, led_color, Qt::white);
611 backdrop->setPalette(pal);
613 titlelabel->setFont(Prefs::ledFont());
614 artistlabel->setFont(Prefs::ledFont());
615 volumelabel->setFont(Prefs::ledFont());
616 statuslabel->setFont(Prefs::ledFont());
617 tracklabel->setFont(Prefs::ledFont());
618 totaltimelabel->setFont(Prefs::ledFont());
621 void KSCD::readSettings()
623 if (Prefs::cdDevice().isEmpty())
624 Prefs::setCdDevice(KCompactDisc::defaultCdromDeviceName());
627 void KSCD::writeSettings()
629 Prefs::self()->writeConfig();
632 void KSCD::CDDialogSelected()
634 if (!cddialog)
636 cddialog = new CDDBDlg(this);
638 connect(cddialog,SIGNAL(cddbQuery()),SLOT(lookupCDDB()));
639 connect(cddialog,SIGNAL(newCDInfoStored(KCDDB::CDInfo)),
640 SLOT(setCDInfo(KCDDB::CDInfo)));
641 connect(cddialog,SIGNAL(finished()),SLOT(CDDialogDone()));
642 connect(cddialog,SIGNAL(play(int)),SLOT(trackSelected(int)));
645 cddialog->show();
646 cddialog->raise();
649 void KSCD::CDDialogDone()
651 cddialog->delayedDestruct();
652 cddialog = 0L;
655 void KSCD::lookupCDDB()
657 if (m_cd->isNoDisc() || m_cd->discId() == 0)
658 return;
660 kDebug(67000) << "lookupCDDB() called";
662 showArtistLabel(i18n("Start freedb lookup."));
664 led_on();
666 cddb->config().reparse();
667 cddb->setBlockingMode(false);
668 cddb->lookup(m_cd->discSignature());
671 void KSCD::lookupCDDBDone(Result result)
673 led_off();
674 if ((result != KCDDB::Success) &&
675 (result != KCDDB::MultipleRecordFound))
677 showArtistLabel(result == NoRecordFound ? i18n("No matching freedb entry found.") :
678 i18n("Error getting freedb entry."));
679 QTimer::singleShot(3000, this, SLOT(restoreArtistLabel()));
680 return;
683 // The intent of the original code here seems to have been to perform the
684 // lookup, and then to convert all the string data within the CDDB response
685 // using the use Prefs::selectedEncoding() and a QTextCodec. However, that
686 // seems to be irrelevant these days.
687 KCDDB::CDInfo info = cddb->lookupResponse().first();
688 // TODO Why doesn't libcddb not return MultipleRecordFound?
689 //if( result == KCDDB::MultipleRecordFound ) {
690 if(cddb->lookupResponse().count() > 1) {
691 CDInfoList cddb_info = cddb->lookupResponse();
692 CDInfoList::iterator it;
693 QStringList list;
694 for ( it = cddb_info.begin(); it != cddb_info.end(); ++it ) {
695 list.append( QString("%1, %2, %3").arg((*it).get(Artist).toString())
696 .arg((*it).get(Title).toString()).arg((*it).get(Genre).toString()));
699 bool ok(false);
700 QString res = KInputDialog::getItem(
701 i18n("Select CDDB Entry"),
702 i18n("Select a CDDB entry:"), list, 0, false, &ok,
703 this );
704 if ( ok ) {
705 // The user selected and item and pressed OK
706 int c = 0;
707 for ( QStringList::Iterator it = list.begin(); it != list.end(); ++it ) {
708 if( *it == res) break;
709 c++;
711 if( c < cddb_info.size() )
712 info = cddb_info[c];
713 } else {
714 return;
715 // user pressed Cancel
719 setCDInfo(info);
722 void KSCD::setCDInfo(KCDDB::CDInfo info)
724 // Some sanity provisions to ensure that the number of records matches what
725 // the CD actually contains.
727 Q_ASSERT(info.numberOfTracks() == m_cd->tracks());
729 cddbInfo = info;
730 populateSongList();
731 restoreArtistLabel();
734 void KSCD::led_off()
736 queryledtimer.stop();
737 queryled->setVisible(false);
738 totaltimelabel->raise();
739 totaltimelabel->show();
742 void KSCD::led_on()
744 totaltimelabel->hide();
745 totaltimelabel->lower();
746 queryledtimer.start(800);
747 queryled->setVisible(true);
750 void KSCD::togglequeryled()
752 queryled->setVisible(!queryled->isVisible());
755 void KSCD::titlelabeltimeout()
757 // clear the cddb error message on the title label.
758 titlelabeltimer.stop();
759 titlelabel->clear();
762 int KSCD::currentTrack()
764 return m_cd->track();
767 int KSCD::currentTrackLength()
769 return m_cd->trackLength();
772 int KSCD::currentPosition()
774 return m_cd->trackPosition();
777 int KSCD::getStatus()
779 if (m_cd->isPlaying())
780 return 2;
781 else if (m_cd->isPaused())
782 return 4;
783 else if (!m_cd->isNoDisc())
784 return 5;
785 else
786 return 6;
789 bool KSCD::playing()
791 return m_cd->isPlaying();
794 void KSCD::trackPosition(unsigned trackPosition)
796 unsigned tmp;
798 kDebug(67000) << "trackPosition(" << trackPosition << ")";
799 switch (Prefs::timeDisplayMode())
801 case Prefs::EnumTimeDisplayMode::TRACK_REM:
802 tmp = m_cd->trackLength() - trackPosition;
803 break;
805 case Prefs::EnumTimeDisplayMode::TOTAL_SEC:
806 tmp = m_cd->discPosition();
807 break;
809 case Prefs::EnumTimeDisplayMode::TOTAL_REM:
810 tmp = m_cd->discLength() - m_cd->discPosition();
811 break;
813 case Prefs::EnumTimeDisplayMode::TRACK_SEC:
814 default:
815 tmp = trackPosition;
816 break;
818 if (updateTime)
820 setLEDs(tmp);
821 timeSlider->blockSignals(true);
822 timeSlider->setValue(trackPosition);
823 timeSlider->blockSignals(false);
827 void KSCD::discChanged(unsigned tracks)
829 kDebug(67000) << "discChanged(" << tracks << ")";
830 if (tracks > 0) {
831 populateSongList();
833 // Set the total time.
834 QTime dml;
835 dml = dml.addSecs(m_cd->discLength());
837 QString fmt;
838 if(dml.hour() > 0)
839 fmt.sprintf("%02d:%02d:%02d", dml.hour(), dml.minute(), dml.second());
840 else
841 fmt.sprintf("%02d:%02d", dml.minute(), dml.second());
842 totaltimelabel->setText(fmt);
844 if ((Prefs::autoplay() || KCmdLineArgs::parsedArgs()->isSet("start"))
845 && !m_cd->isPlaying())
846 playClicked();
848 // We just populated the GUI with what we got from the CD. Now look for
849 // more from the Internet...
850 showArtistLabel(i18n("Start freedb lookup."));
852 led_on();
854 cddb->config().reparse();
855 cddb->setBlockingMode(false);
856 cddb->lookup(m_cd->discSignature());
857 } else {
858 trackChanged(0);
859 populateSongList();
860 restoreArtistLabel();
861 totaltimelabel->hide();
865 void KSCD::discInformation(KCompactDisc::DiscInfo info)
867 populateSongList();
868 restoreArtistLabel();
871 void KSCD::discStatusChanged(KCompactDisc::DiscStatus status)
873 kDebug(67000) << "discStatusChanged(" << m_cd->discStatusString(status) << ")";
874 statuslabel->setText(m_cd->discStatusString(status));
876 switch(status)
878 case KCompactDisc::Stopped:
879 trackChanged(0);
880 trackPosition(-1);
881 if (Prefs::ejectOnFinish() && !stoppedByUser)
882 ejectClicked();
884 playPB->setText(i18n("Play"));
885 playPB->setIcon(KIcon(SmallIcon("media-playback-start")));
887 /* reset to initial value, only stopclicked() sets this to true */
888 stoppedByUser = false;
889 break;
891 case KCompactDisc::Playing:
892 playPB->setIcon(KIcon(SmallIcon("media-playback-pause")));
893 playPB->setText(i18n("Pause"));
894 break;
896 case KCompactDisc::Paused:
897 playPB->setIcon(KIcon(SmallIcon("media-playback-start")));
898 playPB->setText(i18n("Play"));
899 break;
901 default:
902 break;
906 void KSCD::trackChanged(unsigned track)
908 kDebug(67000) << "trackChanged(" << track << ")";
909 QString tooltip = artistlabel->text();
911 if (track < 1)
913 setLEDs(-1);
914 resetTimeSlider(true);
915 tracklabel->setText("--/--");
916 titlelabel->clear();
917 if (songListCB->count())
919 songListCB->setCurrentIndex(0);
922 else
924 if (songListCB->count())
926 songListCB->setCurrentIndex(track - 1);
927 // drop the number.
928 // for Mahlah, a picky though otherwise wonderful person - AJS
929 QString justTheName = songListCB->currentText();
930 justTheName = justTheName.right(justTheName.length() - 4);
932 songListCB->setToolTip( i18n("Current track: %1", justTheName));
934 timeSlider->blockSignals(true);
935 timeSlider->setRange(0, m_cd->trackLength(track));
936 timeSlider->blockSignals(false);
937 QString str;
938 str.sprintf("%02d/%02d", track, m_cd->tracks());
939 tracklabel->setText(str);
941 QString title;
942 if (m_cd->trackArtist() != m_cd->discArtist())
943 title.append(m_cd->trackArtist()).append(" - ");
944 title.append(m_cd->trackTitle());
945 titlelabel->setText(title);
946 tooltip += '/' + KStringHandler::rsqueeze(title, 30);
948 emit tooltipCurrentTrackChanged(tooltip);
951 void KSCD::cycleplaytimemode()
953 /* switch to the next mode */
954 switch (Prefs::timeDisplayMode())
956 case Prefs::EnumTimeDisplayMode::TRACK_SEC:
957 Prefs::setTimeDisplayMode(Prefs::EnumTimeDisplayMode::TRACK_REM);
958 break;
960 case Prefs::EnumTimeDisplayMode::TRACK_REM:
961 Prefs::setTimeDisplayMode(Prefs::EnumTimeDisplayMode::TOTAL_SEC);
962 break;
964 case Prefs::EnumTimeDisplayMode::TOTAL_SEC:
965 Prefs::setTimeDisplayMode(Prefs::EnumTimeDisplayMode::TOTAL_REM);
966 break;
968 case Prefs::EnumTimeDisplayMode::TOTAL_REM:
969 default:
970 Prefs::setTimeDisplayMode(Prefs::EnumTimeDisplayMode::TRACK_SEC);
971 break;
974 /* and display it */
975 switch(Prefs::timeDisplayMode())
977 case Prefs::EnumTimeDisplayMode::TRACK_REM:
978 volumelabel->setText(i18n("Tra Rem"));
979 break;
981 case Prefs::EnumTimeDisplayMode::TOTAL_SEC:
982 volumelabel->setText(i18n("Tot Sec"));
983 break;
985 case Prefs::EnumTimeDisplayMode::TOTAL_REM:
986 volumelabel->setText(i18n("Tot Rem"));
987 break;
989 case Prefs::EnumTimeDisplayMode::TRACK_SEC:
990 default:
991 volumelabel->setText(i18n("Tra Sec"));
992 break;
995 QTimer::singleShot(3000, this, SLOT(showVolumeInLabel()));
998 void KSCD::showVolumeInLabel()
1000 QString str;
1001 str = ki18n("Vol: %1%").subs(Prefs::volume(), 2).toString();
1002 volumelabel->setText(str);
1005 void KSCD::showArtistLabel(QString infoStatus)
1007 artistlabel->setText(infoStatus);
1011 * KDE 4.0 quick fix: it looks like the conversion to mode
1012 * CDDB info into KCompactDisc wasn't finished, so we work around
1013 * it here for now by explicitly overriding data from m_cd with
1014 * data from cddbInfo iff cddbInfo.isValid() &&
1015 * cddbInfo.numberOfTracks() == m_cd->tracks()
1018 void KSCD::restoreArtistLabel()
1020 if(m_cd->tracks()) {
1021 QString artist, title;
1023 if (cddbInfo.isValid() && cddbInfo.numberOfTracks() == m_cd->tracks()) {
1024 artist = cddbInfo.get(KCDDB::Artist).toString();
1025 title = cddbInfo.get(KCDDB::Title).toString();
1026 } else {
1027 artist = m_cd->discArtist();
1028 title = m_cd->discTitle();
1031 showArtistLabel(QString("%1 - %2").arg(artist, title));
1032 } else {
1033 showArtistLabel(i18n("NO DISC"));
1037 void KSCD::information(QAction *action)
1039 QString artist = m_cd->trackArtist();
1041 // see comment before restoreArtistLabel()
1042 if (cddbInfo.isValid() && cddbInfo.numberOfTracks() == m_cd->tracks()) {
1043 const KCDDB::TrackInfo& t = cddbInfo.track(m_cd->track() - 1);
1044 artist = t.get(KCDDB::Artist).toString();
1047 if(artist.isEmpty())
1048 return;
1050 //QString encodedArtist = KUrl::encode_string_no_slash(cddbInfo.get(Artist).toString());
1052 KUrl url;
1053 QString server = action->text();
1055 if(server == "MusicMoz") {
1056 url = KUrl("http://musicmoz.org/cgi-bin/ext.cgi");
1057 url.addQueryItem( "artist", artist );
1058 } else if (server == "Ultimate Bandlist") {
1059 url = KUrl("http://ubl.artistdirect.com/cgi-bin/gx.cgi/AppLogic+Search?select=MusicArtist&searchtype=NormalSearch");
1060 url.addQueryItem( "searchstr", artist );
1061 } else if (server == "CD Universe") {
1062 url = KUrl( QString( "http://www.cduniverse.com/cgi-bin/cdubin.exe/rlinka/ean=%1" ).arg( QString::fromLatin1(KUrl::toPercentEncoding(artist)) ) );
1063 } else if (server == "AlltheWeb") {
1064 url = KUrl("http://www.alltheweb.com/search?cat=web");
1065 url.addQueryItem( "q", artist );
1066 } else if (server == "Altavista") {
1067 url = KUrl("http://altavista.com/web/results?kgs=0&kls=1&avkw=xytx");
1068 url.addQueryItem( "q", artist );
1069 } else if (server == "Excite") {
1070 url = KUrl("http://msxml.excite.com/_1_2UDOUB70SVHVHR__info.xcite/dog/results?otmpl=dog/webresults.htm&qcat=web&qk=20&top=1&start=&ver=14060");
1071 url.addQueryItem( "qkw", artist );
1072 } else if (server == "Google") {
1073 url = KUrl("http://www.google.com/search");
1074 url.addQueryItem( "q", artist );
1075 } else if (server == "Google Groups") {
1076 url = KUrl("http://groups.google.com/groups?oi=djq&num=20");
1077 url.addQueryItem( "as_q", artist );
1078 } else if (server == "HotBot") {
1079 url = KUrl("http://www.hotbot.com/default.asp?prov=Inktomi&ps=&loc=searchbox&tab=web");
1080 url.addQueryItem( "query", artist );
1081 } else if (server == "Lycos") {
1082 url = KUrl("http://search.lycos.com/default.asp?lpv=1&loc=searchhp&tab=web");
1083 url.addQueryItem( "query", artist );
1084 } else if (server == "Open Directory") {
1085 url = KUrl("http://search.dmoz.org/cgi-bin/search");
1086 url.addQueryItem( "search", artist );
1087 } else if (server == "Yahoo!") {
1088 url = KUrl("http://search.yahoo.com/bin/search");
1089 url.addQueryItem( "p", artist );
1090 } else {
1091 return;
1094 KRun::runUrl( url, "text/html", 0L);
1098 * Save state on session termination
1100 bool KSCD::saveState(QSessionManager& /*sm*/)
1102 writeSettings();
1103 KConfigGroup config(KApplication::kApplication()->sessionConfig(), "General");
1104 config.writeEntry("Show", isVisible());
1105 return true;
1109 * Allow the user to type in the number of the track
1111 void KSCD::keyPressEvent(QKeyEvent* e)
1113 bool isNum;
1114 uint value = e->text().toUInt(&isNum);
1116 if (e->key() == Qt::Key_F1)
1118 KToolInvocation::invokeHelp();
1120 else if (isNum)
1122 if (0 < value && value <= m_cd->tracks())
1123 songListCB->setCurrentIndex(value - 1);
1125 else
1127 QWidget::keyPressEvent(e);
1131 QString KSCD::currentTrackTitle()
1133 // see comment before restoreArtistLabel()
1134 if (cddbInfo.isValid() && cddbInfo.numberOfTracks() == m_cd->tracks()) {
1135 const KCDDB::TrackInfo& t = cddbInfo.track(m_cd->track() - 1);
1136 return t.get(KCDDB::Title).toString();
1139 return m_cd->trackTitle();
1142 QString KSCD::currentAlbum()
1144 // see comment before restoreArtistLabel()
1145 if (cddbInfo.isValid() && cddbInfo.numberOfTracks() == m_cd->tracks()) {
1146 return cddbInfo.get(KCDDB::Title).toString();
1149 return m_cd->discTitle();
1152 QString KSCD::currentArtist()
1154 // see comment before restoreArtistLabel()
1155 if (cddbInfo.isValid() && cddbInfo.numberOfTracks() == m_cd->tracks()) {
1156 const KCDDB::TrackInfo& t = cddbInfo.track(m_cd->track() - 1);
1157 return t.get(KCDDB::Artist).toString();
1160 return m_cd->trackArtist();
1163 QStringList KSCD::trackList()
1165 QStringList tracks;
1167 // see comment before restoreArtistLabel()
1168 if (cddbInfo.isValid() && cddbInfo.numberOfTracks() == m_cd->tracks()) {
1169 for (uint i = 0; i < m_cd->tracks(); ++i) {
1170 const KCDDB::TrackInfo& t = cddbInfo.track(i);
1171 tracks << t.get(KCDDB::Artist).toString();
1173 } else {
1174 for (uint i = 0; i < m_cd->tracks(); ++i)
1175 tracks << m_cd->trackTitle(i);
1178 return tracks;
1181 void KSCD::populateSongList()
1183 songListCB->clear();
1184 for (uint i = 1; i <= m_cd->tracks(); ++i)
1186 unsigned tmp = m_cd->trackLength(i);
1187 unsigned mymin;
1188 unsigned mysec;
1189 mymin = tmp / 60;
1190 mysec = (tmp % 60);
1191 QString str1;
1192 str1.sprintf("%02u: ", i);
1194 QString str2;
1195 str2.sprintf(" (%02u:%02u) ", mymin, mysec);
1196 // see comment before restoreArtistLabel()
1197 if (cddbInfo.isValid() && cddbInfo.numberOfTracks() == m_cd->tracks()) {
1198 const KCDDB::TrackInfo& t = cddbInfo.track(i - 1);
1200 if (cddbInfo.get(KCDDB::Artist).toString() != t.get(KCDDB::Artist).toString())
1201 str1.append(t.get(KCDDB::Artist).toString()).append(" - ");
1202 str1.append(t.get(KCDDB::Title).toString());
1203 } else {
1204 if (m_cd->discArtist() != m_cd->trackArtist(i))
1205 str1.append(m_cd->trackArtist(i)).append(" - ");
1206 str1.append(m_cd->trackTitle(i));
1208 str1.append(str2);
1209 songListCB->addItem(str1);
1215 * main()
1217 int main( int argc, char *argv[] )
1219 KAboutData aboutData("kscd", 0, ki18n("KsCD"),
1220 "1.5", ki18n(description),
1221 KAboutData::License_GPL,
1222 ki18n("(c) 2001, Dirk Försterling\n(c) 2003, Aaron J. Seigo"));
1223 aboutData.addAuthor(ki18n("Aaron J. Seigo"), ki18n("Current maintainer"), "aseigo@kde.org");
1224 aboutData.addAuthor(ki18n("Alexander Kern"),ki18n("Workman library update, CDTEXT, CDDA"), "kernalex@kde.org");
1225 aboutData.addAuthor(ki18n("Bernd Johannes Wuebben"),KLocalizedString(), "wuebben@kde.org");
1226 aboutData.addAuthor(ki18n("Dirk Försterling"), ki18n("Workman library, previous maintainer"), "milliByte@gmx.net");
1227 aboutData.addCredit(ki18n("Wilfried Huss"), ki18n("Patches galore"));
1228 aboutData.addCredit(ki18n("Steven Grimm"), ki18n("Workman library"));
1229 aboutData.addCredit(ki18n("Sven Lueppken"), ki18n("UI Work"));
1230 aboutData.addCredit(ki18n("freedb.org"), ki18n("Special thanks to freedb.org for providing a free CDDB-like CD database"), 0, "http://freedb.org");
1232 KCmdLineArgs::init( argc, argv, &aboutData );
1234 KCmdLineOptions options;
1235 options.add("s");
1236 options.add("start", ki18n("Start playing"));
1237 options.add("+[device]", ki18n("CD device, can be a path or a media:/ URL"));
1238 KCmdLineArgs::addCmdLineOptions(options);
1239 KUniqueApplication::addCmdLineOptions();
1241 KCmdLineArgs* args = KCmdLineArgs::parsedArgs();
1242 if (!KUniqueApplication::start())
1244 fprintf(stderr, "kscd is already running\n");
1245 if (args->count() > 0 || args->isSet("start"))
1247 QDBusInterface kscd("org.kde.kscd", "/CDPlayer", "org.kde.kscd.CDPlayer");
1248 // Forward the command line args to the running instance.
1249 if (args->count() > 0)
1251 kscd.call( "setDevice", QString(args->arg(0)));
1253 if (args->isSet("start"))
1255 kscd.call( "play" );
1258 exit(0);
1260 KUniqueApplication a;
1262 KSCD *k = new KSCD();
1264 a.setTopWidget( k );
1265 a.setMainWidget( k );
1267 k->setWindowTitle(KGlobal::caption());
1269 if (kapp->isSessionRestored())
1271 KConfigGroup group(KApplication::kApplication()->sessionConfig(), "General");
1272 if (group.readEntry("Show", false))
1273 k->show();
1275 else
1277 k->show();
1280 if (args->count() > 0)
1281 Prefs::self()->setCdDevice(args->arg(0));
1283 return a.exec();
1286 #include "kscd.moc"