1 
2 #include "cdopener.h"
3 #include "../metadata/tagengine.h"
4 #include "../config.h"
5 #include "../options.h"
6 #include "../outputdirectory.h"
7 #include "../global.h"
8 
9 #include <KLocale>
10 #include <KPushButton>
11 #include <KLineEdit>
12 #include <KComboBox>
13 #include <KNumInput>
14 #include <KTextEdit>
15 #include <KFileDialog>
16 #include <KMessageBox>
17 #include <KStandardDirs>
18 #include <KInputDialog>
19 #include <KIcon>
20 
21 #include <QApplication>
22 #include <QLayout>
23 #include <QBoxLayout>
24 #include <QGridLayout>
25 #include <QLabel>
26 #include <QGroupBox>
27 #include <QTreeWidget>
28 #include <QDateTime>
29 #include <QColor>
30 #include <QDir>
31 #include <QFile>
32 #include <QCheckBox>
33 #include <QHeaderView>
34 
35 #include <solid/device.h>
36 #include <solid/block.h>
37 #include <solid/opticaldisc.h>
38 
39 
PlayerWidget(Phonon::MediaObject * mediaObject,int _track,QTreeWidgetItem * _treeWidgetItem,QWidget * parent,Qt::WindowFlags f)40 PlayerWidget::PlayerWidget( Phonon::MediaObject *mediaObject, int _track, QTreeWidgetItem *_treeWidgetItem, QWidget *parent, Qt::WindowFlags f )
41     : QWidget( parent, f ),
42     track( _track ),
43     m_treeWidgetItem( _treeWidgetItem )
44 {
45     const int fontHeight = QFontMetrics(QApplication::font()).boundingRect("M").size().height();
46 
47     QHBoxLayout *trackPlayerBox = new QHBoxLayout();
48     setLayout( trackPlayerBox );
49 
50     pStartPlayback = new KPushButton( KIcon("media-playback-start"), "", this );
51     pStartPlayback->setFixedSize( 1.5*fontHeight, 1.5*fontHeight );
52     trackPlayerBox->addWidget( pStartPlayback );
53     connect( pStartPlayback, SIGNAL(clicked()), this, SLOT(startPlaybackClicked()) );
54     pStopPlayback = new KPushButton( KIcon("media-playback-stop"), "", this );
55     pStopPlayback->setFixedSize( 1.5*fontHeight, 1.5*fontHeight );
56     pStopPlayback->hide();
57     trackPlayerBox->addWidget( pStopPlayback );
58     connect( pStopPlayback, SIGNAL(clicked()), this, SLOT(stopPlaybackClicked()) );
59     seekSlider = new Phonon::SeekSlider( this );
60     seekSlider->setMediaObject( mediaObject );
61     seekSlider->setIconVisible( false );
62     seekSlider->hide();
63     trackPlayerBox->addWidget( seekSlider, 1 );
64     trackPlayerBox->addStretch();
65 }
66 
~PlayerWidget()67 PlayerWidget::~PlayerWidget()
68 {}
69 
startPlaybackClicked()70 void PlayerWidget::startPlaybackClicked()
71 {
72 /*    playing = true;
73     pStartPlayback->hide();
74     pStopPlayback->show();
75     seekSlider->show();*/
76     emit startPlayback( track );
77 }
78 
stopPlaybackClicked()79 void PlayerWidget::stopPlaybackClicked()
80 {
81 /*    playing = false;
82     pStartPlayback->show();
83     pStopPlayback->hide();
84     seekSlider->hide();*/
85     emit stopPlayback();
86 }
87 
trackChanged(int _track)88 void PlayerWidget::trackChanged( int _track )
89 {
90     if( _track != track )
91     {
92         playing = false;
93         pStartPlayback->show();
94         pStopPlayback->hide();
95         seekSlider->hide();
96     }
97     else
98     {
99         playing = true;
100         pStartPlayback->hide();
101         pStopPlayback->show();
102         seekSlider->show();
103     }
104 }
105 
106 
CDOpener(Config * _config,const QString & _device,QWidget * parent,Qt::WFlags f)107 CDOpener::CDOpener( Config *_config, const QString& _device, QWidget *parent, Qt::WFlags f )
108     : KDialog( parent, f ),
109     noCdFound( false ),
110     config( _config ),
111     cdDrive( 0 ),
112     cdParanoia( 0 ),
113     cddb( 0 ),
114     cdTextFound( false ),
115     cddbFound( false )
116 {
117     setButtons( 0 );
118 
119     page = CdOpenPage;
120 
121     const int fontHeight = QFontMetrics(QApplication::font()).boundingRect("M").size().height();
122 
123     // let the dialog look nice
124     setCaption( i18n("Add CD tracks") );
125     setWindowIcon( KIcon("media-optical-audio") );
126 
127     QWidget *widget = new QWidget( this );
128     QGridLayout *mainGrid = new QGridLayout( widget );
129     QGridLayout *topGrid = new QGridLayout();
130     mainGrid->addLayout( topGrid, 0, 0 );
131     setMainWidget( widget );
132 
133     lSelector = new QLabel( i18n("1. Select CD tracks"), widget );
134     QFont font;
135     font.setBold( true );
136     lSelector->setFont( font );
137     topGrid->addWidget( lSelector, 0, 0 );
138     lOptions = new QLabel( i18n("2. Set conversion options"), widget );
139     topGrid->addWidget( lOptions, 0, 1 );
140 
141     // draw a horizontal line
142     QFrame *lineFrame = new QFrame( widget );
143     lineFrame->setFrameShape( QFrame::HLine );
144     lineFrame->setFrameShadow( QFrame::Sunken );
145     mainGrid->addWidget( lineFrame, 1, 0 );
146 
147 
148     // CD Opener Widget
149 
150     cdOpenerWidget = new QWidget( widget );
151     mainGrid->addWidget( cdOpenerWidget, 2, 0 );
152 
153     // the grid for all widgets in the dialog
154     QGridLayout *gridLayout = new QGridLayout( cdOpenerWidget );
155 
156     // the box for the cover and artist/album grid
157     QHBoxLayout *topBoxLayout = new QHBoxLayout();
158     gridLayout->addLayout( topBoxLayout, 0, 0 );
159 
160     // the album cover
161     QLabel *lAlbumCover = new QLabel( "", cdOpenerWidget );
162     topBoxLayout->addWidget( lAlbumCover );
163     lAlbumCover->setPixmap( QPixmap( KStandardDirs::locate("data","soundkonverter/images/nocover.png") ) );
164     lAlbumCover->setContentsMargins( 0, 0, 0.5*fontHeight, 0 );
165 
166     // the grid for the artist and album input
167     QGridLayout *topGridLayout = new QGridLayout();
168     topBoxLayout->addLayout( topGridLayout );
169 
170     // set up the first row at the top
171     QLabel *lArtistLabel = new QLabel( i18n("Album artist:"), cdOpenerWidget );
172     topGridLayout->addWidget( lArtistLabel, 0, 0 );
173     lArtist = new KLineEdit( cdOpenerWidget );
174     topGridLayout->addWidget( lArtist, 0, 1 );
175     connect( lArtist, SIGNAL(textChanged(const QString&)), this, SLOT(artistChanged(const QString&)) );
176 
177     // set up the second row at the top
178     QLabel *lAlbumLabel = new QLabel( i18n("Album:"), cdOpenerWidget );
179     topGridLayout->addWidget( lAlbumLabel, 1, 0 );
180     lAlbum = new KLineEdit( cdOpenerWidget );
181     topGridLayout->addWidget( lAlbum, 1, 1 );
182 
183     // set up the third row at the top
184     QLabel *lDiscLabel = new QLabel( i18n("Disc No.:"), cdOpenerWidget );
185     topGridLayout->addWidget( lDiscLabel, 2, 0 );
186     // add a horizontal box layout for the year and genre
187     QHBoxLayout *yearBox = new QHBoxLayout();
188     topGridLayout->addLayout( yearBox, 2, 1 );
189     // and fill it up
190     iDisc = new KIntSpinBox( 1, 99, 1, 1, cdOpenerWidget );
191     yearBox->addWidget( iDisc );
192     QLabel *lDiscTotalLabel = new QLabel( i18nc("Track/Disc No. x of y","of"), cdOpenerWidget );
193     lDiscTotalLabel->setAlignment( Qt::AlignHCenter | Qt::AlignVCenter );
194     yearBox->addWidget( lDiscTotalLabel );
195     iDiscTotal = new KIntSpinBox( 1, 99, 1, 1, cdOpenerWidget );
196     yearBox->addWidget( iDiscTotal );
197     QLabel *lYearLabel = new QLabel( i18n("Year:"), cdOpenerWidget );
198     lYearLabel->setAlignment( Qt::AlignRight | Qt::AlignVCenter );
199     yearBox->addWidget( lYearLabel );
200     iYear = new KIntSpinBox( 0, 99999, 1, QDate::currentDate().year(), cdOpenerWidget );
201     yearBox->addWidget( iYear );
202     QLabel *lGenreLabel = new QLabel( i18n("Genre:"), cdOpenerWidget );
203     lGenreLabel->setAlignment( Qt::AlignRight | Qt::AlignVCenter );
204     yearBox->addWidget( lGenreLabel );
205     cGenre = new KComboBox( true, cdOpenerWidget );
206     cGenre->addItems( config->tagEngine()->genreList );
207     cGenre->setEditText( "" );
208     KCompletion *cGenreCompletion = cGenre->completionObject();
209     cGenreCompletion->insertItems( config->tagEngine()->genreList );
210     cGenreCompletion->setIgnoreCase( true );
211     yearBox->addWidget( cGenre );
212 
213     topGridLayout->setColumnStretch( 1, 1 );
214 
215 
216     // generate the list view for the tracks
217     trackList = new QTreeWidget( cdOpenerWidget );
218     gridLayout->addWidget( trackList, 1, 0 );
219     // and fill in the headers
220     trackList->setColumnCount( 5 );
221     QStringList labels;
222     labels.append( i18nc("column title","Rip") );
223     labels.append( i18n("Track") );
224     labels.append( i18n("Artist") );
225     labels.append( i18n("Composer") );
226     labels.append( i18n("Title") );
227     labels.append( i18n("Length") );
228     labels.append( i18n("Player") );
229     trackList->setHeaderLabels( labels );
230     trackList->setSelectionBehavior( QAbstractItemView::SelectRows );
231     trackList->setSelectionMode( QAbstractItemView::ExtendedSelection );
232     trackList->setSortingEnabled( false );
233     trackList->setRootIsDecorated( false );
234     trackList->header()->setResizeMode( Column_Artist, QHeaderView::ResizeToContents );
235     trackList->header()->setResizeMode( Column_Composer, QHeaderView::ResizeToContents );
236     trackList->header()->setResizeMode( Column_Title, QHeaderView::ResizeToContents );
237 //     trackList->setMouseTracking( true );
238     connect( trackList, SIGNAL(itemSelectionChanged()), this, SLOT(trackChanged()) );
239 //     connect( trackList, SIGNAL(itemEntered(QTreeWidgetItem*,int)), this, SLOT(itemHighlighted(QTreeWidgetItem*,int)) );
240     gridLayout->setRowStretch( 1, 1 );
241 
242 
243     // create the box at the bottom for editing the tags
244     tagGroupBox = new QGroupBox( i18n("No track selected"), cdOpenerWidget );
245     gridLayout->addWidget( tagGroupBox, 2, 0 );
246     QGridLayout *tagGridLayout = new QGridLayout( tagGroupBox );
247 
248     // add the up and down buttons
249     pTrackUp = new KPushButton( "", tagGroupBox );
250     pTrackUp->setIcon( KIcon("arrow-up") );
251     pTrackUp->setFixedSize( pTrackUp->sizeHint().height(), pTrackUp->sizeHint().height() );
252     pTrackUp->setAutoRepeat( true );
253     connect( pTrackUp, SIGNAL(clicked()), this, SLOT(trackUpPressed()) );
254     tagGridLayout->addWidget( pTrackUp, 0, 0 );
255     pTrackDown = new KPushButton( "", tagGroupBox );
256     pTrackDown->setIcon( KIcon("arrow-down") );
257     pTrackDown->setFixedSize( pTrackDown->sizeHint().height(), pTrackDown->sizeHint().height() );
258     pTrackDown->setAutoRepeat( true );
259     connect( pTrackDown, SIGNAL(clicked()), this, SLOT(trackDownPressed()) );
260     tagGridLayout->addWidget( pTrackDown, 1, 0 );
261 
262     setTabOrder(pTrackDown, pTrackUp);
263 
264     // add the inputs
265     // add a horizontal box layout for the title
266     QHBoxLayout *trackTitleBox = new QHBoxLayout();
267     tagGridLayout->addLayout( trackTitleBox, 0, 2 );
268     // and fill it up
269     QLabel *lTrackTitleLabel = new QLabel( i18n("Title:"), tagGroupBox );
270     tagGridLayout->addWidget( lTrackTitleLabel, 0, 1 );
271     lTrackTitle = new KLineEdit( tagGroupBox );
272     trackTitleBox->addWidget( lTrackTitle );
273     connect( lTrackTitle, SIGNAL(textChanged(const QString&)), this, SLOT(trackTitleChanged(const QString&)) );
274     pTrackTitleEdit = new KPushButton( "", tagGroupBox );
275     pTrackTitleEdit->setIcon( KIcon("document-edit") );
276     pTrackTitleEdit->setFixedSize( lTrackTitle->sizeHint().height(), lTrackTitle->sizeHint().height() );
277     pTrackTitleEdit->hide();
278     trackTitleBox->addWidget( pTrackTitleEdit );
279     connect( pTrackTitleEdit, SIGNAL(clicked()), this, SLOT(editTrackTitleClicked()) );
280     // add a horizontal box layout for the composer
281     QHBoxLayout *trackArtistBox = new QHBoxLayout();
282     tagGridLayout->addLayout( trackArtistBox, 1, 2 );
283     // and fill it up
284     QLabel *lTrackArtistLabel = new QLabel( i18n("Artist:"), tagGroupBox );
285     tagGridLayout->addWidget( lTrackArtistLabel, 1, 1 );
286     lTrackArtist = new KLineEdit( tagGroupBox );
287     trackArtistBox->addWidget( lTrackArtist );
288     connect( lTrackArtist, SIGNAL(textChanged(const QString&)), this, SLOT(trackArtistChanged(const QString&)) );
289     pTrackArtistEdit = new KPushButton( "", tagGroupBox );
290     pTrackArtistEdit->setIcon( KIcon("document-edit") );
291     pTrackArtistEdit->setFixedSize( lTrackArtist->sizeHint().height(), lTrackArtist->sizeHint().height() );
292     pTrackArtistEdit->hide();
293     trackArtistBox->addWidget( pTrackArtistEdit );
294     connect( pTrackArtistEdit, SIGNAL(clicked()), this, SLOT(editTrackArtistClicked()) );
295     QLabel *lTrackComposerLabel = new QLabel( i18n("Composer:"), tagGroupBox );
296     trackArtistBox->addWidget( lTrackComposerLabel );
297     lTrackComposer = new KLineEdit( tagGroupBox );
298     trackArtistBox->addWidget( lTrackComposer );
299     connect( lTrackComposer, SIGNAL(textChanged(const QString&)), this, SLOT(trackComposerChanged(const QString&)) );
300     pTrackComposerEdit = new KPushButton( "", tagGroupBox );
301     pTrackComposerEdit->setIcon( KIcon("document-edit") );
302     pTrackComposerEdit->setFixedSize( lTrackComposer->sizeHint().height(), lTrackComposer->sizeHint().height() );
303     pTrackComposerEdit->hide();
304     trackArtistBox->addWidget( pTrackComposerEdit );
305     connect( pTrackComposerEdit, SIGNAL(clicked()), this, SLOT(editTrackComposerClicked()) );
306     // add a horizontal box layout for the comment
307     QHBoxLayout *trackCommentBox = new QHBoxLayout();
308     tagGridLayout->addLayout( trackCommentBox, 2, 2 );
309     // and fill it up
310     QLabel *lTrackCommentLabel = new QLabel( i18n("Comment:"), tagGroupBox );
311     tagGridLayout->addWidget( lTrackCommentLabel, 2, 1 );
312     tTrackComment = new KTextEdit( tagGroupBox );
313     trackCommentBox->addWidget( tTrackComment );
314     tTrackComment->setFixedHeight( 4*fontHeight );
315     connect( tTrackComment, SIGNAL(textChanged()), this, SLOT(trackCommentChanged()) );
316     pTrackCommentEdit = new KPushButton( "", tagGroupBox );
317     pTrackCommentEdit->setIcon( KIcon("document-edit") );
318     pTrackCommentEdit->setFixedSize( lTrackTitle->sizeHint().height(), lTrackTitle->sizeHint().height() );
319     pTrackCommentEdit->hide();
320     trackCommentBox->addWidget( pTrackCommentEdit );
321     connect( pTrackCommentEdit, SIGNAL(clicked()), this, SLOT(editTrackCommentClicked()) );
322 
323 
324     audioOutput = new Phonon::AudioOutput( Phonon::MusicCategory, this );
325     audioOutput->setVolume( 0.5 );
326     mediaObject = new Phonon::MediaObject( this );
327     mediaObject->setTickInterval( 500 );
328 
329     Phonon::createPath( mediaObject, audioOutput );
330 
331     mediaController = new Phonon::MediaController( mediaObject );
332     mediaController->setAutoplayTitles( false );
333 
334     connect( mediaController, SIGNAL(titleChanged(int)), this, SLOT(playbackTitleChanged(int)) );
335     connect( mediaObject, SIGNAL(stateChanged(Phonon::State,Phonon::State)), this, SLOT(playbackStateChanged(Phonon::State,Phonon::State)) );
336 
337 
338 
339     // Cd Opener Overlay Widget
340 
341     cdOpenerOverlayWidget = new QWidget( widget );
342     mainGrid->addWidget( cdOpenerOverlayWidget, 2, 0 );
343     QHBoxLayout *cdOpenerOverlayLayout = new QHBoxLayout();
344     cdOpenerOverlayWidget->setLayout( cdOpenerOverlayLayout );
345 //     lOverlayLabel = new QLabel( i18n("Please wait, trying to read audio CD ..."), cdOpenerOverlayWidget );
346     lOverlayLabel = new QLabel( cdOpenerOverlayWidget );
347     cdOpenerOverlayLayout->addWidget( lOverlayLabel );
348     lOverlayLabel->setAlignment( Qt::AlignCenter );
349     cdOpenerOverlayWidget->setAutoFillBackground( true );
350     QPalette newPalette = cdOpenerOverlayWidget->palette();
351     newPalette.setBrush( QPalette::Window, brushSetAlpha( newPalette.window(), 192 ) );
352     cdOpenerOverlayWidget->setPalette( newPalette );
353 
354 
355     // Conversion Options Widget
356 
357     // add a vertical box layout for the options widget
358     QVBoxLayout *optionsBox = new QVBoxLayout();
359     mainGrid->addLayout( optionsBox, 2, 0 );
360 
361     options = new Options( config, i18n("Select your desired output options and click on \"Ok\"."), widget );
362     optionsBox->addWidget( options );
363     options->hide();
364     optionsBox->addStretch();
365 
366 
367     // draw a horizontal line
368     QFrame *buttonLineFrame = new QFrame( widget );
369     buttonLineFrame->setFrameShape( QFrame::HLine );
370     buttonLineFrame->setFrameShadow( QFrame::Sunken );
371     buttonLineFrame->setFrameShape( QFrame::HLine );
372     mainGrid->addWidget( buttonLineFrame, 4, 0 );
373 
374     // add a horizontal box layout for the control elements
375     QHBoxLayout *controlBox = new QHBoxLayout();
376     mainGrid->addLayout( controlBox, 5, 0 );
377 
378     // add the control elements
379     pSaveCue = new KPushButton( KIcon("document-save"), i18n("Save cue sheet..."), widget );
380     controlBox->addWidget( pSaveCue );
381     connect( pSaveCue, SIGNAL(clicked()), this, SLOT(saveCuesheetClicked()) );
382     controlBox->addSpacing( fontHeight );
383 
384     pCDDB = new KPushButton( KIcon("download"), i18n("Request CDDB"), widget );
385     controlBox->addWidget( pCDDB );
386     connect( pCDDB, SIGNAL(clicked()), this, SLOT(requestCddb()) );
387     controlBox->addStretch();
388 
389     cEntireCd = new QCheckBox( i18n("Rip entire CD to one file"), widget );
390     QStringList errorList;
391     cEntireCd->setEnabled( config->pluginLoader()->canRipEntireCd(&errorList) );
392     if( !cEntireCd->isEnabled() )
393     {
394         QPalette notificationPalette = cEntireCd->palette();
395         notificationPalette.setColor( QPalette::Disabled, QPalette::WindowText, QColor(174,127,130) ); // QColor(181,96,101)
396         cEntireCd->setPalette( notificationPalette );
397         if( !errorList.isEmpty() )
398         {
399             errorList.prepend( i18n("Ripping an entire cd to a single file is not supported by the installed backends.\nPossible solutions are listed below.\n") );
400         }
401         else
402         {
403             errorList += i18n("Ripping an entire cd to a single file is not supported by the installed backends.\nPlease check your distribution's package manager in order to install an additional ripper plugin which supports ripping to one file.");
404         }
405         cEntireCd->setToolTip( errorList.join("\n") );
406     }
407     controlBox->addWidget( cEntireCd );
408     controlBox->addSpacing( 2*fontHeight );
409 
410     pProceed = new KPushButton( KIcon("go-next"), i18n("Proceed"), widget );
411     controlBox->addWidget( pProceed );
412     connect( pProceed, SIGNAL(clicked()), this, SLOT(proceedClicked()) );
413     pAdd = new KPushButton( KIcon("dialog-ok"), i18n("Ok"), widget );
414     controlBox->addWidget( pAdd );
415     pAdd->hide();
416     connect( pAdd, SIGNAL(clicked()), this, SLOT(addClicked()) );
417     pCancel = new KPushButton( KIcon("dialog-cancel"), i18n("Cancel"), widget );
418     controlBox->addWidget( pCancel );
419     connect( pCancel, SIGNAL(clicked()), this, SLOT(reject()) );
420 
421     connect( &fadeTimer, SIGNAL(timeout()), this, SLOT(fadeAnim()) );
422     fadeAlpha = 255.0f;
423 
424 
425     cddb = new KCDDB::Client();
426     connect( cddb, SIGNAL(finished(KCDDB::Result)), this, SLOT(lookup_cddb_done(KCDDB::Result)) );
427 
428 
429     // set up timeout timer
430     timeoutTimer.setSingleShot( true );
431     connect( &timeoutTimer, SIGNAL(timeout()), this, SLOT(timeout()) );
432 
433 
434     if( !_device.isEmpty() )
435     {
436         device = _device;
437     }
438     else
439     {
440         const QMap<QString,QString> devices = cdDevices();
441         if( devices.count() <= 0 )
442         {
443             noCdFound = true;
444             return;
445         }
446         else if( devices.count() == 1 )
447         {
448             device = devices.keys().at(0);
449         }
450         else
451         {
452             QStringList list;
453             foreach( const QString& desc, devices.values() )
454             {
455                 list.append( desc );
456             }
457             bool ok = false;
458             const QString selection = KInputDialog::getItem( i18n("Select CD-ROM drive"), i18n("Multiple CD-ROM drives where found. Please select one:"), list, 0, false, &ok, this );
459 
460             if( ok )
461             {
462                 // The user selected an item and pressed OK
463                 device = devices.keys().at(list.indexOf(selection));
464             }
465             else
466             {
467                 noCdFound = true;
468                 return;
469             }
470         }
471     }
472 
473     const bool success = openCdDevice( device );
474     if( !success )
475     {
476         KMessageBox::information(this,"success = false, couldn't open audio device.\nplease report this bug.");
477         noCdFound = true;
478         return;
479     }
480 
481 
482     mediaSource = new Phonon::MediaSource( Phonon::Cd, device );
483     mediaObject->setCurrentSource( *mediaSource ); // WARNING doesn't work with phonon-xine
484 
485 
486     // Prevent the dialog from beeing too wide because of the directory history
487     if( parent && width() > parent->width() )
488         setInitialSize( QSize(parent->width()-fontHeight,sizeHint().height()) );
489 
490     KSharedConfig::Ptr conf = KGlobal::config();
491     KConfigGroup group = conf->group( "CDOpener" );
492     restoreDialogSize( group );
493 }
494 
~CDOpener()495 CDOpener::~CDOpener()
496 {
497     KSharedConfig::Ptr conf = KGlobal::config();
498     KConfigGroup group = conf->group( "CDOpener" );
499     saveDialogSize( group );
500 
501     if( cdParanoia )
502     {
503         paranoia_free( cdParanoia );
504 //         delete cdParanoia;
505     }
506     if( cdDrive )
507     {
508         cdda_close( cdDrive );
509 //         delete cdDrive;
510     }
511 
512     if( cddb )
513         delete cddb;
514 }
515 
setProfile(const QString & profile)516 void CDOpener::setProfile( const QString& profile )
517 {
518     options->setProfile( profile );
519 }
520 
setFormat(const QString & format)521 void CDOpener::setFormat( const QString& format )
522 {
523     options->setFormat( format );
524 }
525 
setOutputDirectory(const QString & directory)526 void CDOpener::setOutputDirectory( const QString& directory )
527 {
528     options->setOutputDirectory( directory );
529 }
530 
setCommand(const QString & _command)531 void CDOpener::setCommand( const QString& _command )
532 {
533     command = _command;
534 }
535 
cdDevices()536 QMap<QString,QString> CDOpener::cdDevices()
537 {
538     QMap<QString,QString> devices;
539 
540     QList<Solid::Device> solidDevices = Solid::Device::listFromType(Solid::DeviceInterface::OpticalDisc, QString());
541     foreach( Solid::Device solidDevice, solidDevices )
542     {
543         Solid::OpticalDisc *opticalDisc = solidDevice.as<Solid::OpticalDisc>();
544         if( opticalDisc && opticalDisc->availableContent() & Solid::OpticalDisc::Audio )
545         {
546             Solid::Block *block = solidDevice.as<Solid::Block>();
547             if( block )
548             {
549                 const QString device = block->device();
550                 const Solid::Device parentDevice( solidDevice.parentUdi() );
551                 const QString name = parentDevice.product();
552 
553                 cdDrive = cdda_identify( device.toAscii(), CDDA_MESSAGE_PRINTIT, 0 );
554                 if( cdDrive && cdda_open(cdDrive) == 0 )
555                 {
556                     const QString desc = i18n("%1 (%2): Audio CD with %3 tracks").arg(name).arg(device).arg(cdda_audio_tracks(cdDrive));
557                     devices.insert( device, desc );
558                 }
559             }
560         }
561     }
562 
563     return devices;
564 }
565 
cdda_audio_tracks(cdrom_drive * cdDrive) const566 int CDOpener::cdda_audio_tracks( cdrom_drive *cdDrive ) const
567 {
568     const int nrOfTracks = cdda_tracks(cdDrive);
569     for( int i=1; i<=nrOfTracks; i++ )
570     {
571         if( !(IS_AUDIO(cdDrive,i-1)) )
572             return i-1;
573     }
574     return nrOfTracks;
575 }
576 
openCdDevice(const QString & _device)577 bool CDOpener::openCdDevice( const QString& _device )
578 {
579     // paranoia init
580 
581     QFile deviceFile(_device);
582 
583     if( !deviceFile.exists() )
584     {
585         return false;
586     }
587     else
588     {
589         cdDrive = cdda_identify( _device.toAscii(), CDDA_MESSAGE_PRINTIT, 0 );
590         if( !cdDrive || cdda_open( cdDrive ) != 0 )
591         {
592             return false;
593         }
594     }
595     cdParanoia = paranoia_init( cdDrive );
596 
597     // cd text
598 
599 //     const int status = wm_cd_init( device.toAscii().data(), "", "", "", &wmHandle );
600 //
601 //     struct cdtext_info *info = 0;
602 //
603 //     if( !WM_CDS_ERROR(status) )
604 //     {
605 //         info = wm_cd_get_cdtext( wmHandle );
606 //
607 //         if( !info || !info->valid || info->count_of_entries != cdda_tracks(cdDrive) )
608 //         if( !info || !info->valid )
609 //         {
610 //             kDebug() << "no or invalid CDTEXT";
611 //             info = 0;
612 //         }
613 //     }
614 
615 
616     // add tracks to list
617 
618     qDeleteAll( tags );
619     tags.clear();
620 
621     TagData *newTags = new TagData();
622     newTags->track = 1;
623     newTags->trackTotal = 1;
624     newTags->disc = 1;
625     newTags->discTotal = 1;
626     newTags->year = (QDate::currentDate()).year();
627     tags += newTags;
628 
629     const int trackTotal = cdda_audio_tracks( cdDrive );
630     for( int i=0; i<trackTotal; i++ )
631     {
632         TagData *newTags = new TagData();
633         newTags->track = i+1;
634         newTags->trackTotal = trackTotal;
635         const long size = CD_FRAMESIZE_RAW * (cdda_track_lastsector(cdDrive,newTags->track)-cdda_track_firstsector(cdDrive,newTags->track));
636         newTags->length = (8 * size) / (44100 * 2 * 16);
637         tags += newTags;
638 
639         QStringList data;
640         data.append( "" );
641         data.append( QString().sprintf("%02i",newTags->track) );
642         data.append( newTags->artist );
643         data.append( newTags->composer );
644         data.append( newTags->title );
645         data.append( QString().sprintf("%i:%02i",newTags->length/60,newTags->length%60) );
646         QTreeWidgetItem *item = new QTreeWidgetItem( trackList, data );
647         PlayerWidget *playerWidget = new PlayerWidget( mediaObject, newTags->track, item, this );
648 //         playerWidget->hide();
649         connect( playerWidget, SIGNAL(startPlayback(int)), this, SLOT(startPlayback(int)) );
650         connect( playerWidget, SIGNAL(stopPlayback()), this, SLOT(stopPlayback()) );
651         playerWidgets.append( playerWidget );
652         trackList->setItemWidget( item, Column_Player, playerWidget );
653         item->setCheckState( 0, Qt::Checked );
654     }
655     trackList->resizeColumnToContents( Column_Rip );
656     trackList->resizeColumnToContents( Column_Track );
657     trackList->resizeColumnToContents( Column_Length );
658 
659     if( trackList->topLevelItem(0) )
660         trackList->topLevelItem(0)->setSelected( true );
661 
662     lArtist->setText( tags.at(0)->artist );
663     lAlbum->setText( tags.at(0)->album );
664     iDisc->setValue( tags.at(0)->disc );
665     iDiscTotal->setValue( tags.at(0)->discTotal );
666     iYear->setValue( tags.at(0)->year );
667     cGenre->setEditText( tags.at(0)->genre );
668 
669     artistChanged( lArtist->text() );
670     adjustComposerColumn();
671 
672 
673     // request cddb data
674     requestCddb( true );
675 
676     return true;
677 }
678 
requestCddb(bool autoRequest)679 void CDOpener::requestCddb( bool autoRequest )
680 {
681     lOverlayLabel->setText( i18n("Please wait, trying to download CDDB data ...") );
682 
683     timeoutTimer.start( autoRequest ? 10000 : 20000 );
684 
685     // cddb needs offsets +150 frames (2 seconds * 75 frames per second)
686     KCDDB::TrackOffsetList offsets;
687     for( int i=1; i<=cdda_tracks(cdDrive); i++ )
688     {
689         if( !(IS_AUDIO(cdDrive,i-1)) )
690             break;
691 
692         offsets.append( cdda_track_firstsector(cdDrive,i) + 150 );
693     }
694     offsets.append( cdda_disc_lastsector(cdDrive) + 150 + 1 );
695 
696     cddb->config().reparse();
697     cddb->setBlockingMode( false );
698     cddb->lookup( offsets );
699 }
700 
lookup_cddb_done(KCDDB::Result result)701 void CDOpener::lookup_cddb_done( KCDDB::Result result )
702 {
703     timeoutTimer.stop();
704 
705     if( result != KCDDB::Success && result != KCDDB::MultipleRecordFound )
706     {
707         // TODO error message if request was initiated by the user
708         // Error(i18n("No entry found in CDDB."), i18n("This means no data found in the CDDB database. Please enter the data manually. Maybe try another CDDB server."), Error::ERROR, this);
709         fadeOut();
710         return;
711     }
712 
713     cddbFound = true;
714 
715     KCDDB::CDInfo info = cddb->lookupResponse().first();
716     if( cddb->lookupResponse().count() > 1 || cdTextFound )
717     {
718         KCDDB::CDInfoList cddb_info = cddb->lookupResponse();
719         QStringList list;
720         if( cdTextFound )
721         {
722             // list.append( QString("CD Text: %1, %2").arg(compact_disc->discArtist()).arg(compact_disc->discTitle()) );
723         }
724         for( int i=0; i<cddb_info.count(); i++ )
725         {
726             list.append( QString("%1, %2, %3").arg(cddb_info.at(i).get(KCDDB::Artist).toString()).arg(cddb_info.at(i).get(KCDDB::Title).toString()).arg(cddb_info.at(i).get(KCDDB::Genre).toString()) );
727         }
728 
729         bool ok = false;
730         const QString cddbItem = KInputDialog::getItem( i18n("Select CDDB Entry"), i18n("Multiple CDDB entries where found. Please select one:"), list, 0, false, &ok, this );
731 
732         if( ok )
733         {
734             // The user selected and item and pressed OK
735             const int offset = cdTextFound ? 1 : 0;
736             const int index = list.indexOf( cddbItem );
737             if( index - offset < 0 )
738             {
739                 fadeOut();
740                 return;
741             }
742             info = cddb_info.at( index - offset );
743         }
744         else
745         {
746             // user pressed Cancel
747             fadeOut();
748             return;
749         }
750     }
751 
752     for( int i=1; i<=cdda_audio_tracks(cdDrive); i++ )
753     {
754         tags.at(i)->artist = info.track(i-1).get(KCDDB::Artist).toString();
755         tags.at(i)->title = info.track(i-1).get(KCDDB::Title).toString();
756         tags.at(i)->comment = info.track(i-1).get(KCDDB::Comment).toString();
757 
758         QTreeWidgetItem *item = trackList->topLevelItem(i-1);
759         item->setText( 2, tags.at(i)->artist );
760         item->setText( 4, tags.at(i)->title );
761     }
762 
763     tags.at(0)->album = info.get(KCDDB::Title).toString();
764     tags.at(0)->artist = info.get(KCDDB::Artist).toString();
765     tags.at(0)->year = info.get(KCDDB::Year).toInt();
766     tags.at(0)->genre = info.get(KCDDB::Genre).toString();
767 
768     // TODO resize colums up to a certain width
769 
770     lArtist->setText( tags.at(0)->artist );
771     lAlbum->setText( tags.at(0)->album );
772     iDisc->setValue( tags.at(0)->disc );
773     iDiscTotal->setValue( tags.at(0)->discTotal );
774     iYear->setValue( tags.at(0)->year );
775     cGenre->setEditText( tags.at(0)->genre );
776 
777     artistChanged( lArtist->text() );
778 
779     fadeOut();
780 }
781 
timeout()782 void CDOpener::timeout()
783 {
784     fadeOut();
785 }
786 
trackUpPressed()787 void CDOpener::trackUpPressed()
788 {
789     QTreeWidgetItem *item = trackList->topLevelItem( selectedTracks.first() - 2 );
790 
791     if( !item )
792         return;
793 
794     disconnect( trackList, SIGNAL(itemSelectionChanged()), 0, 0 ); // avoid backfireing
795 
796     for( int i=0; i<selectedTracks.count(); i++ )
797     {
798         QTreeWidgetItem *item = trackList->topLevelItem( selectedTracks.at(i)-1 );
799         if( item )
800             item->setSelected( false );
801     }
802 
803     item->setSelected( true );
804     trackList->scrollToItem( item );
805 
806     connect( trackList, SIGNAL(itemSelectionChanged()), this, SLOT(trackChanged()) );
807 
808     trackChanged();
809 }
810 
trackDownPressed()811 void CDOpener::trackDownPressed()
812 {
813     QTreeWidgetItem *item = trackList->topLevelItem( selectedTracks.last() );
814 
815     if( !item )
816         return;
817 
818     disconnect( trackList, SIGNAL(itemSelectionChanged()), 0, 0 ); // avoid backfireing
819 
820     for( int i=0; i<selectedTracks.count(); i++ )
821     {
822         QTreeWidgetItem *item = trackList->topLevelItem( selectedTracks.at(i)-1 );
823         if( item )
824             item->setSelected( false );
825     }
826 
827     item->setSelected( true );
828     trackList->scrollToItem( item );
829 
830     connect( trackList, SIGNAL(itemSelectionChanged()), this, SLOT(trackChanged()) );
831 
832     trackChanged();
833 }
834 
trackChanged()835 void CDOpener::trackChanged()
836 {
837     // NOTE if no track is selected soundkonverter could use the current item as default item (like qlistview does)
838 
839     // rebuild the list of the selected tracks
840     selectedTracks.clear();
841     for( int i=0; i<trackList->topLevelItemCount(); i++ )
842     {
843         QTreeWidgetItem *item = trackList->topLevelItem( i );
844         if( item->isSelected() )
845         {
846             selectedTracks.append( i+1 );
847         }
848     }
849 
850     // insert the new values
851     if( selectedTracks.count() < 1 )
852     {
853         pTrackUp->setEnabled( false );
854         pTrackDown->setEnabled( false );
855 
856         lTrackTitle->setEnabled( false );
857         lTrackTitle->setText( "" );
858         pTrackTitleEdit->hide();
859         lTrackArtist->setEnabled( false );
860         lTrackArtist->setText( "" );
861         pTrackArtistEdit->hide();
862         lTrackComposer->setEnabled( false );
863         lTrackComposer->setText( "" );
864         pTrackComposerEdit->hide();
865         tTrackComment->setEnabled( false );
866         tTrackComment->setReadOnly( true );
867         tTrackComment->setText( "" );
868         pTrackCommentEdit->hide();
869 
870         pTrackUp->setEnabled( false );
871         pTrackDown->setEnabled( false );
872 
873         return;
874     }
875     else if( selectedTracks.count() > 1 )
876     {
877         if( selectedTracks.first() > 1 )
878             pTrackUp->setEnabled( true );
879         else
880             pTrackUp->setEnabled( false );
881 
882         if( selectedTracks.last() < trackList->topLevelItemCount() )
883             pTrackDown->setEnabled( true );
884         else
885             pTrackDown->setEnabled( false );
886 
887         QString trackListString = "";
888         if( selectedTracks.count() == trackList->topLevelItemCount() )
889         {
890             trackListString = i18n("All tracks");
891         }
892         else
893         {
894             trackListString = i18n("Tracks") + QString().sprintf( " %02i", selectedTracks.at(0) );
895             for( int i=1; i<selectedTracks.count(); i++ )
896             {
897                 trackListString += QString().sprintf( ", %02i", selectedTracks.at(i) );
898             }
899         }
900         tagGroupBox->setTitle( trackListString );
901 
902         const QString title = tags.at(selectedTracks.at(0))->title;
903         bool equalTitles = true;
904         const QString artist = tags.at(selectedTracks.at(0))->artist;
905         bool equalArtists = true;
906         const QString composer = tags.at(selectedTracks.at(0))->composer;
907         bool equalComposers = true;
908         const QString comment = tags.at(selectedTracks.at(0))->comment;
909         bool equalComments = true;
910         for( int i=1; i<selectedTracks.count(); i++ )
911         {
912             if( title != tags.at(selectedTracks.at(i))->title )
913                 equalTitles = false;
914             if( artist != tags.at(selectedTracks.at(i))->artist )
915                 equalArtists = false;
916             if( composer != tags.at(selectedTracks.at(i))->composer )
917                 equalComposers = false;
918             if( comment != tags.at(selectedTracks.at(i))->comment )
919                 equalComments = false;
920         }
921 
922         if( equalTitles )
923         {
924             lTrackTitle->setEnabled( true );
925             lTrackTitle->setText( title );
926             pTrackTitleEdit->hide();
927         }
928         else
929         {
930             lTrackTitle->setEnabled( false );
931             lTrackTitle->setText( "" );
932             pTrackTitleEdit->show();
933         }
934 
935         if( equalArtists )
936         {
937             lTrackArtist->setEnabled( true );
938             lTrackArtist->setText( artist );
939             pTrackArtistEdit->hide();
940         }
941         else
942         {
943             lTrackArtist->setEnabled( false );
944             lTrackArtist->setText( "" );
945             pTrackArtistEdit->show();
946         }
947 
948         if( equalComposers )
949         {
950             lTrackComposer->setEnabled( true );
951             lTrackComposer->setText( composer );
952             pTrackComposerEdit->hide();
953         }
954         else
955         {
956             lTrackComposer->setEnabled( false );
957             lTrackComposer->setText( "" );
958             pTrackComposerEdit->show();
959         }
960 
961         if( equalComments )
962         {
963             tTrackComment->setEnabled( true );
964             tTrackComment->setReadOnly( false );
965             tTrackComment->setText( comment );
966             pTrackCommentEdit->hide();
967         }
968         else
969         {
970             tTrackComment->setEnabled( false );
971             tTrackComment->setReadOnly( true );
972             tTrackComment->setText( "" );
973             pTrackCommentEdit->show();
974         }
975     }
976     else
977     {
978         if( selectedTracks.first() > 1 )
979             pTrackUp->setEnabled( true );
980         else
981             pTrackUp->setEnabled( false );
982 
983         if( selectedTracks.last() < trackList->topLevelItemCount() )
984             pTrackDown->setEnabled( true );
985         else
986             pTrackDown->setEnabled( false );
987 
988         tagGroupBox->setTitle( i18n("Track") + QString().sprintf(" %02i",selectedTracks.at(0)) );
989 
990         lTrackTitle->setEnabled( true );
991         lTrackTitle->setText( tags.at(selectedTracks.at(0))->title );
992         pTrackTitleEdit->hide();
993 
994         lTrackArtist->setEnabled( true );
995         lTrackArtist->setText( tags.at(selectedTracks.at(0))->artist );
996         pTrackArtistEdit->hide();
997 
998         lTrackComposer->setEnabled( true );
999         lTrackComposer->setText( tags.at(selectedTracks.at(0))->composer );
1000         pTrackComposerEdit->hide();
1001 
1002         tTrackComment->setEnabled( true );
1003         tTrackComment->setReadOnly( false );
1004         tTrackComment->setText( tags.at(selectedTracks.at(0))->comment );
1005         pTrackCommentEdit->hide();
1006     }
1007 }
1008 
artistChanged(const QString & text)1009 void CDOpener::artistChanged( const QString& text )
1010 {
1011     for( int i=1; i<tags.count(); i++ )
1012     {
1013         if( tags.at(i)->artist == lastAlbumArtist )
1014         {
1015             tags.at(i)->artist = text;
1016             if( QTreeWidgetItem *item = trackList->topLevelItem( i-1 ) )
1017             {
1018                 item->setText( Column_Artist, text );
1019             }
1020         }
1021     }
1022 
1023     tags.at(0)->artist = text;
1024 
1025     lastAlbumArtist = text;
1026 
1027     adjustArtistColumn();
1028     trackChanged();
1029 }
1030 
adjustArtistColumn()1031 void CDOpener::adjustArtistColumn()
1032 {
1033     QString albumArtist = tags.at(0)->artist;
1034 
1035     for( int i=1; i<tags.count(); i++ )
1036     {
1037         if( tags.at(i)->artist != albumArtist )
1038         {
1039             trackList->setColumnHidden( Column_Artist, false );
1040             return;
1041         }
1042     }
1043 
1044     trackList->setColumnHidden( Column_Artist, true );
1045 }
1046 
adjustComposerColumn()1047 void CDOpener::adjustComposerColumn()
1048 {
1049     for( int i=1; i<tags.count(); i++ )
1050     {
1051         if( !tags.at(i)->composer.isEmpty() )
1052         {
1053             trackList->setColumnHidden( Column_Composer, false );
1054             return;
1055         }
1056     }
1057 
1058     trackList->setColumnHidden( Column_Composer, true );
1059 }
1060 
trackTitleChanged(const QString & text)1061 void CDOpener::trackTitleChanged( const QString& text )
1062 {
1063     if( !lTrackTitle->isEnabled() )
1064         return;
1065 
1066     for( int i=0; i<selectedTracks.count(); i++ )
1067     {
1068         QTreeWidgetItem *item = trackList->topLevelItem( selectedTracks.at(i)-1 );
1069         if( item )
1070             item->setText( Column_Title, text );
1071         tags.at(selectedTracks.at(i))->title = text;
1072     }
1073 }
1074 
trackArtistChanged(const QString & text)1075 void CDOpener::trackArtistChanged( const QString& text )
1076 {
1077     if( !lTrackArtist->isEnabled() )
1078         return;
1079 
1080     for( int i=0; i<selectedTracks.count(); i++ )
1081     {
1082         QTreeWidgetItem *item = trackList->topLevelItem( selectedTracks.at(i)-1 );
1083         if( item )
1084             item->setText( Column_Artist, text );
1085         tags.at(selectedTracks.at(i))->artist = text;
1086     }
1087 
1088     adjustArtistColumn();
1089 }
1090 
trackComposerChanged(const QString & text)1091 void CDOpener::trackComposerChanged( const QString& text )
1092 {
1093     if( !lTrackComposer->isEnabled() )
1094         return;
1095 
1096     for( int i=0; i<selectedTracks.count(); i++ )
1097     {
1098         QTreeWidgetItem *item = trackList->topLevelItem( selectedTracks.at(i)-1 );
1099         if( item )
1100             item->setText( Column_Composer, text );
1101         tags.at(selectedTracks.at(i))->composer = text;
1102     }
1103 
1104     adjustComposerColumn();
1105 }
1106 
trackCommentChanged()1107 void CDOpener::trackCommentChanged()
1108 {
1109     QString text = tTrackComment->toPlainText();
1110 
1111     if( !tTrackComment->isEnabled() )
1112         return;
1113 
1114     for( int i=0; i<selectedTracks.count(); i++ )
1115     {
1116         tags.at(selectedTracks.at(i))->comment = text;
1117     }
1118 }
1119 
editTrackTitleClicked()1120 void CDOpener::editTrackTitleClicked()
1121 {
1122     lTrackTitle->setEnabled( true );
1123     lTrackTitle->setFocus();
1124     pTrackTitleEdit->hide();
1125     trackTitleChanged( lTrackTitle->text() );
1126 }
1127 
editTrackArtistClicked()1128 void CDOpener::editTrackArtistClicked()
1129 {
1130     lTrackArtist->setEnabled( true );
1131     lTrackArtist->setFocus();
1132     pTrackArtistEdit->hide();
1133     trackArtistChanged( lTrackArtist->text() );
1134 }
1135 
editTrackComposerClicked()1136 void CDOpener::editTrackComposerClicked()
1137 {
1138     lTrackComposer->setEnabled( true );
1139     lTrackComposer->setFocus();
1140     pTrackComposerEdit->hide();
1141     trackComposerChanged( lTrackComposer->text() );
1142 }
1143 
editTrackCommentClicked()1144 void CDOpener::editTrackCommentClicked()
1145 {
1146     tTrackComment->setEnabled( true );
1147     tTrackComment->setReadOnly( false );
1148     tTrackComment->setFocus();
1149     pTrackCommentEdit->hide();
1150     trackCommentChanged();
1151 }
1152 
fadeIn()1153 void CDOpener::fadeIn()
1154 {
1155     fadeTimer.start( 50 );
1156     fadeMode = 1;
1157     cdOpenerOverlayWidget->show();
1158 }
1159 
fadeOut()1160 void CDOpener::fadeOut()
1161 {
1162     fadeTimer.start( 50 );
1163     fadeMode = 2;
1164 }
1165 
fadeAnim()1166 void CDOpener::fadeAnim()
1167 {
1168     if( fadeMode == 1 )
1169     {
1170         fadeAlpha += 255.0f/50.0f*8.0f;
1171     }
1172     else if( fadeMode == 2 )
1173     {
1174         fadeAlpha -= 255.0f/50.0f*8.0f;
1175     }
1176 
1177     if( fadeAlpha <= 0.0f )
1178     {
1179         fadeAlpha = 0.0f;
1180         fadeMode = 0;
1181         cdOpenerOverlayWidget->hide();
1182     }
1183     else if( fadeAlpha >= 255.0f )
1184     {
1185         fadeAlpha = 255.0f;
1186         fadeMode = 0;
1187     }
1188     else
1189     {
1190         fadeTimer.start( 50 );
1191     }
1192 
1193     QPalette newPalette = cdOpenerOverlayWidget->palette();
1194     newPalette.setBrush( QPalette::Window, brushSetAlpha( newPalette.window(), 192.0f/255.0f*fadeAlpha ) );
1195     cdOpenerOverlayWidget->setPalette( newPalette );
1196 
1197     newPalette = lOverlayLabel->palette();
1198     newPalette.setBrush( QPalette::WindowText, brushSetAlpha( newPalette.windowText(), fadeAlpha ) );
1199     lOverlayLabel->setPalette( newPalette );
1200 }
1201 
proceedClicked()1202 void CDOpener::proceedClicked()
1203 {
1204     int trackCount = 0;
1205 
1206     for( int i=0; i<trackList->topLevelItemCount(); i++ )
1207     {
1208         if( trackList->topLevelItem(i)->checkState(0) == Qt::Checked )
1209             trackCount++;
1210     }
1211 
1212     if( trackCount == 0 )
1213     {
1214         KMessageBox::error( this, i18n("Please select at least one track in order to proceed.") );
1215         return;
1216     }
1217 
1218     if( options->currentConversionOptions() && options->currentConversionOptions()->outputDirectoryMode == OutputDirectory::Source )
1219     {
1220         options->setOutputDirectoryMode( (int)OutputDirectory::MetaData );
1221     }
1222 
1223     cdOpenerWidget->hide();
1224     pSaveCue->hide();
1225     pCDDB->hide();
1226     cEntireCd->hide();
1227     options->show();
1228     page = ConversionOptionsPage;
1229     QFont font;
1230     font.setBold( false );
1231     lSelector->setFont( font );
1232     font.setBold( true );
1233     lOptions->setFont( font );
1234     pProceed->hide();
1235     pAdd->show();
1236 }
1237 
addClicked()1238 void CDOpener::addClicked()
1239 {
1240     ConversionOptions *conversionOptions = options->currentConversionOptions();
1241     if( conversionOptions )
1242     {
1243         QList<int> tracks;
1244         QList<TagData*> tagList;
1245         const int trackCount = cdda_audio_tracks( cdDrive );
1246 
1247         if( cEntireCd->isEnabled() && cEntireCd->isChecked() )
1248         {
1249             tags.at(0)->title = lAlbum->text();
1250             tags.at(0)->artist = lArtist->text();
1251             tags.at(0)->albumArtist = lArtist->text();
1252             tags.at(0)->album = lAlbum->text();
1253             tags.at(0)->disc = iDisc->value();
1254             tags.at(0)->discTotal = iDiscTotal->value();
1255             tags.at(0)->year = iYear->value();
1256             tags.at(0)->genre = cGenre->currentText();
1257             const long size = CD_FRAMESIZE_RAW * (cdda_track_lastsector(cdDrive,trackCount)-cdda_track_firstsector(cdDrive,1));
1258             tags.at(0)->length = (8 * size) / (44100 * 2 * 16);
1259 
1260             tagList.append( tags.at(0) );
1261             tracks.append( 0 );
1262         }
1263         else
1264         {
1265             for( int i=0; i<trackList->topLevelItemCount(); i++ )
1266             {
1267                 if( trackList->topLevelItem(i)->checkState(0) == Qt::Checked )
1268                 {
1269                     tags.at(i+1)->albumArtist = lArtist->text();
1270                     tags.at(i+1)->album = lAlbum->text();
1271                     tags.at(i+1)->disc = iDisc->value();
1272                     tags.at(i+1)->discTotal = iDiscTotal->value();
1273                     tags.at(i+1)->year = iYear->value();
1274                     tags.at(i+1)->genre = cGenre->currentText();
1275                     const long size = CD_FRAMESIZE_RAW * (cdda_track_lastsector(cdDrive,i+1)-cdda_track_firstsector(cdDrive,i+1));
1276                     tags.at(i+1)->length = (8 * size) / (44100 * 2 * 16);
1277 
1278                     tagList.append( tags.at(i+1) );
1279                     tracks.append( i+1 );
1280                 }
1281             }
1282         }
1283 
1284         options->accepted();
1285 
1286         emit addTracks( device, tracks, trackCount, tagList, conversionOptions, command );
1287 
1288         accept();
1289     }
1290     else
1291     {
1292         KMessageBox::error( this, i18n("No conversion options selected.") );
1293     }
1294 }
1295 
saveCuesheetClicked()1296 void CDOpener::saveCuesheetClicked()
1297 {
1298     QString filename = KFileDialog::getSaveFileName( QDir::homePath(), "*.cue" );
1299     if( filename.isEmpty() )
1300         return;
1301 
1302     QFile cueFile( filename );
1303     if( cueFile.exists() )
1304     {
1305         const int ret = KMessageBox::questionYesNo( this,
1306                     i18n("A file with this name already exists.\n\nDo you want to overwrite the existing one?"),
1307                     i18n("File already exists") );
1308         if( ret == KMessageBox::No )
1309             return;
1310     }
1311     if( !cueFile.open( QIODevice::WriteOnly ) )
1312         return;
1313 
1314     QString content;
1315 
1316     content.append( "REM COMMENT \"soundKonverter " + QString(SOUNDKONVERTER_VERSION_STRING) + "\"\n" );
1317     content.append( "TITLE \"" + lAlbum->text() + "\"\n" );
1318     content.append( "PERFORMER \"" + lArtist->text() + "\"\n" );
1319     content.append( "FILE \"\" WAVE\n" );
1320 
1321     for( int i=1; i<tags.count(); i++ )
1322     {
1323         content.append( QString().sprintf("  TRACK %02i AUDIO\n",tags.at(i)->track ) );
1324         content.append( "    TITLE \"" + tags.at(i)->title + "\"\n" );
1325         content.append( "    PERFORMER \"" + tags.at(i)->artist + "\"\n" );
1326         content.append( "    SONGWRITER \"" + tags.at(i)->composer + "\"\n" );
1327         const long size = CD_FRAMESIZE_RAW * cdda_track_firstsector(cdDrive,i);
1328         const long length = (8 * size) / (44100 * 2 * 16);
1329         const long frames = (8 * size) / (588 * 2 * 16);
1330         content.append( QString().sprintf("    INDEX 01 %02li:%02li:%02li\n",length/60,length%60,frames%75) );
1331     }
1332 
1333     QTextStream ts( &cueFile );
1334     ts << content;
1335 
1336     cueFile.close();
1337 }
1338 
1339 // void CDOpener::itemHighlighted( QTreeWidgetItem *item, int column )
1340 // {
1341 //     for( int i=0; i<playerWidgets.count(); i++ )
1342 //     {
1343 //         if( item == playerWidgets.at(i)->treeWidgetItem() )
1344 //             playerWidgets[i]->show();
1345 //         else if( !playerWidgets.at(i)->isPlaying() )
1346 //             playerWidgets[i]->hide();
1347 //     }
1348 // }
1349 
startPlayback(int track)1350 void CDOpener::startPlayback( int track )
1351 {
1352     for( int i=0; i<playerWidgets.count(); i++ )
1353     {
1354         if( i+1 != track && playerWidgets.at(i)->isPlaying() )
1355             playerWidgets[i]->trackChanged( track );
1356     }
1357 
1358     mediaController->setCurrentTitle( track );
1359     mediaObject->play();
1360 }
1361 
stopPlayback()1362 void CDOpener::stopPlayback()
1363 {
1364     mediaObject->stop();
1365 }
1366 
playbackTitleChanged(int title)1367 void CDOpener::playbackTitleChanged( int title )
1368 {
1369     for( int i=0; i<playerWidgets.count(); i++ )
1370     {
1371         if( ( i+1 != title &&  playerWidgets.at(i)->isPlaying() ) ||
1372             ( i+1 == title && !playerWidgets.at(i)->isPlaying() )
1373         )
1374             playerWidgets[i]->trackChanged( title );
1375     }
1376 }
1377 
playbackStateChanged(Phonon::State newstate,Phonon::State oldstate)1378 void CDOpener::playbackStateChanged( Phonon::State newstate, Phonon::State oldstate )
1379 {
1380     Q_UNUSED(oldstate)
1381 
1382     if( newstate == Phonon::StoppedState )
1383     {
1384         playbackTitleChanged( 0 );
1385     }
1386     else if( newstate == Phonon::PlayingState )
1387     {
1388         playbackTitleChanged( mediaController->currentTitle() );
1389     }
1390 }
1391 
1392 
1393