Merge branch 'master' into c++11
This commit is contained in:
commit
767965a2f4
|
@ -183,31 +183,39 @@ static const unsigned int KeyTbl[] = {
|
||||||
|
|
||||||
// numeric and function keypad keys
|
// numeric and function keypad keys
|
||||||
|
|
||||||
XK_KP_Space, Qt::Key_Space,
|
|
||||||
XK_KP_Tab, Qt::Key_Tab,
|
|
||||||
XK_KP_Enter, Qt::Key_Enter,
|
XK_KP_Enter, Qt::Key_Enter,
|
||||||
//XK_KP_F1, Qt::Key_F1,
|
|
||||||
//XK_KP_F2, Qt::Key_F2,
|
// special and additional keys
|
||||||
//XK_KP_F3, Qt::Key_F3,
|
|
||||||
//XK_KP_F4, Qt::Key_F4,
|
XK_Clear, Qt::Key_Clear,
|
||||||
XK_KP_Home, Qt::Key_Home,
|
XK_Delete, Qt::Key_Delete,
|
||||||
XK_KP_Left, Qt::Key_Left,
|
XK_space, Qt::Key_Space,
|
||||||
XK_KP_Up, Qt::Key_Up,
|
XK_exclam, Qt::Key_Exclam,
|
||||||
XK_KP_Right, Qt::Key_Right,
|
XK_quotedbl, Qt::Key_QuoteDbl,
|
||||||
XK_KP_Down, Qt::Key_Down,
|
XK_numbersign, Qt::Key_NumberSign,
|
||||||
XK_KP_Prior, Qt::Key_PageUp,
|
XK_dollar, Qt::Key_Dollar,
|
||||||
XK_KP_Next, Qt::Key_PageDown,
|
XK_percent, Qt::Key_Percent,
|
||||||
XK_KP_End, Qt::Key_End,
|
XK_ampersand, Qt::Key_Ampersand,
|
||||||
XK_KP_Begin, Qt::Key_Clear,
|
XK_apostrophe, Qt::Key_Apostrophe,
|
||||||
XK_KP_Insert, Qt::Key_Insert,
|
XK_parenleft, Qt::Key_ParenLeft,
|
||||||
XK_KP_Delete, Qt::Key_Delete,
|
XK_parenright, Qt::Key_ParenRight,
|
||||||
XK_KP_Equal, Qt::Key_Equal,
|
XK_asterisk, Qt::Key_Asterisk,
|
||||||
XK_KP_Multiply, Qt::Key_Asterisk,
|
XK_plus, Qt::Key_Plus,
|
||||||
XK_KP_Add, Qt::Key_Plus,
|
XK_comma, Qt::Key_Comma,
|
||||||
XK_KP_Separator, Qt::Key_Comma,
|
XK_minus, Qt::Key_Minus,
|
||||||
XK_KP_Subtract, Qt::Key_Minus,
|
XK_period, Qt::Key_Period,
|
||||||
XK_KP_Decimal, Qt::Key_Period,
|
XK_slash, Qt::Key_Slash,
|
||||||
XK_KP_Divide, Qt::Key_Slash,
|
XK_colon, Qt::Key_Colon,
|
||||||
|
XK_semicolon, Qt::Key_Semicolon,
|
||||||
|
XK_less, Qt::Key_Less,
|
||||||
|
XK_equal, Qt::Key_Equal,
|
||||||
|
XK_greater, Qt::Key_Greater,
|
||||||
|
XK_question, Qt::Key_Question,
|
||||||
|
XK_bracketleft, Qt::Key_BracketLeft,
|
||||||
|
XK_backslash, Qt::Key_Backslash,
|
||||||
|
XK_bracketright, Qt::Key_BracketRight,
|
||||||
|
XK_asciicircum, Qt::Key_AsciiCircum,
|
||||||
|
XK_underscore, Qt::Key_Underscore,
|
||||||
|
|
||||||
// International input method support keys
|
// International input method support keys
|
||||||
|
|
||||||
|
|
|
@ -96,11 +96,9 @@ find_path(SPARSEHASH_INCLUDE_DIRS google/sparsetable)
|
||||||
# distros. If the user seems to want Drive support (ie. they have sparsehash
|
# distros. If the user seems to want Drive support (ie. they have sparsehash
|
||||||
# installed and haven't disabled drive), and has an old taglib, compile our
|
# installed and haven't disabled drive), and has an old taglib, compile our
|
||||||
# internal one and use that instead.
|
# internal one and use that instead.
|
||||||
option(USE_BUILTIN_TAGLIB "If the system's version of Taglib is too old for Google Drive support, compile our builtin version instead" ON)
|
option(USE_BUILTIN_TAGLIB "If the system's version of Taglib is too old, compile our builtin version instead" ON)
|
||||||
if (USE_BUILTIN_TAGLIB AND
|
if (USE_BUILTIN_TAGLIB AND TAGLIB_VERSION VERSION_LESS 1.8)
|
||||||
(NOT "${ENABLE_GOOGLE_DRIVE}" STREQUAL "OFF") AND
|
message(STATUS "Using builtin taglib because your system's version is too old")
|
||||||
SPARSEHASH_INCLUDE_DIRS AND
|
|
||||||
TAGLIB_VERSION VERSION_LESS 1.8)
|
|
||||||
set(TAGLIB_VERSION 1.9.1)
|
set(TAGLIB_VERSION 1.9.1)
|
||||||
set(TAGLIB_INCLUDE_DIRS "${CMAKE_BINARY_DIR}/3rdparty/taglib/headers/taglib/;${CMAKE_BINARY_DIR}/3rdparty/taglib/headers/")
|
set(TAGLIB_INCLUDE_DIRS "${CMAKE_BINARY_DIR}/3rdparty/taglib/headers/taglib/;${CMAKE_BINARY_DIR}/3rdparty/taglib/headers/")
|
||||||
set(TAGLIB_LIBRARY_DIRS "")
|
set(TAGLIB_LIBRARY_DIRS "")
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
Clementine
|
||||||
|
==========
|
||||||
|
|
||||||
|
Clementine is a modern music player and library organizer for Windows, Linux and Mac OS X.
|
||||||
|
|
||||||
|
- Website: http://www.clementine-player.org/
|
||||||
|
- Github: https://github.com/clementine-player/Clementine
|
||||||
|
- Buildbot: http://buildbot.clementine-player.org/grid
|
||||||
|
- Latest developer builds: http://builds.clementine-player.org/
|
||||||
|
|
||||||
|
Compiling from source
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
Get the code (if you haven't already):
|
||||||
|
|
||||||
|
git clone https://github.com/clementine-player/Clementine.git && cd Clementine
|
||||||
|
|
||||||
|
Compile and install:
|
||||||
|
|
||||||
|
cd bin
|
||||||
|
cmake ..
|
||||||
|
make -j8
|
||||||
|
sudo make install
|
||||||
|
|
||||||
|
See the Wiki for more instructions and a list of dependencies:
|
||||||
|
https://github.com/clementine-player/Clementine/wiki/Compiling-from-Source
|
|
@ -1027,9 +1027,13 @@ optional_source(HAVE_AUDIOCD
|
||||||
SOURCES
|
SOURCES
|
||||||
devices/cddadevice.cpp
|
devices/cddadevice.cpp
|
||||||
devices/cddalister.cpp
|
devices/cddalister.cpp
|
||||||
|
ui/ripcd.cpp
|
||||||
HEADERS
|
HEADERS
|
||||||
devices/cddadevice.h
|
devices/cddadevice.h
|
||||||
devices/cddalister.h
|
devices/cddalister.h
|
||||||
|
ui/ripcd.h
|
||||||
|
UI
|
||||||
|
ui/ripcd.ui
|
||||||
)
|
)
|
||||||
|
|
||||||
# mtp device
|
# mtp device
|
||||||
|
|
|
@ -451,4 +451,12 @@ void EnableFullScreen(const QWidget& main_window) {
|
||||||
[window setCollectionBehavior: kFullScreenPrimary];
|
[window setCollectionBehavior: kFullScreenPrimary];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float GetDevicePixelRatio(QWidget* widget) {
|
||||||
|
NSView* view = reinterpret_cast<NSView*>(widget->winId());
|
||||||
|
if ([[view window] respondsToSelector: @selector(backingScaleFactor)]) {
|
||||||
|
return [[view window] backingScaleFactor];
|
||||||
|
}
|
||||||
|
return 1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace mac
|
} // namespace mac
|
||||||
|
|
|
@ -29,5 +29,6 @@ namespace mac {
|
||||||
|
|
||||||
QKeySequence KeySequenceFromNSEvent(NSEvent* event);
|
QKeySequence KeySequenceFromNSEvent(NSEvent* event);
|
||||||
void DumpDictionary(CFDictionaryRef dict);
|
void DumpDictionary(CFDictionaryRef dict);
|
||||||
|
float GetDevicePixelRatio(QWidget* widget);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,7 +69,7 @@ void Player::Init() {
|
||||||
connect(engine_.get(), SIGNAL(TrackAboutToEnd()), SLOT(TrackAboutToEnd()));
|
connect(engine_.get(), SIGNAL(TrackAboutToEnd()), SLOT(TrackAboutToEnd()));
|
||||||
connect(engine_.get(), SIGNAL(TrackEnded()), SLOT(TrackEnded()));
|
connect(engine_.get(), SIGNAL(TrackEnded()), SLOT(TrackEnded()));
|
||||||
connect(engine_.get(), SIGNAL(MetaData(Engine::SimpleMetaBundle)),
|
connect(engine_.get(), SIGNAL(MetaData(Engine::SimpleMetaBundle)),
|
||||||
SLOT(EngineMetadataReceived(Engine::SimpleMetaBundle)));
|
SLOT(EngineMetadataReceived(Engine::SimpleMetaBundle)));
|
||||||
|
|
||||||
engine_->SetVolume(settings_.value("volume", 50).toInt());
|
engine_->SetVolume(settings_.value("volume", 50).toInt());
|
||||||
|
|
||||||
|
|
|
@ -797,7 +797,7 @@ void Song::BindToQuery(QSqlQuery *query) const {
|
||||||
&& Utilities::UrlOnSameDriveAsClementine(d->url_)) {
|
&& Utilities::UrlOnSameDriveAsClementine(d->url_)) {
|
||||||
query->bindValue(":filename", Utilities::GetRelativePathToClementineBin(d->url_));
|
query->bindValue(":filename", Utilities::GetRelativePathToClementineBin(d->url_));
|
||||||
} else {
|
} else {
|
||||||
query->bindValue(":filename", d->url_);
|
query->bindValue(":filename", d->url_.toEncoded());
|
||||||
}
|
}
|
||||||
|
|
||||||
query->bindValue(":mtime", notnullintval(d->mtime_));
|
query->bindValue(":mtime", notnullintval(d->mtime_));
|
||||||
|
|
|
@ -33,16 +33,17 @@
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "core/concurrentrun.h"
|
#include "core/concurrentrun.h"
|
||||||
#include "core/logging.h"
|
#include "core/logging.h"
|
||||||
#include "core/song.h"
|
#include "core/player.h"
|
||||||
#include "core/signalchecker.h"
|
#include "core/signalchecker.h"
|
||||||
|
#include "core/song.h"
|
||||||
#include "core/tagreaderclient.h"
|
#include "core/tagreaderclient.h"
|
||||||
#include "core/timeconstants.h"
|
#include "core/timeconstants.h"
|
||||||
#include "internet/fixlastfm.h"
|
#include "internet/fixlastfm.h"
|
||||||
#include "internet/internetmodel.h"
|
#include "internet/internetmodel.h"
|
||||||
#include "library/librarybackend.h"
|
#include "library/librarybackend.h"
|
||||||
#include "library/sqlrow.h"
|
#include "library/sqlrow.h"
|
||||||
#include "playlistparsers/parserbase.h"
|
|
||||||
#include "playlistparsers/cueparser.h"
|
#include "playlistparsers/cueparser.h"
|
||||||
|
#include "playlistparsers/parserbase.h"
|
||||||
#include "playlistparsers/playlistparser.h"
|
#include "playlistparsers/playlistparser.h"
|
||||||
#include "podcasts/podcastparser.h"
|
#include "podcasts/podcastparser.h"
|
||||||
#include "podcasts/podcastservice.h"
|
#include "podcasts/podcastservice.h"
|
||||||
|
@ -52,7 +53,9 @@
|
||||||
QSet<QString> SongLoader::sRawUriSchemes;
|
QSet<QString> SongLoader::sRawUriSchemes;
|
||||||
const int SongLoader::kDefaultTimeout = 5000;
|
const int SongLoader::kDefaultTimeout = 5000;
|
||||||
|
|
||||||
SongLoader::SongLoader(LibraryBackendInterface* library, QObject *parent)
|
SongLoader::SongLoader(LibraryBackendInterface* library,
|
||||||
|
const Player* player,
|
||||||
|
QObject *parent)
|
||||||
: QObject(parent),
|
: QObject(parent),
|
||||||
timeout_timer_(new QTimer(this)),
|
timeout_timer_(new QTimer(this)),
|
||||||
playlist_parser_(new PlaylistParser(library, this)),
|
playlist_parser_(new PlaylistParser(library, this)),
|
||||||
|
@ -63,7 +66,8 @@ SongLoader::SongLoader(LibraryBackendInterface* library, QObject *parent)
|
||||||
success_(false),
|
success_(false),
|
||||||
parser_(NULL),
|
parser_(NULL),
|
||||||
is_podcast_(false),
|
is_podcast_(false),
|
||||||
library_(library)
|
library_(library),
|
||||||
|
player_(player)
|
||||||
{
|
{
|
||||||
if (sRawUriSchemes.isEmpty()) {
|
if (sRawUriSchemes.isEmpty()) {
|
||||||
sRawUriSchemes << "udp" << "mms" << "mmsh" << "mmst" << "mmsu" << "rtsp"
|
sRawUriSchemes << "udp" << "mms" << "mmsh" << "mmst" << "mmsu" << "rtsp"
|
||||||
|
@ -91,9 +95,10 @@ SongLoader::Result SongLoader::Load(const QUrl& url) {
|
||||||
return LoadLocal(url_.toLocalFile());
|
return LoadLocal(url_.toLocalFile());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sRawUriSchemes.contains(url_.scheme())) {
|
if (sRawUriSchemes.contains(url_.scheme()) ||
|
||||||
// The URI scheme indicates that it can't possibly be a playlist, so add
|
player_->HandlerForUrl(url) != nullptr) {
|
||||||
// it as a raw stream.
|
// The URI scheme indicates that it can't possibly be a playlist, or we have
|
||||||
|
// a custom handler for the URL, so add it as a raw stream.
|
||||||
AddAsRawStream();
|
AddAsRawStream();
|
||||||
return Success;
|
return Success;
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,13 +33,15 @@
|
||||||
class CueParser;
|
class CueParser;
|
||||||
class LibraryBackendInterface;
|
class LibraryBackendInterface;
|
||||||
class ParserBase;
|
class ParserBase;
|
||||||
|
class Player;
|
||||||
class PlaylistParser;
|
class PlaylistParser;
|
||||||
class PodcastParser;
|
class PodcastParser;
|
||||||
|
|
||||||
class SongLoader : public QObject {
|
class SongLoader : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
SongLoader(LibraryBackendInterface* library, QObject* parent = 0);
|
SongLoader(LibraryBackendInterface* library, const Player* player,
|
||||||
|
QObject* parent = 0);
|
||||||
~SongLoader();
|
~SongLoader();
|
||||||
|
|
||||||
enum Result {
|
enum Result {
|
||||||
|
@ -130,6 +132,7 @@ private:
|
||||||
bool is_podcast_;
|
bool is_podcast_;
|
||||||
QByteArray buffer_;
|
QByteArray buffer_;
|
||||||
LibraryBackendInterface* library_;
|
LibraryBackendInterface* library_;
|
||||||
|
const Player* player_;
|
||||||
|
|
||||||
boost::shared_ptr<GstElement> pipeline_;
|
boost::shared_ptr<GstElement> pipeline_;
|
||||||
|
|
||||||
|
|
|
@ -457,9 +457,9 @@ QByteArray Sha256(const QByteArray& data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// File must not be open and will be closed afterwards!
|
// File must not be open and will be closed afterwards!
|
||||||
QByteArray Md5File(QFile &file) {
|
QByteArray Sha1File(QFile &file) {
|
||||||
file.open(QIODevice::ReadOnly);
|
file.open(QIODevice::ReadOnly);
|
||||||
QCryptographicHash hash(QCryptographicHash::Md5);
|
QCryptographicHash hash(QCryptographicHash::Sha1);
|
||||||
QByteArray data;
|
QByteArray data;
|
||||||
|
|
||||||
while(!file.atEnd()) {
|
while(!file.atEnd()) {
|
||||||
|
|
|
@ -67,7 +67,7 @@ namespace Utilities {
|
||||||
QByteArray HmacSha256(const QByteArray& key, const QByteArray& data);
|
QByteArray HmacSha256(const QByteArray& key, const QByteArray& data);
|
||||||
QByteArray HmacSha1(const QByteArray& key, const QByteArray& data);
|
QByteArray HmacSha1(const QByteArray& key, const QByteArray& data);
|
||||||
QByteArray Sha256(const QByteArray& data);
|
QByteArray Sha256(const QByteArray& data);
|
||||||
QByteArray Md5File(QFile& file);
|
QByteArray Sha1File(QFile& file);
|
||||||
QByteArray Sha1CoverHash(const QString& artist, const QString& album);
|
QByteArray Sha1CoverHash(const QString& artist, const QString& album);
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ using boost::scoped_ptr;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
static const char* kServiceName = "Skydrive";
|
static const char* kServiceName = "OneDrive";
|
||||||
static const char* kServiceId = "skydrive";
|
static const char* kServiceId = "skydrive";
|
||||||
static const char* kSettingsGroup = "Skydrive";
|
static const char* kSettingsGroup = "Skydrive";
|
||||||
|
|
||||||
|
|
|
@ -212,6 +212,10 @@ void LibraryFilterWidget::SetQueryMode(QueryOptions::QueryMode query_mode) {
|
||||||
model_->SetFilterQueryMode(query_mode);
|
model_->SetFilterQueryMode(query_mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LibraryFilterWidget::ShowInLibrary(const QString& search) {
|
||||||
|
ui_->filter->setText(search);
|
||||||
|
}
|
||||||
|
|
||||||
void LibraryFilterWidget::SetAgeFilterEnabled(bool enabled) {
|
void LibraryFilterWidget::SetAgeFilterEnabled(bool enabled) {
|
||||||
filter_age_menu_->setEnabled(enabled);
|
filter_age_menu_->setEnabled(enabled);
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,6 +56,7 @@ class LibraryFilterWidget : public QWidget {
|
||||||
void SetDelayBehaviour(DelayBehaviour behaviour) { delay_behaviour_ = behaviour; }
|
void SetDelayBehaviour(DelayBehaviour behaviour) { delay_behaviour_ = behaviour; }
|
||||||
void SetAgeFilterEnabled(bool enabled);
|
void SetAgeFilterEnabled(bool enabled);
|
||||||
void SetGroupByEnabled(bool enabled);
|
void SetGroupByEnabled(bool enabled);
|
||||||
|
void ShowInLibrary(const QString& search);
|
||||||
|
|
||||||
QMenu* menu() const { return library_menu_; }
|
QMenu* menu() const { return library_menu_; }
|
||||||
void AddMenuAction(QAction* action);
|
void AddMenuAction(QAction* action);
|
||||||
|
|
|
@ -39,19 +39,37 @@ LibraryQuery::LibraryQuery(const QueryOptions& options)
|
||||||
// expected with sqlite's FTS3:
|
// expected with sqlite's FTS3:
|
||||||
// 1) Append * to all tokens.
|
// 1) Append * to all tokens.
|
||||||
// 2) Prefix "fts" to column names.
|
// 2) Prefix "fts" to column names.
|
||||||
|
// 3) Remove colons which don't correspond to column names.
|
||||||
|
|
||||||
// Split on whitespace
|
// Split on whitespace
|
||||||
QStringList tokens(options.filter().split(QRegExp("\\s+")));
|
QStringList tokens(options.filter().split(
|
||||||
|
QRegExp("\\s+"), QString::SkipEmptyParts));
|
||||||
QString query;
|
QString query;
|
||||||
foreach (QString token, tokens) {
|
foreach (QString token, tokens) {
|
||||||
token.remove('(');
|
token.remove('(');
|
||||||
token.remove(')');
|
token.remove(')');
|
||||||
token.remove('"');
|
token.remove('"');
|
||||||
|
token.replace('-', ' ');
|
||||||
|
|
||||||
if (token.contains(':'))
|
if (token.contains(':')) {
|
||||||
query += "fts" + token + "* ";
|
// Only prefix fts if the token is a valid column name.
|
||||||
else
|
if (Song::kFtsColumns.contains("fts" + token.section(':', 0, 0),
|
||||||
|
Qt::CaseInsensitive)) {
|
||||||
|
// Account for multiple colons.
|
||||||
|
QString columntoken = token.section(
|
||||||
|
':', 0, 0, QString::SectionIncludeTrailingSep);
|
||||||
|
QString subtoken = token.section(':', 1, -1);
|
||||||
|
subtoken.replace(":", " ");
|
||||||
|
subtoken = subtoken.trimmed();
|
||||||
|
query += "fts" + columntoken + subtoken + "* ";
|
||||||
|
} else {
|
||||||
|
token.replace(":", " ");
|
||||||
|
token = token.trimmed();
|
||||||
|
query += token + "* ";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
query += token + "* ";
|
query += token + "* ";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
where_clauses_ << "fts.%fts_table_noprefix MATCH ?";
|
where_clauses_ << "fts.%fts_table_noprefix MATCH ?";
|
||||||
|
|
|
@ -642,9 +642,9 @@ void OutgoingDataCreator::SendSingleSong(RemoteClient* client, const Song &song,
|
||||||
// Open the file
|
// Open the file
|
||||||
QFile file(song.url().toLocalFile());
|
QFile file(song.url().toLocalFile());
|
||||||
|
|
||||||
// Get md5 for file
|
// Get sha1 for file
|
||||||
QByteArray md5 = Utilities::Md5File(file).toHex();
|
QByteArray sha1 = Utilities::Sha1File(file).toHex();
|
||||||
qLog(Debug) << "md5 for file" << song.url().toLocalFile() << "=" << md5;
|
qLog(Debug) << "sha1 for file" << song.url().toLocalFile() << "=" << sha1;
|
||||||
|
|
||||||
file.open(QIODevice::ReadOnly);
|
file.open(QIODevice::ReadOnly);
|
||||||
|
|
||||||
|
@ -670,7 +670,7 @@ void OutgoingDataCreator::SendSingleSong(RemoteClient* client, const Song &song,
|
||||||
chunk->set_file_number(song_no);
|
chunk->set_file_number(song_no);
|
||||||
chunk->set_size(file.size());
|
chunk->set_size(file.size());
|
||||||
chunk->set_data(data.data(), data.size());
|
chunk->set_data(data.data(), data.size());
|
||||||
chunk->set_file_hash(md5.data(), md5.size());
|
chunk->set_file_hash(sha1.data(), sha1.size());
|
||||||
|
|
||||||
// On the first chunk send the metadata, so the client knows
|
// On the first chunk send the metadata, so the client knows
|
||||||
// what file it receives.
|
// what file it receives.
|
||||||
|
@ -753,9 +753,9 @@ void OutgoingDataCreator::SendLibrary(RemoteClient *client) {
|
||||||
// Open the file
|
// Open the file
|
||||||
QFile file(temp_file_name);
|
QFile file(temp_file_name);
|
||||||
|
|
||||||
// Get the md5 hash
|
// Get the sha1 hash
|
||||||
QByteArray md5 = Utilities::Md5File(file).toHex();
|
QByteArray sha1 = Utilities::Sha1File(file).toHex();
|
||||||
qLog(Debug) << "Library md5" << md5;
|
qLog(Debug) << "Library sha1" << sha1;
|
||||||
|
|
||||||
file.open(QIODevice::ReadOnly);
|
file.open(QIODevice::ReadOnly);
|
||||||
|
|
||||||
|
@ -777,7 +777,7 @@ void OutgoingDataCreator::SendLibrary(RemoteClient *client) {
|
||||||
chunk->set_chunk_number(chunk_number);
|
chunk->set_chunk_number(chunk_number);
|
||||||
chunk->set_size(file.size());
|
chunk->set_size(file.size());
|
||||||
chunk->set_data(data.data(), data.size());
|
chunk->set_data(data.data(), data.size());
|
||||||
chunk->set_file_hash(md5.data(), md5.size());
|
chunk->set_file_hash(sha1.data(), sha1.size());
|
||||||
|
|
||||||
// Send data directly to the client
|
// Send data directly to the client
|
||||||
client->SendData(&msg);
|
client->SendData(&msg);
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include "songloaderinserter.h"
|
#include "songloaderinserter.h"
|
||||||
#include "songmimedata.h"
|
#include "songmimedata.h"
|
||||||
#include "songplaylistitem.h"
|
#include "songplaylistitem.h"
|
||||||
|
#include "core/application.h"
|
||||||
#include "core/closure.h"
|
#include "core/closure.h"
|
||||||
#include "core/logging.h"
|
#include "core/logging.h"
|
||||||
#include "core/modelfuturewatcher.h"
|
#include "core/modelfuturewatcher.h"
|
||||||
|
@ -761,7 +762,8 @@ bool Playlist::dropMimeData(const QMimeData* data, Qt::DropAction action, int ro
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (data->hasFormat(kCddaMimeType)) {
|
} else if (data->hasFormat(kCddaMimeType)) {
|
||||||
SongLoaderInserter* inserter = new SongLoaderInserter(task_manager_, library_);
|
SongLoaderInserter* inserter = new SongLoaderInserter(
|
||||||
|
task_manager_, library_, backend_->app()->player());
|
||||||
connect(inserter, SIGNAL(Error(QString)), SIGNAL(LoadTracksError(QString)));
|
connect(inserter, SIGNAL(Error(QString)), SIGNAL(LoadTracksError(QString)));
|
||||||
inserter->LoadAudioCD(this, row, play_now, enqueue_now);
|
inserter->LoadAudioCD(this, row, play_now, enqueue_now);
|
||||||
} else if (data->hasUrls()) {
|
} else if (data->hasUrls()) {
|
||||||
|
@ -773,7 +775,8 @@ bool Playlist::dropMimeData(const QMimeData* data, Qt::DropAction action, int ro
|
||||||
}
|
}
|
||||||
|
|
||||||
void Playlist::InsertUrls(const QList<QUrl> &urls, int pos, bool play_now, bool enqueue) {
|
void Playlist::InsertUrls(const QList<QUrl> &urls, int pos, bool play_now, bool enqueue) {
|
||||||
SongLoaderInserter* inserter = new SongLoaderInserter(task_manager_, library_);
|
SongLoaderInserter* inserter = new SongLoaderInserter(
|
||||||
|
task_manager_, library_, backend_->app()->player());
|
||||||
connect(inserter, SIGNAL(Error(QString)), SIGNAL(LoadTracksError(QString)));
|
connect(inserter, SIGNAL(Error(QString)), SIGNAL(LoadTracksError(QString)));
|
||||||
|
|
||||||
inserter->Load(this, pos, play_now, enqueue, urls);
|
inserter->Load(this, pos, play_now, enqueue, urls);
|
||||||
|
|
|
@ -78,6 +78,8 @@ class PlaylistBackend : public QObject {
|
||||||
void FavoritePlaylist(int id, bool is_favorite);
|
void FavoritePlaylist(int id, bool is_favorite);
|
||||||
void RemovePlaylist(int id);
|
void RemovePlaylist(int id);
|
||||||
|
|
||||||
|
Application* app() const { return app_; }
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void SavePlaylist(int playlist, const PlaylistItemList& items,
|
void SavePlaylist(int playlist, const PlaylistItemList& items,
|
||||||
int last_played, smart_playlists::GeneratorPtr dynamic);
|
int last_played, smart_playlists::GeneratorPtr dynamic);
|
||||||
|
|
|
@ -16,13 +16,6 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "playlistdelegates.h"
|
#include "playlistdelegates.h"
|
||||||
#include "queue.h"
|
|
||||||
#include "core/logging.h"
|
|
||||||
#include "core/player.h"
|
|
||||||
#include "core/utilities.h"
|
|
||||||
#include "library/librarybackend.h"
|
|
||||||
#include "widgets/trackslider.h"
|
|
||||||
#include "ui/iconloader.h"
|
|
||||||
|
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
|
@ -39,6 +32,18 @@
|
||||||
#include <QWhatsThis>
|
#include <QWhatsThis>
|
||||||
#include <QtConcurrentRun>
|
#include <QtConcurrentRun>
|
||||||
|
|
||||||
|
#include "queue.h"
|
||||||
|
#include "core/logging.h"
|
||||||
|
#include "core/player.h"
|
||||||
|
#include "core/utilities.h"
|
||||||
|
#include "library/librarybackend.h"
|
||||||
|
#include "widgets/trackslider.h"
|
||||||
|
#include "ui/iconloader.h"
|
||||||
|
|
||||||
|
#ifdef Q_OS_DARWIN
|
||||||
|
#include "core/mac_utilities.h"
|
||||||
|
#endif // Q_OS_DARWIN
|
||||||
|
|
||||||
const int QueuedItemDelegate::kQueueBoxBorder = 1;
|
const int QueuedItemDelegate::kQueueBoxBorder = 1;
|
||||||
const int QueuedItemDelegate::kQueueBoxCornerRadius = 3;
|
const int QueuedItemDelegate::kQueueBoxCornerRadius = 3;
|
||||||
const int QueuedItemDelegate::kQueueBoxLength = 30;
|
const int QueuedItemDelegate::kQueueBoxLength = 30;
|
||||||
|
@ -492,8 +497,14 @@ void SongSourceDelegate::paint(
|
||||||
const QUrl& url = index.data().toUrl();
|
const QUrl& url = index.data().toUrl();
|
||||||
QPixmap pixmap = LookupPixmap(url, option_copy.decorationSize);
|
QPixmap pixmap = LookupPixmap(url, option_copy.decorationSize);
|
||||||
|
|
||||||
|
float device_pixel_ratio = 1.0f;
|
||||||
|
#ifdef Q_OS_DARWIN
|
||||||
|
QWidget* parent_widget = reinterpret_cast<QWidget*>(parent());
|
||||||
|
device_pixel_ratio = mac::GetDevicePixelRatio(parent_widget);
|
||||||
|
#endif
|
||||||
|
|
||||||
// Draw the pixmap in the middle of the rectangle
|
// Draw the pixmap in the middle of the rectangle
|
||||||
QRect draw_rect(QPoint(0, 0), option_copy.decorationSize);
|
QRect draw_rect(QPoint(0, 0), option_copy.decorationSize / device_pixel_ratio);
|
||||||
draw_rect.moveCenter(option_copy.rect.center());
|
draw_rect.moveCenter(option_copy.rect.center());
|
||||||
|
|
||||||
painter->drawPixmap(draw_rect, pixmap);
|
painter->drawPixmap(draw_rect, pixmap);
|
||||||
|
|
|
@ -156,7 +156,7 @@ void PlaylistManager::New(const QString& name, const SongList& songs,
|
||||||
|
|
||||||
void PlaylistManager::Load(const QString& filename) {
|
void PlaylistManager::Load(const QString& filename) {
|
||||||
QUrl url = QUrl::fromLocalFile(filename);
|
QUrl url = QUrl::fromLocalFile(filename);
|
||||||
SongLoader* loader = new SongLoader(library_backend_, this);
|
SongLoader* loader = new SongLoader(library_backend_, app_->player(), this);
|
||||||
connect(loader, SIGNAL(LoadFinished(bool)), SLOT(LoadFinished(bool)));
|
connect(loader, SIGNAL(LoadFinished(bool)), SLOT(LoadFinished(bool)));
|
||||||
SongLoader::Result result = loader->Load(url);
|
SongLoader::Result result = loader->Load(url);
|
||||||
QFileInfo info(filename);
|
QFileInfo info(filename);
|
||||||
|
|
|
@ -1254,3 +1254,24 @@ void PlaylistView::FadePreviousBackgroundImage(qreal value) {
|
||||||
void PlaylistView::PlayerStopped() {
|
void PlaylistView::PlayerStopped() {
|
||||||
CurrentSongChanged(Song(), QString(), QImage());
|
CurrentSongChanged(Song(), QString(), QImage());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PlaylistView::focusInEvent(QFocusEvent* event) {
|
||||||
|
QTreeView::focusInEvent(event);
|
||||||
|
|
||||||
|
if (event->reason() == Qt::TabFocusReason ||
|
||||||
|
event->reason() == Qt::BacktabFocusReason) {
|
||||||
|
// If there's a current item but no selection it probably means the list was
|
||||||
|
// filtered, and the selected item does not match the filter. If there's
|
||||||
|
// only 1 item in the view it is now impossible to select that item without
|
||||||
|
// using the mouse.
|
||||||
|
const QModelIndex& current = selectionModel()->currentIndex();
|
||||||
|
if (current.isValid() &&
|
||||||
|
selectionModel()->selectedIndexes().isEmpty()) {
|
||||||
|
QItemSelection new_selection(
|
||||||
|
current.sibling(current.row(), 0),
|
||||||
|
current.sibling(current.row(),
|
||||||
|
current.model()->columnCount(current.parent()) - 1));
|
||||||
|
selectionModel()->select(new_selection, QItemSelectionModel::Select);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -134,6 +134,7 @@ class PlaylistView : public QTreeView {
|
||||||
void dropEvent(QDropEvent *event);
|
void dropEvent(QDropEvent *event);
|
||||||
void resizeEvent(QResizeEvent* event);
|
void resizeEvent(QResizeEvent* event);
|
||||||
bool eventFilter(QObject* object, QEvent* event);
|
bool eventFilter(QObject* object, QEvent* event);
|
||||||
|
void focusInEvent(QFocusEvent* event);
|
||||||
|
|
||||||
// QAbstractScrollArea
|
// QAbstractScrollArea
|
||||||
void scrollContentsBy(int dx, int dy);
|
void scrollContentsBy(int dx, int dy);
|
||||||
|
|
|
@ -23,8 +23,9 @@
|
||||||
#include "core/songloader.h"
|
#include "core/songloader.h"
|
||||||
#include "core/taskmanager.h"
|
#include "core/taskmanager.h"
|
||||||
|
|
||||||
SongLoaderInserter::SongLoaderInserter(
|
SongLoaderInserter::SongLoaderInserter(TaskManager* task_manager,
|
||||||
TaskManager* task_manager, LibraryBackendInterface* library)
|
LibraryBackendInterface* library,
|
||||||
|
const Player* player)
|
||||||
: task_manager_(task_manager),
|
: task_manager_(task_manager),
|
||||||
destination_(NULL),
|
destination_(NULL),
|
||||||
row_(-1),
|
row_(-1),
|
||||||
|
@ -32,7 +33,8 @@ SongLoaderInserter::SongLoaderInserter(
|
||||||
enqueue_(false),
|
enqueue_(false),
|
||||||
async_load_id_(0),
|
async_load_id_(0),
|
||||||
async_progress_(0),
|
async_progress_(0),
|
||||||
library_(library) {
|
library_(library),
|
||||||
|
player_(player) {
|
||||||
}
|
}
|
||||||
|
|
||||||
SongLoaderInserter::~SongLoaderInserter() {
|
SongLoaderInserter::~SongLoaderInserter() {
|
||||||
|
@ -53,7 +55,7 @@ void SongLoaderInserter::Load(Playlist *destination,
|
||||||
destination, SLOT(UpdateItems(const SongList&)));
|
destination, SLOT(UpdateItems(const SongList&)));
|
||||||
|
|
||||||
foreach (const QUrl& url, urls) {
|
foreach (const QUrl& url, urls) {
|
||||||
SongLoader* loader = new SongLoader(library_, this);
|
SongLoader* loader = new SongLoader(library_, player_, this);
|
||||||
|
|
||||||
// we're connecting this before we're even sure if this is an async load
|
// we're connecting this before we're even sure if this is an async load
|
||||||
// to avoid race conditions (signal emission before we're listening to it)
|
// to avoid race conditions (signal emission before we're listening to it)
|
||||||
|
@ -92,7 +94,7 @@ void SongLoaderInserter::LoadAudioCD(Playlist *destination,
|
||||||
play_now_ = play_now;
|
play_now_ = play_now;
|
||||||
enqueue_ = enqueue;
|
enqueue_ = enqueue;
|
||||||
|
|
||||||
SongLoader *loader = new SongLoader(library_, this);
|
SongLoader* loader = new SongLoader(library_, player_, this);
|
||||||
connect(loader, SIGNAL(LoadFinished(bool)), SLOT(AudioCDTagsLoaded(bool)));
|
connect(loader, SIGNAL(LoadFinished(bool)), SLOT(AudioCDTagsLoaded(bool)));
|
||||||
qLog(Info) << "Loading audio CD...";
|
qLog(Info) << "Loading audio CD...";
|
||||||
SongLoader::Result ret = loader->LoadAudioCD();
|
SongLoader::Result ret = loader->LoadAudioCD();
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include "core/song.h"
|
#include "core/song.h"
|
||||||
|
|
||||||
class LibraryBackendInterface;
|
class LibraryBackendInterface;
|
||||||
|
class Player;
|
||||||
class Playlist;
|
class Playlist;
|
||||||
class SongLoader;
|
class SongLoader;
|
||||||
class TaskManager;
|
class TaskManager;
|
||||||
|
@ -34,7 +35,9 @@ class QModelIndex;
|
||||||
class SongLoaderInserter : public QObject {
|
class SongLoaderInserter : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
SongLoaderInserter(TaskManager* task_manager, LibraryBackendInterface* library);
|
SongLoaderInserter(TaskManager* task_manager,
|
||||||
|
LibraryBackendInterface* library,
|
||||||
|
const Player* player);
|
||||||
~SongLoaderInserter();
|
~SongLoaderInserter();
|
||||||
|
|
||||||
void Load(Playlist* destination, int row, bool play_now, bool enqueue,
|
void Load(Playlist* destination, int row, bool play_now, bool enqueue,
|
||||||
|
@ -70,6 +73,7 @@ private:
|
||||||
int async_load_id_;
|
int async_load_id_;
|
||||||
int async_progress_;
|
int async_progress_;
|
||||||
LibraryBackendInterface* library_;
|
LibraryBackendInterface* library_;
|
||||||
|
const Player* player_;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // SONGLOADERINSERTER_H
|
#endif // SONGLOADERINSERTER_H
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
/* This file is part of Clementine.
|
/* This file is part of Clementine.
|
||||||
Copyright 2012, David Sansome <me@davidsansome.com>
|
Copyright 2012, David Sansome <me@davidsansome.com>
|
||||||
|
|
||||||
Clementine is free software: you can redistribute it and/or modify
|
Clementine is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
|
|
||||||
Clementine is distributed in the hope that it will be useful,
|
Clementine is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
|
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
@ -27,6 +27,12 @@
|
||||||
#include <QRegExp>
|
#include <QRegExp>
|
||||||
#include <QSet>
|
#include <QSet>
|
||||||
|
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
#include <time.h>
|
||||||
|
#else
|
||||||
|
#include <sys/time.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
class Application;
|
class Application;
|
||||||
class PodcastBackend;
|
class PodcastBackend;
|
||||||
|
|
||||||
|
|
|
@ -138,7 +138,7 @@ void UltimateLyricsProvider::LyricsFetched() {
|
||||||
|
|
||||||
// Apply exclude rules
|
// Apply exclude rules
|
||||||
foreach (const Rule& rule, exclude_rules_) {
|
foreach (const Rule& rule, exclude_rules_) {
|
||||||
ApplyExcludeRule(rule, &lyrics);
|
ApplyExcludeRule(rule, &content);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!content.isEmpty() and HTMLHasAlphaNumeric(content)) {
|
if (!content.isEmpty() and HTMLHasAlphaNumeric(content)) {
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include "transcoderoptionsdialog.h"
|
#include "transcoderoptionsdialog.h"
|
||||||
#include "ui_transcodedialog.h"
|
#include "ui_transcodedialog.h"
|
||||||
#include "ui_transcodelogdialog.h"
|
#include "ui_transcodelogdialog.h"
|
||||||
|
#include "ui/iconloader.h"
|
||||||
#include "ui/mainwindow.h"
|
#include "ui/mainwindow.h"
|
||||||
#include "widgets/fileview.h"
|
#include "widgets/fileview.h"
|
||||||
|
|
||||||
|
@ -35,6 +36,7 @@
|
||||||
|
|
||||||
const char* TranscodeDialog::kSettingsGroup = "Transcoder";
|
const char* TranscodeDialog::kSettingsGroup = "Transcoder";
|
||||||
const int TranscodeDialog::kProgressInterval = 500;
|
const int TranscodeDialog::kProgressInterval = 500;
|
||||||
|
const int TranscodeDialog::kMaxDestinationItems = 10;
|
||||||
|
|
||||||
static bool ComparePresetsByName(const TranscoderPreset& left,
|
static bool ComparePresetsByName(const TranscoderPreset& left,
|
||||||
const TranscoderPreset& right) {
|
const TranscoderPreset& right) {
|
||||||
|
@ -103,6 +105,8 @@ TranscodeDialog::TranscodeDialog(QWidget *parent)
|
||||||
connect(close_button_, SIGNAL(clicked()), SLOT(hide()));
|
connect(close_button_, SIGNAL(clicked()), SLOT(hide()));
|
||||||
connect(ui_->details, SIGNAL(clicked()), log_dialog_, SLOT(show()));
|
connect(ui_->details, SIGNAL(clicked()), log_dialog_, SLOT(show()));
|
||||||
connect(ui_->options, SIGNAL(clicked()), SLOT(Options()));
|
connect(ui_->options, SIGNAL(clicked()), SLOT(Options()));
|
||||||
|
connect(ui_->select, SIGNAL(clicked()), SLOT(AddDestination()));
|
||||||
|
|
||||||
|
|
||||||
connect(transcoder_, SIGNAL(JobComplete(QString,bool)), SLOT(JobComplete(QString,bool)));
|
connect(transcoder_, SIGNAL(JobComplete(QString,bool)), SLOT(JobComplete(QString,bool)));
|
||||||
connect(transcoder_, SIGNAL(LogLine(QString)), SLOT(LogLine(QString)));
|
connect(transcoder_, SIGNAL(LogLine(QString)), SLOT(LogLine(QString)));
|
||||||
|
@ -138,7 +142,8 @@ void TranscodeDialog::Start() {
|
||||||
// Add jobs to the transcoder
|
// Add jobs to the transcoder
|
||||||
for (int i=0 ; i<file_model->rowCount() ; ++i) {
|
for (int i=0 ; i<file_model->rowCount() ; ++i) {
|
||||||
QString filename = file_model->index(i, 0).data(Qt::UserRole).toString();
|
QString filename = file_model->index(i, 0).data(Qt::UserRole).toString();
|
||||||
transcoder_->AddJob(filename, preset);
|
QString outfilename = GetOutputFileName(filename, preset);
|
||||||
|
transcoder_->AddJob(filename, preset, outfilename);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set up the progressbar
|
// Set up the progressbar
|
||||||
|
@ -265,3 +270,50 @@ void TranscodeDialog::Options() {
|
||||||
dialog.exec();
|
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_;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -25,6 +25,8 @@ class Transcoder;
|
||||||
class Ui_TranscodeDialog;
|
class Ui_TranscodeDialog;
|
||||||
class Ui_TranscodeLogDialog;
|
class Ui_TranscodeLogDialog;
|
||||||
|
|
||||||
|
struct TranscoderPreset;
|
||||||
|
|
||||||
class TranscodeDialog : public QDialog {
|
class TranscodeDialog : public QDialog {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
|
@ -34,6 +36,7 @@ class TranscodeDialog : public QDialog {
|
||||||
|
|
||||||
static const char* kSettingsGroup;
|
static const char* kSettingsGroup;
|
||||||
static const int kProgressInterval;
|
static const int kProgressInterval;
|
||||||
|
static const int kMaxDestinationItems;
|
||||||
|
|
||||||
void SetFilenames(const QStringList& filenames);
|
void SetFilenames(const QStringList& filenames);
|
||||||
|
|
||||||
|
@ -49,11 +52,15 @@ class TranscodeDialog : public QDialog {
|
||||||
void LogLine(const QString& message);
|
void LogLine(const QString& message);
|
||||||
void AllJobsComplete();
|
void AllJobsComplete();
|
||||||
void Options();
|
void Options();
|
||||||
|
void AddDestination();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void SetWorking(bool working);
|
void SetWorking(bool working);
|
||||||
void UpdateStatusText();
|
void UpdateStatusText();
|
||||||
void UpdateProgress();
|
void UpdateProgress();
|
||||||
|
QString TrimPath(const QString& path) const;
|
||||||
|
QString GetOutputFileName(const QString& input,
|
||||||
|
const TranscoderPreset& preset) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ui_TranscodeDialog* ui_;
|
Ui_TranscodeDialog* ui_;
|
||||||
|
|
|
@ -98,7 +98,7 @@
|
||||||
<property name="title">
|
<property name="title">
|
||||||
<string>Output options</string>
|
<string>Output options</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QFormLayout" name="formLayout">
|
<layout class="QGridLayout" name="gridLayout">
|
||||||
<item row="0" column="0">
|
<item row="0" column="0">
|
||||||
<widget class="QLabel" name="label">
|
<widget class="QLabel" name="label">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
|
@ -107,25 +107,21 @@
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="1">
|
<item row="0" column="1">
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
<widget class="QComboBox" name="format">
|
||||||
<item>
|
<property name="sizePolicy">
|
||||||
<widget class="QComboBox" name="format">
|
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||||
<property name="sizePolicy">
|
<horstretch>0</horstretch>
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
<verstretch>0</verstretch>
|
||||||
<horstretch>0</horstretch>
|
</sizepolicy>
|
||||||
<verstretch>0</verstretch>
|
</property>
|
||||||
</sizepolicy>
|
</widget>
|
||||||
</property>
|
</item>
|
||||||
</widget>
|
<item row="0" column="2">
|
||||||
</item>
|
<widget class="QPushButton" name="options">
|
||||||
<item>
|
<property name="text">
|
||||||
<widget class="QPushButton" name="options">
|
<string>Options...</string>
|
||||||
<property name="text">
|
</property>
|
||||||
<string>Options...</string>
|
</widget>
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="0">
|
<item row="1" column="0">
|
||||||
<widget class="QLabel" name="label_2">
|
<widget class="QLabel" name="label_2">
|
||||||
|
@ -136,6 +132,15 @@
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="1">
|
<item row="1" column="1">
|
||||||
<widget class="QComboBox" name="destination">
|
<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>
|
<item>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Alongside the originals</string>
|
<string>Alongside the originals</string>
|
||||||
|
@ -143,6 +148,13 @@
|
||||||
</item>
|
</item>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="1" column="2">
|
||||||
|
<widget class="QPushButton" name="select">
|
||||||
|
<property name="text">
|
||||||
|
<string>Select...</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
@ -196,7 +208,6 @@
|
||||||
<tabstop>add</tabstop>
|
<tabstop>add</tabstop>
|
||||||
<tabstop>remove</tabstop>
|
<tabstop>remove</tabstop>
|
||||||
<tabstop>format</tabstop>
|
<tabstop>format</tabstop>
|
||||||
<tabstop>destination</tabstop>
|
|
||||||
<tabstop>button_box</tabstop>
|
<tabstop>button_box</tabstop>
|
||||||
</tabstops>
|
</tabstops>
|
||||||
<resources/>
|
<resources/>
|
||||||
|
|
|
@ -297,7 +297,7 @@ void Transcoder::AddJob(const QString& input,
|
||||||
// Never overwrite existing files
|
// Never overwrite existing files
|
||||||
if (QFile::exists(job.output)) {
|
if (QFile::exists(job.output)) {
|
||||||
for (int i=0 ; ; ++i) {
|
for (int i=0 ; ; ++i) {
|
||||||
QString new_filename = QString("%1.%2").arg(job.output).arg(i);
|
QString new_filename = QString("%1.%2.%3").arg(job.output.section('.',0,-2)).arg(i).arg(preset.extension_);
|
||||||
if (!QFile::exists(new_filename)) {
|
if (!QFile::exists(new_filename)) {
|
||||||
job.output = new_filename;
|
job.output = new_filename;
|
||||||
break;
|
break;
|
||||||
|
@ -331,8 +331,10 @@ Transcoder::StartJobStatus Transcoder::MaybeStartNextJob() {
|
||||||
}
|
}
|
||||||
|
|
||||||
Job job = queued_jobs_.takeFirst();
|
Job job = queued_jobs_.takeFirst();
|
||||||
if (StartJob(job))
|
if (StartJob(job)) {
|
||||||
|
emit(JobOutputName(job.output));
|
||||||
return StartedSuccessfully;
|
return StartedSuccessfully;
|
||||||
|
}
|
||||||
|
|
||||||
emit JobComplete(job.input, false);
|
emit JobComplete(job.input, false);
|
||||||
return FailedToStart;
|
return FailedToStart;
|
||||||
|
|
|
@ -75,6 +75,7 @@ class Transcoder : public QObject {
|
||||||
void JobComplete(const QString& filename, bool success);
|
void JobComplete(const QString& filename, bool success);
|
||||||
void LogLine(const QString& message);
|
void LogLine(const QString& message);
|
||||||
void AllJobsComplete();
|
void AllJobsComplete();
|
||||||
|
void JobOutputName(const QString& filename);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool event(QEvent* e);
|
bool event(QEvent* e);
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -27,10 +27,11 @@ class AlbumCoverFetcher;
|
||||||
class AlbumCoverSearcher;
|
class AlbumCoverSearcher;
|
||||||
class Application;
|
class Application;
|
||||||
class CoverFromURLDialog;
|
class CoverFromURLDialog;
|
||||||
class CoverSearchStatistics;
|
|
||||||
class QFileDialog;
|
class QFileDialog;
|
||||||
class Song;
|
class Song;
|
||||||
|
|
||||||
|
struct CoverSearchStatistics;
|
||||||
|
|
||||||
// Controller for the common album cover related menu options.
|
// Controller for the common album cover related menu options.
|
||||||
class AlbumCoverChoiceController : public QWidget {
|
class AlbumCoverChoiceController : public QWidget {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue