/*************************************************************************** radio.cpp - description ------------------- begin : Sat March 29 2003 copyright : (C) 2003 by Klas Kalass, Ernst Martin Witte email : klas@kde.org, 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 "../../src/include/radiostation.h" #include "../../src/include/aboutwidget.h" #include "../../src/include/radiodevice_interfaces.h" #include "radio.h" #include "radio-configuration.h" #include #include #include #include #include "../../src/include/debug-profiler.h" /////////////////////////////////////////////////////////////////////// //// plugin library functions PLUGIN_LIBRARY_FUNCTIONS(Radio, "kradio-radio", i18n("Central Radio Device Multiplexer")); ///////////////////////////////////////////////////////////////////////////// Radio::Radio(const TQString &name) : PluginBase(name, i18n("Radio Multiplexer Plugin")), IRadioDeviceClient(-1), m_presetFile(locateLocal("data", "kradio/stations.krp")), m_activeDevice (NULL) { } Radio::~Radio() { } bool Radio::connectI (Interface *i) { bool a = IRadio::connectI(i); bool b = IRadioDeviceClient::connectI(i); bool c = IRadioDevicePool::connectI(i); bool d = PluginBase::connectI(i); bool e = ISoundStreamClient::connectI(i); // no "return IA::connectI() | return IB::connnectI to // prevent "early termination" optimization in boolean expressions return a || b || c || d || e; } bool Radio::disconnectI (Interface *i) { bool a = IRadio::disconnectI(i); bool b = IRadioDeviceClient::disconnectI(i); bool c = IRadioDevicePool::disconnectI(i); bool d = PluginBase::disconnectI(i); bool e = ISoundStreamClient::disconnectI(i); // no "return IA::disconnectI() | return IB::disconnnectI to // prevent "early termination" optimization in boolean expressions return a || b || c || d || e; } void Radio::saveState (KConfig *config) const { config->setGroup(TQString("radio-") + name()); config->writeEntry("presetfile", m_presetFile); m_stationList.writeXML(m_presetFile, *this); } void Radio::restoreState (KConfig *config) { config->setGroup(TQString("radio-") + name()); m_presetFile = config->readEntry("presetfile", TQString()); bool first_restore = false; if (m_presetFile.isNull() || m_presetFile.length() == 0) { m_presetFile = locateLocal("data", "kradio/stations.krp"); first_restore = true; } m_stationList.readXML(KURL(m_presetFile), *this, /*enable-messagebox*/ !first_restore); notifyStationsChanged(m_stationList); notifyPresetFileChanged(m_presetFile); } ConfigPageInfo Radio::createConfigurationPage() { RadioConfiguration *conf = new RadioConfiguration (NULL, *this); connectI (conf); return ConfigPageInfo( conf, i18n("Radio Stations"), i18n("Setup Radio Stations"), "kradio" ); } AboutPageInfo Radio::createAboutPage() { /* KAboutData aboutData("kradio", NULL, NULL, I18N_NOOP("Radio Device Multiplexer and Station Management for KRadio"), KAboutData::License_GPL, "(c) 2002-2005 Martin Witte, Klas Kalass", 0, "http://sourceforge.net/projects/kradio", 0); aboutData.addAuthor("Martin Witte", "", "witte@kawo1.rwth-aachen.de"); aboutData.addAuthor("Klas Kalass", "", "klas.kalass@gmx.de"); return AboutPageInfo( new KRadioAboutWidget(aboutData, KRadioAboutWidget::AbtTabbed), i18n("Device and Station Management"), i18n("Radio Device Multiplexer and Station Management"), "kradio" ); */ return AboutPageInfo(); } /* IRadio Interface Methods */ /* offer new station to current device. if that does not accept, try all other devices. Any device will be powered off if it does not accept the station */ bool Radio::activateStation (const RadioStation &rs) { if (sendActivateStation(rs)) { // first try activeDevice return true; } else { // hmm... active device did not want it. Try others... int n = 0; for (IRadioDeviceClient::IFIterator it(IRadioDeviceClient::iConnections); it.current(); ++it) { if (it.current()->activateStation(rs)) { setActiveDevice(it.current()); // select new device ++n; } else { it.current()->powerOff(); } } return n > 0; } } bool Radio::activateStation(int index) { if (index < 0 || index >= m_stationList.count()) return false; return activateStation(m_stationList.at(index)); } bool Radio::setStations(const StationList &sl) { if (true/*m_stationList != sl*/) { BlockProfiler("Radio::setStations"); m_stationList = sl; notifyStationsChanged(m_stationList); } return true; } bool Radio::setPresetFile(const TQString &presetFile) { if (m_presetFile != presetFile) { m_presetFile = presetFile; notifyPresetFileChanged(m_presetFile); } return true; } int Radio::getStationIdx(const RadioStation &rs) const { RawStationList &sl = const_cast(m_stationList.all()); return sl.tqfind(&rs); } int Radio::getCurrentStationIdx() const { return getStationIdx(getCurrentStation()); } SoundStreamID Radio::getCurrentSoundStreamID() const { return queryCurrentSoundStreamID(); } /* IRadioDevicePool Interface Methods */ bool Radio::setActiveDevice(IRadioDevice *rd, bool keepPower) { // do nothing if old == new if (m_activeDevice == rd) return true; // check if new station is in "connections" // special case: rd == NULL: power off active device, new active device = NULL if (!rd || IRadioDeviceClient::iConnections.tqcontainsRef(rd)) { // new device is ok // save old power state and power off old device bool oldPowerOn = false; if (m_activeDevice) { oldPowerOn = m_activeDevice->isPowerOn(); m_activeDevice->powerOff(); } // setup new active device && send notifications m_activeDevice = rd; // send notifications notifyActiveDeviceChanged(m_activeDevice); notifyCurrentSoundStreamIDChanged(queryCurrentSoundStreamID()); const RadioStation &rs = queryCurrentStation(); notifyStationChanged(rs, getStationIdx(rs)); if (keepPower) oldPowerOn ? sendPowerOn() : sendPowerOff(); return true; } else { return false; } } IRadioDevice *Radio::getActiveDevice() const { return m_activeDevice; } const TQPtrList &Radio::getDevices() const { return IRadioDeviceClient::iConnections; } const TQString &Radio::getDeviceDescription() const { return queryDescription(); } /* IRadioDeviceClient Interface Methods Many things are overwritten, particularly all sending methods */ int Radio::sendPowerOn() const { return m_activeDevice ? m_activeDevice->powerOn() : 0; } int Radio::sendPowerOff() const { return m_activeDevice ? m_activeDevice->powerOff() : 0; } int Radio::sendActivateStation (const RadioStation &rs) const { return m_activeDevice ? m_activeDevice->activateStation(rs) : 0; } bool Radio::queryIsPowerOn() const { return m_activeDevice ? m_activeDevice->isPowerOn() : false; } bool Radio::queryIsPowerOff() const { return m_activeDevice ? m_activeDevice->isPowerOff() : true; } const RadioStation & Radio::queryCurrentStation() const { if (m_activeDevice) { RadioStation &rs = const_cast(m_activeDevice->getCurrentStation()); int idx = getStationIdx(rs); if (idx >= 0) { rs.copyDescriptionFrom(m_stationList.at(idx)); } else { rs.copyDescriptionFrom(undefinedRadioStation); } return rs; } else { return undefinedRadioStation; } } static TQString qstrUnknown(I18N_NOOP("unknown")); static TQString i18nqstrUnknown; const TQString &Radio::queryDescription() const { return m_activeDevice ? m_activeDevice->getDescription() : (i18nqstrUnknown = i18n(qstrUnknown.ascii())); } bool Radio::noticePowerChanged (bool on, const IRadioDevice *sender) { if (on) { setActiveDevice(const_cast(sender), false); // false: do not set power state on new device // constcast valid because power-state of sender is not changed notifyPowerChanged(true); return true; } else { if (sender == m_activeDevice) { sendStopCountdown(); notifyPowerChanged(false); return true; } return false; } } bool Radio::noticeStationChanged (const RadioStation &_rs, const IRadioDevice *sender) { RadioStation &rs = const_cast(_rs); int idx = getStationIdx(rs); RadioStation &known = (idx >= 0) ? (RadioStation&)m_stationList.at(idx) : (RadioStation&)undefinedRadioStation; rs.copyDescriptionFrom(known); if (sender == m_activeDevice) notifyStationChanged(rs, idx); return true; } bool Radio::noticeDescriptionChanged (const TQString &s, const IRadioDevice *sender) { if (sender == m_activeDevice) notifyDeviceDescriptionChanged(s); return true; } bool Radio::noticeCurrentSoundStreamIDChanged(SoundStreamID id, const IRadioDevice *sender) { if (sender == m_activeDevice) notifyCurrentSoundStreamIDChanged(id); return true; } SoundStreamID Radio::queryCurrentSoundStreamID() const { return m_activeDevice ? m_activeDevice->getCurrentSoundStreamID() : SoundStreamID::InvalidID; } void Radio::noticeConnectedI(IRadioDeviceClient::cmplInterface *dev, bool pointer_valid) { IRadioDeviceClient::noticeConnectedI(dev, pointer_valid); if (! m_activeDevice && pointer_valid) setActiveDevice (dev, false); notifyDevicesChanged(IRadioDeviceClient::iConnections); } void Radio::noticeDisconnectI(IRadioDeviceClient::cmplInterface *rd, bool pointer_valid) { IRadioDeviceClient::noticeDisconnectI(rd, pointer_valid); if (rd == m_activeDevice) { // search a new active device if (IRadioDeviceClient::iConnections.tqfindRef(rd) >= 0) { IRadioDevice *new_rd = NULL; new_rd = IRadioDeviceClient::iConnections.next(); // choose next device as active device if next exists if (!new_rd) { IRadioDeviceClient::iConnections.tqfindRef(rd); new_rd = IRadioDeviceClient::iConnections.prev(); // otherwise try prev then, may be NULL (no connections) } setActiveDevice(new_rd); } else { // strange error occurred, m_activeDevice not in connections... set to first. setActiveDevice(IRadioDeviceClient::iConnections.first()); } } notifyDevicesChanged(IRadioDeviceClient::iConnections); } // ITimeControlClient bool Radio::noticeAlarm(const Alarm &a) { if (a.alarmType() == Alarm::StartPlaying || a.alarmType() == Alarm::StartRecording) { const RawStationList &sl = getStations().all(); const RadioStation &rs = sl.stationWithID(a.stationID()); activateStation(rs); powerOn(); if (a.volumePreset() >= 0) sendPlaybackVolume(getCurrentSoundStreamID(), a.volumePreset()); SoundStreamID id = getCurrentSoundStreamID(); bool r = false; SoundFormat sf; queryIsRecordingRunning(id, r, sf); if (a.alarmType() == Alarm::StartRecording && !r) sendStartRecording(id); } else { powerOff(); } return true; } bool Radio::noticeCountdownZero() { powerOff(); return true; } void Radio::aboutToQuit() { sendPowerOff(); }