File indexing completed on 2024-04-21 04:54:25
0001 /* 0002 * 0003 * Copyright (C) 2004-2007 Matthias Kretz <kretz@kde.org> 0004 * Copyright (C) by Alexander Kern <alex.kern@gmx.de> 0005 * 0006 * This library is free software; you can redistribute it and/or 0007 * modify it under the terms of the GNU Library General Public 0008 * License as published by the Free Software Foundation; either 0009 * version 2 of the License, or (at your option) any later version. 0010 * 0011 * This library is distributed in the hope that it will be useful, 0012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0014 * Library General Public License for more details. 0015 * 0016 * You should have received a copy of the GNU Library General Public 0017 * License along with this library; if not, write to the Free 0018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 0019 * 0020 * 0021 * CDDA version taken from guitest in phonon test directory 0022 */ 0023 0024 #include "phonon_interface.h" 0025 0026 #include <QtGlobal> 0027 0028 #include <KLocalizedString> 0029 0030 #include <phonon/Global> 0031 #include <phonon/MediaObject> 0032 #include <phonon/AudioOutput> 0033 #include <phonon/Path> 0034 #include <phonon/MediaController> 0035 0036 #include <Solid/Device> 0037 #include <Solid/OpticalDrive> 0038 #include <Solid/OpticalDisc> 0039 0040 #define WM_MSG_CLASS WM_MSG_CLASS_PLATFORM 0041 0042 using namespace Phonon; 0043 0044 class ProducerWidget : public QObject 0045 { 0046 public: 0047 ProducerWidget(KPhononCompactDiscPrivate *, const QString &); 0048 ~ProducerWidget() override; 0049 0050 public: 0051 MediaObject *m_media; 0052 AudioOutput *m_output; 0053 MediaController *m_mediaController; 0054 }; 0055 0056 ProducerWidget::ProducerWidget(KPhononCompactDiscPrivate *p, const QString &Udi) : 0057 m_media(nullptr), 0058 m_output(nullptr), 0059 m_mediaController(nullptr) 0060 { 0061 m_media = new MediaObject(this); 0062 connect(m_media, SIGNAL(metaDataChanged()), SLOT(updateMetaData())); 0063 m_media->setTickInterval(1000); 0064 0065 m_output = new AudioOutput(Phonon::MusicCategory, this); 0066 Phonon::createPath(m_media, m_output); 0067 0068 connect(m_media, SIGNAL(stateChanged(Phonon::State,Phonon::State)), 0069 p, SLOT(stateChanged(Phonon::State,Phonon::State))); 0070 0071 connect(m_media, SIGNAL(tick(qint64)), p, SLOT(tick(qint64))); 0072 0073 MediaSource *m_mediaSource = new MediaSource(Phonon::Cd, Udi); 0074 m_media->setCurrentSource(*m_mediaSource); 0075 0076 m_mediaController = new MediaController(m_media); 0077 } 0078 0079 ProducerWidget::~ProducerWidget() 0080 { 0081 delete(m_mediaController); 0082 delete(m_output); 0083 delete(m_media); 0084 } 0085 0086 KPhononCompactDiscPrivate::KPhononCompactDiscPrivate(KCompactDisc *p, 0087 const QString &dev) : 0088 KCompactDiscPrivate(p, dev), 0089 m_producerWidget(nullptr), 0090 m_udi(KCompactDisc::cdromDeviceUdi(dev)) 0091 { 0092 m_interface = QLatin1String("phonon"); 0093 } 0094 0095 KPhononCompactDiscPrivate::~KPhononCompactDiscPrivate() 0096 { 0097 delete m_producerWidget; 0098 m_producerWidget = nullptr; 0099 } 0100 0101 bool KPhononCompactDiscPrivate::createInterface() 0102 { 0103 qDebug() << "createInterface called"; 0104 Solid::Device opticalDevice(m_udi); 0105 Solid::OpticalDrive *opticalDrive = opticalDevice.as<Solid::OpticalDrive>(); 0106 0107 if(opticalDrive) { 0108 Q_Q(KCompactDisc); 0109 0110 m_deviceVendor = opticalDevice.vendor(); 0111 m_deviceModel = opticalDevice.product(); 0112 0113 Q_EMIT q->discChanged(0); 0114 0115 producer(); 0116 0117 return true; 0118 } 0119 0120 return false; 0121 } 0122 0123 ProducerWidget *KPhononCompactDiscPrivate::producer() 0124 { 0125 //try to create 0126 if(!m_producerWidget) { 0127 Solid::Device opticalDevice(m_udi); 0128 Solid::OpticalDrive *opticalDrive = opticalDevice.as<Solid::OpticalDrive>(); 0129 qDebug() << "producer called, opticalDrive is " << opticalDrive; 0130 0131 if(opticalDrive) { 0132 Solid::OpticalDisc *opticalDisc = opticalDevice.as<Solid::OpticalDisc>(); 0133 qDebug() << "opticalDisc " << opticalDisc; 0134 //if(opticalDisc && (opticalDisc->availableContent() == Solid::OpticalDisc::Audio)) { 0135 m_producerWidget = new ProducerWidget(this, m_udi); 0136 stateChanged(m_producerWidget->m_media->state(), Phonon::StoppedState); 0137 //} 0138 } 0139 } 0140 0141 return m_producerWidget; 0142 } 0143 0144 unsigned KPhononCompactDiscPrivate::trackLength(unsigned track) 0145 { 0146 if(!producer() || m_producerWidget->m_mediaController->currentTitle() != track) 0147 return 0; 0148 0149 return MS2SEC(m_producerWidget->m_media->totalTime()); 0150 } 0151 0152 bool KPhononCompactDiscPrivate::isTrackAudio(unsigned) 0153 { 0154 return true; 0155 } 0156 0157 void KPhononCompactDiscPrivate::playTrackPosition(unsigned track, unsigned position) 0158 { 0159 if(!producer()) 0160 return; 0161 0162 qDebug() << "play track " << track << " position " << position; 0163 0164 m_producerWidget->m_mediaController->setCurrentTitle(track); 0165 m_producerWidget->m_media->seek(SEC2MS(position)); 0166 Q_EMIT m_producerWidget->m_media->play(); 0167 } 0168 0169 void KPhononCompactDiscPrivate::pause() 0170 { 0171 if(!producer()) 0172 return; 0173 0174 Q_EMIT m_producerWidget->m_media->pause(); 0175 } 0176 0177 void KPhononCompactDiscPrivate::stop() 0178 { 0179 if(!producer()) 0180 return; 0181 0182 Q_EMIT m_producerWidget->m_media->stop(); 0183 } 0184 0185 void KPhononCompactDiscPrivate::eject() 0186 { 0187 Solid::Device opticalDevice(m_udi); 0188 Solid::OpticalDrive *opticalDrive = opticalDevice.as<Solid::OpticalDrive>(); 0189 Solid::OpticalDisc *opticalDisc = opticalDevice.as<Solid::OpticalDisc>(); 0190 0191 if(!opticalDrive || !opticalDisc) 0192 return; 0193 0194 opticalDrive->eject(); 0195 } 0196 0197 void KPhononCompactDiscPrivate::closetray() 0198 { 0199 Solid::Device opticalDevice(m_udi); 0200 Solid::OpticalDrive *opticalDrive = opticalDevice.as<Solid::OpticalDrive>(); 0201 Solid::OpticalDisc *opticalDisc = opticalDevice.as<Solid::OpticalDisc>(); 0202 0203 if(!opticalDrive || opticalDisc) 0204 return; 0205 0206 opticalDrive->eject(); 0207 } 0208 0209 void KPhononCompactDiscPrivate::setVolume(unsigned volume) 0210 { 0211 if(!producer()) 0212 return; 0213 0214 /* 1.0 = 100% */ 0215 m_producerWidget->m_output->setVolume(volume * 0.01); 0216 } 0217 0218 void KPhononCompactDiscPrivate::setBalance(unsigned) 0219 { 0220 } 0221 0222 unsigned KPhononCompactDiscPrivate::volume() 0223 { 0224 if(!producer()) 0225 return 0; 0226 0227 return (unsigned)(m_producerWidget->m_output->volume() * 100.0); 0228 } 0229 0230 unsigned KPhononCompactDiscPrivate::balance() 0231 { 0232 return 50; 0233 } 0234 0235 void KPhononCompactDiscPrivate::queryMetadata() 0236 { 0237 Q_Q(KCompactDisc); 0238 0239 if(!producer()) 0240 return; 0241 0242 QMultiMap<QString, QString> data = m_producerWidget->m_media->metaData(); 0243 qDebug() << "METADATA"; 0244 //qDebug() << data; 0245 0246 m_trackArtists[0] = data.take(QLatin1String( "ARTIST" )); 0247 m_trackTitles[0] = data.take(QLatin1String( "ALBUM" )); 0248 0249 m_trackArtists[m_track] = data.take(QLatin1String( "ARTIST" )); 0250 m_trackTitles[m_track] = data.take(QLatin1String( "TITLE" )); 0251 0252 Q_EMIT q->discInformation(KCompactDisc::PhononMetadata); 0253 } 0254 0255 KCompactDisc::DiscStatus KPhononCompactDiscPrivate::discStatusTranslate(Phonon::State state) 0256 { 0257 switch (state) { 0258 case Phonon::PlayingState: 0259 return KCompactDisc::Playing; 0260 case Phonon::PausedState: 0261 return KCompactDisc::Paused; 0262 case Phonon::StoppedState: 0263 return KCompactDisc::Stopped; 0264 case Phonon::ErrorState: 0265 return KCompactDisc::NoDisc; 0266 case Phonon::LoadingState: 0267 case Phonon::BufferingState: 0268 return KCompactDisc::NotReady; 0269 default: 0270 return KCompactDisc::Error; 0271 } 0272 } 0273 0274 void KPhononCompactDiscPrivate::tick(qint64 t) 0275 { 0276 unsigned track; 0277 Q_Q(KCompactDisc); 0278 0279 track = m_producerWidget->m_mediaController->currentTitle(); 0280 if(track != m_track) { 0281 m_track = track; 0282 m_discLength = trackLength(m_track); 0283 Q_EMIT q->playoutTrackChanged(m_track); 0284 0285 /* phonon gives us Metadata only per Track */ 0286 if(m_autoMetadata) 0287 queryMetadata(); 0288 } 0289 0290 m_trackPosition = MS2SEC(t); 0291 m_discPosition = m_trackPosition; 0292 // Update the current playing position. 0293 if(m_seek) { 0294 qDebug() << "seek: " << m_seek << " trackPosition " << m_trackPosition; 0295 if(abs((long)(m_trackExpectedPosition - m_trackPosition)) > m_seek) 0296 m_seek = 0; 0297 else 0298 m_seek = abs((long)(m_trackExpectedPosition - m_trackPosition)); 0299 } 0300 0301 if(!m_seek) { 0302 Q_EMIT q->playoutPositionChanged(m_trackPosition); 0303 } 0304 } 0305 0306 void KPhononCompactDiscPrivate::stateChanged(Phonon::State newstate, Phonon::State) 0307 { 0308 qDebug() << "stateChanged with state " << newstate; 0309 KCompactDisc::DiscStatus status; 0310 Q_Q(KCompactDisc); 0311 0312 status = discStatusTranslate(newstate); 0313 0314 if(m_status != status) { 0315 if(skipStatusChange(status)) 0316 return; 0317 0318 m_status = status; 0319 0320 switch(m_status) { 0321 case KCompactDisc::Ejected: 0322 case KCompactDisc::NoDisc: 0323 clearDiscInfo(); 0324 break; 0325 default: 0326 if(m_tracks == 0) { 0327 m_tracks = m_producerWidget->m_mediaController->availableTitles(); 0328 qDebug() << "Got " << m_tracks << " tracks from media controller"; 0329 if(m_tracks > 0) { 0330 qDebug() << "New disc with " << m_tracks << " tracks"; 0331 0332 make_playlist(); 0333 0334 m_trackArtists.append(i18n("Unknown Artist")); 0335 m_trackTitles.append(i18n("Unknown Title")); 0336 for(unsigned i = 1; i <= m_tracks; ++i) { 0337 m_trackArtists.append(i18n("Unknown Artist")); 0338 m_trackTitles.append(ki18n("Track %1").subs(i, 2).toString()); 0339 } 0340 0341 Q_EMIT q->discChanged(m_tracks); 0342 0343 if(m_autoMetadata) 0344 queryMetadata(); 0345 } 0346 } 0347 0348 break; 0349 } 0350 } 0351 } 0352 0353 #include "moc_phonon_interface.cpp"