File indexing completed on 2024-04-14 04:49:21
0001 /* 0002 * KCompactDisc - A CD drive interface for the KDE Project. 0003 * 0004 * Copyright (C) 2007 Alexander Kern <alex.kern@gmx.de> 0005 * 0006 * This program is free software; you can redistribute it and/or modify 0007 * it under the terms of the GNU General Public License as published by 0008 * the Free Software Foundation; either version 2, or (at your option) 0009 * any later version. 0010 * 0011 * This program 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 0014 * GNU General Public License for more details. 0015 * 0016 * You should have received a copy of the GNU General Public License 0017 * along with this program; if not, write to the Free Software 0018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 0019 */ 0020 0021 #include "wmlib_interface.h" 0022 0023 #include <QtGlobal> 0024 0025 #include <KLocalizedString> 0026 0027 extern "C" 0028 { 0029 // We don't have libWorkMan installed already, so get everything 0030 // from within our own directory 0031 #include "wmlib/include/wm_cdrom.h" 0032 #include "wmlib/include/wm_cdtext.h" 0033 #include "wmlib/include/wm_helpers.h" 0034 } 0035 0036 #define TRACK_VALID(track) ((track) && (track <= m_tracks)) 0037 0038 KWMLibCompactDiscPrivate::KWMLibCompactDiscPrivate(KCompactDisc *p, 0039 const QString &dev, const QString &audioSystem, const QString &audioDevice) : 0040 KCompactDiscPrivate(p, dev), 0041 m_handle(nullptr), 0042 m_audioSystem(audioSystem), 0043 m_audioDevice(audioDevice) 0044 { 0045 m_interface = m_audioSystem; 0046 } 0047 0048 KWMLibCompactDiscPrivate::~KWMLibCompactDiscPrivate() 0049 { 0050 if (m_handle) { 0051 wm_cd_destroy(m_handle); 0052 } 0053 } 0054 0055 bool KWMLibCompactDiscPrivate::createInterface() 0056 { 0057 const QString devicePath = KCompactDisc::cdromDeviceUrl(m_deviceName).path(); 0058 0059 // Debug. 0060 if (qEnvironmentVariableIsSet("KCOMPACTDISC_WMLIB_DEBUG")) { 0061 wm_cd_set_verbosity(WM_MSG_LEVEL_DEBUG | WM_MSG_CLASS_ALL); 0062 } 0063 0064 int status = wm_cd_init( 0065 devicePath.toLatin1().data(), 0066 m_audioSystem.toLatin1().data(), 0067 m_audioDevice.toLatin1().data(), 0068 nullptr, 0069 &m_handle); 0070 0071 if(!WM_CDS_ERROR(status)) { 0072 m_deviceVendor = QLatin1String(wm_drive_vendor(m_handle)); 0073 m_deviceModel = QLatin1String(wm_drive_model(m_handle)); 0074 m_deviceRevision = QLatin1String(wm_drive_revision(m_handle)); 0075 0076 Q_Q(KCompactDisc); 0077 Q_EMIT q->discChanged(0); 0078 0079 if (m_infoMode == KCompactDisc::Asynchronous) { 0080 timerExpired(); 0081 } else { 0082 QTimer::singleShot(1000, this, SLOT(timerExpired())); 0083 } 0084 0085 return true; 0086 } 0087 m_handle = nullptr; 0088 return false; 0089 } 0090 0091 unsigned KWMLibCompactDiscPrivate::trackLength(unsigned track) 0092 { 0093 return (unsigned)wm_cd_gettracklen(m_handle, track); 0094 } 0095 0096 bool KWMLibCompactDiscPrivate::isTrackAudio(unsigned track) 0097 { 0098 return !wm_cd_gettrackdata(m_handle, track); 0099 } 0100 0101 void KWMLibCompactDiscPrivate::playTrackPosition(unsigned track, unsigned position) 0102 { 0103 unsigned firstTrack, lastTrack; 0104 0105 firstTrack = TRACK_VALID(track) ? track : 1; 0106 lastTrack = firstTrack + 1; 0107 lastTrack = TRACK_VALID(lastTrack) ? lastTrack : WM_ENDTRACK; 0108 0109 qDebug() << "play track " << firstTrack << " position " 0110 << position; 0111 0112 wm_cd_play(m_handle, firstTrack, position, lastTrack); 0113 } 0114 0115 void KWMLibCompactDiscPrivate::pause() 0116 { 0117 wm_cd_pause(m_handle); 0118 } 0119 0120 void KWMLibCompactDiscPrivate::stop() 0121 { 0122 wm_cd_stop(m_handle); 0123 } 0124 0125 void KWMLibCompactDiscPrivate::eject() 0126 { 0127 wm_cd_eject(m_handle); 0128 } 0129 0130 void KWMLibCompactDiscPrivate::closetray() 0131 { 0132 wm_cd_closetray(m_handle); 0133 } 0134 0135 /* WM_VOLUME_MUTE ... WM_VOLUME_MAXIMAL */ 0136 /* WM_BALANCE_ALL_LEFTS .WM_BALANCE_SYMMETRED. WM_BALANCE_ALL_RIGHTS */ 0137 #define RANGE2PERCENT(x, min, max) (((x) - (min)) * 100)/ ((max) - (min)) 0138 #define PERCENT2RANGE(x, min, max) ((((x) * ((max) - (min))) / 100 ) + (min)) 0139 void KWMLibCompactDiscPrivate::setVolume(unsigned volume) 0140 { 0141 int vol, bal; 0142 vol = PERCENT2RANGE(volume, WM_VOLUME_MUTE, WM_VOLUME_MAXIMAL); 0143 bal = wm_cd_getbalance(m_handle); 0144 wm_cd_volume(m_handle, vol, bal); 0145 } 0146 0147 void KWMLibCompactDiscPrivate::setBalance(unsigned balance) 0148 { 0149 int vol, bal; 0150 vol = wm_cd_getvolume(m_handle); 0151 bal = PERCENT2RANGE(balance, WM_BALANCE_ALL_LEFTS, WM_BALANCE_ALL_RIGHTS); 0152 wm_cd_volume(m_handle, vol, bal); 0153 } 0154 0155 unsigned KWMLibCompactDiscPrivate::volume() 0156 { 0157 int vol = wm_cd_getvolume(m_handle); 0158 unsigned volume = RANGE2PERCENT(vol, WM_VOLUME_MUTE, WM_VOLUME_MAXIMAL); 0159 return volume; 0160 } 0161 0162 unsigned KWMLibCompactDiscPrivate::balance() 0163 { 0164 int bal = wm_cd_getbalance(m_handle); 0165 unsigned balance = RANGE2PERCENT(bal, WM_BALANCE_ALL_LEFTS, WM_BALANCE_ALL_RIGHTS); 0166 0167 return balance; 0168 } 0169 0170 void KWMLibCompactDiscPrivate::queryMetadata() 0171 { 0172 cdtext(); 0173 //cddb(); 0174 } 0175 0176 KCompactDisc::DiscStatus KWMLibCompactDiscPrivate::discStatusTranslate(int status) 0177 { 0178 switch (status) { 0179 case WM_CDM_TRACK_DONE: 0180 case WM_CDM_PLAYING: 0181 case WM_CDM_FORWARD: 0182 return KCompactDisc::Playing; 0183 case WM_CDM_PAUSED: 0184 return KCompactDisc::Paused; 0185 case WM_CDM_STOPPED: 0186 return KCompactDisc::Stopped; 0187 case WM_CDM_EJECTED: 0188 return KCompactDisc::Ejected; 0189 case WM_CDM_NO_DISC: 0190 case WM_CDM_UNKNOWN: 0191 return KCompactDisc::NoDisc; 0192 case WM_CDM_CDDAERROR: 0193 case WM_CDM_LOADING: 0194 case WM_CDM_BUFFERING: 0195 return KCompactDisc::NotReady; 0196 default: 0197 return KCompactDisc::Error; 0198 } 0199 } 0200 0201 void KWMLibCompactDiscPrivate::timerExpired() 0202 { 0203 KCompactDisc::DiscStatus status; 0204 unsigned track, i; 0205 Q_Q(KCompactDisc); 0206 0207 status = discStatusTranslate(wm_cd_status(m_handle)); 0208 0209 if(m_status != status) { 0210 if(skipStatusChange(status)) 0211 goto timerExpiredExit; 0212 0213 m_status = status; 0214 0215 switch(m_status) { 0216 case KCompactDisc::Ejected: 0217 case KCompactDisc::NoDisc: 0218 clearDiscInfo(); 0219 break; 0220 default: 0221 if(m_tracks == 0) { 0222 m_tracks = wm_cd_getcountoftracks(m_handle); 0223 if(m_tracks > 0) { 0224 qDebug() << "New disc with " << m_tracks << " tracks"; 0225 m_discId = wm_cddb_discid(m_handle); 0226 0227 for(i = 1; i <= m_tracks; ++i) { 0228 m_trackStartFrames.append(wm_cd_gettrackstart(m_handle, i)); 0229 } 0230 m_trackStartFrames.append(wm_cd_gettrackstart(m_handle, i)); 0231 0232 m_discLength = FRAMES2SEC(m_trackStartFrames[m_tracks] - 0233 m_trackStartFrames[0]); 0234 0235 make_playlist(); 0236 0237 m_trackArtists.append(i18n("Unknown Artist")); 0238 m_trackTitles.append(i18n("Unknown Title")); 0239 for(i = 1; i <= m_tracks; ++i) { 0240 m_trackArtists.append(i18n("Unknown Artist")); 0241 m_trackTitles.append(ki18n("Track %1").subs(i, 2).toString()); 0242 } 0243 0244 qDebug() << "m_tracks " << m_tracks; 0245 qDebug() << "m_trackStartFrames " << m_trackStartFrames; 0246 qDebug() << "m_trackArtists " << m_trackArtists; 0247 qDebug() << "m_trackTitles " << m_trackTitles; 0248 0249 Q_EMIT q->discChanged(m_tracks); 0250 0251 if(m_autoMetadata) 0252 queryMetadata(); 0253 } 0254 } 0255 break; 0256 } 0257 } 0258 0259 switch(m_status) { 0260 case KCompactDisc::Playing: 0261 m_trackPosition = wm_get_cur_pos_rel(m_handle); 0262 m_discPosition = wm_get_cur_pos_abs(m_handle) - FRAMES2SEC(m_trackStartFrames[0]); 0263 // Update the current playing position. 0264 if(m_seek) { 0265 qDebug() << "seek: " << m_seek << " trackPosition " << m_trackPosition; 0266 if(abs((long)(m_trackExpectedPosition - m_trackPosition)) > m_seek) 0267 m_seek = 0; 0268 else 0269 m_seek = abs((long)(m_trackExpectedPosition - m_trackPosition)); 0270 } 0271 0272 if(!m_seek) { 0273 Q_EMIT q->playoutPositionChanged(m_trackPosition); 0274 //Q_EMIT q->playoutDiscPositionChanged(m_discPosition); 0275 } 0276 0277 // Per-event processing. 0278 track = wm_cd_getcurtrack(m_handle); 0279 0280 if(m_track != track) { 0281 m_track = track; 0282 Q_EMIT q->playoutTrackChanged(m_track); 0283 } 0284 break; 0285 0286 case KCompactDisc::Stopped: 0287 m_seek = 0; 0288 m_track = 0; 0289 break; 0290 0291 default: 0292 break; 0293 } 0294 0295 timerExpiredExit: 0296 // Now that we have incurred any delays caused by the signals, we'll start the timer. 0297 QTimer::singleShot(1000, this, SLOT(timerExpired())); 0298 } 0299 0300 void KWMLibCompactDiscPrivate::cdtext() 0301 { 0302 struct cdtext_info *info; 0303 unsigned i; 0304 Q_Q(KCompactDisc); 0305 0306 info = wm_cd_get_cdtext(m_handle); 0307 0308 if(!info || !info->valid || (unsigned)info->count_of_entries != (m_tracks + 1)) { 0309 qDebug() << "no or invalid CDTEXT"; 0310 return; 0311 } 0312 0313 m_trackArtists[0] = QLatin1String( reinterpret_cast<char*>(info->blocks[0]->performer[0]) ); 0314 m_trackTitles[0] = QLatin1String( reinterpret_cast<char*>(info->blocks[0]->name[0]) ); 0315 0316 for(i = 1; i <= m_tracks; ++i) { 0317 m_trackArtists[i] = QLatin1String( reinterpret_cast<char*>(info->blocks[0]->performer[i]) ); 0318 m_trackTitles[i] =QLatin1String( reinterpret_cast<char*>(info->blocks[0]->name[i]) ); 0319 } 0320 0321 qDebug() << "CDTEXT"; 0322 qDebug() << "m_trackArtists " << m_trackArtists; 0323 qDebug() << "m_trackTitles " << m_trackTitles; 0324 0325 Q_EMIT q->discInformation(KCompactDisc::Cdtext); 0326 } 0327 0328 #include "moc_wmlib_interface.cpp"