KCompactDisc

wmlib_interface.cpp
1/*
2 * KCompactDisc - A CD drive interface for the KDE Project.
3 *
4 * Copyright (C) 2007 Alexander Kern <alex.kern@gmx.de>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2, or (at your option)
9 * any later version.
10 *
11 * This program 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
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 */
20
21#include "wmlib_interface.h"
22
23#include <QtGlobal>
24
25#include <KLocalizedString>
26
27extern "C"
28{
29 // We don't have libWorkMan installed already, so get everything
30 // from within our own directory
31 #include "wmlib/include/wm_cdrom.h"
32 #include "wmlib/include/wm_cdtext.h"
33 #include "wmlib/include/wm_helpers.h"
34}
35
36#define TRACK_VALID(track) ((track) && (track <= m_tracks))
37
38KWMLibCompactDiscPrivate::KWMLibCompactDiscPrivate(KCompactDisc *p,
39 const QString &dev, const QString &audioSystem, const QString &audioDevice) :
40 KCompactDiscPrivate(p, dev),
41 m_handle(nullptr),
42 m_audioSystem(audioSystem),
43 m_audioDevice(audioDevice)
44{
45 m_interface = m_audioSystem;
46}
47
48KWMLibCompactDiscPrivate::~KWMLibCompactDiscPrivate()
49{
50 if (m_handle) {
51 wm_cd_destroy(m_handle);
52 }
53}
54
55bool KWMLibCompactDiscPrivate::createInterface()
56{
57 const QString devicePath = KCompactDisc::cdromDeviceUrl(m_deviceName).path();
58
59 // Debug.
60 if (qEnvironmentVariableIsSet("KCOMPACTDISC_WMLIB_DEBUG")) {
61 wm_cd_set_verbosity(WM_MSG_LEVEL_DEBUG | WM_MSG_CLASS_ALL);
62 }
63
64 int status = wm_cd_init(
65 devicePath.toLatin1().data(),
66 m_audioSystem.toLatin1().data(),
67 m_audioDevice.toLatin1().data(),
68 nullptr,
69 &m_handle);
70
71 if(!WM_CDS_ERROR(status)) {
72 m_deviceVendor = QLatin1String(wm_drive_vendor(m_handle));
73 m_deviceModel = QLatin1String(wm_drive_model(m_handle));
74 m_deviceRevision = QLatin1String(wm_drive_revision(m_handle));
75
76 Q_Q(KCompactDisc);
77 Q_EMIT q->discChanged(0);
78
79 if (m_infoMode == KCompactDisc::Asynchronous) {
80 timerExpired();
81 } else {
82 QTimer::singleShot(1000, this, SLOT(timerExpired()));
83 }
84
85 return true;
86 }
87 m_handle = nullptr;
88 return false;
89}
90
91unsigned KWMLibCompactDiscPrivate::trackLength(unsigned track)
92{
93 return (unsigned)wm_cd_gettracklen(m_handle, track);
94}
95
96bool KWMLibCompactDiscPrivate::isTrackAudio(unsigned track)
97{
98 return !wm_cd_gettrackdata(m_handle, track);
99}
100
101void KWMLibCompactDiscPrivate::playTrackPosition(unsigned track, unsigned position)
102{
103 unsigned firstTrack, lastTrack;
104
105 firstTrack = TRACK_VALID(track) ? track : 1;
106 lastTrack = firstTrack + 1;
107 lastTrack = TRACK_VALID(lastTrack) ? lastTrack : WM_ENDTRACK;
108
109 qDebug() << "play track " << firstTrack << " position "
110 << position;
111
112 wm_cd_play(m_handle, firstTrack, position, lastTrack);
113}
114
115void KWMLibCompactDiscPrivate::pause()
116{
117 wm_cd_pause(m_handle);
118}
119
120void KWMLibCompactDiscPrivate::stop()
121{
122 wm_cd_stop(m_handle);
123}
124
125void KWMLibCompactDiscPrivate::eject()
126{
127 wm_cd_eject(m_handle);
128}
129
130void KWMLibCompactDiscPrivate::closetray()
131{
132 wm_cd_closetray(m_handle);
133}
134
135/* WM_VOLUME_MUTE ... WM_VOLUME_MAXIMAL */
136/* WM_BALANCE_ALL_LEFTS .WM_BALANCE_SYMMETRED. WM_BALANCE_ALL_RIGHTS */
137#define RANGE2PERCENT(x, min, max) (((x) - (min)) * 100)/ ((max) - (min))
138#define PERCENT2RANGE(x, min, max) ((((x) * ((max) - (min))) / 100 ) + (min))
139void KWMLibCompactDiscPrivate::setVolume(unsigned volume)
140{
141 int vol, bal;
142 vol = PERCENT2RANGE(volume, WM_VOLUME_MUTE, WM_VOLUME_MAXIMAL);
143 bal = wm_cd_getbalance(m_handle);
144 wm_cd_volume(m_handle, vol, bal);
145}
146
147void KWMLibCompactDiscPrivate::setBalance(unsigned balance)
148{
149 int vol, bal;
150 vol = wm_cd_getvolume(m_handle);
151 bal = PERCENT2RANGE(balance, WM_BALANCE_ALL_LEFTS, WM_BALANCE_ALL_RIGHTS);
152 wm_cd_volume(m_handle, vol, bal);
153}
154
155unsigned KWMLibCompactDiscPrivate::volume()
156{
157 int vol = wm_cd_getvolume(m_handle);
158 unsigned volume = RANGE2PERCENT(vol, WM_VOLUME_MUTE, WM_VOLUME_MAXIMAL);
159 return volume;
160}
161
162unsigned KWMLibCompactDiscPrivate::balance()
163{
164 int bal = wm_cd_getbalance(m_handle);
165 unsigned balance = RANGE2PERCENT(bal, WM_BALANCE_ALL_LEFTS, WM_BALANCE_ALL_RIGHTS);
166
167 return balance;
168}
169
170void KWMLibCompactDiscPrivate::queryMetadata()
171{
172 cdtext();
173 //cddb();
174}
175
176KCompactDisc::DiscStatus KWMLibCompactDiscPrivate::discStatusTranslate(int status)
177{
178 switch (status) {
179 case WM_CDM_TRACK_DONE:
180 case WM_CDM_PLAYING:
181 case WM_CDM_FORWARD:
182 return KCompactDisc::Playing;
183 case WM_CDM_PAUSED:
184 return KCompactDisc::Paused;
185 case WM_CDM_STOPPED:
186 return KCompactDisc::Stopped;
187 case WM_CDM_EJECTED:
188 return KCompactDisc::Ejected;
189 case WM_CDM_NO_DISC:
190 case WM_CDM_UNKNOWN:
191 return KCompactDisc::NoDisc;
192 case WM_CDM_CDDAERROR:
193 case WM_CDM_LOADING:
194 case WM_CDM_BUFFERING:
195 return KCompactDisc::NotReady;
196 default:
197 return KCompactDisc::Error;
198 }
199}
200
201void KWMLibCompactDiscPrivate::timerExpired()
202{
203 KCompactDisc::DiscStatus status;
204 unsigned track, i;
205 Q_Q(KCompactDisc);
206
207 status = discStatusTranslate(wm_cd_status(m_handle));
208
209 if(m_status != status) {
210 if(skipStatusChange(status))
211 goto timerExpiredExit;
212
213 m_status = status;
214
215 switch(m_status) {
216 case KCompactDisc::Ejected:
217 case KCompactDisc::NoDisc:
218 clearDiscInfo();
219 break;
220 default:
221 if(m_tracks == 0) {
222 m_tracks = wm_cd_getcountoftracks(m_handle);
223 if(m_tracks > 0) {
224 qDebug() << "New disc with " << m_tracks << " tracks";
225 m_discId = wm_cddb_discid(m_handle);
226
227 for(i = 1; i <= m_tracks; ++i) {
228 m_trackStartFrames.append(wm_cd_gettrackstart(m_handle, i));
229 }
230 m_trackStartFrames.append(wm_cd_gettrackstart(m_handle, i));
231
232 m_discLength = FRAMES2SEC(m_trackStartFrames[m_tracks] -
233 m_trackStartFrames[0]);
234
235 make_playlist();
236
237 m_trackArtists.append(i18n("Unknown Artist"));
238 m_trackTitles.append(i18n("Unknown Title"));
239 for(i = 1; i <= m_tracks; ++i) {
240 m_trackArtists.append(i18n("Unknown Artist"));
241 m_trackTitles.append(ki18n("Track %1").subs(i, 2).toString());
242 }
243
244qDebug() << "m_tracks " << m_tracks;
245qDebug() << "m_trackStartFrames " << m_trackStartFrames;
246qDebug() << "m_trackArtists " << m_trackArtists;
247qDebug() << "m_trackTitles " << m_trackTitles;
248
249 Q_EMIT q->discChanged(m_tracks);
250
251 if(m_autoMetadata)
252 queryMetadata();
253 }
254 }
255 break;
256 }
257 }
258
259 switch(m_status) {
260 case KCompactDisc::Playing:
261 m_trackPosition = wm_get_cur_pos_rel(m_handle);
262 m_discPosition = wm_get_cur_pos_abs(m_handle) - FRAMES2SEC(m_trackStartFrames[0]);
263 // Update the current playing position.
264 if(m_seek) {
265 qDebug() << "seek: " << m_seek << " trackPosition " << m_trackPosition;
266 if(abs((long)(m_trackExpectedPosition - m_trackPosition)) > m_seek)
267 m_seek = 0;
268 else
269 m_seek = abs((long)(m_trackExpectedPosition - m_trackPosition));
270 }
271
272 if(!m_seek) {
273 Q_EMIT q->playoutPositionChanged(m_trackPosition);
274 //Q_EMIT q->playoutDiscPositionChanged(m_discPosition);
275 }
276
277 // Per-event processing.
278 track = wm_cd_getcurtrack(m_handle);
279
280 if(m_track != track) {
281 m_track = track;
282 Q_EMIT q->playoutTrackChanged(m_track);
283 }
284 break;
285
286 case KCompactDisc::Stopped:
287 m_seek = 0;
288 m_track = 0;
289 break;
290
291 default:
292 break;
293 }
294
295timerExpiredExit:
296 // Now that we have incurred any delays caused by the signals, we'll start the timer.
297 QTimer::singleShot(1000, this, SLOT(timerExpired()));
298}
299
300void KWMLibCompactDiscPrivate::cdtext()
301{
302 struct cdtext_info *info;
303 unsigned i;
304 Q_Q(KCompactDisc);
305
306 info = wm_cd_get_cdtext(m_handle);
307
308 if(!info || !info->valid || (unsigned)info->count_of_entries != (m_tracks + 1)) {
309 qDebug() << "no or invalid CDTEXT";
310 return;
311 }
312
313 m_trackArtists[0] = QLatin1String( reinterpret_cast<char*>(info->blocks[0]->performer[0]) );
314 m_trackTitles[0] = QLatin1String( reinterpret_cast<char*>(info->blocks[0]->name[0]) );
315
316 for(i = 1; i <= m_tracks; ++i) {
317 m_trackArtists[i] = QLatin1String( reinterpret_cast<char*>(info->blocks[0]->performer[i]) );
318 m_trackTitles[i] =QLatin1String( reinterpret_cast<char*>(info->blocks[0]->name[i]) );
319 }
320
321 qDebug() << "CDTEXT";
322 qDebug() << "m_trackArtists " << m_trackArtists;
323 qDebug() << "m_trackTitles " << m_trackTitles;
324
325 Q_EMIT q->discInformation(KCompactDisc::Cdtext);
326}
327
328#include "moc_wmlib_interface.cpp"
KCompactDisc - A CD drive interface for the KDE Project.
static const QUrl cdromDeviceUrl(const QString &)
The Url of named CDROM device for this system.
Q_SCRIPTABLE CaptureState status()
KLocalizedString KI18N_EXPORT ki18n(const char *text)
QString i18n(const char *text, const TYPE &arg...)
char * toString(const EngineQuery &query)
char * data()
QByteArray toLatin1() const const
QString path(ComponentFormattingOptions options) const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Mon Nov 18 2024 12:08:26 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.