/*************************************************************************** radioview.cpp - description ------------------- begin : Mit Mai 28 2003 copyright : (C) 2003 by Martin Witte email : witte@kawo1.rwth-aachen.de ***************************************************************************/ /*************************************************************************** * * * 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. * * * ***************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "../../src/include/radiodevice_interfaces.h" #include "../../src/include/radiostation.h" #include "../../src/include/stationlist.h" #include "../../src/include/pluginmanager.h" #include "../../src/include/plugin_configuration_dialog.h" #include "../../src/include/aboutwidget.h" #include "radioview.h" #include "radioview_frequencyradio.h" #include "radioview_volume.h" #include "radioview_frequencyseeker.h" #include "radioview-configuration.h" #include #define POPUP_ID_START_RECORDING_DEFAULT 0 #define POPUP_ID_STOP_RECORDING_BASE 100 /////////////////////////////////////////////////////////////////////// PLUGIN_LIBRARY_FUNCTIONS(RadioView, "tderadio-gui-standard-display", i18n("Standard Display for TDERadio")); /////////////////////////////////////////////////////////////////////// bool RadioView::ElementCfg::operator == (const ElementCfg &x) const { if (!x.element || !element) return x.cfg == cfg; if (!x.cfg || !cfg) return x.element == element; return element == x.element && cfg == x.cfg; } /////////////////////////////////////////////////////////////////////// RadioView::RadioView(const TQString &name) : TQWidget(NULL, name.ascii()), WidgetPluginBase(name, i18n("Radio Display")), enableToolbarFlag(false), btnPower(NULL), btnConfigure(NULL), btnQuit(NULL), btnRecording(NULL), btnSnooze(NULL), btnPlugins(NULL), comboStations(NULL), currentDevice(NULL), m_RecordingMenu(NULL), m_NextRecordingMenuID(POPUP_ID_STOP_RECORDING_BASE), m_PluginMenu(NULL) { for (int i = 0; i < clsClassMAX; ++i) maxUsability[i] = 0; TQBoxLayout *l01 = new TQBoxLayout(this, TQBoxLayout::LeftToRight, /*spacing=*/3); l01->setMargin(1); l01->setSpacing(2); widgetStacks[clsRadioSound] = new TQWidgetStack (this); l01->addWidget(widgetStacks[clsRadioSound]); TQBoxLayout *l02 = new TQBoxLayout(l01, TQBoxLayout::Down); TQBoxLayout *l03 = new TQBoxLayout(l02, TQBoxLayout::LeftToRight); comboStations = new KComboBox (this); l02->addWidget (comboStations); TQBoxLayout *l05 = new TQBoxLayout(l03, TQBoxLayout::Down); widgetStacks[clsRadioDisplay] = new TQWidgetStack (this); l05->addWidget(widgetStacks[clsRadioDisplay]); widgetStacks[clsRadioSeek] = new TQWidgetStack (this); l05->addWidget(widgetStacks[clsRadioSeek]); TQGridLayout *l04 = new TQGridLayout (l03, /*rows=*/ 3, /*cols=*/ 2); btnPower = new TQToolButton(this); btnPower->setToggleButton(true); btnRecording = new TQToolButton(this); btnRecording->setToggleButton(true); btnConfigure = new TQToolButton(this); btnConfigure->setToggleButton(true); btnQuit = new TQToolButton(this); btnSnooze = new TQToolButton(this); btnSnooze->setToggleButton(true); btnPlugins = new TQToolButton(this); btnPlugins->setPopupDelay(1); l04->addWidget (btnPower, 0, 0); l04->addWidget (btnRecording, 0, 1); l04->addWidget (btnConfigure, 1, 0); l04->addWidget (btnQuit, 1, 1); l04->addWidget (btnSnooze, 2, 0); l04->addWidget (btnPlugins, 2, 1); m_pauseMenu = new TDEPopupMenu(btnPower); m_pauseMenu->insertItem(SmallIcon("tderadio_pause"), i18n("Pause TDERadio"), this, TQ_SLOT(slotPause())); btnPower->setPopupDelay(200); m_RecordingMenu = new TDEPopupMenu(btnRecording); m_RecordingMenu->insertItem(SmallIcon("tderadio_record"), i18n("Start Recording"), POPUP_ID_START_RECORDING_DEFAULT); TQObject::connect(m_RecordingMenu, TQ_SIGNAL(activated(int)), this, TQ_SLOT(slotRecordingMenu(int))); btnRecording->setPopup(m_RecordingMenu); m_SnoozeMenu = new TDEPopupMenu(btnSnooze); m_SnoozeMenu->insertItem(i18n("5 min"), this, TQ_SLOT(slotSnooze(int)), 0, 5); m_SnoozeMenu->insertItem(i18n("10 min"), this, TQ_SLOT(slotSnooze(int)), 0, 10); m_SnoozeMenu->insertItem(i18n("15 min"), this, TQ_SLOT(slotSnooze(int)), 0, 15); m_SnoozeMenu->insertItem(i18n("30 min"), this, TQ_SLOT(slotSnooze(int)), 0, 30); m_SnoozeMenu->insertItem(i18n("60 min"), this, TQ_SLOT(slotSnooze(int)), 0, 60); btnSnooze->setPopup(m_SnoozeMenu); btnSnooze->setPopupDelay(200); // Plugin-Button/Menu m_PluginMenu = new TDEPopupMenu(btnPlugins); if (m_manager) m_manager->addWidgetPluginMenuItems(m_PluginMenu, m_Plugins2MenuID); btnPlugins->setPopup(m_PluginMenu); // ICONS btnPower->setIconSet(SmallIconSet("tderadio_muteon")); btnRecording->setIconSet(SmallIconSet("tderadio_record")); btnConfigure->setIconSet(SmallIconSet("configure")); btnQuit->setIconSet(SmallIconSet("system-log-out")); btnSnooze->setIconSet(SmallIconSet("tderadio_zzz")); btnPlugins->setIconSet(SmallIconSet("tderadio_plugins")); widgetStacks[clsRadioSound] ->setSizePolicy(TQSizePolicy(TQSizePolicy::Minimum, TQSizePolicy::Preferred)); widgetStacks[clsRadioDisplay]->setSizePolicy(TQSizePolicy(TQSizePolicy::Expanding, TQSizePolicy::Preferred)); widgetStacks[clsRadioSeek] ->setSizePolicy(TQSizePolicy(TQSizePolicy::Expanding, TQSizePolicy::Fixed)); comboStations ->setSizePolicy(TQSizePolicy(TQSizePolicy::Expanding, TQSizePolicy::Fixed)); comboStations->setMinimumHeight(28); TQObject::connect(btnPower, TQ_SIGNAL(toggled(bool)), this, TQ_SLOT(slotPower(bool))); TQObject::connect(btnQuit, TQ_SIGNAL(clicked()), kapp, TQ_SLOT(quit())); TQObject::connect(btnConfigure, TQ_SIGNAL(toggled(bool)), this, TQ_SLOT(slotConfigure(bool))); TQObject::connect(btnRecording, TQ_SIGNAL(clicked()), this, TQ_SLOT(slotRecord())); TQObject::connect(btnSnooze, TQ_SIGNAL(toggled(bool)), this, TQ_SLOT(slotSnooze(bool))); TQObject::connect(comboStations, TQ_SIGNAL(activated(int)), this, TQ_SLOT(slotComboStationSelected(int))); TQObject::connect(btnPlugins, TQ_SIGNAL(clicked()), this, TQ_SLOT(slotBtnPluginsClicked())); // tooltips TQToolTip::add(btnConfigure, i18n("Configure TDERadio")); TQToolTip::add(btnPower, i18n("Power On/Off")); TQToolTip::add(btnQuit, i18n("Quit TDERadio Application")); TQToolTip::add(btnRecording, i18n("Start/Stop Recording")); TQToolTip::add(btnSnooze, i18n("Start/Stop Sleep Countdown")); TQToolTip::add(btnPlugins, i18n("Show/Hide Plugins")); TQToolTip::add(comboStations, i18n("Select a Radio Station")); // testing addElement (new RadioViewFrequencyRadio (this, TQString())); addElement (new RadioViewVolume(this, TQString())); addElement (new RadioViewFrequencySeeker(this, TQString())); autoSetCaption(); } RadioView::~RadioView () { TQPtrListIterator it(configPages); while (configPages.first()) { delete configPages.first(); } configPages.clear(); } bool RadioView::addElement (RadioViewElement *e) { if (!e) return false; RadioViewClass cls = e->getClass(); if (cls < 0 || cls >= clsClassMAX) return false; e->reparent(this, TQPoint(0, 0), true); TQObject::connect(e, TQ_SIGNAL(destroyed(TQObject*)), this, TQ_SLOT(removeElement(TQObject*))); elements.append(e); widgetStacks[cls]->addWidget(e); // connect Element with device, disconnect doesn't matter (comp. removeElement) // other devices follow if currentDevice changes if (currentDevice) e->connectI(currentDevice); e->connectI(getSoundStreamServer()); TQPtrListIterator it(configPages); for (; it.current(); ++it) { addConfigurationTabFor(e, (TQTabWidget *)it.current()); } selectTopWidgets(); return true; } bool RadioView::removeElement (TQObject *_e) { RadioViewElement *e = dynamic_cast(_e); if (!e) return false; ElementCfgListIterator it; while ((it = elementConfigPages.find(e)) != elementConfigPages.end()) { delete (*it).cfg; // it must not used behind, the element will be deleted automatically // by slotElementConfigPageDeleted } e->disconnectI(getSoundStreamServer()); if (currentDevice) e->disconnectI(currentDevice); RadioViewClass cls = e->getClass(); TQObject::disconnect(e, TQ_SIGNAL(destroyed(TQObject*)), this, TQ_SLOT(removeElement(TQObject*))); widgetStacks[cls]->removeWidget(e); elements.remove(e); selectTopWidgets(); return true; } void RadioView::selectTopWidgets() { for (int i = 0; i < clsClassMAX; ++i) maxUsability[i] = 0; for (ElementListIterator i(elements); i.current(); ++i) { RadioViewElement *e = i.current(); RadioViewClass cls = e->getClass(); float u = e->getUsability(currentDevice); if (u > maxUsability[cls]) { maxUsability[cls] = u; widgetStacks[cls]->raiseWidget(e); } } // adjustLayout!? } // IRadioClient bool RadioView::noticePowerChanged(bool on) { btnPower->setIconSet(SmallIconSet( on ? "tderadio_muteoff" : "tderadio_muteon")); btnPower->setOn(on); if (on) { btnPower->setPopup(m_pauseMenu); } else { btnPower->setPopup(NULL); } autoSetCaption(); return true; } bool RadioView::noticeStationChanged (const RadioStation &, int idx) { // add 1 for "no preset defined" entry comboStations->setCurrentItem(idx + 1); autoSetCaption(); bool r = false; SoundFormat sf; queryIsRecordingRunning(queryCurrentSoundStreamID(), r, sf); m_RecordingMenu->setItemEnabled(POPUP_ID_START_RECORDING_DEFAULT, !r); return true; } bool RadioView::noticeStationsChanged(const StationList &sl) { const RawStationList &list = sl.all(); comboStations->clear(); comboStations->insertItem("<" + i18n("no preset defined") + ">"); for (RawStationList::Iterator i(list); i.current(); ++i) { RadioStation *stn = i.current(); TQString icon = stn->iconName(); if (icon.length() && TQFile(icon).exists()) { TQImage img(icon); int h = img.height(); float f = (float)(comboStations->height() - 4) / (h ? (float)h : 1.0); comboStations->insertItem(img.smoothScale((int)(img.width()*f), (int)(h * f)), stn->name()); } else { comboStations->insertItem(stn->name()); } } noticeStationChanged(queryCurrentStation(), queryCurrentStationIdx()); return true; } bool RadioView::noticeCurrentSoundStreamIDChanged(SoundStreamID /*id*/) { // FIXME: perhaps do something return false; } // IRadioDevicePoolClient bool RadioView::noticeActiveDeviceChanged(IRadioDevice *newDevice) { IRadioDevice *oldDevice = currentDevice; currentDevice = newDevice; for (ElementListIterator i(elements); i.current(); ++i) { RadioViewElement *e = i.current(); if (oldDevice) e->disconnectI(oldDevice); if (newDevice) e->connectI(currentDevice); } selectTopWidgets(); return true; } // Interface bool RadioView::connectI(Interface *i) { bool a = IRadioClient::connectI(i); bool b = IRadioDevicePoolClient::connectI(i); bool c = PluginBase::connectI(i); bool d = ITimeControlClient::connectI(i); // Callbacks for ISoundStreamClient bool e = ISoundStreamClient::connectI(i); return a || b || c || d || e; } bool RadioView::disconnectI(Interface *i) { bool a = IRadioClient::disconnectI(i); bool b = IRadioDevicePoolClient::disconnectI(i); bool c = PluginBase::disconnectI(i); bool d = ITimeControlClient::disconnectI(i); bool e = ISoundStreamClient::disconnectI(i); if (e) { // special task for soundstreamclient, different from radio device pool for (ElementListIterator it(elements); it.current(); ++it) { RadioViewElement *e = it.current(); e->disconnectI(i); } } return a || b || c || d || e; } void RadioView::noticeConnectedI (ISoundStreamServer *s, bool pointer_valid) { ISoundStreamClient::noticeConnectedI(s, pointer_valid); if (s && pointer_valid) { s->register4_sendStartRecordingWithFormat(this); s->register4_sendStopRecording (this); s->register4_notifySoundStreamChanged (this); // special task for soundstreamclient, different from radio device pool for (ElementListIterator it(elements); it.current(); ++it) { RadioViewElement *e = it.current(); e->connectI(s); } } } // ISoundStreamClient bool RadioView::startRecordingWithFormat( SoundStreamID id, const SoundFormat &/*proposed_format*/, SoundFormat &/*real_format*/) { if (!id.isValid() || id != queryCurrentSoundStreamID() || m_StreamID2MenuID.contains(id)) return false; TQString descr; querySoundStreamDescription(id, descr); int menu_id = m_NextRecordingMenuID++; m_RecordingMenu->insertItem(SmallIcon("tderadio_record"), i18n("Stop Recording of %1").arg(descr), menu_id); m_MenuID2StreamID.insert(menu_id, id); m_StreamID2MenuID.insert(id, menu_id); btnRecording->setOn(true); if (id == queryCurrentSoundStreamID()) m_RecordingMenu->setItemEnabled(POPUP_ID_START_RECORDING_DEFAULT, false); return false; // this is only a "hook" that does not initiate the recording so don't say that we handled the event } bool RadioView::stopRecording (SoundStreamID id) { if (!id.isValid() || !m_StreamID2MenuID.contains(id)) return false; int menu_id = m_StreamID2MenuID[id]; m_RecordingMenu->removeItem(menu_id); m_MenuID2StreamID.remove(menu_id); m_StreamID2MenuID.remove(id); btnRecording->setOn(m_StreamID2MenuID.count() > 0); if (id == queryCurrentSoundStreamID()) m_RecordingMenu->setItemEnabled(POPUP_ID_START_RECORDING_DEFAULT, true); return false; } bool RadioView::noticeSoundStreamChanged(SoundStreamID id) { if (m_StreamID2MenuID.contains(id)) { TQString descr; querySoundStreamDescription(id, descr); m_RecordingMenu->changeItem(m_StreamID2MenuID[id], SmallIcon("tderadio_record"), i18n("Stop Recording of %1").arg(descr)); return true; } return false; } // ITimeControl bool RadioView::noticeCountdownStarted(const TQDateTime &) { btnSnooze->setOn(true); return true; } bool RadioView::noticeCountdownStopped() { btnSnooze->setOn(false); return true; } bool RadioView::noticeCountdownZero() { btnSnooze->setOn(false); return true; } // WidgetPluginBase void RadioView::saveState (TDEConfig *config) const { config->setGroup(TQString("radioview-") + name()); config->writeEntry("enableToobarFlag", enableToolbarFlag); WidgetPluginBase::saveState(config); for (ElementListIterator i(elements); i.current(); ++i) { RadioViewElement *e = i.current(); e->saveState(config); } } void RadioView::restoreState (TDEConfig *config) { config->setGroup(TQString("radioview-") + name()); enableToolbarFlag = config->readBoolEntry("enableToolbarFlag", false); WidgetPluginBase::restoreState(config); for (ElementListIterator i(elements); i.current(); ++i) { RadioViewElement *e = i.current(); e->restoreState(config); } } ConfigPageInfo RadioView::createConfigurationPage() { RadioViewConfiguration *c = new RadioViewConfiguration(); //addCommonConfigurationTab(c); for (ElementListIterator i(elements); i.current(); ++i) { addConfigurationTabFor(i.current(), c); } configPages.append(c); TQObject::connect(c, TQ_SIGNAL(destroyed(TQObject *)), this, TQ_SLOT(slotConfigPageDeleted(TQObject *))); return ConfigPageInfo( c, i18n("Display"), i18n("Display Configuration"), "openterm" ); } void RadioView::addConfigurationTabFor(RadioViewElement *e, TQTabWidget *c) { if (!e || !c) return; ConfigPageInfo inf = e->createConfigurationPage(); if (inf.page) { if (inf.iconName.length()) { c->addTab(inf.page, TQIconSet(SmallIconSet(inf.iconName)), inf.itemName); } else { c->addTab(inf.page, inf.itemName); } elementConfigPages.push_back(ElementCfg(e, inf.page)); TQObject::connect(inf.page, TQ_SIGNAL(destroyed(TQObject *)), this, TQ_SLOT(slotElementConfigPageDeleted(TQObject *))); } } void RadioView::addCommonConfigurationTab(TQTabWidget *c) { if (!c) return; TQFrame *f = new TQFrame(c); TQVBoxLayout *l = new TQVBoxLayout(f, 10); l->addWidget(new TQCheckBox(i18n("set Toolbar-Flag for Display"), f)); l->addItem(new TQSpacerItem(1, 3, TQSizePolicy::Fixed, TQSizePolicy::Expanding)); c->addTab(f, i18n("Common")); elementConfigPages.push_back(ElementCfg(f)); TQObject::connect(f, TQ_SIGNAL(destroyed(TQObject *)), this, TQ_SLOT(slotElementConfigPageDeleted(TQObject *))); } AboutPageInfo RadioView::createAboutPage() { /* TDEAboutData aboutData("tderadio", NULL, NULL, I18N_NOOP("Standard Radio Display for TDERadio"), TDEAboutData::License_GPL, "(c) 2002-2005 Martin Witte, Klas Kalass", 0, "http://sourceforge.net/projects/tderadio", 0); aboutData.addAuthor("Martin Witte", "", "witte@kawo1.rwth-aachen.de"); aboutData.addAuthor("Klas Kalass", "", "klas.kalass@gmx.de"); return AboutPageInfo( new TDERadioAboutWidget(aboutData, TDERadioAboutWidget::AbtTabbed), i18n("Display"), i18n("Standard Radio Display for TDERadio"), "openterm" );*/ return AboutPageInfo(); } void RadioView::noticeWidgetPluginShown(WidgetPluginBase *p, bool shown) { if (!m_manager || !p) return; if ((WidgetPluginBase*)m_manager->getConfigDialog() == p) { btnConfigure->blockSignals(true); btnConfigure->setOn(shown); btnConfigure->blockSignals(false); } if (m_Plugins2MenuID.contains(p)) { m_manager->updateWidgetPluginMenuItem(p, m_PluginMenu, m_Plugins2MenuID, shown); } } // own Stuff void RadioView::noticePluginsChanged(const PluginList &/*l*/) { m_Plugins2MenuID.clear(); m_PluginMenu->clear(); if (m_manager) m_manager->addWidgetPluginMenuItems(m_PluginMenu, m_Plugins2MenuID); } void RadioView::slotPower(bool on) { on ? sendPowerOn() : sendPowerOff(); btnPower->setOn(queryIsPowerOn()); } void RadioView::slotPause() { if (queryIsPowerOn()) { sendPausePlayback(queryCurrentSoundStreamID()); } } void RadioView::slotConfigure(bool b) { TQWidget *w = m_manager ? m_manager->getConfigDialog() : NULL; if (w) b ? w->show() : w->hide(); if (!w) btnConfigure->setOn(false); } void RadioView::slotRecord() { SoundStreamID id = queryCurrentSoundStreamID(); bool b = btnRecording->isOn(); bool r = false; SoundFormat sf; queryIsRecordingRunning(id, r, sf); if (!r && b /*!m_StreamID2MenuID.contains(id)*/) { if (!queryIsPowerOn()) sendPowerOn(); sendStartRecording(id); } else if (r && !b) { sendStopRecording(id); } } void RadioView::slotRecordingMenu(int i) { if (i == POPUP_ID_START_RECORDING_DEFAULT) { SoundStreamID id = queryCurrentSoundStreamID(); bool r = false; SoundFormat sf; queryIsRecordingRunning(id, r, sf); if (!r) { if (!queryIsPowerOn()) sendPowerOn(); sendStartRecording(id); } } else if (m_MenuID2StreamID.contains(i)) { sendStopRecording(m_MenuID2StreamID[i]); } } void RadioView::slotSnooze(bool on) { if (on) sendStartCountdown(); else sendStopCountdown(); } void RadioView::slotSnooze(int n) { sendCountdownSeconds(n*60); sendStartCountdown(); } void RadioView::slotComboStationSelected(int idx) { if (idx > 0) { sendActivateStation(idx - 1); } else { comboStations->setCurrentItem(queryCurrentStationIdx() + 1); } } void RadioView::slotBtnPluginsClicked() { btnPlugins->openPopup(); } void RadioView::slotConfigPageDeleted(TQObject *o) { configPages.remove(o); } void RadioView::slotElementConfigPageDeleted(TQObject *o) { ElementCfgListIterator it; while ((it = elementConfigPages.find(o)) != elementConfigPages.end()) { elementConfigPages.remove(it); } } void RadioView::show() { if (enableToolbarFlag) KWin::setType(winId(), NET::Toolbar); else KWin::setType(winId(), NET::Normal); WidgetPluginBase::pShow(); TQWidget::show(); } void RadioView::showOnOrgDesktop() { WidgetPluginBase::pShowOnOrgDesktop(); //TQWidget::show(); } void RadioView::hide() { WidgetPluginBase::pHide(); TQWidget::hide(); } void RadioView::showEvent(TQShowEvent *e) { TQWidget::showEvent(e); WidgetPluginBase::pShowEvent(e); } void RadioView::hideEvent(TQHideEvent *e) { TQWidget::hideEvent(e); WidgetPluginBase::pHideEvent(e); } void RadioView::autoSetCaption() { const RadioStation &rs = queryCurrentStation(); setCaption((queryIsPowerOn() && rs.isValid()) ? rs.longName() : TQString("TDERadio")); } #include "radioview.moc"