Initial commit.
This commit is contained in:
356
src/transcoder/transcodedialog.cpp
Normal file
356
src/transcoder/transcodedialog.cpp
Normal file
@@ -0,0 +1,356 @@
|
||||
/*
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Strawberry is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Strawberry. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "transcodedialog.h"
|
||||
#include "transcoder.h"
|
||||
#include "transcoderoptionsdialog.h"
|
||||
#include "ui_transcodedialog.h"
|
||||
#include "ui_transcodelogdialog.h"
|
||||
#include "core/iconloader.h"
|
||||
#include "core/mainwindow.h"
|
||||
#include "widgets/fileview.h"
|
||||
|
||||
#include <QPushButton>
|
||||
#include <QFileDialog>
|
||||
#include <QDirIterator>
|
||||
#include <QSettings>
|
||||
#include <QDateTime>
|
||||
|
||||
// winspool.h defines this :(
|
||||
#ifdef AddJob
|
||||
#undef AddJob
|
||||
#endif
|
||||
|
||||
const char *TranscodeDialog::kSettingsGroup = "Transcoder";
|
||||
const int TranscodeDialog::kProgressInterval = 500;
|
||||
const int TranscodeDialog::kMaxDestinationItems = 10;
|
||||
|
||||
static bool ComparePresetsByName(const TranscoderPreset &left, const TranscoderPreset &right) {
|
||||
return left.name_ < right.name_;
|
||||
}
|
||||
|
||||
TranscodeDialog::TranscodeDialog(QWidget *parent)
|
||||
: QDialog(parent),
|
||||
ui_(new Ui_TranscodeDialog),
|
||||
log_ui_(new Ui_TranscodeLogDialog),
|
||||
log_dialog_(new QDialog(this)),
|
||||
transcoder_(new Transcoder(this)),
|
||||
queued_(0),
|
||||
finished_success_(0),
|
||||
finished_failed_(0) {
|
||||
|
||||
ui_->setupUi(this);
|
||||
ui_->files->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
|
||||
|
||||
log_ui_->setupUi(log_dialog_);
|
||||
QPushButton *clear_button = log_ui_->buttonBox->addButton(tr("Clear"), QDialogButtonBox::ResetRole);
|
||||
connect(clear_button, SIGNAL(clicked()), log_ui_->log, SLOT(clear()));
|
||||
|
||||
// Get presets
|
||||
QList<TranscoderPreset> presets = Transcoder::GetAllPresets();
|
||||
qSort(presets.begin(), presets.end(), ComparePresetsByName);
|
||||
for (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();
|
||||
last_import_dir_ = s.value("last_import_dir", QDir::homePath()).toString();
|
||||
|
||||
QString last_output_format = s.value("last_output_format", "audio/x-vorbis").toString();
|
||||
for (int i = 0; i < ui_->format->count(); ++i) {
|
||||
if (last_output_format ==
|
||||
ui_->format->itemData(i).value<TranscoderPreset>().codec_mimetype_) {
|
||||
ui_->format->setCurrentIndex(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Add a start button
|
||||
start_button_ = ui_->button_box->addButton(tr("Start transcoding"), QDialogButtonBox::ActionRole);
|
||||
cancel_button_ = ui_->button_box->button(QDialogButtonBox::Cancel);
|
||||
close_button_ = ui_->button_box->button(QDialogButtonBox::Close);
|
||||
|
||||
close_button_->setShortcut(QKeySequence::Close);
|
||||
|
||||
// Hide elements
|
||||
cancel_button_->hide();
|
||||
ui_->progress_group->hide();
|
||||
|
||||
// Connect stuff
|
||||
connect(ui_->add, SIGNAL(clicked()), SLOT(Add()));
|
||||
connect(ui_->import, SIGNAL(clicked()), SLOT(Import()));
|
||||
connect(ui_->remove, SIGNAL(clicked()), SLOT(Remove()));
|
||||
connect(start_button_, SIGNAL(clicked()), SLOT(Start()));
|
||||
connect(cancel_button_, SIGNAL(clicked()), SLOT(Cancel()));
|
||||
connect(close_button_, SIGNAL(clicked()), SLOT(hide()));
|
||||
connect(ui_->details, SIGNAL(clicked()), log_dialog_, SLOT(show()));
|
||||
connect(ui_->options, SIGNAL(clicked()), SLOT(Options()));
|
||||
connect(ui_->select, SIGNAL(clicked()), SLOT(AddDestination()));
|
||||
|
||||
connect(transcoder_, SIGNAL(JobComplete(QString, QString, bool)), SLOT(JobComplete(QString, QString, bool)));
|
||||
connect(transcoder_, SIGNAL(LogLine(QString)), SLOT(LogLine(QString)));
|
||||
connect(transcoder_, SIGNAL(AllJobsComplete()), SLOT(AllJobsComplete()));
|
||||
|
||||
}
|
||||
|
||||
TranscodeDialog::~TranscodeDialog() {
|
||||
delete log_ui_;
|
||||
delete ui_;
|
||||
}
|
||||
|
||||
void TranscodeDialog::SetWorking(bool working) {
|
||||
|
||||
start_button_->setVisible(!working);
|
||||
cancel_button_->setVisible(working);
|
||||
close_button_->setVisible(!working);
|
||||
ui_->input_group->setEnabled(!working);
|
||||
ui_->output_group->setEnabled(!working);
|
||||
ui_->progress_group->setVisible(true);
|
||||
|
||||
if (working)
|
||||
progress_timer_.start(kProgressInterval, this);
|
||||
else
|
||||
progress_timer_.stop();
|
||||
|
||||
}
|
||||
|
||||
void TranscodeDialog::Start() {
|
||||
|
||||
SetWorking(true);
|
||||
|
||||
QAbstractItemModel *file_model = ui_->files->model();
|
||||
TranscoderPreset preset = ui_->format->itemData(ui_->format->currentIndex()).value<TranscoderPreset>();
|
||||
|
||||
// Add jobs to the transcoder
|
||||
for (int i = 0; i < file_model->rowCount(); ++i) {
|
||||
QString filename = file_model->index(i, 0).data(Qt::UserRole).toString();
|
||||
QString outfilename = GetOutputFileName(filename, preset);
|
||||
transcoder_->AddJob(filename, preset, outfilename);
|
||||
}
|
||||
|
||||
// Set up the progressbar
|
||||
ui_->progress_bar->setValue(0);
|
||||
ui_->progress_bar->setMaximum(file_model->rowCount() * 100);
|
||||
|
||||
// Reset the UI
|
||||
queued_ = file_model->rowCount();
|
||||
finished_success_ = 0;
|
||||
finished_failed_ = 0;
|
||||
UpdateStatusText();
|
||||
|
||||
// Start transcoding
|
||||
transcoder_->Start();
|
||||
|
||||
// Save the last output format
|
||||
QSettings s;
|
||||
s.beginGroup(kSettingsGroup);
|
||||
s.setValue("last_output_format", preset.codec_mimetype_);
|
||||
|
||||
}
|
||||
|
||||
void TranscodeDialog::Cancel() {
|
||||
|
||||
transcoder_->Cancel();
|
||||
SetWorking(false);
|
||||
|
||||
}
|
||||
|
||||
void TranscodeDialog::JobComplete(const QString &input, const QString &output, bool success) {
|
||||
|
||||
(*(success ? &finished_success_ : &finished_failed_))++;
|
||||
queued_--;
|
||||
|
||||
UpdateStatusText();
|
||||
UpdateProgress();
|
||||
|
||||
}
|
||||
|
||||
void TranscodeDialog::UpdateProgress() {
|
||||
|
||||
int progress = (finished_success_ + finished_failed_) * 100;
|
||||
|
||||
QMap<QString, float> current_jobs = transcoder_->GetProgress();
|
||||
for (float value : current_jobs.values()) {
|
||||
progress += qBound(0, int(value * 100), 99);
|
||||
}
|
||||
|
||||
ui_->progress_bar->setValue(progress);
|
||||
|
||||
}
|
||||
|
||||
void TranscodeDialog::UpdateStatusText() {
|
||||
|
||||
QStringList sections;
|
||||
|
||||
if (queued_) {
|
||||
sections << "<font color=\"#3467c8\">" + tr("%n remaining", "", queued_) + "</font>";
|
||||
}
|
||||
|
||||
if (finished_success_) {
|
||||
sections << "<font color=\"#02b600\">" + tr("%n finished", "", finished_success_) + "</font>";
|
||||
}
|
||||
|
||||
if (finished_failed_) {
|
||||
sections << "<font color=\"#b60000\">" + tr("%n failed", "", finished_failed_) + "</font>";
|
||||
}
|
||||
|
||||
ui_->progress_text->setText(sections.join(", "));
|
||||
|
||||
}
|
||||
|
||||
void TranscodeDialog::AllJobsComplete() {
|
||||
SetWorking(false);
|
||||
}
|
||||
|
||||
void TranscodeDialog::Add() {
|
||||
|
||||
//qLog(Debug) << __PRETTY_FUNCTION__;
|
||||
|
||||
QStringList filenames = QFileDialog::getOpenFileNames(
|
||||
this, tr("Add files to transcode"), last_add_dir_,
|
||||
QString("%1 (%2);;%3").arg(tr("Music"), FileView::kFileFilter, tr(MainWindow::kAllFilesFilterSpec)));
|
||||
|
||||
if (filenames.isEmpty()) return;
|
||||
|
||||
SetFilenames(filenames);
|
||||
|
||||
last_add_dir_ = filenames[0];
|
||||
QSettings s;
|
||||
s.beginGroup(kSettingsGroup);
|
||||
s.setValue("last_add_dir", last_add_dir_);
|
||||
|
||||
}
|
||||
|
||||
void TranscodeDialog::Import() {
|
||||
|
||||
QString path = QFileDialog::getExistingDirectory(this, tr("Open a directory to import music from"), last_import_dir_, QFileDialog::ShowDirsOnly);
|
||||
|
||||
if (path.isEmpty()) return;
|
||||
|
||||
QStringList filenames;
|
||||
QStringList audioTypes = QString(FileView::kFileFilter).split(" ", QString::SkipEmptyParts);
|
||||
QDirIterator files(path, audioTypes, QDir::Files | QDir::Readable, QDirIterator::Subdirectories);
|
||||
|
||||
while (files.hasNext()) {
|
||||
filenames << files.next();
|
||||
}
|
||||
|
||||
SetFilenames(filenames);
|
||||
|
||||
last_import_dir_ = path;
|
||||
QSettings settings;
|
||||
settings.beginGroup(kSettingsGroup);
|
||||
settings.setValue("last_import_dir", last_import_dir_);
|
||||
|
||||
}
|
||||
|
||||
void TranscodeDialog::SetFilenames(const QStringList &filenames) {
|
||||
|
||||
for (const QString &filename : filenames) {
|
||||
QString name = filename.section('/', -1, -1);
|
||||
QString path = filename.section('/', 0, -2);
|
||||
|
||||
QTreeWidgetItem *item = new QTreeWidgetItem(ui_->files, QStringList() << name << path);
|
||||
item->setData(0, Qt::UserRole, filename);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void TranscodeDialog::Remove() { qDeleteAll(ui_->files->selectedItems()); }
|
||||
|
||||
void TranscodeDialog::LogLine(const QString &message) {
|
||||
|
||||
QString date(QDateTime::currentDateTime().toString(Qt::TextDate));
|
||||
log_ui_->log->appendPlainText(QString("%1: %2").arg(date, message));
|
||||
|
||||
}
|
||||
|
||||
void TranscodeDialog::timerEvent(QTimerEvent *e) {
|
||||
|
||||
QDialog::timerEvent(e);
|
||||
|
||||
if (e->timerId() == progress_timer_.timerId()) {
|
||||
UpdateProgress();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void TranscodeDialog::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 TranscodeDialog::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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Returns the rightmost non-empty part of 'path'.
|
||||
QString TranscodeDialog::TrimPath(const QString &path) const {
|
||||
return path.section('/', -1, -1, QString::SectionSkipEmpty);
|
||||
}
|
||||
|
||||
QString TranscodeDialog::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_;
|
||||
}
|
||||
}
|
||||
91
src/transcoder/transcodedialog.h
Normal file
91
src/transcoder/transcodedialog.h
Normal file
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Strawberry is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Strawberry. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TRANSCODEDIALOG_H
|
||||
#define TRANSCODEDIALOG_H
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <QBasicTimer>
|
||||
#include <QDialog>
|
||||
#include <QFileInfo>
|
||||
|
||||
class Transcoder;
|
||||
class Ui_TranscodeDialog;
|
||||
class Ui_TranscodeLogDialog;
|
||||
|
||||
struct TranscoderPreset;
|
||||
|
||||
class TranscodeDialog : public QDialog {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
TranscodeDialog(QWidget *parent = nullptr);
|
||||
~TranscodeDialog();
|
||||
|
||||
static const char *kSettingsGroup;
|
||||
static const int kProgressInterval;
|
||||
static const int kMaxDestinationItems;
|
||||
|
||||
void SetFilenames(const QStringList &filenames);
|
||||
|
||||
protected:
|
||||
void timerEvent(QTimerEvent *e);
|
||||
|
||||
private slots:
|
||||
void Add();
|
||||
void Import();
|
||||
void Remove();
|
||||
void Start();
|
||||
void Cancel();
|
||||
void JobComplete(const QString &input, const QString &output, bool success);
|
||||
void LogLine(const QString &message);
|
||||
void AllJobsComplete();
|
||||
void Options();
|
||||
void AddDestination();
|
||||
|
||||
private:
|
||||
void SetWorking(bool working);
|
||||
void UpdateStatusText();
|
||||
void UpdateProgress();
|
||||
QString TrimPath(const QString &path) const;
|
||||
QString GetOutputFileName(const QString &input, const TranscoderPreset &preset) const;
|
||||
|
||||
private:
|
||||
Ui_TranscodeDialog *ui_;
|
||||
Ui_TranscodeLogDialog *log_ui_;
|
||||
QDialog *log_dialog_;
|
||||
|
||||
QBasicTimer progress_timer_;
|
||||
|
||||
QPushButton *start_button_;
|
||||
QPushButton *cancel_button_;
|
||||
QPushButton *close_button_;
|
||||
|
||||
QString last_add_dir_;
|
||||
QString last_import_dir_;
|
||||
|
||||
Transcoder *transcoder_;
|
||||
int queued_;
|
||||
int finished_success_;
|
||||
int finished_failed_;
|
||||
};
|
||||
|
||||
#endif // TRANSCODEDIALOG_H
|
||||
225
src/transcoder/transcodedialog.ui
Normal file
225
src/transcoder/transcodedialog.ui
Normal file
@@ -0,0 +1,225 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>TranscodeDialog</class>
|
||||
<widget class="QDialog" name="TranscodeDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>499</width>
|
||||
<height>448</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Transcode Music</string>
|
||||
</property>
|
||||
<property name="windowIcon">
|
||||
<iconset>
|
||||
<normaloff>:/icons/64x64/strawberry.png</normaloff>:/icons/64x64/strawberry.png</iconset>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="input_group">
|
||||
<property name="title">
|
||||
<string>Files to transcode</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QTreeWidget" name="files">
|
||||
<property name="alternatingRowColors">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::ExtendedSelection</enum>
|
||||
</property>
|
||||
<property name="rootIsDecorated">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="uniformRowHeights">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="itemsExpandable">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="allColumnsShowFocus">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<attribute name="headerStretchLastSection">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Filename</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Directory</string>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QPushButton" name="add">
|
||||
<property name="text">
|
||||
<string>Add...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="remove">
|
||||
<property name="text">
|
||||
<string>Remove</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="import">
|
||||
<property name="toolTip">
|
||||
<string>Add all tracks from a directory and all its subdirectories</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Import...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="output_group">
|
||||
<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>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="progress_group">
|
||||
<property name="title">
|
||||
<string>Progress</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QLabel" name="progress_text">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::RichText</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="details">
|
||||
<property name="text">
|
||||
<string>Details...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QProgressBar" name="progress_bar"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="button_box">
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Close</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>files</tabstop>
|
||||
<tabstop>add</tabstop>
|
||||
<tabstop>remove</tabstop>
|
||||
<tabstop>format</tabstop>
|
||||
<tabstop>button_box</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
58
src/transcoder/transcodelogdialog.ui
Normal file
58
src/transcoder/transcodelogdialog.ui
Normal file
@@ -0,0 +1,58 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>TranscodeLogDialog</class>
|
||||
<widget class="QDialog" name="TranscodeLogDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>676</width>
|
||||
<height>358</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Transcoder Log</string>
|
||||
</property>
|
||||
<property name="windowIcon">
|
||||
<iconset resource="../../data/data.qrc">
|
||||
<normaloff>:/icons/64x64/strawberry.png</normaloff>:/icons/64x64/strawberry.png</iconset>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QPlainTextEdit" name="log">
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Close</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources>
|
||||
<include location="../../data/data.qrc"/>
|
||||
</resources>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>TranscodeLogDialog</receiver>
|
||||
<slot>hide()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>599</x>
|
||||
<y>331</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>582</x>
|
||||
<y>355</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
587
src/transcoder/transcoder.cpp
Normal file
587
src/transcoder/transcoder.cpp
Normal file
@@ -0,0 +1,587 @@
|
||||
/*
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Strawberry is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Strawberry. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "transcoder.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QSettings>
|
||||
#include <QThread>
|
||||
#include <QtDebug>
|
||||
|
||||
#include "core/logging.h"
|
||||
#include "core/signalchecker.h"
|
||||
#include "core/utilities.h"
|
||||
|
||||
using std::shared_ptr;
|
||||
|
||||
int Transcoder::JobFinishedEvent::sEventType = -1;
|
||||
|
||||
|
||||
TranscoderPreset::TranscoderPreset(Song::FileType type, const QString &name, const QString &extension, const QString &codec_mimetype, const QString &muxer_mimetype)
|
||||
: type_(type),
|
||||
name_(name),
|
||||
extension_(extension),
|
||||
codec_mimetype_(codec_mimetype),
|
||||
muxer_mimetype_(muxer_mimetype) {}
|
||||
|
||||
|
||||
GstElement *Transcoder::CreateElement(const QString &factory_name, GstElement *bin, const QString &name) {
|
||||
|
||||
GstElement *ret = gst_element_factory_make(factory_name.toLatin1().constData(), name.isNull() ? factory_name.toLatin1().constData() : name.toLatin1().constData());
|
||||
|
||||
if (ret && bin) gst_bin_add(GST_BIN(bin), ret);
|
||||
|
||||
if (!ret) {
|
||||
emit LogLine(tr("Could not create the GStreamer element \"%1\" - make sure you have all the required GStreamer plugins installed").arg(factory_name));
|
||||
}
|
||||
else {
|
||||
SetElementProperties(factory_name, G_OBJECT(ret));
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
struct SuitableElement {
|
||||
|
||||
SuitableElement(const QString &name = QString(), int rank = 0) : name_(name), rank_(rank) {}
|
||||
|
||||
bool operator<(const SuitableElement &other) const {
|
||||
return rank_ < other.rank_;
|
||||
}
|
||||
|
||||
QString name_;
|
||||
int rank_;
|
||||
|
||||
};
|
||||
|
||||
GstElement *Transcoder::CreateElementForMimeType(const QString &element_type, const QString &mime_type, GstElement *bin) {
|
||||
|
||||
if (mime_type.isEmpty()) return nullptr;
|
||||
|
||||
// HACK: Force ffmux_mp4 because it doesn't set any useful src caps
|
||||
if (mime_type == "audio/mp4") {
|
||||
LogLine(QString("Using '%1' (rank %2)").arg("ffmux_mp4").arg(-1));
|
||||
return CreateElement("ffmux_mp4", bin);
|
||||
}
|
||||
|
||||
// Keep track of all the suitable elements we find and figure out which
|
||||
// is the best at the end.
|
||||
QList<SuitableElement> suitable_elements_;
|
||||
|
||||
// The caps we're trying to find
|
||||
GstCaps *target_caps = gst_caps_from_string(mime_type.toUtf8().constData());
|
||||
|
||||
GstRegistry *registry = gst_registry_get();
|
||||
GList *const features = gst_registry_get_feature_list(registry, GST_TYPE_ELEMENT_FACTORY);
|
||||
|
||||
for (GList *p = features; p; p = g_list_next(p)) {
|
||||
GstElementFactory *factory = GST_ELEMENT_FACTORY(p->data);
|
||||
|
||||
// Is this the right type of plugin?
|
||||
if (QString(gst_element_factory_get_klass(factory)).contains(element_type)) {
|
||||
const GList *const templates = gst_element_factory_get_static_pad_templates(factory);
|
||||
for (const GList *p = templates; p; p = g_list_next(p)) {
|
||||
// Only interested in source pads
|
||||
GstStaticPadTemplate *pad_template = reinterpret_cast<GstStaticPadTemplate*>(p->data);
|
||||
if (pad_template->direction != GST_PAD_SRC) continue;
|
||||
|
||||
// Does this pad support the mime type we want?
|
||||
GstCaps *caps = gst_static_pad_template_get_caps(pad_template);
|
||||
GstCaps *intersection = gst_caps_intersect(caps, target_caps);
|
||||
|
||||
if (intersection) {
|
||||
if (!gst_caps_is_empty(intersection)) {
|
||||
int rank = gst_plugin_feature_get_rank(GST_PLUGIN_FEATURE(factory));
|
||||
QString name = GST_OBJECT_NAME(factory);
|
||||
|
||||
if (name.startsWith("ffmux") || name.startsWith("ffenc"))
|
||||
rank = -1; // ffmpeg usually sucks
|
||||
|
||||
suitable_elements_ << SuitableElement(name, rank);
|
||||
}
|
||||
gst_caps_unref(intersection);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gst_plugin_feature_list_free(features);
|
||||
gst_caps_unref(target_caps);
|
||||
|
||||
if (suitable_elements_.isEmpty()) return nullptr;
|
||||
|
||||
// Sort by rank
|
||||
qSort(suitable_elements_);
|
||||
const SuitableElement &best = suitable_elements_.last();
|
||||
|
||||
LogLine(QString("Using '%1' (rank %2)").arg(best.name_).arg(best.rank_));
|
||||
|
||||
if (best.name_ == "lamemp3enc") {
|
||||
// Special case: we need to add xingmux and id3v2mux to the pipeline when
|
||||
// using lamemp3enc because it doesn't write the VBR or ID3v2 headers
|
||||
// itself.
|
||||
|
||||
LogLine("Adding xingmux and id3v2mux to the pipeline");
|
||||
|
||||
// Create the bin
|
||||
GstElement *mp3bin = gst_bin_new("mp3bin");
|
||||
gst_bin_add(GST_BIN(bin), mp3bin);
|
||||
|
||||
// Create the elements
|
||||
GstElement *lame = CreateElement("lamemp3enc", mp3bin);
|
||||
GstElement *xing = CreateElement("xingmux", mp3bin);
|
||||
GstElement *id3v2 = CreateElement("id3v2mux", mp3bin);
|
||||
|
||||
if (!lame || !xing || !id3v2) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Link the elements together
|
||||
gst_element_link_many(lame, xing, id3v2, nullptr);
|
||||
|
||||
// Link the bin's ghost pads to the elements on each end
|
||||
GstPad *pad = gst_element_get_static_pad(lame, "sink");
|
||||
gst_element_add_pad(mp3bin, gst_ghost_pad_new("sink", pad));
|
||||
gst_object_unref(GST_OBJECT(pad));
|
||||
|
||||
pad = gst_element_get_static_pad(id3v2, "src");
|
||||
gst_element_add_pad(mp3bin, gst_ghost_pad_new("src", pad));
|
||||
gst_object_unref(GST_OBJECT(pad));
|
||||
|
||||
return mp3bin;
|
||||
}
|
||||
else {
|
||||
return CreateElement(best.name_, bin);
|
||||
}
|
||||
}
|
||||
|
||||
Transcoder::JobFinishedEvent::JobFinishedEvent(JobState *state, bool success)
|
||||
: QEvent(QEvent::Type(sEventType)), state_(state), success_(success) {}
|
||||
|
||||
void Transcoder::JobState::PostFinished(bool success) {
|
||||
|
||||
if (success) {
|
||||
emit parent_->LogLine(tr("Successfully written %1").arg(QDir::toNativeSeparators(job_.output)));
|
||||
}
|
||||
|
||||
QCoreApplication::postEvent(parent_, new Transcoder::JobFinishedEvent(this, success));
|
||||
|
||||
}
|
||||
|
||||
Transcoder::Transcoder(QObject *parent, const QString &settings_postfix)
|
||||
: QObject(parent), max_threads_(QThread::idealThreadCount()), settings_postfix_(settings_postfix) {
|
||||
|
||||
if (JobFinishedEvent::sEventType == -1)
|
||||
JobFinishedEvent::sEventType = QEvent::registerEventType();
|
||||
|
||||
// Initialise some settings for the lamemp3enc element.
|
||||
QSettings s;
|
||||
s.beginGroup("Transcoder/lamemp3enc" + settings_postfix_);
|
||||
|
||||
if (s.value("target").isNull()) {
|
||||
s.setValue("target", 1); // 1 == bitrate
|
||||
}
|
||||
if (s.value("cbr").isNull()) {
|
||||
s.setValue("cbr", true);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
QList<TranscoderPreset> Transcoder::GetAllPresets() {
|
||||
|
||||
QList<TranscoderPreset> ret;
|
||||
ret << PresetForFileType(Song::Type_Flac);
|
||||
ret << PresetForFileType(Song::Type_Mp4);
|
||||
ret << PresetForFileType(Song::Type_Mpeg);
|
||||
ret << PresetForFileType(Song::Type_OggVorbis);
|
||||
ret << PresetForFileType(Song::Type_OggFlac);
|
||||
ret << PresetForFileType(Song::Type_OggSpeex);
|
||||
ret << PresetForFileType(Song::Type_Asf);
|
||||
ret << PresetForFileType(Song::Type_Wav);
|
||||
ret << PresetForFileType(Song::Type_OggOpus);
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
TranscoderPreset Transcoder::PresetForFileType(Song::FileType type) {
|
||||
|
||||
switch (type) {
|
||||
case Song::Type_Flac:
|
||||
return TranscoderPreset(type, tr("Flac"), "flac", "audio/x-flac");
|
||||
case Song::Type_Mp4:
|
||||
return TranscoderPreset(type, tr("M4A AAC"), "mp4", "audio/mpeg, mpegversion=(int)4", "audio/mp4");
|
||||
case Song::Type_Mpeg:
|
||||
return TranscoderPreset(type, tr("MP3"), "mp3", "audio/mpeg, mpegversion=(int)1, layer=(int)3");
|
||||
case Song::Type_OggVorbis:
|
||||
return TranscoderPreset(type, tr("Ogg Vorbis"), "ogg", "audio/x-vorbis", "application/ogg");
|
||||
case Song::Type_OggFlac:
|
||||
return TranscoderPreset(type, tr("Ogg Flac"), "ogg", "audio/x-flac", "application/ogg");
|
||||
case Song::Type_OggSpeex:
|
||||
return TranscoderPreset(type, tr("Ogg Speex"), "spx", "audio/x-speex", "application/ogg");
|
||||
case Song::Type_OggOpus:
|
||||
return TranscoderPreset(type, tr("Ogg Opus"), "opus", "audio/x-opus", "application/ogg");
|
||||
case Song::Type_Asf:
|
||||
return TranscoderPreset(type, tr("Windows Media audio"), "wma", "audio/x-wma", "video/x-ms-asf");
|
||||
case Song::Type_Wav:
|
||||
return TranscoderPreset(type, tr("Wav"), "wav", QString(), "audio/x-wav");
|
||||
default:
|
||||
qLog(Warning) << "Unsupported format in PresetForFileType:" << type;
|
||||
return TranscoderPreset();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Song::FileType Transcoder::PickBestFormat(QList<Song::FileType> supported) {
|
||||
|
||||
if (supported.isEmpty()) return Song::Type_Unknown;
|
||||
|
||||
QList<Song::FileType> best_formats;
|
||||
best_formats << Song::Type_Mpeg;
|
||||
best_formats << Song::Type_OggVorbis;
|
||||
best_formats << Song::Type_Asf;
|
||||
|
||||
for (Song::FileType type : best_formats) {
|
||||
if (supported.isEmpty() || supported.contains(type)) return type;
|
||||
}
|
||||
|
||||
return supported[0];
|
||||
|
||||
}
|
||||
|
||||
void Transcoder::AddJob(const QString &input, const TranscoderPreset &preset, const QString &output) {
|
||||
|
||||
Job job;
|
||||
job.input = input;
|
||||
job.preset = preset;
|
||||
|
||||
// Use the supplied filename if there was one, otherwise take the file
|
||||
// extension off the input filename and append the correct one.
|
||||
if (!output.isEmpty())
|
||||
job.output = output;
|
||||
else
|
||||
job.output = input.section('.', 0, -2) + '.' + preset.extension_;
|
||||
|
||||
// Never overwrite existing files
|
||||
if (QFile::exists(job.output)) {
|
||||
for (int i = 0;; ++i) {
|
||||
QString new_filename = QString("%1.%2.%3").arg(job.output.section('.', 0, -2)).arg(i).arg( preset.extension_);
|
||||
if (!QFile::exists(new_filename)) {
|
||||
job.output = new_filename;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
queued_jobs_ << job;
|
||||
|
||||
}
|
||||
|
||||
void Transcoder::AddTemporaryJob(const QString &input, const TranscoderPreset &preset) {
|
||||
|
||||
Job job;
|
||||
job.input = input;
|
||||
job.output = Utilities::GetTemporaryFileName();
|
||||
job.preset = preset;
|
||||
|
||||
queued_jobs_ << job;
|
||||
|
||||
}
|
||||
|
||||
void Transcoder::Start() {
|
||||
|
||||
emit LogLine(tr("Transcoding %1 files using %2 threads").arg(queued_jobs_.count()).arg(max_threads()));
|
||||
|
||||
forever {
|
||||
StartJobStatus status = MaybeStartNextJob();
|
||||
if (status == AllThreadsBusy || status == NoMoreJobs) break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Transcoder::StartJobStatus Transcoder::MaybeStartNextJob() {
|
||||
|
||||
if (current_jobs_.count() >= max_threads()) return AllThreadsBusy;
|
||||
if (queued_jobs_.isEmpty()) {
|
||||
if (current_jobs_.isEmpty()) {
|
||||
emit AllJobsComplete();
|
||||
}
|
||||
|
||||
return NoMoreJobs;
|
||||
}
|
||||
|
||||
Job job = queued_jobs_.takeFirst();
|
||||
if (StartJob(job)) {
|
||||
return StartedSuccessfully;
|
||||
}
|
||||
|
||||
emit JobComplete(job.input, job.output, false);
|
||||
return FailedToStart;
|
||||
|
||||
}
|
||||
|
||||
void Transcoder::NewPadCallback(GstElement*, GstPad *pad, gpointer data) {
|
||||
|
||||
JobState *state = reinterpret_cast<JobState*>(data);
|
||||
GstPad *const audiopad = gst_element_get_static_pad(state->convert_element_, "sink");
|
||||
|
||||
if (GST_PAD_IS_LINKED(audiopad)) {
|
||||
qLog(Debug) << "audiopad is already linked, unlinking old pad";
|
||||
gst_pad_unlink(audiopad, GST_PAD_PEER(audiopad));
|
||||
}
|
||||
|
||||
gst_pad_link(pad, audiopad);
|
||||
gst_object_unref(audiopad);
|
||||
|
||||
}
|
||||
|
||||
GstBusSyncReply Transcoder::BusCallbackSync(GstBus*, GstMessage *msg, gpointer data) {
|
||||
|
||||
JobState *state = reinterpret_cast<JobState*>(data);
|
||||
switch (GST_MESSAGE_TYPE(msg)) {
|
||||
case GST_MESSAGE_EOS:
|
||||
state->PostFinished(true);
|
||||
break;
|
||||
|
||||
case GST_MESSAGE_ERROR:
|
||||
state->ReportError(msg);
|
||||
state->PostFinished(false);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return GST_BUS_PASS;
|
||||
|
||||
}
|
||||
|
||||
void Transcoder::JobState::ReportError(GstMessage *msg) {
|
||||
|
||||
GError *error;
|
||||
gchar *debugs;
|
||||
|
||||
gst_message_parse_error(msg, &error, &debugs);
|
||||
QString message = QString::fromLocal8Bit(error->message);
|
||||
|
||||
g_error_free(error);
|
||||
free(debugs);
|
||||
|
||||
emit parent_->LogLine(tr("Error processing %1: %2").arg(QDir::toNativeSeparators(job_.input), message));
|
||||
|
||||
}
|
||||
|
||||
bool Transcoder::StartJob(const Job &job) {
|
||||
|
||||
shared_ptr<JobState> state(new JobState(job, this));
|
||||
|
||||
emit LogLine(tr("Starting %1").arg(QDir::toNativeSeparators(job.input)));
|
||||
|
||||
// Create the pipeline.
|
||||
// This should be a scoped_ptr, but scoped_ptr doesn't support custom
|
||||
// destructors.
|
||||
state->pipeline_ = gst_pipeline_new("pipeline");
|
||||
if (!state->pipeline_) return false;
|
||||
|
||||
// Create all the elements
|
||||
GstElement *src = CreateElement("filesrc", state->pipeline_);
|
||||
GstElement *decode = CreateElement("decodebin", state->pipeline_);
|
||||
GstElement *convert = CreateElement("audioconvert", state->pipeline_);
|
||||
GstElement *resample = CreateElement("audioresample", state->pipeline_);
|
||||
GstElement *codec = CreateElementForMimeType("Codec/Encoder/Audio", job.preset.codec_mimetype_, state->pipeline_);
|
||||
GstElement *muxer = CreateElementForMimeType("Codec/Muxer", job.preset.muxer_mimetype_, state->pipeline_);
|
||||
GstElement *sink = CreateElement("filesink", state->pipeline_);
|
||||
|
||||
if (!src || !decode || !convert || !sink) return false;
|
||||
|
||||
if (!codec && !job.preset.codec_mimetype_.isEmpty()) {
|
||||
LogLine(tr("Couldn't find an encoder for %1, check you have the correct GStreamer plugins installed").arg(job.preset.codec_mimetype_));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!muxer && !job.preset.muxer_mimetype_.isEmpty()) {
|
||||
LogLine(tr("Couldn't find a muxer for %1, check you have the correct GStreamer plugins installed").arg(job.preset.muxer_mimetype_));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Join them together
|
||||
gst_element_link(src, decode);
|
||||
if (codec && muxer) gst_element_link_many(convert, resample, codec, muxer, sink, nullptr);
|
||||
else if (codec) gst_element_link_many(convert, resample, codec, sink, nullptr);
|
||||
else if (muxer) gst_element_link_many(convert, resample, muxer, sink, nullptr);
|
||||
|
||||
// Set properties
|
||||
g_object_set(src, "location", job.input.toUtf8().constData(), nullptr);
|
||||
g_object_set(sink, "location", job.output.toUtf8().constData(), nullptr);
|
||||
|
||||
// Set callbacks
|
||||
state->convert_element_ = convert;
|
||||
|
||||
CHECKED_GCONNECT(decode, "pad-added", &NewPadCallback, state.get());
|
||||
gst_bus_set_sync_handler(gst_pipeline_get_bus(GST_PIPELINE(state->pipeline_)), BusCallbackSync, state.get(), nullptr);
|
||||
|
||||
// Start the pipeline
|
||||
gst_element_set_state(state->pipeline_, GST_STATE_PLAYING);
|
||||
|
||||
// GStreamer now transcodes in another thread, so we can return now and do
|
||||
// something else. Keep the JobState object around. It'll post an event
|
||||
// to our event loop when it finishes.
|
||||
current_jobs_ << state;
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
Transcoder::JobState::~JobState() {
|
||||
|
||||
if (pipeline_) {
|
||||
gst_element_set_state(pipeline_, GST_STATE_NULL);
|
||||
gst_object_unref(pipeline_);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool Transcoder::event(QEvent *e) {
|
||||
|
||||
if (e->type() == JobFinishedEvent::sEventType) {
|
||||
JobFinishedEvent *finished_event = static_cast<JobFinishedEvent*>(e);
|
||||
|
||||
// Find this job in the list
|
||||
JobStateList::iterator it = current_jobs_.begin();
|
||||
while (it != current_jobs_.end()) {
|
||||
if (it->get() == finished_event->state_) break;
|
||||
++it;
|
||||
}
|
||||
if (it == current_jobs_.end()) {
|
||||
// Couldn't find it, maybe GStreamer gave us an event after we'd destroyed
|
||||
// the pipeline?
|
||||
return true;
|
||||
}
|
||||
|
||||
QString input = (*it)->job_.input;
|
||||
QString output = (*it)->job_.output;
|
||||
|
||||
// Remove event handlers from the gstreamer pipeline so they don't get
|
||||
// called after the pipeline is shutting down
|
||||
gst_bus_set_sync_handler(gst_pipeline_get_bus(GST_PIPELINE(finished_event->state_->pipeline_)), nullptr, nullptr, nullptr);
|
||||
|
||||
// Remove it from the list - this will also destroy the GStreamer pipeline
|
||||
current_jobs_.erase(it);
|
||||
|
||||
// Emit the finished signal
|
||||
emit JobComplete(input, output, finished_event->success_);
|
||||
|
||||
// Start some more jobs
|
||||
MaybeStartNextJob();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return QObject::event(e);
|
||||
|
||||
}
|
||||
|
||||
void Transcoder::Cancel() {
|
||||
|
||||
// Remove all pending jobs
|
||||
queued_jobs_.clear();
|
||||
|
||||
// Stop the running ones
|
||||
JobStateList::iterator it = current_jobs_.begin();
|
||||
while (it != current_jobs_.end()) {
|
||||
shared_ptr<JobState> state(*it);
|
||||
|
||||
// Remove event handlers from the gstreamer pipeline so they don't get
|
||||
// called after the pipeline is shutting down
|
||||
gst_bus_set_sync_handler(gst_pipeline_get_bus(GST_PIPELINE(state->pipeline_)), nullptr, nullptr, nullptr);
|
||||
|
||||
// Stop the pipeline
|
||||
if (gst_element_set_state(state->pipeline_, GST_STATE_NULL) == GST_STATE_CHANGE_ASYNC) {
|
||||
// Wait for it to finish stopping...
|
||||
gst_element_get_state(state->pipeline_, nullptr, nullptr, GST_CLOCK_TIME_NONE);
|
||||
}
|
||||
|
||||
// Remove the job, this destroys the GStreamer pipeline too
|
||||
it = current_jobs_.erase(it);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
QMap<QString, float> Transcoder::GetProgress() const {
|
||||
|
||||
QMap<QString, float> ret;
|
||||
|
||||
for (const auto &state : current_jobs_) {
|
||||
if (!state->pipeline_) continue;
|
||||
|
||||
gint64 position = 0;
|
||||
gint64 duration = 0;
|
||||
|
||||
gst_element_query_position(state->pipeline_, GST_FORMAT_TIME, &position);
|
||||
gst_element_query_duration(state->pipeline_, GST_FORMAT_TIME, &duration);
|
||||
|
||||
ret[state->job_.input] = float(position) / duration;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
void Transcoder::SetElementProperties(const QString &name, GObject *object) {
|
||||
|
||||
QSettings s;
|
||||
s.beginGroup("Transcoder/" + name + settings_postfix_);
|
||||
|
||||
guint properties_count = 0;
|
||||
GParamSpec **properties = g_object_class_list_properties( G_OBJECT_GET_CLASS(object), &properties_count);
|
||||
|
||||
for (int i = 0; i < properties_count; ++i) {
|
||||
GParamSpec *property = properties[i];
|
||||
|
||||
const QVariant value = s.value(property->name);
|
||||
if (value.isNull()) continue;
|
||||
|
||||
LogLine(QString("Setting %1 property: %2 = %3").arg(name, property->name, value.toString()));
|
||||
|
||||
switch (property->value_type) {
|
||||
case G_TYPE_DOUBLE:
|
||||
g_object_set(object, property->name, value.toDouble(), nullptr);
|
||||
break;
|
||||
case G_TYPE_FLOAT:
|
||||
g_object_set(object, property->name, value.toFloat(), nullptr);
|
||||
break;
|
||||
case G_TYPE_BOOLEAN:
|
||||
g_object_set(object, property->name, value.toInt(), nullptr);
|
||||
break;
|
||||
case G_TYPE_INT:
|
||||
default:
|
||||
g_object_set(object, property->name, value.toInt(), nullptr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
g_free(properties);
|
||||
|
||||
}
|
||||
144
src/transcoder/transcoder.h
Normal file
144
src/transcoder/transcoder.h
Normal file
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Strawberry is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Strawberry. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TRANSCODER_H
|
||||
#define TRANSCODER_H
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <gst/gst.h>
|
||||
|
||||
#include <QObject>
|
||||
#include <QStringList>
|
||||
#include <QEvent>
|
||||
#include <QMetaType>
|
||||
|
||||
#include "core/song.h"
|
||||
|
||||
struct TranscoderPreset {
|
||||
TranscoderPreset() : type_(Song::Type_Unknown) {}
|
||||
TranscoderPreset(Song::FileType type, const QString &name, const QString &extension, const QString &codec_mimetype, const QString &muxer_mimetype_ = QString());
|
||||
|
||||
Song::FileType type_;
|
||||
QString name_;
|
||||
QString extension_;
|
||||
QString codec_mimetype_;
|
||||
QString muxer_mimetype_;
|
||||
};
|
||||
Q_DECLARE_METATYPE(TranscoderPreset);
|
||||
|
||||
class Transcoder : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
Transcoder(QObject *parent = nullptr, const QString &settings_postfix = "");
|
||||
|
||||
static TranscoderPreset PresetForFileType(Song::FileType type);
|
||||
static QList<TranscoderPreset> GetAllPresets();
|
||||
static Song::FileType PickBestFormat(QList<Song::FileType> supported);
|
||||
|
||||
int max_threads() const { return max_threads_; }
|
||||
void set_max_threads(int count) { max_threads_ = count; }
|
||||
|
||||
void AddJob(const QString &input, const TranscoderPreset &preset, const QString &output = QString());
|
||||
void AddTemporaryJob(const QString &input, const TranscoderPreset &preset);
|
||||
|
||||
QMap<QString, float> GetProgress() const;
|
||||
int QueuedJobsCount() const { return queued_jobs_.count(); }
|
||||
|
||||
public slots:
|
||||
void Start();
|
||||
void Cancel();
|
||||
|
||||
signals:
|
||||
void JobComplete(const QString &input, const QString &output, bool success);
|
||||
void LogLine(const QString &message);
|
||||
void AllJobsComplete();
|
||||
|
||||
protected:
|
||||
bool event(QEvent *e);
|
||||
|
||||
private:
|
||||
// The description of a file to transcode - lives in the main thread.
|
||||
struct Job {
|
||||
QString input;
|
||||
QString output;
|
||||
TranscoderPreset preset;
|
||||
};
|
||||
|
||||
// State held by a job and shared across gstreamer callbacks - lives in the
|
||||
// job's thread.
|
||||
struct JobState {
|
||||
JobState(const Job &job, Transcoder *parent)
|
||||
: job_(job),
|
||||
parent_(parent),
|
||||
pipeline_(nullptr),
|
||||
convert_element_(nullptr) {}
|
||||
~JobState();
|
||||
|
||||
void PostFinished(bool success);
|
||||
void ReportError(GstMessage *msg);
|
||||
|
||||
Job job_;
|
||||
Transcoder *parent_;
|
||||
GstElement *pipeline_;
|
||||
GstElement *convert_element_;
|
||||
};
|
||||
|
||||
// Event passed from a GStreamer callback to the Transcoder when a job
|
||||
// finishes.
|
||||
struct JobFinishedEvent : public QEvent {
|
||||
JobFinishedEvent(JobState *state, bool success);
|
||||
|
||||
static int sEventType;
|
||||
|
||||
JobState *state_;
|
||||
bool success_;
|
||||
};
|
||||
|
||||
enum StartJobStatus {
|
||||
StartedSuccessfully,
|
||||
FailedToStart,
|
||||
NoMoreJobs,
|
||||
AllThreadsBusy,
|
||||
};
|
||||
|
||||
StartJobStatus MaybeStartNextJob();
|
||||
bool StartJob(const Job &job);
|
||||
|
||||
GstElement *CreateElement(const QString &factory_name, GstElement *bin = nullptr, const QString &name = QString());
|
||||
GstElement *CreateElementForMimeType(const QString &element_type, const QString &mime_type, GstElement *bin = nullptr);
|
||||
void SetElementProperties(const QString &name, GObject *element);
|
||||
|
||||
static void NewPadCallback(GstElement*, GstPad *pad, gpointer data);
|
||||
static GstBusSyncReply BusCallbackSync(GstBus*, GstMessage *msg, gpointer data);
|
||||
|
||||
private:
|
||||
typedef QList<std::shared_ptr<JobState>> JobStateList;
|
||||
|
||||
int max_threads_;
|
||||
QList<Job> queued_jobs_;
|
||||
JobStateList current_jobs_;
|
||||
QString settings_postfix_;
|
||||
};
|
||||
|
||||
#endif // TRANSCODER_H
|
||||
58
src/transcoder/transcoderoptionsaac.cpp
Normal file
58
src/transcoder/transcoderoptionsaac.cpp
Normal file
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Strawberry is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Strawberry. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "transcoderoptionsaac.h"
|
||||
#include "ui_transcoderoptionsaac.h"
|
||||
|
||||
#include <QSettings>
|
||||
|
||||
const char *TranscoderOptionsAAC::kSettingsGroup = "Transcoder/faac";
|
||||
|
||||
TranscoderOptionsAAC::TranscoderOptionsAAC(QWidget* parent) : TranscoderOptionsInterface(parent), ui_(new Ui_TranscoderOptionsAAC) {
|
||||
ui_->setupUi(this);
|
||||
}
|
||||
|
||||
TranscoderOptionsAAC::~TranscoderOptionsAAC() {
|
||||
delete ui_;
|
||||
}
|
||||
|
||||
void TranscoderOptionsAAC::Load() {
|
||||
QSettings s;
|
||||
s.beginGroup(kSettingsGroup + settings_postfix_);
|
||||
|
||||
ui_->bitrate_slider->setValue(s.value("bitrate", 128000).toInt() / 1000);
|
||||
ui_->profile->setCurrentIndex(s.value("profile", 2).toInt() - 1);
|
||||
ui_->tns->setChecked(s.value("tns", false).toBool());
|
||||
ui_->midside->setChecked(s.value("midside", true).toBool());
|
||||
ui_->shortctl->setCurrentIndex(s.value("shortctl", 0).toInt());
|
||||
}
|
||||
|
||||
void TranscoderOptionsAAC::Save() {
|
||||
QSettings s;
|
||||
s.beginGroup(kSettingsGroup + settings_postfix_);
|
||||
|
||||
s.setValue("bitrate", ui_->bitrate_slider->value() * 1000);
|
||||
s.setValue("profile", ui_->profile->currentIndex() + 1);
|
||||
s.setValue("tns", ui_->tns->isChecked());
|
||||
s.setValue("midside", ui_->midside->isChecked());
|
||||
s.setValue("shortctl", ui_->shortctl->currentIndex());
|
||||
}
|
||||
44
src/transcoder/transcoderoptionsaac.h
Normal file
44
src/transcoder/transcoderoptionsaac.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Strawberry is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Strawberry. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TRANSCODEROPTIONSAAC_H
|
||||
#define TRANSCODEROPTIONSAAC_H
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "transcoderoptionsinterface.h"
|
||||
|
||||
class Ui_TranscoderOptionsAAC;
|
||||
|
||||
class TranscoderOptionsAAC : public TranscoderOptionsInterface {
|
||||
public:
|
||||
TranscoderOptionsAAC(QWidget *parent = nullptr);
|
||||
~TranscoderOptionsAAC();
|
||||
|
||||
void Load();
|
||||
void Save();
|
||||
|
||||
private:
|
||||
static const char *kSettingsGroup;
|
||||
|
||||
Ui_TranscoderOptionsAAC *ui_;
|
||||
};
|
||||
|
||||
#endif // TRANSCODEROPTIONSAAC_H
|
||||
185
src/transcoder/transcoderoptionsaac.ui
Normal file
185
src/transcoder/transcoderoptionsaac.ui
Normal file
@@ -0,0 +1,185 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>TranscoderOptionsAAC</class>
|
||||
<widget class="QWidget" name="TranscoderOptionsAAC">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>480</width>
|
||||
<height>344</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Bitrate</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QSlider" name="bitrate_slider">
|
||||
<property name="minimum">
|
||||
<number>8</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>320</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>128</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="bitrate_spinbox">
|
||||
<property name="suffix">
|
||||
<string> kbps</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>8</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>320</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<number>8</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>128</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Profile</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QComboBox" name="profile">
|
||||
<property name="currentIndex">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Main profile (MAIN)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Low complexity profile (LC)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Scalable sampling rate profile (SSR)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Long term prediction profile (LTP)</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="tns">
|
||||
<property name="text">
|
||||
<string>Use temporal noise shaping</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="midside">
|
||||
<property name="text">
|
||||
<string>Allow mid/side encoding</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Block type</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QComboBox" name="shortctl">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Normal block type</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>No short blocks</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>No long blocks</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>bitrate_slider</tabstop>
|
||||
<tabstop>bitrate_spinbox</tabstop>
|
||||
<tabstop>profile</tabstop>
|
||||
<tabstop>shortctl</tabstop>
|
||||
<tabstop>tns</tabstop>
|
||||
<tabstop>midside</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>bitrate_slider</sender>
|
||||
<signal>valueChanged(int)</signal>
|
||||
<receiver>bitrate_spinbox</receiver>
|
||||
<slot>setValue(int)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>170</x>
|
||||
<y>29</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>445</x>
|
||||
<y>24</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>bitrate_spinbox</sender>
|
||||
<signal>valueChanged(int)</signal>
|
||||
<receiver>bitrate_slider</receiver>
|
||||
<slot>setValue(int)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>407</x>
|
||||
<y>18</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>191</x>
|
||||
<y>29</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
81
src/transcoder/transcoderoptionsdialog.cpp
Normal file
81
src/transcoder/transcoderoptionsdialog.cpp
Normal file
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Strawberry is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Strawberry. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "transcoderoptionsaac.h"
|
||||
#include "transcoderoptionsdialog.h"
|
||||
#include "transcoderoptionsflac.h"
|
||||
#include "transcoderoptionsmp3.h"
|
||||
#include "transcoderoptionsspeex.h"
|
||||
#include "transcoderoptionsvorbis.h"
|
||||
#include "transcoderoptionsopus.h"
|
||||
#include "transcoderoptionswma.h"
|
||||
#include "ui_transcoderoptionsdialog.h"
|
||||
|
||||
TranscoderOptionsDialog::TranscoderOptionsDialog(Song::FileType type, QWidget *parent)
|
||||
: QDialog(parent), ui_(new Ui_TranscoderOptionsDialog), options_(nullptr) {
|
||||
|
||||
ui_->setupUi(this);
|
||||
|
||||
switch (type) {
|
||||
case Song::Type_Flac:
|
||||
case Song::Type_OggFlac: options_ = new TranscoderOptionsFlac(this); break;
|
||||
case Song::Type_Mp4: options_ = new TranscoderOptionsAAC(this); break;
|
||||
case Song::Type_Mpeg: options_ = new TranscoderOptionsMP3(this); break;
|
||||
case Song::Type_OggVorbis: options_ = new TranscoderOptionsVorbis(this); break;
|
||||
case Song::Type_OggOpus: options_ = new TranscoderOptionsOpus(this); break;
|
||||
case Song::Type_OggSpeex: options_ = new TranscoderOptionsSpeex(this); break;
|
||||
case Song::Type_Asf: options_ = new TranscoderOptionsWma(this); break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (options_) {
|
||||
setWindowTitle(windowTitle() + " - " + Song::TextForFiletype(type));
|
||||
options_->layout()->setContentsMargins(0, 0, 0, 0);
|
||||
ui_->verticalLayout->insertWidget(0, options_);
|
||||
resize(width(), minimumHeight());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
TranscoderOptionsDialog::~TranscoderOptionsDialog() {
|
||||
delete ui_;
|
||||
}
|
||||
|
||||
void TranscoderOptionsDialog::showEvent(QShowEvent *e) {
|
||||
if (options_) {
|
||||
options_->Load();
|
||||
}
|
||||
}
|
||||
|
||||
void TranscoderOptionsDialog::accept() {
|
||||
if (options_) {
|
||||
options_->Save();
|
||||
}
|
||||
QDialog::accept();
|
||||
}
|
||||
|
||||
void TranscoderOptionsDialog::set_settings_postfix(const QString &settings_postfix) {
|
||||
if (options_) {
|
||||
options_->settings_postfix_ = settings_postfix;
|
||||
}
|
||||
}
|
||||
54
src/transcoder/transcoderoptionsdialog.h
Normal file
54
src/transcoder/transcoderoptionsdialog.h
Normal file
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Strawberry is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Strawberry. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TRANSCODEROPTIONSDIALOG_H
|
||||
#define TRANSCODEROPTIONSDIALOG_H
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
#include "transcoderoptionsinterface.h"
|
||||
#include "core/song.h"
|
||||
|
||||
class Ui_TranscoderOptionsDialog;
|
||||
|
||||
class TranscoderOptionsDialog : public QDialog {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
TranscoderOptionsDialog(Song::FileType type, QWidget *parent = nullptr);
|
||||
~TranscoderOptionsDialog();
|
||||
|
||||
bool is_valid() const { return options_; }
|
||||
|
||||
void accept();
|
||||
|
||||
void set_settings_postfix(const QString &settings_postfix);
|
||||
|
||||
protected:
|
||||
void showEvent(QShowEvent *e);
|
||||
|
||||
private:
|
||||
Ui_TranscoderOptionsDialog *ui_;
|
||||
TranscoderOptionsInterface *options_;
|
||||
};
|
||||
|
||||
#endif // TRANSCODEROPTIONSDIALOG_H
|
||||
64
src/transcoder/transcoderoptionsdialog.ui
Normal file
64
src/transcoder/transcoderoptionsdialog.ui
Normal file
@@ -0,0 +1,64 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>TranscoderOptionsDialog</class>
|
||||
<widget class="QDialog" name="TranscoderOptionsDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>400</width>
|
||||
<height>300</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Transcoding options</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>TranscoderOptionsDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>TranscoderOptionsDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
51
src/transcoder/transcoderoptionsflac.cpp
Normal file
51
src/transcoder/transcoderoptionsflac.cpp
Normal file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Strawberry is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Strawberry. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "transcoderoptionsflac.h"
|
||||
#include "ui_transcoderoptionsflac.h"
|
||||
|
||||
#include <QSettings>
|
||||
|
||||
const char *TranscoderOptionsFlac::kSettingsGroup = "Transcoder/flacenc";
|
||||
|
||||
TranscoderOptionsFlac::TranscoderOptionsFlac(QWidget *parent)
|
||||
: TranscoderOptionsInterface(parent), ui_(new Ui_TranscoderOptionsFlac) {
|
||||
ui_->setupUi(this);
|
||||
}
|
||||
|
||||
TranscoderOptionsFlac::~TranscoderOptionsFlac() {
|
||||
delete ui_;
|
||||
}
|
||||
|
||||
void TranscoderOptionsFlac::Load() {
|
||||
QSettings s;
|
||||
s.beginGroup(kSettingsGroup + settings_postfix_);
|
||||
|
||||
ui_->quality->setValue(s.value("quality", 5).toInt());
|
||||
}
|
||||
|
||||
void TranscoderOptionsFlac::Save() {
|
||||
QSettings s;
|
||||
s.beginGroup(kSettingsGroup + settings_postfix_);
|
||||
|
||||
s.setValue("quality", ui_->quality->value());
|
||||
}
|
||||
44
src/transcoder/transcoderoptionsflac.h
Normal file
44
src/transcoder/transcoderoptionsflac.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Strawberry is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Strawberry. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TRANSCODEROPTIONSFLAC_H
|
||||
#define TRANSCODEROPTIONSFLAC_H
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "transcoderoptionsinterface.h"
|
||||
|
||||
class Ui_TranscoderOptionsFlac;
|
||||
|
||||
class TranscoderOptionsFlac : public TranscoderOptionsInterface {
|
||||
public:
|
||||
TranscoderOptionsFlac(QWidget *parent = nullptr);
|
||||
~TranscoderOptionsFlac();
|
||||
|
||||
void Load();
|
||||
void Save();
|
||||
|
||||
private:
|
||||
static const char *kSettingsGroup;
|
||||
|
||||
Ui_TranscoderOptionsFlac *ui_;
|
||||
};
|
||||
|
||||
#endif // TRANSCODEROPTIONSFLAC_H
|
||||
62
src/transcoder/transcoderoptionsflac.ui
Normal file
62
src/transcoder/transcoderoptionsflac.ui
Normal file
@@ -0,0 +1,62 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>TranscoderOptionsFlac</class>
|
||||
<widget class="QWidget" name="TranscoderOptionsFlac">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>400</width>
|
||||
<height>102</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string comment="Sound quality">Quality</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Fast</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSlider" name="quality">
|
||||
<property name="maximum">
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="tickPosition">
|
||||
<enum>QSlider::TicksBelow</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Best</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
39
src/transcoder/transcoderoptionsinterface.h
Normal file
39
src/transcoder/transcoderoptionsinterface.h
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Strawberry is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Strawberry. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TRANSCODEROPTIONSINTERFACE_H
|
||||
#define TRANSCODEROPTIONSINTERFACE_H
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
class TranscoderOptionsInterface : public QWidget {
|
||||
public:
|
||||
TranscoderOptionsInterface(QWidget *parent) : QWidget(parent) {}
|
||||
virtual ~TranscoderOptionsInterface() {}
|
||||
|
||||
virtual void Load() = 0;
|
||||
virtual void Save() = 0;
|
||||
|
||||
QString settings_postfix_;
|
||||
};
|
||||
|
||||
#endif // TRANSCODEROPTIONSINTERFACE_H
|
||||
82
src/transcoder/transcoderoptionsmp3.cpp
Normal file
82
src/transcoder/transcoderoptionsmp3.cpp
Normal file
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Strawberry is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Strawberry. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "transcoderoptionsmp3.h"
|
||||
#include "ui_transcoderoptionsmp3.h"
|
||||
|
||||
#include <QSettings>
|
||||
|
||||
const char* TranscoderOptionsMP3::kSettingsGroup = "Transcoder/lamemp3enc";
|
||||
|
||||
TranscoderOptionsMP3::TranscoderOptionsMP3(QWidget *parent)
|
||||
: TranscoderOptionsInterface(parent), ui_(new Ui_TranscoderOptionsMP3) {
|
||||
ui_->setupUi(this);
|
||||
|
||||
connect(ui_->quality_slider, SIGNAL(valueChanged(int)), SLOT(QualitySliderChanged(int)));
|
||||
connect(ui_->quality_spinbox, SIGNAL(valueChanged(double)), SLOT(QualitySpinboxChanged(double)));
|
||||
|
||||
}
|
||||
|
||||
TranscoderOptionsMP3::~TranscoderOptionsMP3() {
|
||||
delete ui_;
|
||||
}
|
||||
|
||||
void TranscoderOptionsMP3::Load() {
|
||||
|
||||
QSettings s;
|
||||
s.beginGroup(kSettingsGroup + settings_postfix_);
|
||||
|
||||
if (s.value("target", 1).toInt() == 0) {
|
||||
ui_->target_quality->setChecked(true);
|
||||
} else {
|
||||
ui_->target_bitrate->setChecked(true);
|
||||
}
|
||||
|
||||
ui_->quality_spinbox->setValue(s.value("quality", 4.0).toFloat());
|
||||
ui_->bitrate_slider->setValue(s.value("bitrate", 128).toInt());
|
||||
ui_->cbr->setChecked(s.value("cbr", true).toBool());
|
||||
ui_->encoding_engine_quality->setCurrentIndex(s.value("encoding-engine-quality", 1).toInt());
|
||||
ui_->mono->setChecked(s.value("mono", false).toBool());
|
||||
|
||||
}
|
||||
|
||||
void TranscoderOptionsMP3::Save() {
|
||||
|
||||
QSettings s;
|
||||
s.beginGroup(kSettingsGroup + settings_postfix_);
|
||||
|
||||
s.setValue("target", ui_->target_quality->isChecked() ? 0 : 1);
|
||||
s.setValue("quality", ui_->quality_spinbox->value());
|
||||
s.setValue("bitrate", ui_->bitrate_slider->value());
|
||||
s.setValue("cbr", ui_->cbr->isChecked());
|
||||
s.setValue("encoding-engine-quality", ui_->encoding_engine_quality->currentIndex());
|
||||
s.setValue("mono", ui_->mono->isChecked());
|
||||
|
||||
}
|
||||
|
||||
void TranscoderOptionsMP3::QualitySliderChanged(int value) {
|
||||
ui_->quality_spinbox->setValue(float(value) / 100);
|
||||
}
|
||||
|
||||
void TranscoderOptionsMP3::QualitySpinboxChanged(double value) {
|
||||
ui_->quality_slider->setValue(value * 100);
|
||||
}
|
||||
50
src/transcoder/transcoderoptionsmp3.h
Normal file
50
src/transcoder/transcoderoptionsmp3.h
Normal file
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Strawberry is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Strawberry. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TRANSCODEROPTIONSMP3_H
|
||||
#define TRANSCODEROPTIONSMP3_H
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "transcoderoptionsinterface.h"
|
||||
|
||||
class Ui_TranscoderOptionsMP3;
|
||||
|
||||
class TranscoderOptionsMP3 : public TranscoderOptionsInterface {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
TranscoderOptionsMP3(QWidget *parent = nullptr);
|
||||
~TranscoderOptionsMP3();
|
||||
|
||||
void Load();
|
||||
void Save();
|
||||
|
||||
private slots:
|
||||
void QualitySliderChanged(int value);
|
||||
void QualitySpinboxChanged(double value);
|
||||
|
||||
private:
|
||||
static const char* kSettingsGroup;
|
||||
|
||||
Ui_TranscoderOptionsMP3 *ui_;
|
||||
};
|
||||
|
||||
#endif // TRANSCODEROPTIONSMP3_H
|
||||
291
src/transcoder/transcoderoptionsmp3.ui
Normal file
291
src/transcoder/transcoderoptionsmp3.ui
Normal file
@@ -0,0 +1,291 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>TranscoderOptionsMP3</class>
|
||||
<widget class="QWidget" name="TranscoderOptionsMP3">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>557</width>
|
||||
<height>486</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout_2">
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="QRadioButton" name="target_quality">
|
||||
<property name="text">
|
||||
<string>Optimize for quality</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="2">
|
||||
<widget class="QWidget" name="widget" native="true">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<property name="leftMargin">
|
||||
<number>32</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string comment="Sound quality">Quality</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QSlider" name="quality_slider">
|
||||
<property name="maximum">
|
||||
<number>999</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>400</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="tickPosition">
|
||||
<enum>QSlider::TicksBelow</enum>
|
||||
</property>
|
||||
<property name="tickInterval">
|
||||
<number>100</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDoubleSpinBox" name="quality_spinbox">
|
||||
<property name="maximum">
|
||||
<double>9.990000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>4.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="2">
|
||||
<widget class="QRadioButton" name="target_bitrate">
|
||||
<property name="text">
|
||||
<string>Optimize for bitrate</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0" colspan="2">
|
||||
<widget class="QWidget" name="widget_2" native="true">
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<property name="leftMargin">
|
||||
<number>32</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Bitrate</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
<widget class="QSlider" name="bitrate_slider">
|
||||
<property name="minimum">
|
||||
<number>8</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>320</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>128</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="tickPosition">
|
||||
<enum>QSlider::TicksBelow</enum>
|
||||
</property>
|
||||
<property name="tickInterval">
|
||||
<number>32</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="bitrate_spinbox">
|
||||
<property name="suffix">
|
||||
<string> kbps</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>8</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>320</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<number>8</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>128</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="cbr">
|
||||
<property name="text">
|
||||
<string>Constant bitrate</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Encoding engine quality</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QComboBox" name="encoding_engine_quality">
|
||||
<property name="currentIndex">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Fast</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Standard</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>High</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="mono">
|
||||
<property name="text">
|
||||
<string>Force mono encoding</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>target_quality</tabstop>
|
||||
<tabstop>quality_slider</tabstop>
|
||||
<tabstop>quality_spinbox</tabstop>
|
||||
<tabstop>target_bitrate</tabstop>
|
||||
<tabstop>bitrate_slider</tabstop>
|
||||
<tabstop>bitrate_spinbox</tabstop>
|
||||
<tabstop>cbr</tabstop>
|
||||
<tabstop>encoding_engine_quality</tabstop>
|
||||
<tabstop>mono</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>bitrate_slider</sender>
|
||||
<signal>valueChanged(int)</signal>
|
||||
<receiver>bitrate_spinbox</receiver>
|
||||
<slot>setValue(int)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>191</x>
|
||||
<y>109</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>492</x>
|
||||
<y>115</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>bitrate_spinbox</sender>
|
||||
<signal>valueChanged(int)</signal>
|
||||
<receiver>bitrate_slider</receiver>
|
||||
<slot>setValue(int)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>485</x>
|
||||
<y>115</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>182</x>
|
||||
<y>113</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>target_quality</sender>
|
||||
<signal>toggled(bool)</signal>
|
||||
<receiver>widget</receiver>
|
||||
<slot>setEnabled(bool)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>65</x>
|
||||
<y>23</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>20</x>
|
||||
<y>49</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>target_bitrate</sender>
|
||||
<signal>toggled(bool)</signal>
|
||||
<receiver>widget_2</receiver>
|
||||
<slot>setEnabled(bool)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>46</x>
|
||||
<y>87</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>22</x>
|
||||
<y>122</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
53
src/transcoder/transcoderoptionsopus.cpp
Normal file
53
src/transcoder/transcoderoptionsopus.cpp
Normal file
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2013, Martin Brodbeck <martin@brodbeck-online.de>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Strawberry is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Strawberry. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "transcoderoptionsopus.h"
|
||||
#include "ui_transcoderoptionsopus.h"
|
||||
|
||||
#include <QSettings>
|
||||
|
||||
// TODO: Add more options than only bitrate as soon as gst doesn't crash
|
||||
// anymore while using the cbr parmameter (like cbr=false)
|
||||
|
||||
const char* TranscoderOptionsOpus::kSettingsGroup = "Transcoder/opusenc";
|
||||
|
||||
TranscoderOptionsOpus::TranscoderOptionsOpus(QWidget *parent) : TranscoderOptionsInterface(parent), ui_(new Ui_TranscoderOptionsOpus) {
|
||||
ui_->setupUi(this);
|
||||
}
|
||||
|
||||
TranscoderOptionsOpus::~TranscoderOptionsOpus() {
|
||||
delete ui_;
|
||||
}
|
||||
|
||||
void TranscoderOptionsOpus::Load() {
|
||||
QSettings s;
|
||||
s.beginGroup(kSettingsGroup + settings_postfix_);
|
||||
|
||||
ui_->bitrate_slider->setValue(s.value("bitrate", 128000).toInt() / 1000);
|
||||
}
|
||||
|
||||
void TranscoderOptionsOpus::Save() {
|
||||
QSettings s;
|
||||
s.beginGroup(kSettingsGroup + settings_postfix_);
|
||||
|
||||
s.setValue("bitrate", ui_->bitrate_slider->value() * 1000);
|
||||
}
|
||||
44
src/transcoder/transcoderoptionsopus.h
Normal file
44
src/transcoder/transcoderoptionsopus.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2013, Martin Brodbeck <martin@brodbeck-online.de>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Strawberry is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Strawberry. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TRANSCODEROPTIONSOPUS_H
|
||||
#define TRANSCODEROPTIONSOPUS_H
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "transcoderoptionsinterface.h"
|
||||
|
||||
class Ui_TranscoderOptionsOpus;
|
||||
|
||||
class TranscoderOptionsOpus : public TranscoderOptionsInterface {
|
||||
public:
|
||||
TranscoderOptionsOpus(QWidget *parent = nullptr);
|
||||
~TranscoderOptionsOpus();
|
||||
|
||||
void Load();
|
||||
void Save();
|
||||
|
||||
private:
|
||||
static const char* kSettingsGroup;
|
||||
|
||||
Ui_TranscoderOptionsOpus* ui_;
|
||||
};
|
||||
|
||||
#endif // TRANSCODEROPTIONSOPUS_H
|
||||
94
src/transcoder/transcoderoptionsopus.ui
Normal file
94
src/transcoder/transcoderoptionsopus.ui
Normal file
@@ -0,0 +1,94 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>TranscoderOptionsOpus</class>
|
||||
<widget class="QWidget" name="TranscoderOptionsOpus">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>400</width>
|
||||
<height>300</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Bitrate</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QSlider" name="bitrate_slider">
|
||||
<property name="minimum">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>510</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>128</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="bitrate_spinbox">
|
||||
<property name="suffix">
|
||||
<string> kbps</string>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>320</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>128</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>bitrate_slider</sender>
|
||||
<signal>valueChanged(int)</signal>
|
||||
<receiver>bitrate_spinbox</receiver>
|
||||
<slot>setValue(int)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>166</x>
|
||||
<y>25</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>323</x>
|
||||
<y>24</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>bitrate_spinbox</sender>
|
||||
<signal>valueChanged(int)</signal>
|
||||
<receiver>bitrate_slider</receiver>
|
||||
<slot>setValue(int)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>325</x>
|
||||
<y>14</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>190</x>
|
||||
<y>31</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
71
src/transcoder/transcoderoptionsspeex.cpp
Normal file
71
src/transcoder/transcoderoptionsspeex.cpp
Normal file
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Strawberry is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Strawberry. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "transcoderoptionsspeex.h"
|
||||
#include "ui_transcoderoptionsspeex.h"
|
||||
|
||||
#include <QSettings>
|
||||
|
||||
const char *TranscoderOptionsSpeex::kSettingsGroup = "Transcoder/speexenc";
|
||||
|
||||
TranscoderOptionsSpeex::TranscoderOptionsSpeex(QWidget *parent)
|
||||
: TranscoderOptionsInterface(parent), ui_(new Ui_TranscoderOptionsSpeex) {
|
||||
ui_->setupUi(this);
|
||||
}
|
||||
|
||||
TranscoderOptionsSpeex::~TranscoderOptionsSpeex() {
|
||||
delete ui_;
|
||||
}
|
||||
|
||||
void TranscoderOptionsSpeex::Load() {
|
||||
|
||||
QSettings s;
|
||||
s.beginGroup(kSettingsGroup + settings_postfix_);
|
||||
|
||||
ui_->quality_slider->setValue(s.value("quality", 8).toInt());
|
||||
ui_->bitrate_slider->setValue(s.value("bitrate", 0).toInt() / 1000);
|
||||
ui_->mode->setCurrentIndex(s.value("mode", 0).toInt());
|
||||
ui_->vbr->setChecked(s.value("vbr", false).toBool());
|
||||
ui_->abr_slider->setValue(s.value("abr", 0).toInt() / 1000);
|
||||
ui_->vad->setChecked(s.value("vad", false).toBool());
|
||||
ui_->dtx->setChecked(s.value("dtx", false).toBool());
|
||||
ui_->complexity->setValue(s.value("complexity", 3).toInt());
|
||||
ui_->nframes->setValue(s.value("nframes", 1).toInt());
|
||||
|
||||
}
|
||||
|
||||
void TranscoderOptionsSpeex::Save() {
|
||||
|
||||
QSettings s;
|
||||
s.beginGroup(kSettingsGroup + settings_postfix_);
|
||||
|
||||
s.setValue("quality", ui_->quality_slider->value());
|
||||
s.setValue("bitrate", ui_->bitrate_slider->value() * 1000);
|
||||
s.setValue("mode", ui_->mode->currentIndex());
|
||||
s.setValue("vbr", ui_->vbr->isChecked());
|
||||
s.setValue("abr", ui_->abr_slider->value() * 1000);
|
||||
s.setValue("vad", ui_->vad->isChecked());
|
||||
s.setValue("dtx", ui_->dtx->isChecked());
|
||||
s.setValue("complexity", ui_->complexity->value());
|
||||
s.setValue("nframes", ui_->nframes->value());
|
||||
|
||||
}
|
||||
44
src/transcoder/transcoderoptionsspeex.h
Normal file
44
src/transcoder/transcoderoptionsspeex.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Strawberry is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Strawberry. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TRANSCODEROPTIONSSPEEX_H
|
||||
#define TRANSCODEROPTIONSSPEEX_H
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "transcoderoptionsinterface.h"
|
||||
|
||||
class Ui_TranscoderOptionsSpeex;
|
||||
|
||||
class TranscoderOptionsSpeex : public TranscoderOptionsInterface {
|
||||
public:
|
||||
TranscoderOptionsSpeex(QWidget *parent = nullptr);
|
||||
~TranscoderOptionsSpeex();
|
||||
|
||||
void Load();
|
||||
void Save();
|
||||
|
||||
private:
|
||||
static const char *kSettingsGroup;
|
||||
|
||||
Ui_TranscoderOptionsSpeex *ui_;
|
||||
};
|
||||
|
||||
#endif // TRANSCODEROPTIONSSPEEX_H
|
||||
353
src/transcoder/transcoderoptionsspeex.ui
Normal file
353
src/transcoder/transcoderoptionsspeex.ui
Normal file
@@ -0,0 +1,353 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>TranscoderOptionsSpeex</class>
|
||||
<widget class="QWidget" name="TranscoderOptionsSpeex">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>555</width>
|
||||
<height>424</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string comment="Sound quality">Quality</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QSlider" name="quality_slider">
|
||||
<property name="maximum">
|
||||
<number>10</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>8</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="tickPosition">
|
||||
<enum>QSlider::TicksBelow</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="quality_spinbox">
|
||||
<property name="maximum">
|
||||
<number>10</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>8</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Bitrate</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QSlider" name="bitrate_slider">
|
||||
<property name="maximum">
|
||||
<number>320</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<number>8</number>
|
||||
</property>
|
||||
<property name="pageStep">
|
||||
<number>32</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="bitrate_spinbox">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="specialValueText">
|
||||
<string>automatic</string>
|
||||
</property>
|
||||
<property name="suffix">
|
||||
<string> kbps</string>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>320</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<number>8</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Average bitrate</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
<widget class="QSlider" name="abr_slider">
|
||||
<property name="maximum">
|
||||
<number>320</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<number>8</number>
|
||||
</property>
|
||||
<property name="pageStep">
|
||||
<number>32</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="abr_spinbox">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="specialValueText">
|
||||
<string>disabled</string>
|
||||
</property>
|
||||
<property name="suffix">
|
||||
<string> kbps</string>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>320</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<number>8</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Encoding mode</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QComboBox" name="mode">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Auto</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Ultra wide band (UWB)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Wide band (WB)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Narrow band (NB)</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="vbr">
|
||||
<property name="text">
|
||||
<string>Variable bit rate</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="vad">
|
||||
<property name="text">
|
||||
<string>Voice activity detection</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="dtx">
|
||||
<property name="text">
|
||||
<string>Discontinuous transmission</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Encoding complexity</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="1">
|
||||
<widget class="QSpinBox" name="complexity">
|
||||
<property name="maximum">
|
||||
<number>10000</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>3</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="0">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>Frames per buffer</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="1">
|
||||
<widget class="QSpinBox" name="nframes">
|
||||
<property name="maximum">
|
||||
<number>10000</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>1</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>quality_slider</tabstop>
|
||||
<tabstop>quality_spinbox</tabstop>
|
||||
<tabstop>bitrate_slider</tabstop>
|
||||
<tabstop>bitrate_spinbox</tabstop>
|
||||
<tabstop>abr_slider</tabstop>
|
||||
<tabstop>abr_spinbox</tabstop>
|
||||
<tabstop>mode</tabstop>
|
||||
<tabstop>vbr</tabstop>
|
||||
<tabstop>vad</tabstop>
|
||||
<tabstop>dtx</tabstop>
|
||||
<tabstop>complexity</tabstop>
|
||||
<tabstop>nframes</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>quality_slider</sender>
|
||||
<signal>valueChanged(int)</signal>
|
||||
<receiver>quality_spinbox</receiver>
|
||||
<slot>setValue(int)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>232</x>
|
||||
<y>29</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>525</x>
|
||||
<y>23</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>quality_spinbox</sender>
|
||||
<signal>valueChanged(int)</signal>
|
||||
<receiver>quality_slider</receiver>
|
||||
<slot>setValue(int)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>517</x>
|
||||
<y>25</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>248</x>
|
||||
<y>31</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>bitrate_slider</sender>
|
||||
<signal>valueChanged(int)</signal>
|
||||
<receiver>bitrate_spinbox</receiver>
|
||||
<slot>setValue(int)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>185</x>
|
||||
<y>66</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>445</x>
|
||||
<y>51</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>bitrate_spinbox</sender>
|
||||
<signal>valueChanged(int)</signal>
|
||||
<receiver>bitrate_slider</receiver>
|
||||
<slot>setValue(int)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>471</x>
|
||||
<y>68</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>214</x>
|
||||
<y>56</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>abr_slider</sender>
|
||||
<signal>valueChanged(int)</signal>
|
||||
<receiver>abr_spinbox</receiver>
|
||||
<slot>setValue(int)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>323</x>
|
||||
<y>90</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>500</x>
|
||||
<y>95</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>abr_spinbox</sender>
|
||||
<signal>valueChanged(int)</signal>
|
||||
<receiver>abr_slider</receiver>
|
||||
<slot>setValue(int)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>493</x>
|
||||
<y>84</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>339</x>
|
||||
<y>94</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
81
src/transcoder/transcoderoptionsvorbis.cpp
Normal file
81
src/transcoder/transcoderoptionsvorbis.cpp
Normal file
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Strawberry is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Strawberry. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "transcoderoptionsvorbis.h"
|
||||
#include "ui_transcoderoptionsvorbis.h"
|
||||
|
||||
#include <QSettings>
|
||||
|
||||
const char* TranscoderOptionsVorbis::kSettingsGroup = "Transcoder/vorbisenc";
|
||||
|
||||
TranscoderOptionsVorbis::TranscoderOptionsVorbis(QWidget* parent)
|
||||
: TranscoderOptionsInterface(parent), ui_(new Ui_TranscoderOptionsVorbis) {
|
||||
ui_->setupUi(this);
|
||||
}
|
||||
|
||||
TranscoderOptionsVorbis::~TranscoderOptionsVorbis() {
|
||||
delete ui_;
|
||||
}
|
||||
|
||||
void TranscoderOptionsVorbis::Load() {
|
||||
|
||||
QSettings s;
|
||||
s.beginGroup(kSettingsGroup + settings_postfix_);
|
||||
|
||||
#define GET_BITRATE(variable, property) \
|
||||
int variable = s.value(property, -1).toInt(); \
|
||||
variable = variable == -1 ? 0 : variable / 1000
|
||||
|
||||
GET_BITRATE(bitrate, "bitrate");
|
||||
GET_BITRATE(min_bitrate, "min-bitrate");
|
||||
GET_BITRATE(max_bitrate, "max-bitrate");
|
||||
#undef GET_BITRATE
|
||||
|
||||
ui_->quality_slider->setValue(s.value("quality", 0.3).toDouble() * 10);
|
||||
ui_->managed->setChecked(s.value("managed", false).toBool());
|
||||
ui_->max_bitrate_slider->setValue(max_bitrate);
|
||||
ui_->min_bitrate_slider->setValue(min_bitrate);
|
||||
ui_->bitrate_slider->setValue(bitrate);
|
||||
|
||||
}
|
||||
|
||||
void TranscoderOptionsVorbis::Save() {
|
||||
|
||||
QSettings s;
|
||||
s.beginGroup(kSettingsGroup + settings_postfix_);
|
||||
|
||||
#define GET_BITRATE(variable, ui_slider) \
|
||||
int variable = ui_slider->value(); \
|
||||
variable = variable == 0 ? -1 : variable * 1000
|
||||
|
||||
GET_BITRATE(bitrate, ui_->bitrate_slider);
|
||||
GET_BITRATE(min_bitrate, ui_->min_bitrate_slider);
|
||||
GET_BITRATE(max_bitrate, ui_->max_bitrate_slider);
|
||||
#undef GET_BITRATE
|
||||
|
||||
s.setValue("quality", double(ui_->quality_slider->value()) / 10);
|
||||
s.setValue("managed", ui_->managed->isChecked());
|
||||
s.setValue("bitrate", bitrate);
|
||||
s.setValue("min-bitrate", min_bitrate);
|
||||
s.setValue("max-bitrate", max_bitrate);
|
||||
|
||||
}
|
||||
44
src/transcoder/transcoderoptionsvorbis.h
Normal file
44
src/transcoder/transcoderoptionsvorbis.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Strawberry is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Strawberry. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TRANSCODEROPTIONSVORBIS_H
|
||||
#define TRANSCODEROPTIONSVORBIS_H
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "transcoderoptionsinterface.h"
|
||||
|
||||
class Ui_TranscoderOptionsVorbis;
|
||||
|
||||
class TranscoderOptionsVorbis : public TranscoderOptionsInterface {
|
||||
public:
|
||||
TranscoderOptionsVorbis(QWidget* parent = nullptr);
|
||||
~TranscoderOptionsVorbis();
|
||||
|
||||
void Load();
|
||||
void Save();
|
||||
|
||||
private:
|
||||
static const char *kSettingsGroup;
|
||||
|
||||
Ui_TranscoderOptionsVorbis *ui_;
|
||||
};
|
||||
|
||||
#endif // TRANSCODEROPTIONSVORBIS_H
|
||||
365
src/transcoder/transcoderoptionsvorbis.ui
Normal file
365
src/transcoder/transcoderoptionsvorbis.ui
Normal file
@@ -0,0 +1,365 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>TranscoderOptionsVorbis</class>
|
||||
<widget class="QWidget" name="TranscoderOptionsVorbis">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>400</width>
|
||||
<height>300</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout_2">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string comment="Sound quality">Quality</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||
<item>
|
||||
<widget class="QSlider" name="quality_slider">
|
||||
<property name="minimum">
|
||||
<number>-1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>10</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="tickPosition">
|
||||
<enum>QSlider::TicksBelow</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="quality_spinbox">
|
||||
<property name="minimum">
|
||||
<number>-1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>10</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>3</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="managed">
|
||||
<property name="text">
|
||||
<string>Use bitrate management engine</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="2">
|
||||
<widget class="QWidget" name="widget" native="true">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<property name="leftMargin">
|
||||
<number>32</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Target bitrate</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QSlider" name="bitrate_slider">
|
||||
<property name="maximum">
|
||||
<number>250</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>128</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="bitrate_spinbox">
|
||||
<property name="suffix">
|
||||
<string> kbps</string>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>250</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>128</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Minimum bitrate</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QSlider" name="min_bitrate_slider">
|
||||
<property name="maximum">
|
||||
<number>250</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="min_bitrate_spinbox">
|
||||
<property name="specialValueText">
|
||||
<string>disabled</string>
|
||||
</property>
|
||||
<property name="suffix">
|
||||
<string> kbps</string>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>250</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Maximum bitrate</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
<widget class="QSlider" name="max_bitrate_slider">
|
||||
<property name="maximum">
|
||||
<number>250</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="max_bitrate_spinbox">
|
||||
<property name="specialValueText">
|
||||
<string>disabled</string>
|
||||
</property>
|
||||
<property name="suffix">
|
||||
<string> kbps</string>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>250</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>quality_slider</tabstop>
|
||||
<tabstop>quality_spinbox</tabstop>
|
||||
<tabstop>managed</tabstop>
|
||||
<tabstop>bitrate_slider</tabstop>
|
||||
<tabstop>bitrate_spinbox</tabstop>
|
||||
<tabstop>min_bitrate_slider</tabstop>
|
||||
<tabstop>min_bitrate_spinbox</tabstop>
|
||||
<tabstop>max_bitrate_slider</tabstop>
|
||||
<tabstop>max_bitrate_spinbox</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>quality_slider</sender>
|
||||
<signal>valueChanged(int)</signal>
|
||||
<receiver>quality_spinbox</receiver>
|
||||
<slot>setValue(int)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>176</x>
|
||||
<y>29</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>365</x>
|
||||
<y>31</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>quality_spinbox</sender>
|
||||
<signal>valueChanged(int)</signal>
|
||||
<receiver>quality_slider</receiver>
|
||||
<slot>setValue(int)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>358</x>
|
||||
<y>19</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>136</x>
|
||||
<y>29</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>bitrate_slider</sender>
|
||||
<signal>valueChanged(int)</signal>
|
||||
<receiver>bitrate_spinbox</receiver>
|
||||
<slot>setValue(int)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>255</x>
|
||||
<y>83</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>344</x>
|
||||
<y>88</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>bitrate_spinbox</sender>
|
||||
<signal>valueChanged(int)</signal>
|
||||
<receiver>bitrate_slider</receiver>
|
||||
<slot>setValue(int)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>341</x>
|
||||
<y>77</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>244</x>
|
||||
<y>80</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>min_bitrate_spinbox</sender>
|
||||
<signal>valueChanged(int)</signal>
|
||||
<receiver>min_bitrate_slider</receiver>
|
||||
<slot>setValue(int)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>324</x>
|
||||
<y>122</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>265</x>
|
||||
<y>115</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>min_bitrate_slider</sender>
|
||||
<signal>valueChanged(int)</signal>
|
||||
<receiver>min_bitrate_spinbox</receiver>
|
||||
<slot>setValue(int)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>217</x>
|
||||
<y>122</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>347</x>
|
||||
<y>124</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>max_bitrate_slider</sender>
|
||||
<signal>valueChanged(int)</signal>
|
||||
<receiver>max_bitrate_spinbox</receiver>
|
||||
<slot>setValue(int)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>278</x>
|
||||
<y>157</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>323</x>
|
||||
<y>155</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>max_bitrate_spinbox</sender>
|
||||
<signal>valueChanged(int)</signal>
|
||||
<receiver>max_bitrate_slider</receiver>
|
||||
<slot>setValue(int)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>344</x>
|
||||
<y>166</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>216</x>
|
||||
<y>155</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>managed</sender>
|
||||
<signal>toggled(bool)</signal>
|
||||
<receiver>widget</receiver>
|
||||
<slot>setEnabled(bool)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>55</x>
|
||||
<y>58</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>25</x>
|
||||
<y>86</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
55
src/transcoder/transcoderoptionswma.cpp
Normal file
55
src/transcoder/transcoderoptionswma.cpp
Normal file
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Strawberry is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Strawberry. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "transcoderoptionswma.h"
|
||||
#include "ui_transcoderoptionswma.h"
|
||||
|
||||
#include <QSettings>
|
||||
|
||||
const char *TranscoderOptionsWma::kSettingsGroup = "Transcoder/ffenc_wmav2";
|
||||
|
||||
TranscoderOptionsWma::TranscoderOptionsWma(QWidget *parent)
|
||||
: TranscoderOptionsInterface(parent), ui_(new Ui_TranscoderOptionsWma) {
|
||||
ui_->setupUi(this);
|
||||
}
|
||||
|
||||
TranscoderOptionsWma::~TranscoderOptionsWma() {
|
||||
delete ui_;
|
||||
}
|
||||
|
||||
void TranscoderOptionsWma::Load() {
|
||||
|
||||
QSettings s;
|
||||
s.beginGroup(kSettingsGroup + settings_postfix_);
|
||||
|
||||
ui_->bitrate_slider->setValue(s.value("bitrate", 128000).toInt() / 1000);
|
||||
|
||||
}
|
||||
|
||||
void TranscoderOptionsWma::Save() {
|
||||
|
||||
QSettings s;
|
||||
s.beginGroup(kSettingsGroup + settings_postfix_);
|
||||
|
||||
s.setValue("bitrate", ui_->bitrate_slider->value() * 1000);
|
||||
|
||||
}
|
||||
44
src/transcoder/transcoderoptionswma.h
Normal file
44
src/transcoder/transcoderoptionswma.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Strawberry is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Strawberry. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TRANSCODEROPTIONSWMA_H
|
||||
#define TRANSCODEROPTIONSWMA_H
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "transcoderoptionsinterface.h"
|
||||
|
||||
class Ui_TranscoderOptionsWma;
|
||||
|
||||
class TranscoderOptionsWma : public TranscoderOptionsInterface {
|
||||
public:
|
||||
TranscoderOptionsWma(QWidget *parent = nullptr);
|
||||
~TranscoderOptionsWma();
|
||||
|
||||
void Load();
|
||||
void Save();
|
||||
|
||||
private:
|
||||
static const char *kSettingsGroup;
|
||||
|
||||
Ui_TranscoderOptionsWma *ui_;
|
||||
};
|
||||
|
||||
#endif // TRANSCODEROPTIONSWMA_H
|
||||
91
src/transcoder/transcoderoptionswma.ui
Normal file
91
src/transcoder/transcoderoptionswma.ui
Normal file
@@ -0,0 +1,91 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>TranscoderOptionsWma</class>
|
||||
<widget class="QWidget" name="TranscoderOptionsWma">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>400</width>
|
||||
<height>300</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Bitrate</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QSlider" name="bitrate_slider">
|
||||
<property name="maximum">
|
||||
<number>320</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>128</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="bitrate_spinbox">
|
||||
<property name="suffix">
|
||||
<string> kbps</string>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>320</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>128</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>bitrate_slider</sender>
|
||||
<signal>valueChanged(int)</signal>
|
||||
<receiver>bitrate_spinbox</receiver>
|
||||
<slot>setValue(int)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>166</x>
|
||||
<y>25</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>323</x>
|
||||
<y>24</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>bitrate_spinbox</sender>
|
||||
<signal>valueChanged(int)</signal>
|
||||
<receiver>bitrate_slider</receiver>
|
||||
<slot>setValue(int)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>325</x>
|
||||
<y>14</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>190</x>
|
||||
<y>31</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
Reference in New Issue
Block a user