KCompactDisc

phonon_interface.cpp
1/*
2 *
3 * Copyright (C) 2004-2007 Matthias Kretz <kretz@kde.org>
4 * Copyright (C) by Alexander Kern <alex.kern@gmx.de>
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
42using namespace Phonon;
43
44class 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
56ProducerWidget::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
79ProducerWidget::~ProducerWidget()
80{
81 delete(m_mediaController);
82 delete(m_output);
83 delete(m_media);
84}
85
86KPhononCompactDiscPrivate::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
95KPhononCompactDiscPrivate::~KPhononCompactDiscPrivate()
96{
97 delete m_producerWidget;
98 m_producerWidget = nullptr;
99}
100
101bool 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
123ProducerWidget *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
144unsigned 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
152bool KPhononCompactDiscPrivate::isTrackAudio(unsigned)
153{
154 return true;
155}
156
157void 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
169void KPhononCompactDiscPrivate::pause()
170{
171 if(!producer())
172 return;
173
174 Q_EMIT m_producerWidget->m_media->pause();
175}
176
177void KPhononCompactDiscPrivate::stop()
178{
179 if(!producer())
180 return;
181
182 Q_EMIT m_producerWidget->m_media->stop();
183}
184
185void 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
197void 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
209void 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
218void KPhononCompactDiscPrivate::setBalance(unsigned)
219{
220}
221
222unsigned KPhononCompactDiscPrivate::volume()
223{
224 if(!producer())
225 return 0;
226
227 return (unsigned)(m_producerWidget->m_output->volume() * 100.0);
228}
229
230unsigned KPhononCompactDiscPrivate::balance()
231{
232 return 50;
233}
234
235void 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
255KCompactDisc::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
274void 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
306void 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}
352
353#include "moc_phonon_interface.cpp"
KCompactDisc - A CD drive interface for the KDE Project.
void setCurrentTitle(int titleNumber)
State state() const
QMultiMap< QString, QString > metaData() const
void seek(qint64 time)
qint64 totalTime() const
Q_SCRIPTABLE CaptureState status()
KLocalizedString KI18N_EXPORT ki18n(const char *text)
QString i18n(const char *text, const TYPE &arg...)
char * toString(const EngineQuery &query)
T take(const Key &key)
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:13:35 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.