KCompactDisc

wmlib_interface.cpp
1 /*
2  * KCompactDisc - A CD drive interface for the KDE Project.
3  *
4  * Copyright (C) 2007 Alexander Kern <[email protected]>
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 
27 extern "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 
38 KWMLibCompactDiscPrivate::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 
48 KWMLibCompactDiscPrivate::~KWMLibCompactDiscPrivate()
49 {
50  if (m_handle) {
51  wm_cd_destroy(m_handle);
52  }
53 }
54 
55 bool 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 
91 unsigned KWMLibCompactDiscPrivate::trackLength(unsigned track)
92 {
93  return (unsigned)wm_cd_gettracklen(m_handle, track);
94 }
95 
96 bool KWMLibCompactDiscPrivate::isTrackAudio(unsigned track)
97 {
98  return !wm_cd_gettrackdata(m_handle, track);
99 }
100 
101 void 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 
115 void KWMLibCompactDiscPrivate::pause()
116 {
117  wm_cd_pause(m_handle);
118 }
119 
120 void KWMLibCompactDiscPrivate::stop()
121 {
122  wm_cd_stop(m_handle);
123 }
124 
125 void KWMLibCompactDiscPrivate::eject()
126 {
127  wm_cd_eject(m_handle);
128 }
129 
130 void 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))
139 void 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 
147 void 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 
155 unsigned 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 
162 unsigned 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 
170 void KWMLibCompactDiscPrivate::queryMetadata()
171 {
172  cdtext();
173  //cddb();
174 }
175 
176 KCompactDisc::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 
201 void 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 
244 qDebug() << "m_tracks " << m_tracks;
245 qDebug() << "m_trackStartFrames " << m_trackStartFrames;
246 qDebug() << "m_trackArtists " << m_trackArtists;
247 qDebug() << "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 
295 timerExpiredExit:
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 
300 void 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 }
qreal volume()
static const QUrl cdromDeviceUrl(const QString &)
The Url of named CDROM device for this system.
unsigned track()
Current track.
QString path(QUrl::ComponentFormattingOptions options) const const
KCompactDisc - A CD drive interface for the KDE Project.
Definition: kcompactdisc.h:86
QString i18n(const char *text, const TYPE &arg...)
QByteArray toLatin1() const const
char * toString(const T &value)
char * data()
KLocalizedString KI18N_EXPORT ki18n(const char *text)
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.