mirror of
https://github.com/clementine-player/Clementine
synced 2025-01-31 11:35:24 +01:00
UI integration, needs beautification
Incorporates the 'Select Destiny' feature from 062889b, fetches values provided by user to populate file tags, UI adjustments
This commit is contained in:
parent
34c178af65
commit
a5021e656b
360
src/ui/ripcd.cpp
360
src/ui/ripcd.cpp
@ -1,26 +1,30 @@
|
|||||||
/* This file is part of Clementine.
|
/* This file is part of Clementine.
|
||||||
Copyright 2014, Andre Siviero <altsiviero@gmail.com>
|
Copyright 2014, Andre Siviero <altsiviero@gmail.com>
|
||||||
|
|
||||||
Clementine is free software: you can redistribute it and/or modify
|
Clementine is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
|
|
||||||
Clementine is distributed in the hope that it will be useful,
|
Clementine is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
|
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "ripcd.h"
|
#include "ripcd.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "ui_ripcd.h"
|
#include "ui_ripcd.h"
|
||||||
#include "transcoder/transcoder.h"
|
#include "transcoder/transcoder.h"
|
||||||
|
#include "transcoder/transcoderoptionsdialog.h"
|
||||||
|
#include "ui/iconloader.h"
|
||||||
|
|
||||||
#include <QSettings>
|
#include <QSettings>
|
||||||
#include <QCheckBox>
|
#include <QCheckBox>
|
||||||
|
#include <QFileDialog>
|
||||||
#include <QFrame>
|
#include <QFrame>
|
||||||
#include <QLineEdit>
|
#include <QLineEdit>
|
||||||
#include <QtDebug>
|
#include <QtDebug>
|
||||||
@ -44,66 +48,153 @@
|
|||||||
# undef AddJob
|
# undef AddJob
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
RipCD::RipCD(QWidget* parent)
|
static bool ComparePresetsByName(const TranscoderPreset& left,
|
||||||
: QDialog(parent),
|
const TranscoderPreset& right) {
|
||||||
transcoder_(new Transcoder(this)),
|
return left.name_ < right.name_;
|
||||||
queued_(0),
|
}
|
||||||
finished_success_(0),
|
|
||||||
finished_failed_(0),
|
const char* RipCD::kSettingsGroup = "Transcoder";
|
||||||
checkboxes_(QList<QCheckBox*>()),
|
const int RipCD::kProgressInterval = 500;
|
||||||
generated_files_(QList<QString>())
|
const int RipCD::kMaxDestinationItems = 10;
|
||||||
{
|
|
||||||
|
RipCD::RipCD(QWidget* parent) :
|
||||||
|
QDialog(parent), transcoder_(new Transcoder(this)), queued_(0), finished_success_(
|
||||||
|
0), finished_failed_(0), ui_(new Ui_RipCD()), checkboxes_(
|
||||||
|
QList<QCheckBox*>()), generated_files_(QList<QString>()), tracks_to_rip_(
|
||||||
|
QList<int>()), track_names_(QList<QLineEdit*>()) {
|
||||||
// Init
|
// Init
|
||||||
ui_.setupUi(this);
|
ui_->setupUi(this);
|
||||||
connect(ui_.ripButton,SIGNAL(clicked()),this,SLOT(clickedRipButton()));
|
cancel_button_ = ui_->button_box->button(QDialogButtonBox::Cancel);
|
||||||
|
|
||||||
|
connect(ui_->ripButton, SIGNAL(clicked()), this, SLOT(clickedRipButton()));
|
||||||
|
connect(cancel_button_, SIGNAL(clicked()), SLOT(Cancel()));
|
||||||
|
|
||||||
connect(transcoder_, SIGNAL(JobComplete(QString,bool)), SLOT(JobComplete(QString,bool)));
|
connect(transcoder_, SIGNAL(JobComplete(QString,bool)), SLOT(JobComplete(QString,bool)));
|
||||||
connect(transcoder_, SIGNAL(AllJobsComplete()), SLOT(AllJobsComplete()));
|
connect(transcoder_, SIGNAL(AllJobsComplete()), SLOT(AllJobsComplete()));
|
||||||
connect(transcoder_, SIGNAL(JobOutputName(QString)), SLOT(AppendOutput(QString)));
|
connect(transcoder_, SIGNAL(JobOutputName(QString)),
|
||||||
|
SLOT(AppendOutput(QString)));
|
||||||
connect(this, SIGNAL(RippingComplete()), SLOT(threadedTranscoding()));
|
connect(this, SIGNAL(RippingComplete()), SLOT(threadedTranscoding()));
|
||||||
|
connect(this, SIGNAL(signalUpdateProgress()), SLOT(UpdateProgress()));
|
||||||
|
|
||||||
|
connect(ui_->options, SIGNAL(clicked()), SLOT(Options()));
|
||||||
|
connect(ui_->select, SIGNAL(clicked()), SLOT(AddDestination()));
|
||||||
|
|
||||||
setWindowTitle(tr("Rip CD"));
|
setWindowTitle(tr("Rip CD"));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//track_t i_first_track;
|
//track_t i_first_track;
|
||||||
p_cdio = cdio_open(NULL, DRIVER_UNKNOWN);
|
p_cdio = cdio_open(NULL, DRIVER_UNKNOWN);
|
||||||
//i_first_track = cdio_get_first_track_num(p_cdio);
|
//i_first_track = cdio_get_first_track_num(p_cdio);
|
||||||
i_tracks = cdio_get_num_tracks(p_cdio);
|
i_tracks = cdio_get_num_tracks(p_cdio);
|
||||||
ui_.tableWidget->setRowCount(i_tracks);
|
ui_->tableWidget->setRowCount(i_tracks);
|
||||||
for(int i=1; i<=i_tracks; i++) {
|
for (int i = 1; i <= i_tracks; i++) {
|
||||||
qDebug() << i;
|
QCheckBox *_t = new QCheckBox(tr(""), ui_->tableWidget);
|
||||||
QCheckBox *_t = new QCheckBox(tr(""), ui_.tableWidget);
|
_t->click();
|
||||||
checkboxes_.append(_t);
|
checkboxes_.append(_t);
|
||||||
ui_.tableWidget->setCellWidget(i-1,0,_t);
|
ui_->tableWidget->setCellWidget(i - 1, 0, _t);
|
||||||
ui_.tableWidget->setCellWidget(i-1,1,new QLabel(QString::number(i)));
|
ui_->tableWidget->setCellWidget(i - 1, 1, new QLabel(QString::number(i)));
|
||||||
QString _str_track;
|
QString _str_track;
|
||||||
_str_track = "Track %1";
|
_str_track = "Track %1";
|
||||||
ui_.tableWidget->setCellWidget(i-1,2,new QLineEdit(_str_track.arg(QString::number(i)),ui_.tableWidget));
|
QLineEdit *_ql = new QLineEdit(_str_track.arg(QString::number(i)),
|
||||||
|
ui_->tableWidget);
|
||||||
|
track_names_.append(_ql);
|
||||||
|
ui_->tableWidget->setCellWidget(i - 1, 2, _ql);
|
||||||
|
}
|
||||||
|
// Get presets
|
||||||
|
QList < TranscoderPreset > presets = Transcoder::GetAllPresets();
|
||||||
|
qSort(presets.begin(), presets.end(), ComparePresetsByName);
|
||||||
|
foreach (const TranscoderPreset& preset, presets) {
|
||||||
|
ui_->format->addItem(
|
||||||
|
QString("%1 (.%2)").arg(preset.name_, preset.extension_),
|
||||||
|
QVariant::fromValue(preset));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load settings
|
||||||
|
QSettings s;
|
||||||
|
s.beginGroup(kSettingsGroup);
|
||||||
|
last_add_dir_ = s.value("last_add_dir", QDir::homePath()).toString();
|
||||||
|
|
||||||
|
QString last_output_format = s.value("last_output_format", "ogg").toString();
|
||||||
|
for (int i = 0; i < ui_->format->count(); ++i) {
|
||||||
|
if (last_output_format
|
||||||
|
== ui_->format->itemData(i).value<TranscoderPreset>().extension_) {
|
||||||
|
ui_->format->setCurrentIndex(i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ui_->progress_bar->setValue(0);
|
||||||
|
ui_->progress_bar->setMaximum(100);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RipCD::write_WAV_header(FILE *stream, int32_t i_bytecount) {
|
||||||
|
fwrite("RIFF", sizeof(char), 4, stream);
|
||||||
|
put_num(i_bytecount + 44 - 8, stream, 4); /* 4-7 */
|
||||||
|
fwrite("WAVEfmt ", sizeof(char), 8, stream); /* 8-15 */
|
||||||
|
put_num(16, stream, 4); /* 16-19 */
|
||||||
|
put_num(1, stream, 2); /* 20-21 */
|
||||||
|
put_num(2, stream, 2); /* 22-23 */
|
||||||
|
put_num(44100, stream, 4); /* 24-27 */
|
||||||
|
put_num(44100 * 2 * 2, stream, 4); /* 28-31 */
|
||||||
|
put_num(4, stream, 2); /* 32-33 */
|
||||||
|
put_num(16, stream, 2); /* 34-35 */
|
||||||
|
fwrite("data", sizeof(char), 4, stream); /* 36-39 */
|
||||||
|
put_num(i_bytecount, stream, 4); /* 40-43 */
|
||||||
|
}
|
||||||
|
|
||||||
|
void RipCD::put_num(long int num, FILE *stream, int bytes) {
|
||||||
|
unsigned int i;
|
||||||
|
unsigned char c;
|
||||||
|
|
||||||
|
for (i = 0; bytes--; i++) {
|
||||||
|
c = (num >> (i << 3)) & 0xff;
|
||||||
|
if (fwrite(&c, sizeof(char), 1, stream) == -1) {
|
||||||
|
perror("Could not write to output.");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RipCD::clickedRipButton() {
|
int RipCD::nTracksToRip() {
|
||||||
QtConcurrent::run(this,&RipCD::toThreadClickedRipButton);
|
int k = 0;
|
||||||
|
for (int i = 0; i < checkboxes_.length(); i++) {
|
||||||
|
if (checkboxes_.value(i)->isChecked() == true) {
|
||||||
|
k++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return k;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RipCD::toThreadClickedRipButton() {
|
void RipCD::toThreadClickedRipButton() {
|
||||||
QString source_directory = "/tmp/";
|
QString source_directory = "/tmp/";
|
||||||
//track_t i_tracks = cdio_get_num_tracks(p_cdio);
|
|
||||||
for(int i=1; i <= i_tracks; i++) {
|
finished_success_ = 0;
|
||||||
qDebug() << "Going for track " << i;
|
finished_failed_ = 0;
|
||||||
lsn_t i_first_lsn = cdio_get_track_lsn(p_cdio,i);
|
ui_->progress_bar->setMaximum(nTracksToRip() * 2 * 100);
|
||||||
lsn_t i_last_lsn = cdio_get_track_last_lsn(p_cdio,i);
|
|
||||||
|
emit(signalUpdateProgress());
|
||||||
|
|
||||||
|
// Set up the progressbar
|
||||||
|
|
||||||
|
for (int i = 1; i <= i_tracks; i++) {
|
||||||
|
if (checkboxes_.value(i - 1)->isChecked() == false) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
tracks_to_rip_.append(i);
|
||||||
|
lsn_t i_first_lsn = cdio_get_track_lsn(p_cdio, i);
|
||||||
|
lsn_t i_last_lsn = cdio_get_track_last_lsn(p_cdio, i);
|
||||||
// lsn_t i_last_lsn = i_first_lsn+300; // debug
|
// lsn_t i_last_lsn = i_first_lsn+300; // debug
|
||||||
|
|
||||||
lsn_t i_cursor;
|
lsn_t i_cursor;
|
||||||
int16_t *p_readbuf = (int16_t *)calloc(CDIO_CD_FRAMESIZE_RAW,1);
|
int16_t *p_readbuf = (int16_t *) calloc(CDIO_CD_FRAMESIZE_RAW, 1);
|
||||||
FILE *fp = fopen(QString(source_directory + "track" + QString("0%1").arg(i).right(2) + ".wav").toUtf8().constData(),"w");
|
|
||||||
write_WAV_header(fp,(i_last_lsn-i_first_lsn+1) * CDIO_CD_FRAMESIZE_RAW);
|
QString filename = source_directory + "track"
|
||||||
for ( i_cursor = i_first_lsn; i_cursor <= i_last_lsn; i_cursor ++) {
|
+ QString("0%1").arg(i).right(2) + ".wav";
|
||||||
cdio_read_audio_sector(p_cdio,p_readbuf,i_cursor);
|
FILE *fp = fopen(filename.toUtf8().constData(), "w");
|
||||||
if( !p_readbuf ) {
|
write_WAV_header(fp,
|
||||||
|
(i_last_lsn - i_first_lsn + 1) * CDIO_CD_FRAMESIZE_RAW);
|
||||||
|
for (i_cursor = i_first_lsn; i_cursor <= i_last_lsn; i_cursor++) {
|
||||||
|
cdio_read_audio_sector(p_cdio, p_readbuf, i_cursor);
|
||||||
|
if (!p_readbuf) {
|
||||||
qDebug() << "Read error. Stopping.";
|
qDebug() << "Read error. Stopping.";
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
@ -111,80 +202,139 @@ void RipCD::toThreadClickedRipButton() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
finished_success_++;
|
||||||
|
emit(signalUpdateProgress());
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
free(p_readbuf);
|
free(p_readbuf);
|
||||||
p_readbuf = NULL;
|
p_readbuf = NULL;
|
||||||
|
|
||||||
|
//TranscoderPreset preset(Transcoder::PresetForFileType(Song::Type_OggVorbis));
|
||||||
|
TranscoderPreset preset =
|
||||||
|
ui_->format->itemData(ui_->format->currentIndex()).value<
|
||||||
|
TranscoderPreset>();
|
||||||
|
|
||||||
|
QString outfilename = GetOutputFileName(filename, preset);
|
||||||
|
transcoder_->AddJob(filename.toUtf8().constData(), preset, outfilename);
|
||||||
}
|
}
|
||||||
emit(RippingComplete());
|
emit (RippingComplete());}
|
||||||
|
|
||||||
|
// Returns the rightmost non-empty part of 'path'.
|
||||||
|
QString RipCD::TrimPath(const QString& path) const {
|
||||||
|
return path.section('/', -1, -1, QString::SectionSkipEmpty);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString RipCD::GetOutputFileName(const QString& input,
|
||||||
|
const TranscoderPreset &preset) const {
|
||||||
|
QString path =
|
||||||
|
ui_->destination->itemData(ui_->destination->currentIndex()).toString();
|
||||||
|
if (path.isEmpty()) {
|
||||||
|
// Keep the original path.
|
||||||
|
return input.section('.', 0, -2) + '.' + preset.extension_;
|
||||||
|
} else {
|
||||||
|
QString file_name = TrimPath(input);
|
||||||
|
file_name = file_name.section('.', 0, -2);
|
||||||
|
return path + '/' + file_name + '.' + preset.extension_;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RipCD::UpdateProgress() {
|
||||||
|
int progress = (finished_success_ + finished_failed_) * 100;
|
||||||
|
QMap<QString, float> current_jobs = transcoder_->GetProgress();
|
||||||
|
foreach (float value, current_jobs.values()) {
|
||||||
|
progress += qBound(0, int(value * 100), 99);
|
||||||
|
}
|
||||||
|
|
||||||
|
ui_->progress_bar->setValue(progress);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RipCD::threadedTranscoding() {
|
void RipCD::threadedTranscoding() {
|
||||||
QString source_directory = "/tmp/";
|
|
||||||
//track_t i_tracks = cdio_get_num_tracks(p_cdio);
|
|
||||||
|
|
||||||
TranscoderPreset preset(Transcoder::PresetForFileType(Song::Type_OggVorbis));
|
|
||||||
for(int i=1; i <= i_tracks; i++) {
|
|
||||||
transcoder_->AddJob(QString(source_directory + "track" + QString("0%1").arg(i).right(2) + ".wav").toUtf8().constData(), preset);
|
|
||||||
}
|
|
||||||
qDebug() << "Total jobs: " << transcoder_->QueuedJobsCount();
|
|
||||||
transcoder_->Start();
|
transcoder_->Start();
|
||||||
|
TranscoderPreset preset =
|
||||||
|
ui_->format->itemData(ui_->format->currentIndex()).value<TranscoderPreset>();
|
||||||
|
// Save the last output format
|
||||||
|
QSettings s;
|
||||||
|
s.beginGroup(kSettingsGroup);
|
||||||
|
s.setValue("last_output_format", preset.extension_);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RipCD::put_num(long int num, FILE *stream, int bytes) {
|
void RipCD::clickedRipButton() {
|
||||||
unsigned int i;
|
QtConcurrent::run(this, &RipCD::toThreadClickedRipButton);
|
||||||
unsigned char c;
|
|
||||||
|
|
||||||
for (i=0; bytes--; i++) {
|
|
||||||
c = (num >> (i<<3)) & 0xff;
|
|
||||||
if (fwrite(&c, sizeof(char), 1, stream)==-1) {
|
|
||||||
perror("Could not write to output.");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void RipCD::write_WAV_header(FILE *stream,int32_t i_bytecount) {
|
|
||||||
fwrite("RIFF",sizeof(char),4,stream);
|
|
||||||
put_num(i_bytecount+44-8, stream, 4); /* 4-7 */
|
|
||||||
fwrite("WAVEfmt ",sizeof(char),8,stream); /* 8-15 */
|
|
||||||
put_num(16, stream, 4); /* 16-19 */
|
|
||||||
put_num(1, stream, 2); /* 20-21 */
|
|
||||||
put_num(2, stream, 2); /* 22-23 */
|
|
||||||
put_num(44100, stream, 4); /* 24-27 */
|
|
||||||
put_num(44100*2*2, stream, 4); /* 28-31 */
|
|
||||||
put_num(4, stream, 2); /* 32-33 */
|
|
||||||
put_num(16, stream, 2); /* 34-35 */
|
|
||||||
fwrite("data",sizeof(char),4,stream); /* 36-39 */
|
|
||||||
put_num(i_bytecount, stream, 4); /* 40-43 */
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void RipCD::AllJobsComplete() {
|
|
||||||
qDebug() << "All Jobs Complete emmited";
|
|
||||||
// TODO Handle this properly
|
|
||||||
// having a little trouble on wav files, works fine on ogg
|
|
||||||
qSort(generated_files_);
|
|
||||||
int i;
|
|
||||||
for(i = 1; i <= i_tracks; i++) {
|
|
||||||
qDebug() << generated_files_.value(i-1);
|
|
||||||
TagLib::FileRef f(generated_files_.value(i-1).toUtf8().constData());
|
|
||||||
if(checkboxes_.value(i-1)->isChecked() == true) {
|
|
||||||
f.tag()->setArtist(ui_.artistLineEdit->text().toUtf8().constData());
|
|
||||||
}
|
|
||||||
f.save();
|
|
||||||
}
|
|
||||||
// Resets list
|
|
||||||
generated_files_.QList<QString>::~QList<QString>();
|
|
||||||
generated_files_ = QList<QString>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RipCD::JobComplete(const QString& filename, bool success) {
|
void RipCD::JobComplete(const QString& filename, bool success) {
|
||||||
qDebug() << "Completed";
|
(*(success ? &finished_success_ : &finished_failed_))++;
|
||||||
|
emit(signalUpdateProgress());
|
||||||
|
}
|
||||||
|
|
||||||
|
void RipCD::AllJobsComplete() {
|
||||||
|
|
||||||
|
// having a little trouble on wav files, works fine on ogg-vorbis
|
||||||
|
qSort(generated_files_);
|
||||||
|
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < generated_files_.length(); i++) {
|
||||||
|
TagLib::FileRef f(generated_files_.value(i).toUtf8().constData());
|
||||||
|
|
||||||
|
f.tag()->setTitle(
|
||||||
|
track_names_.value(tracks_to_rip_.value(i) - 1)->text().toUtf8().constData());
|
||||||
|
f.tag()->setAlbum(ui_->albumLineEdit->text().toUtf8().constData());
|
||||||
|
f.tag()->setArtist(ui_->artistLineEdit->text().toUtf8().constData());
|
||||||
|
f.tag()->setGenre(ui_->genreLineEdit->text().toUtf8().constData());
|
||||||
|
f.tag()->setYear(ui_->yearLineEdit->text().toInt());
|
||||||
|
f.tag()->setTrack(tracks_to_rip_.value(i) - 1);
|
||||||
|
// Need to check this
|
||||||
|
//f.tag()->setDisc(ui_->discLineEdit->text().toInt());
|
||||||
|
f.save();
|
||||||
|
}
|
||||||
|
// Resets lists
|
||||||
|
generated_files_.clear();
|
||||||
|
tracks_to_rip_.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RipCD::AppendOutput(const QString &filename) {
|
void RipCD::AppendOutput(const QString &filename) {
|
||||||
qDebug() << filename;
|
|
||||||
generated_files_.append(filename);
|
generated_files_.append(filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RipCD::Options() {
|
||||||
|
TranscoderPreset preset =
|
||||||
|
ui_->format->itemData(ui_->format->currentIndex()).value<TranscoderPreset>();
|
||||||
|
|
||||||
|
TranscoderOptionsDialog dialog(preset.type_, this);
|
||||||
|
if (dialog.is_valid()) {
|
||||||
|
dialog.exec();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adds a folder to the destination box.
|
||||||
|
void RipCD::AddDestination() {
|
||||||
|
int index = ui_->destination->currentIndex();
|
||||||
|
QString initial_dir = (
|
||||||
|
!ui_->destination->itemData(index).isNull() ?
|
||||||
|
ui_->destination->itemData(index).toString() : QDir::homePath());
|
||||||
|
QString dir = QFileDialog::getExistingDirectory(this, tr("Add folder"),
|
||||||
|
initial_dir);
|
||||||
|
|
||||||
|
if (!dir.isEmpty()) {
|
||||||
|
// Keep only a finite number of items in the box.
|
||||||
|
while (ui_->destination->count() >= kMaxDestinationItems) {
|
||||||
|
ui_->destination->removeItem(1); // The oldest folder item.
|
||||||
|
}
|
||||||
|
|
||||||
|
QIcon icon = IconLoader::Load("folder");
|
||||||
|
QVariant data = QVariant::fromValue(dir);
|
||||||
|
// Do not insert duplicates.
|
||||||
|
int duplicate_index = ui_->destination->findData(data);
|
||||||
|
if (duplicate_index == -1) {
|
||||||
|
ui_->destination->addItem(icon, dir, data);
|
||||||
|
ui_->destination->setCurrentIndex(ui_->destination->count() - 1);
|
||||||
|
} else {
|
||||||
|
ui_->destination->setCurrentIndex(duplicate_index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RipCD::Cancel() {
|
||||||
|
transcoder_->Cancel();
|
||||||
|
}
|
||||||
|
@ -1,19 +1,19 @@
|
|||||||
/* This file is part of Clementine.
|
/* This file is part of Clementine.
|
||||||
Copyright 2014, Andre Siviero <altsiviero@gmail.com>
|
Copyright 2014, Andre Siviero <altsiviero@gmail.com>
|
||||||
|
|
||||||
Clementine is free software: you can redistribute it and/or modify
|
Clementine is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
|
|
||||||
Clementine is distributed in the hope that it will be useful,
|
Clementine is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
|
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef RIPCD_H
|
#ifndef RIPCD_H
|
||||||
#define RIPCD_H
|
#define RIPCD_H
|
||||||
@ -24,39 +24,60 @@
|
|||||||
#include <cdio/cdio.h>
|
#include <cdio/cdio.h>
|
||||||
#include "ui_ripcd.h"
|
#include "ui_ripcd.h"
|
||||||
|
|
||||||
|
class Ui_RipCD;
|
||||||
class Transcoder;
|
class Transcoder;
|
||||||
|
|
||||||
class RipCD : public QDialog
|
struct TranscoderPreset;
|
||||||
{
|
|
||||||
|
class RipCD: public QDialog {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
// QThread thread;
|
// QThread thread;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
RipCD(QWidget* parent = 0);
|
RipCD(QWidget* parent = 0);
|
||||||
|
static const char* kSettingsGroup;
|
||||||
|
static const int kProgressInterval;
|
||||||
|
static const int kMaxDestinationItems;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Transcoder* transcoder_;
|
Transcoder* transcoder_;
|
||||||
int queued_;
|
int queued_;
|
||||||
int finished_success_;
|
int finished_success_;
|
||||||
int finished_failed_;
|
int finished_failed_;
|
||||||
track_t i_tracks;
|
track_t i_tracks;
|
||||||
Ui::RipCD ui_;
|
Ui_RipCD* ui_;
|
||||||
CdIo_t *p_cdio;
|
CdIo_t *p_cdio;
|
||||||
void write_WAV_header(FILE *stream,int32_t i_bytecount);
|
|
||||||
void put_num(long int num, FILE *stream, int bytes);
|
|
||||||
void toThreadClickedRipButton();
|
|
||||||
|
|
||||||
QList<QCheckBox*> checkboxes_;
|
QList<QCheckBox*> checkboxes_;
|
||||||
QList<QString> generated_files_;
|
QList<QString> generated_files_;
|
||||||
|
QList<int> tracks_to_rip_;
|
||||||
|
QList<QLineEdit*> track_names_;
|
||||||
|
QString last_add_dir_;
|
||||||
|
QPushButton* cancel_button_;
|
||||||
|
|
||||||
signals:
|
void write_WAV_header(FILE *stream, int32_t i_bytecount);
|
||||||
|
void put_num(long int num, FILE *stream, int bytes);
|
||||||
|
int nTracksToRip();
|
||||||
|
void toThreadClickedRipButton();
|
||||||
|
QString TrimPath(const QString& path) const;
|
||||||
|
QString GetOutputFileName(const QString& input,
|
||||||
|
const TranscoderPreset& preset) const;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
signals:
|
||||||
void RippingComplete();
|
void RippingComplete();
|
||||||
private slots:
|
void signalUpdateProgress();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void UpdateProgress();
|
||||||
void threadedTranscoding();
|
void threadedTranscoding();
|
||||||
void clickedRipButton();
|
void clickedRipButton();
|
||||||
void JobComplete(const QString& filename, bool success);
|
void JobComplete(const QString& filename, bool success);
|
||||||
void AllJobsComplete();
|
void AllJobsComplete();
|
||||||
void AppendOutput(const QString &filename);
|
void AppendOutput(const QString &filename);
|
||||||
|
void Options();
|
||||||
|
void AddDestination();
|
||||||
|
void Cancel();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // RIPCD_H
|
#endif // RIPCD_H
|
||||||
|
160
src/ui/ripcd.ui
160
src/ui/ripcd.ui
@ -16,7 +16,7 @@
|
|||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
<string>Dialog</string>
|
<string>Dialog</string>
|
||||||
</property>
|
</property>
|
||||||
<widget class="QDialogButtonBox" name="buttonBox">
|
<widget class="QDialogButtonBox" name="button_box">
|
||||||
<property name="geometry">
|
<property name="geometry">
|
||||||
<rect>
|
<rect>
|
||||||
<x>240</x>
|
<x>240</x>
|
||||||
@ -60,14 +60,14 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="0">
|
<item row="0" column="0">
|
||||||
<widget class="QLabel" name="title_label">
|
<widget class="QLabel" name="album_label">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Title</string>
|
<string>Album</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="1" colspan="6">
|
<item row="0" column="1" colspan="6">
|
||||||
<widget class="QLineEdit" name="titleLineEdit"/>
|
<widget class="QLineEdit" name="albumLineEdit"/>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="6">
|
<item row="2" column="6">
|
||||||
<widget class="QLineEdit" name="discLineEdit">
|
<widget class="QLineEdit" name="discLineEdit">
|
||||||
@ -117,7 +117,7 @@
|
|||||||
<item row="0" column="0">
|
<item row="0" column="0">
|
||||||
<widget class="QTableWidget" name="tableWidget">
|
<widget class="QTableWidget" name="tableWidget">
|
||||||
<property name="columnCount">
|
<property name="columnCount">
|
||||||
<number>5</number>
|
<number>4</number>
|
||||||
</property>
|
</property>
|
||||||
<attribute name="horizontalHeaderVisible">
|
<attribute name="horizontalHeaderVisible">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
@ -146,11 +146,6 @@
|
|||||||
<string>Title</string>
|
<string>Title</string>
|
||||||
</property>
|
</property>
|
||||||
</column>
|
</column>
|
||||||
<column>
|
|
||||||
<property name="text">
|
|
||||||
<string>Artist</string>
|
|
||||||
</property>
|
|
||||||
</column>
|
|
||||||
<column>
|
<column>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Duration</string>
|
<string>Duration</string>
|
||||||
@ -173,76 +168,6 @@
|
|||||||
<string>&Rip</string>
|
<string>&Rip</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QWidget" name="layoutWidget">
|
|
||||||
<property name="geometry">
|
|
||||||
<rect>
|
|
||||||
<x>120</x>
|
|
||||||
<y>310</y>
|
|
||||||
<width>461</width>
|
|
||||||
<height>29</height>
|
|
||||||
</rect>
|
|
||||||
</property>
|
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
|
||||||
<item>
|
|
||||||
<widget class="QComboBox" name="format">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QPushButton" name="options">
|
|
||||||
<property name="text">
|
|
||||||
<string>Options...</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
<widget class="QLabel" name="label">
|
|
||||||
<property name="geometry">
|
|
||||||
<rect>
|
|
||||||
<x>10</x>
|
|
||||||
<y>310</y>
|
|
||||||
<width>90</width>
|
|
||||||
<height>29</height>
|
|
||||||
</rect>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Audio format</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
<widget class="QLabel" name="label_2">
|
|
||||||
<property name="geometry">
|
|
||||||
<rect>
|
|
||||||
<x>10</x>
|
|
||||||
<y>350</y>
|
|
||||||
<width>79</width>
|
|
||||||
<height>27</height>
|
|
||||||
</rect>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Destination</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
<widget class="QComboBox" name="destination">
|
|
||||||
<property name="geometry">
|
|
||||||
<rect>
|
|
||||||
<x>120</x>
|
|
||||||
<y>350</y>
|
|
||||||
<width>461</width>
|
|
||||||
<height>27</height>
|
|
||||||
</rect>
|
|
||||||
</property>
|
|
||||||
<item>
|
|
||||||
<property name="text">
|
|
||||||
<string>Alongside the originals</string>
|
|
||||||
</property>
|
|
||||||
</item>
|
|
||||||
</widget>
|
|
||||||
<widget class="QProgressBar" name="progress_bar">
|
<widget class="QProgressBar" name="progress_bar">
|
||||||
<property name="geometry">
|
<property name="geometry">
|
||||||
<rect>
|
<rect>
|
||||||
@ -253,11 +178,82 @@
|
|||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
|
<widget class="QGroupBox" name="output_group">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>10</x>
|
||||||
|
<y>300</y>
|
||||||
|
<width>571</width>
|
||||||
|
<height>96</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="title">
|
||||||
|
<string>Output options</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" name="gridLayout">
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QLabel" name="label">
|
||||||
|
<property name="text">
|
||||||
|
<string>Audio format</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="QComboBox" name="format">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="2">
|
||||||
|
<widget class="QPushButton" name="options">
|
||||||
|
<property name="text">
|
||||||
|
<string>Options...</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QLabel" name="label_2">
|
||||||
|
<property name="text">
|
||||||
|
<string>Destination</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="1">
|
||||||
|
<widget class="QComboBox" name="destination">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>Alongside the originals</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="2">
|
||||||
|
<widget class="QPushButton" name="select">
|
||||||
|
<property name="text">
|
||||||
|
<string>Select...</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
</widget>
|
</widget>
|
||||||
<resources/>
|
<resources/>
|
||||||
<connections>
|
<connections>
|
||||||
<connection>
|
<connection>
|
||||||
<sender>buttonBox</sender>
|
<sender>button_box</sender>
|
||||||
<signal>accepted()</signal>
|
<signal>accepted()</signal>
|
||||||
<receiver>RipCD</receiver>
|
<receiver>RipCD</receiver>
|
||||||
<slot>accept()</slot>
|
<slot>accept()</slot>
|
||||||
@ -273,7 +269,7 @@
|
|||||||
</hints>
|
</hints>
|
||||||
</connection>
|
</connection>
|
||||||
<connection>
|
<connection>
|
||||||
<sender>buttonBox</sender>
|
<sender>button_box</sender>
|
||||||
<signal>rejected()</signal>
|
<signal>rejected()</signal>
|
||||||
<receiver>RipCD</receiver>
|
<receiver>RipCD</receiver>
|
||||||
<slot>reject()</slot>
|
<slot>reject()</slot>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user