KCompactDisc

phonon_interface.cpp
1 /*
2  *
3  * Copyright (C) 2004-2007 Matthias Kretz <[email protected]>
4  * Copyright (C) by Alexander Kern <[email protected]>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public
17  * License along with this library; if not, write to the Free
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  *
20  *
21  * CDDA version taken from guitest in phonon test directory
22  */
23 
24 #include "phonon_interface.h"
25 
26 #include <QtGlobal>
27 
28 #include <KLocalizedString>
29 
30 #include <phonon/Global>
31 #include <phonon/MediaObject>
32 #include <phonon/AudioOutput>
33 #include <phonon/Path>
34 #include <phonon/MediaController>
35 
36 #include <Solid/Device>
37 #include <Solid/OpticalDrive>
38 #include <Solid/OpticalDisc>
39 
40 #define WM_MSG_CLASS WM_MSG_CLASS_PLATFORM
41 
42 using namespace Phonon;
43 
44 class ProducerWidget : public QObject
45 {
46  public:
47  ProducerWidget(KPhononCompactDiscPrivate *, const QString &);
48  ~ProducerWidget() override;
49 
50  public:
51  MediaObject *m_media;
52  AudioOutput *m_output;
53  MediaController *m_mediaController;
54 };
55 
56 ProducerWidget::ProducerWidget(KPhononCompactDiscPrivate *p, const QString &Udi) :
57  m_media(nullptr),
58  m_output(nullptr),
59  m_mediaController(nullptr)
60 {
61  m_media = new MediaObject(this);
62  connect(m_media, SIGNAL(metaDataChanged()), SLOT(updateMetaData()));
63  m_media->setTickInterval(1000);
64 
65  m_output = new AudioOutput(Phonon::MusicCategory, this);
66  Phonon::createPath(m_media, m_output);
67 
68  connect(m_media, SIGNAL(stateChanged(Phonon::State,Phonon::State)),
69  p, SLOT(stateChanged(Phonon::State,Phonon::State)));
70 
71  connect(m_media, SIGNAL(tick(qint64)), p, SLOT(tick(qint64)));
72 
73  MediaSource *m_mediaSource = new MediaSource(Phonon::Cd, Udi);
74  m_media->setCurrentSource(*m_mediaSource);
75 
76  m_mediaController = new MediaController(m_media);
77 }
78 
79 ProducerWidget::~ProducerWidget()
80 {
81  delete(m_mediaController);
82  delete(m_output);
83  delete(m_media);
84 }
85 
86 KPhononCompactDiscPrivate::KPhononCompactDiscPrivate(KCompactDisc *p,
87  const QString &dev) :
88  KCompactDiscPrivate(p, dev),
89  m_producerWidget(nullptr),
90  m_udi(KCompactDisc::cdromDeviceUdi(dev))
91 {
92  m_interface = QLatin1String("phonon");
93 }
94 
95 KPhononCompactDiscPrivate::~KPhononCompactDiscPrivate()
96 {
97  delete m_producerWidget;
98  m_producerWidget = nullptr;
99 }
100 
101 bool KPhononCompactDiscPrivate::createInterface()
102 {
103  qDebug() << "createInterface called";
104  Solid::Device opticalDevice(m_udi);
105  Solid::OpticalDrive *opticalDrive = opticalDevice.as<Solid::OpticalDrive>();
106 
107  if(opticalDrive) {
108  Q_Q(KCompactDisc);
109 
110  m_deviceVendor = opticalDevice.vendor();
111  m_deviceModel = opticalDevice.product();
112 
113  Q_EMIT q->discChanged(0);
114 
115  producer();
116 
117  return true;
118  }
119 
120  return false;
121 }
122 
123 ProducerWidget *KPhononCompactDiscPrivate::producer()
124 {
125  //try to create
126  if(!m_producerWidget) {
127  Solid::Device opticalDevice(m_udi);
128  Solid::OpticalDrive *opticalDrive = opticalDevice.as<Solid::OpticalDrive>();
129  qDebug() << "producer called, opticalDrive is " << opticalDrive;
130 
131  if(opticalDrive) {
132  Solid::OpticalDisc *opticalDisc = opticalDevice.as<Solid::OpticalDisc>();
133  qDebug() << "opticalDisc " << opticalDisc;
134  //if(opticalDisc && (opticalDisc->availableContent() == Solid::OpticalDisc::Audio)) {
135  m_producerWidget = new ProducerWidget(this, m_udi);
136  stateChanged(m_producerWidget->m_media->state(), Phonon::StoppedState);
137  //}
138  }
139  }
140 
141  return m_producerWidget;
142 }
143 
144 unsigned KPhononCompactDiscPrivate::trackLength(unsigned track)
145 {
146  if(!producer() || m_producerWidget->m_mediaController->currentTitle() != track)
147  return 0;
148 
149  return MS2SEC(m_producerWidget->m_media->totalTime());
150 }
151 
152 bool KPhononCompactDiscPrivate::isTrackAudio(unsigned)
153 {
154  return true;
155 }
156 
157 void KPhononCompactDiscPrivate::playTrackPosition(unsigned track, unsigned position)
158 {
159  if(!producer())
160  return;
161 
162  qDebug() << "play track " << track << " position " << position;
163 
164  m_producerWidget->m_mediaController->setCurrentTitle(track);
165  m_producerWidget->m_media->seek(SEC2MS(position));
166  Q_EMIT m_producerWidget->m_media->play();
167 }
168 
169 void KPhononCompactDiscPrivate::pause()
170 {
171  if(!producer())
172  return;
173 
174  Q_EMIT m_producerWidget->m_media->pause();
175 }
176 
177 void KPhononCompactDiscPrivate::stop()
178 {
179  if(!producer())
180  return;
181 
182  Q_EMIT m_producerWidget->m_media->stop();
183 }
184 
185 void KPhononCompactDiscPrivate::eject()
186 {
187  Solid::Device opticalDevice(m_udi);
188  Solid::OpticalDrive *opticalDrive = opticalDevice.as<Solid::OpticalDrive>();
189  Solid::OpticalDisc *opticalDisc = opticalDevice.as<Solid::OpticalDisc>();
190 
191  if(!opticalDrive || !opticalDisc)
192  return;
193 
194  opticalDrive->eject();
195 }
196 
197 void KPhononCompactDiscPrivate::closetray()
198 {
199  Solid::Device opticalDevice(m_udi);
200  Solid::OpticalDrive *opticalDrive = opticalDevice.as<Solid::OpticalDrive>();
201  Solid::OpticalDisc *opticalDisc = opticalDevice.as<Solid::OpticalDisc>();
202 
203  if(!opticalDrive || opticalDisc)
204  return;
205 
206  opticalDrive->eject();
207 }
208 
209 void KPhononCompactDiscPrivate::setVolume(unsigned volume)
210 {
211  if(!producer())
212  return;
213 
214  /* 1.0 = 100% */
215  m_producerWidget->m_output->setVolume(volume * 0.01);
216 }
217 
218 void KPhononCompactDiscPrivate::setBalance(unsigned)
219 {
220 }
221 
222 unsigned KPhononCompactDiscPrivate::volume()
223 {
224  if(!producer())
225  return 0;
226 
227  return (unsigned)(m_producerWidget->m_output->volume() * 100.0);
228 }
229 
230 unsigned KPhononCompactDiscPrivate::balance()
231 {
232  return 50;
233 }
234 
235 void KPhononCompactDiscPrivate::queryMetadata()
236 {
237  Q_Q(KCompactDisc);
238 
239  if(!producer())
240  return;
241 
242  QMultiMap<QString, QString> data = m_producerWidget->m_media->metaData();
243  qDebug() << "METADATA";
244  //qDebug() << data;
245 
246  m_trackArtists[0] = data.take(QLatin1String( "ARTIST" ));
247  m_trackTitles[0] = data.take(QLatin1String( "ALBUM" ));
248 
249  m_trackArtists[m_track] = data.take(QLatin1String( "ARTIST" ));
250  m_trackTitles[m_track] = data.take(QLatin1String( "TITLE" ));
251 
252  Q_EMIT q->discInformation(KCompactDisc::PhononMetadata);
253 }
254 
255 KCompactDisc::DiscStatus KPhononCompactDiscPrivate::discStatusTranslate(Phonon::State state)
256 {
257  switch (state) {
258  case Phonon::PlayingState:
259  return KCompactDisc::Playing;
260  case Phonon::PausedState:
261  return KCompactDisc::Paused;
262  case Phonon::StoppedState:
263  return KCompactDisc::Stopped;
264  case Phonon::ErrorState:
265  return KCompactDisc::NoDisc;
266  case Phonon::LoadingState:
267  case Phonon::BufferingState:
268  return KCompactDisc::NotReady;
269  default:
270  return KCompactDisc::Error;
271  }
272 }
273 
274 void KPhononCompactDiscPrivate::tick(qint64 t)
275 {
276  unsigned track;
277  Q_Q(KCompactDisc);
278 
279  track = m_producerWidget->m_mediaController->currentTitle();
280  if(track != m_track) {
281  m_track = track;
282  m_discLength = trackLength(m_track);
283  Q_EMIT q->playoutTrackChanged(m_track);
284 
285  /* phonon gives us Metadata only per Track */
286  if(m_autoMetadata)
287  queryMetadata();
288  }
289 
290  m_trackPosition = MS2SEC(t);
291  m_discPosition = m_trackPosition;
292  // Update the current playing position.
293  if(m_seek) {
294  qDebug() << "seek: " << m_seek << " trackPosition " << m_trackPosition;
295  if(abs((long)(m_trackExpectedPosition - m_trackPosition)) > m_seek)
296  m_seek = 0;
297  else
298  m_seek = abs((long)(m_trackExpectedPosition - m_trackPosition));
299  }
300 
301  if(!m_seek) {
302  Q_EMIT q->playoutPositionChanged(m_trackPosition);
303  }
304 }
305 
306 void KPhononCompactDiscPrivate::stateChanged(Phonon::State newstate, Phonon::State)
307 {
308  qDebug() << "stateChanged with state " << newstate;
309  KCompactDisc::DiscStatus status;
310  Q_Q(KCompactDisc);
311 
312  status = discStatusTranslate(newstate);
313 
314  if(m_status != status) {
315  if(skipStatusChange(status))
316  return;
317 
318  m_status = status;
319 
320  switch(m_status) {
321  case KCompactDisc::Ejected:
322  case KCompactDisc::NoDisc:
323  clearDiscInfo();
324  break;
325  default:
326  if(m_tracks == 0) {
327  m_tracks = m_producerWidget->m_mediaController->availableTitles();
328  qDebug() << "Got " << m_tracks << " tracks from media controller";
329  if(m_tracks > 0) {
330  qDebug() << "New disc with " << m_tracks << " tracks";
331 
332  make_playlist();
333 
334  m_trackArtists.append(i18n("Unknown Artist"));
335  m_trackTitles.append(i18n("Unknown Title"));
336  for(unsigned i = 1; i <= m_tracks; ++i) {
337  m_trackArtists.append(i18n("Unknown Artist"));
338  m_trackTitles.append(ki18n("Track %1").subs(i, 2).toString());
339  }
340 
341  Q_EMIT q->discChanged(m_tracks);
342 
343  if(m_autoMetadata)
344  queryMetadata();
345  }
346  }
347 
348  break;
349  }
350  }
351 }
static const QString cdromDeviceUdi(const QString &)
The Udi of named CDROM device for this system.
unsigned track()
Current track.
unsigned trackLength()
Length of current track.
KCompactDisc - A CD drive interface for the KDE Project.
Definition: kcompactdisc.h:86
QString i18n(const char *text, const TYPE &arg...)
char * toString(const T &value)
KLocalizedString KI18N_EXPORT ki18n(const char *text)
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
T take(const Key &key)
Q_EMITQ_EMIT
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Mon Oct 18 2021 23:23:11 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.