parent
17b1e9fbe6
commit
8279f21251
|
@ -105,9 +105,8 @@ GstEnginePipeline::GstEnginePipeline(GstEngine* engine)
|
||||||
// will receive an error message. We should have a lightweight version of
|
// will receive an error message. We should have a lightweight version of
|
||||||
// server() that just return it (or NULL) without trying to create it IMO to
|
// server() that just return it (or NULL) without trying to create it IMO to
|
||||||
// avoid this issue.
|
// avoid this issue.
|
||||||
// if (InternetModel::Service<SpotifyService>()->IsBlobInstalled()) {
|
//if (InternetModel::Service<SpotifyService>()->IsBlobInstalled()) {
|
||||||
// connect(InternetModel::Service<SpotifyService>()->server(),
|
// connect(InternetModel::Service<SpotifyService>()->server(), SIGNAL(SeekCompleted()),
|
||||||
// SIGNAL(SeekCompleted()),
|
|
||||||
// SLOT(SpotifySeekCompleted()));
|
// SLOT(SpotifySeekCompleted()));
|
||||||
//}
|
//}
|
||||||
}
|
}
|
||||||
|
@ -249,20 +248,25 @@ bool GstEnginePipeline::Init() {
|
||||||
!device_.toString().isEmpty()) {
|
!device_.toString().isEmpty()) {
|
||||||
switch (device_.type()) {
|
switch (device_.type()) {
|
||||||
case QVariant::Int:
|
case QVariant::Int:
|
||||||
g_object_set(G_OBJECT(audiosink_), "device", device_.toInt(), nullptr);
|
g_object_set(G_OBJECT(audiosink_),
|
||||||
|
"device", device_.toInt(),
|
||||||
|
nullptr);
|
||||||
break;
|
break;
|
||||||
case QVariant::String:
|
case QVariant::String:
|
||||||
g_object_set(G_OBJECT(audiosink_), "device",
|
g_object_set(G_OBJECT(audiosink_),
|
||||||
device_.toString().toUtf8().constData(), nullptr);
|
"device", device_.toString().toUtf8().constData(),
|
||||||
|
nullptr);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
#ifdef Q_OS_WIN32
|
#ifdef Q_OS_WIN32
|
||||||
case QVariant::ByteArray: {
|
case QVariant::ByteArray: {
|
||||||
GUID guid = QUuid(device_.toByteArray());
|
GUID guid = QUuid(device_.toByteArray());
|
||||||
g_object_set(G_OBJECT(audiosink_), "device", &guid, nullptr);
|
g_object_set(G_OBJECT(audiosink_),
|
||||||
|
"device", &guid,
|
||||||
|
nullptr);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#endif // Q_OS_WIN32
|
#endif // Q_OS_WIN32
|
||||||
|
|
||||||
default:
|
default:
|
||||||
qLog(Warning) << "Unknown device type" << device_;
|
qLog(Warning) << "Unknown device type" << device_;
|
||||||
|
@ -331,8 +335,8 @@ bool GstEnginePipeline::Init() {
|
||||||
// We do it here because we want pre-equalized and pre-volume samples
|
// We do it here because we want pre-equalized and pre-volume samples
|
||||||
// so that our visualization are not be affected by them.
|
// so that our visualization are not be affected by them.
|
||||||
pad = gst_element_get_static_pad(event_probe, "src");
|
pad = gst_element_get_static_pad(event_probe, "src");
|
||||||
gst_pad_add_probe(pad, GST_PAD_PROBE_TYPE_EVENT_UPSTREAM,
|
gst_pad_add_probe(
|
||||||
&EventHandoffCallback, this, NULL);
|
pad, GST_PAD_PROBE_TYPE_EVENT_UPSTREAM, &EventHandoffCallback, this, NULL);
|
||||||
gst_object_unref(pad);
|
gst_object_unref(pad);
|
||||||
|
|
||||||
// Configure the fakesink properly
|
// Configure the fakesink properly
|
||||||
|
@ -343,8 +347,8 @@ bool GstEnginePipeline::Init() {
|
||||||
|
|
||||||
int last_band_frequency = 0;
|
int last_band_frequency = 0;
|
||||||
for (int i = 0; i < kEqBandCount; ++i) {
|
for (int i = 0; i < kEqBandCount; ++i) {
|
||||||
GstObject* band = GST_OBJECT(
|
GstObject* band = GST_OBJECT(gst_child_proxy_get_child_by_index(
|
||||||
gst_child_proxy_get_child_by_index(GST_CHILD_PROXY(equalizer_), i));
|
GST_CHILD_PROXY(equalizer_), i));
|
||||||
|
|
||||||
const float frequency = kEqBandFrequencies[i];
|
const float frequency = kEqBandFrequencies[i];
|
||||||
const float bandwidth = frequency - last_band_frequency;
|
const float bandwidth = frequency - last_band_frequency;
|
||||||
|
@ -378,8 +382,9 @@ bool GstEnginePipeline::Init() {
|
||||||
|
|
||||||
// Link the elements with special caps
|
// Link the elements with special caps
|
||||||
// The scope path through the tee gets 16-bit ints.
|
// The scope path through the tee gets 16-bit ints.
|
||||||
GstCaps* caps16 = gst_caps_new_simple("audio/x-raw", "format", G_TYPE_STRING,
|
GstCaps* caps16 = gst_caps_new_simple ("audio/x-raw",
|
||||||
"S16LE", NULL);
|
"format", G_TYPE_STRING, "S16LE",
|
||||||
|
NULL);
|
||||||
gst_element_link_filtered(probe_converter, probe_sink, caps16);
|
gst_element_link_filtered(probe_converter, probe_sink, caps16);
|
||||||
gst_caps_unref(caps16);
|
gst_caps_unref(caps16);
|
||||||
|
|
||||||
|
@ -402,7 +407,8 @@ bool GstEnginePipeline::Init() {
|
||||||
|
|
||||||
// Add probes and handlers.
|
// Add probes and handlers.
|
||||||
gst_pad_add_probe(gst_element_get_static_pad(probe_converter, "src"),
|
gst_pad_add_probe(gst_element_get_static_pad(probe_converter, "src"),
|
||||||
GST_PAD_PROBE_TYPE_BUFFER, HandoffCallback, this, nullptr);
|
GST_PAD_PROBE_TYPE_BUFFER,
|
||||||
|
HandoffCallback, this, nullptr);
|
||||||
gst_bus_set_sync_handler(gst_pipeline_get_bus(GST_PIPELINE(pipeline_)),
|
gst_bus_set_sync_handler(gst_pipeline_get_bus(GST_PIPELINE(pipeline_)),
|
||||||
BusCallbackSync, this, nullptr);
|
BusCallbackSync, this, nullptr);
|
||||||
bus_cb_id_ = gst_bus_add_watch(gst_pipeline_get_bus(GST_PIPELINE(pipeline_)),
|
bus_cb_id_ = gst_bus_add_watch(gst_pipeline_get_bus(GST_PIPELINE(pipeline_)),
|
||||||
|
@ -463,8 +469,9 @@ bool GstEnginePipeline::InitFromUrl(const QUrl& url, qint64 end_nanosec) {
|
||||||
|
|
||||||
GstEnginePipeline::~GstEnginePipeline() {
|
GstEnginePipeline::~GstEnginePipeline() {
|
||||||
if (pipeline_) {
|
if (pipeline_) {
|
||||||
gst_bus_set_sync_handler(gst_pipeline_get_bus(GST_PIPELINE(pipeline_)),
|
gst_bus_set_sync_handler(
|
||||||
nullptr, nullptr, nullptr);
|
gst_pipeline_get_bus(GST_PIPELINE(pipeline_)),
|
||||||
|
nullptr, nullptr, nullptr);
|
||||||
g_source_remove(bus_cb_id_);
|
g_source_remove(bus_cb_id_);
|
||||||
gst_element_set_state(pipeline_, GST_STATE_NULL);
|
gst_element_set_state(pipeline_, GST_STATE_NULL);
|
||||||
gst_object_unref(GST_OBJECT(pipeline_));
|
gst_object_unref(GST_OBJECT(pipeline_));
|
||||||
|
@ -934,22 +941,21 @@ GstState GstEnginePipeline::state() const {
|
||||||
|
|
||||||
QFuture<GstStateChangeReturn> GstEnginePipeline::SetState(GstState state) {
|
QFuture<GstStateChangeReturn> GstEnginePipeline::SetState(GstState state) {
|
||||||
if (url_.scheme() == "spotify" && !buffering_) {
|
if (url_.scheme() == "spotify" && !buffering_) {
|
||||||
const GstState current_state = this->state();
|
const GstState current_state = this->state();
|
||||||
|
|
||||||
if (state == GST_STATE_PAUSED && current_state == GST_STATE_PLAYING) {
|
if (state == GST_STATE_PAUSED && current_state == GST_STATE_PLAYING) {
|
||||||
SpotifyService* spotify = InternetModel::Service<SpotifyService>();
|
SpotifyService* spotify = InternetModel::Service<SpotifyService>();
|
||||||
|
|
||||||
// Need to schedule this in the spotify service's thread
|
// Need to schedule this in the spotify service's thread
|
||||||
QMetaObject::invokeMethod(spotify, "SetPaused", Qt::QueuedConnection,
|
QMetaObject::invokeMethod(spotify, "SetPaused", Qt::QueuedConnection,
|
||||||
Q_ARG(bool, true));
|
Q_ARG(bool, true));
|
||||||
} else if (state == GST_STATE_PLAYING &&
|
} else if (state == GST_STATE_PLAYING && current_state == GST_STATE_PAUSED) {
|
||||||
current_state == GST_STATE_PAUSED) {
|
SpotifyService* spotify = InternetModel::Service<SpotifyService>();
|
||||||
SpotifyService* spotify = InternetModel::Service<SpotifyService>();
|
|
||||||
|
|
||||||
// Need to schedule this in the spotify service's thread
|
// Need to schedule this in the spotify service's thread
|
||||||
QMetaObject::invokeMethod(spotify, "SetPaused", Qt::QueuedConnection,
|
QMetaObject::invokeMethod(spotify, "SetPaused", Qt::QueuedConnection,
|
||||||
Q_ARG(bool, false));
|
Q_ARG(bool, false));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ConcurrentRun::Run<GstStateChangeReturn, GstElement*, GstState>(
|
return ConcurrentRun::Run<GstStateChangeReturn, GstElement*, GstState>(
|
||||||
&set_state_threadpool_, &gst_element_set_state, pipeline_, state);
|
&set_state_threadpool_, &gst_element_set_state, pipeline_, state);
|
||||||
|
|
|
@ -131,8 +131,7 @@ signals:
|
||||||
static gboolean BusCallback(GstBus*, GstMessage*, gpointer);
|
static gboolean BusCallback(GstBus*, GstMessage*, gpointer);
|
||||||
static void NewPadCallback(GstElement*, GstPad*, gpointer);
|
static void NewPadCallback(GstElement*, GstPad*, gpointer);
|
||||||
static GstPadProbeReturn HandoffCallback(GstPad*, GstPadProbeInfo*, gpointer);
|
static GstPadProbeReturn HandoffCallback(GstPad*, GstPadProbeInfo*, gpointer);
|
||||||
static GstPadProbeReturn EventHandoffCallback(GstPad*, GstPadProbeInfo*,
|
static GstPadProbeReturn EventHandoffCallback(GstPad*, GstPadProbeInfo*, gpointer);
|
||||||
gpointer);
|
|
||||||
static void SourceDrainedCallback(GstURIDecodeBin*, gpointer);
|
static void SourceDrainedCallback(GstURIDecodeBin*, gpointer);
|
||||||
static void SourceSetupCallback(GstURIDecodeBin*, GParamSpec* pspec,
|
static void SourceSetupCallback(GstURIDecodeBin*, GParamSpec* pspec,
|
||||||
gpointer);
|
gpointer);
|
||||||
|
|
|
@ -338,8 +338,7 @@ void InternetModel::UpdateServices() {
|
||||||
bool setting_val = s.value(service_name).toBool();
|
bool setting_val = s.value(service_name).toBool();
|
||||||
|
|
||||||
// Only update if values are different
|
// Only update if values are different
|
||||||
if (setting_val == true &&
|
if (setting_val == true && shown_services_[internet_service].shown == false) {
|
||||||
shown_services_[internet_service].shown == false) {
|
|
||||||
ShowService(internet_service);
|
ShowService(internet_service);
|
||||||
} else if (setting_val == false &&
|
} else if (setting_val == false &&
|
||||||
shown_services_[internet_service].shown == true) {
|
shown_services_[internet_service].shown == true) {
|
||||||
|
@ -353,7 +352,7 @@ void InternetModel::UpdateServices() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void InternetModel::ShowService(InternetService* service) {
|
void InternetModel::ShowService(InternetService* service) {
|
||||||
if (shown_services_[service].shown != true) {
|
if(shown_services_[service].shown != true) {
|
||||||
invisibleRootItem()->appendRow(shown_services_[service].item);
|
invisibleRootItem()->appendRow(shown_services_[service].item);
|
||||||
shown_services_[service].shown = true;
|
shown_services_[service].shown = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -115,7 +115,7 @@ class InternetModel : public QStandardItemModel {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ServiceItem {
|
struct ServiceItem {
|
||||||
QStandardItem* item;
|
QStandardItem *item;
|
||||||
bool shown;
|
bool shown;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -180,6 +180,7 @@ signals:
|
||||||
void ServiceDeleted();
|
void ServiceDeleted();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
QMap<InternetService*, ServiceItem> shown_services_;
|
QMap<InternetService*, ServiceItem> shown_services_;
|
||||||
|
|
||||||
static QMap<QString, InternetService*>* sServices;
|
static QMap<QString, InternetService*>* sServices;
|
||||||
|
|
|
@ -38,8 +38,7 @@ void InternetShowSettingsPage::Load() {
|
||||||
|
|
||||||
ui_->sources->clear();
|
ui_->sources->clear();
|
||||||
|
|
||||||
for (QMap<InternetService*, InternetModel::ServiceItem>::iterator service =
|
for (QMap<InternetService*, InternetModel::ServiceItem>::iterator service = shown_services.begin();
|
||||||
shown_services.begin();
|
|
||||||
service != shown_services.end(); ++service) {
|
service != shown_services.end(); ++service) {
|
||||||
QTreeWidgetItem* item = new QTreeWidgetItem;
|
QTreeWidgetItem* item = new QTreeWidgetItem;
|
||||||
|
|
||||||
|
@ -47,8 +46,7 @@ void InternetShowSettingsPage::Load() {
|
||||||
item->setText(0, service.value().item->text());
|
item->setText(0, service.value().item->text());
|
||||||
item->setIcon(0, service.value().item->icon());
|
item->setIcon(0, service.value().item->icon());
|
||||||
|
|
||||||
Qt::CheckState check_state =
|
Qt::CheckState check_state = service.value().shown == true ? Qt::Checked : Qt::Unchecked;
|
||||||
service.value().shown == true ? Qt::Checked : Qt::Unchecked;
|
|
||||||
item->setData(0, Qt::CheckStateRole, check_state);
|
item->setData(0, Qt::CheckStateRole, check_state);
|
||||||
/* We have to store the constant name of the service */
|
/* We have to store the constant name of the service */
|
||||||
item->setData(1, Qt::UserRole, service.key()->name());
|
item->setData(1, Qt::UserRole, service.key()->name());
|
||||||
|
|
|
@ -23,14 +23,18 @@
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
static const int sBarkBands[] = {
|
static const int sBarkBands[] = {
|
||||||
100, 200, 300, 400, 510, 630, 770, 920, 1080, 1270, 1480, 1720,
|
100, 200, 300, 400, 510, 630, 770, 920,
|
||||||
2000, 2320, 2700, 3150, 3700, 4400, 5300, 6400, 7700, 9500, 12000, 15500};
|
1080, 1270, 1480, 1720, 2000, 2320, 2700, 3150,
|
||||||
|
3700, 4400, 5300, 6400, 7700, 9500, 12000, 15500 };
|
||||||
|
|
||||||
static const int sBarkBandCount = arraysize(sBarkBands);
|
static const int sBarkBandCount = arraysize(sBarkBands);
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
MoodbarBuilder::MoodbarBuilder() : bands_(0), rate_hz_(0) {}
|
MoodbarBuilder::MoodbarBuilder()
|
||||||
|
: bands_(0),
|
||||||
|
rate_hz_(0) {
|
||||||
|
}
|
||||||
|
|
||||||
int MoodbarBuilder::BandFrequency(int band) const {
|
int MoodbarBuilder::BandFrequency(int band) const {
|
||||||
return ((rate_hz_ / 2) * band + rate_hz_ / 4) / bands_;
|
return ((rate_hz_ / 2) * band + rate_hz_ / 4) / bands_;
|
||||||
|
@ -147,8 +151,9 @@ void MoodbarBuilder::Normalize(QList<Rgb>* vals, double Rgb::*member) {
|
||||||
|
|
||||||
for (auto it = vals->begin(); it != vals->end(); ++it) {
|
for (auto it = vals->begin(); it != vals->end(); ++it) {
|
||||||
double* value = &((*it).*member);
|
double* value = &((*it).*member);
|
||||||
*value =
|
*value = std::isfinite(*value)
|
||||||
std::isfinite(*value) ? qBound(0.0, (*value - mini) / delta, 1.0) : 0;
|
? qBound(0.0, (*value - mini) / delta, 1.0)
|
||||||
|
: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -156,7 +161,8 @@ QByteArray MoodbarBuilder::Finish(int width) {
|
||||||
QByteArray ret;
|
QByteArray ret;
|
||||||
ret.resize(width * 3);
|
ret.resize(width * 3);
|
||||||
char* data = ret.data();
|
char* data = ret.data();
|
||||||
if (frames_.count() == 0) return ret;
|
if (frames_.count() == 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
Normalize(&frames_, &Rgb::r);
|
Normalize(&frames_, &Rgb::r);
|
||||||
Normalize(&frames_, &Rgb::g);
|
Normalize(&frames_, &Rgb::g);
|
||||||
|
|
|
@ -102,13 +102,17 @@ void MoodbarPipeline::Start() {
|
||||||
builder_.reset(new MoodbarBuilder);
|
builder_.reset(new MoodbarBuilder);
|
||||||
|
|
||||||
// Set properties
|
// Set properties
|
||||||
g_object_set(decodebin, "uri", local_filename_.toEncoded().constData(),
|
g_object_set(decodebin,
|
||||||
|
"uri", local_filename_.toEncoded().constData(),
|
||||||
|
nullptr);
|
||||||
|
g_object_set(spectrum,
|
||||||
|
"bands", kBands,
|
||||||
nullptr);
|
nullptr);
|
||||||
g_object_set(spectrum, "bands", kBands, nullptr);
|
|
||||||
|
|
||||||
GstFastSpectrum* fast_spectrum = GST_FASTSPECTRUM(spectrum);
|
GstFastSpectrum* fast_spectrum = GST_FASTSPECTRUM(spectrum);
|
||||||
fast_spectrum->output_callback = [this](
|
fast_spectrum->output_callback = [this](double* magnitudes, int size) {
|
||||||
double* magnitudes, int size) { builder_->AddFrame(magnitudes, size); };
|
builder_->AddFrame(magnitudes, size);
|
||||||
|
};
|
||||||
|
|
||||||
// Connect signals
|
// Connect signals
|
||||||
CHECKED_GCONNECT(decodebin, "pad-added", &NewPadCallback, this);
|
CHECKED_GCONNECT(decodebin, "pad-added", &NewPadCallback, this);
|
||||||
|
|
|
@ -167,8 +167,7 @@ void PlaylistManager::Load(const QString& filename) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Playlist* playlist =
|
Playlist* playlist = AddPlaylist(id, info.baseName(), QString(), QString(), false);
|
||||||
AddPlaylist(id, info.baseName(), QString(), QString(), false);
|
|
||||||
|
|
||||||
QList<QUrl> urls;
|
QList<QUrl> urls;
|
||||||
playlist->InsertUrls(urls << QUrl::fromLocalFile(filename));
|
playlist->InsertUrls(urls << QUrl::fromLocalFile(filename));
|
||||||
|
@ -196,6 +195,7 @@ void PlaylistManager::Save(int id, const QString& filename,
|
||||||
void PlaylistManager::ItemsLoadedForSavePlaylist(QFutureWatcher<Song>* watcher,
|
void PlaylistManager::ItemsLoadedForSavePlaylist(QFutureWatcher<Song>* watcher,
|
||||||
const QString& filename,
|
const QString& filename,
|
||||||
Playlist::Path path_type) {
|
Playlist::Path path_type) {
|
||||||
|
|
||||||
SongList song_list = watcher->future().results();
|
SongList song_list = watcher->future().results();
|
||||||
parser_->Save(song_list, filename, path_type);
|
parser_->Save(song_list, filename, path_type);
|
||||||
}
|
}
|
||||||
|
@ -263,6 +263,7 @@ void PlaylistManager::Rename(int id, const QString& new_name) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlaylistManager::Favorite(int id, bool favorite) {
|
void PlaylistManager::Favorite(int id, bool favorite) {
|
||||||
|
|
||||||
if (playlists_.contains(id)) {
|
if (playlists_.contains(id)) {
|
||||||
// If playlists_ contains this playlist, its means it's opened: star or
|
// If playlists_ contains this playlist, its means it's opened: star or
|
||||||
// unstar it.
|
// unstar it.
|
||||||
|
|
|
@ -76,8 +76,7 @@ class PlaylistManagerInterface : public QObject {
|
||||||
virtual void New(const QString& name, const SongList& songs = SongList(),
|
virtual void New(const QString& name, const SongList& songs = SongList(),
|
||||||
const QString& special_type = QString()) = 0;
|
const QString& special_type = QString()) = 0;
|
||||||
virtual void Load(const QString& filename) = 0;
|
virtual void Load(const QString& filename) = 0;
|
||||||
virtual void Save(int id, const QString& filename,
|
virtual void Save(int id, const QString& filename, Playlist::Path path_type) = 0;
|
||||||
Playlist::Path path_type) = 0;
|
|
||||||
virtual void Rename(int id, const QString& new_name) = 0;
|
virtual void Rename(int id, const QString& new_name) = 0;
|
||||||
virtual void Delete(int id) = 0;
|
virtual void Delete(int id) = 0;
|
||||||
virtual bool Close(int id) = 0;
|
virtual bool Close(int id) = 0;
|
||||||
|
|
|
@ -48,6 +48,5 @@ void PlaylistSaveOptionsDialog::accept() {
|
||||||
}
|
}
|
||||||
|
|
||||||
Playlist::Path PlaylistSaveOptionsDialog::path_type() const {
|
Playlist::Path PlaylistSaveOptionsDialog::path_type() const {
|
||||||
return static_cast<Playlist::Path>(
|
return static_cast<Playlist::Path>(ui->filePaths->itemData(ui->filePaths->currentIndex()).toInt());
|
||||||
ui->filePaths->itemData(ui->filePaths->currentIndex()).toInt());
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -967,9 +967,8 @@ void PlaylistView::paintEvent(QPaintEvent* event) {
|
||||||
if (model()->rowCount() == 0)
|
if (model()->rowCount() == 0)
|
||||||
drop_pos = 1;
|
drop_pos = 1;
|
||||||
else
|
else
|
||||||
drop_pos = 1 +
|
drop_pos = 1 + visualRect(model()->index(model()->rowCount() - 1,
|
||||||
visualRect(model()->index(model()->rowCount() - 1,
|
first_column)).bottom();
|
||||||
first_column)).bottom();
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1113,10 +1112,10 @@ void PlaylistView::ReloadSettings() {
|
||||||
force_background_redraw_ = true;
|
force_background_redraw_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!s.value("click_edit_inline", true).toBool())
|
if(!s.value("click_edit_inline", true).toBool())
|
||||||
setEditTriggers(editTriggers() & ~QAbstractItemView::SelectedClicked);
|
setEditTriggers(editTriggers() & ~QAbstractItemView::SelectedClicked);
|
||||||
else
|
else
|
||||||
setEditTriggers(editTriggers() | QAbstractItemView::SelectedClicked);
|
setEditTriggers(editTriggers() | QAbstractItemView::SelectedClicked);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlaylistView::SaveSettings() {
|
void PlaylistView::SaveSettings() {
|
||||||
|
|
|
@ -50,7 +50,8 @@ SongList AsxIniParser::Load(QIODevice* device, const QString& playlist_path,
|
||||||
}
|
}
|
||||||
|
|
||||||
void AsxIniParser::Save(const SongList& songs, QIODevice* device,
|
void AsxIniParser::Save(const SongList& songs, QIODevice* device,
|
||||||
const QDir& dir, Playlist::Path path_type) const {
|
const QDir& dir,
|
||||||
|
Playlist::Path path_type) const {
|
||||||
QTextStream s(device);
|
QTextStream s(device);
|
||||||
s << "[Reference]" << endl;
|
s << "[Reference]" << endl;
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,8 @@ class AsxIniParser : public ParserBase {
|
||||||
|
|
||||||
SongList Load(QIODevice* device, const QString& playlist_path = "",
|
SongList Load(QIODevice* device, const QString& playlist_path = "",
|
||||||
const QDir& dir = QDir()) const;
|
const QDir& dir = QDir()) const;
|
||||||
void Save(const SongList& songs, QIODevice* device, const QDir& dir = QDir(),
|
void Save(const SongList& songs, QIODevice* device,
|
||||||
|
const QDir& dir = QDir(),
|
||||||
Playlist::Path path_type = Playlist::Path_Automatic) const;
|
Playlist::Path path_type = Playlist::Path_Automatic) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -117,8 +117,8 @@ return_song:
|
||||||
return song;
|
return song;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ASXParser::Save(const SongList& songs, QIODevice* device, const QDir&,
|
void ASXParser::Save(const SongList& songs, QIODevice* device,
|
||||||
Playlist::Path path_type) const {
|
const QDir&, Playlist::Path path_type) const {
|
||||||
QXmlStreamWriter writer(device);
|
QXmlStreamWriter writer(device);
|
||||||
writer.setAutoFormatting(true);
|
writer.setAutoFormatting(true);
|
||||||
writer.setAutoFormattingIndent(2);
|
writer.setAutoFormattingIndent(2);
|
||||||
|
|
|
@ -33,7 +33,8 @@ class ASXParser : public XMLParser {
|
||||||
|
|
||||||
SongList Load(QIODevice* device, const QString& playlist_path = "",
|
SongList Load(QIODevice* device, const QString& playlist_path = "",
|
||||||
const QDir& dir = QDir()) const;
|
const QDir& dir = QDir()) const;
|
||||||
void Save(const SongList& songs, QIODevice* device, const QDir& dir = QDir(),
|
void Save(const SongList& songs, QIODevice* device,
|
||||||
|
const QDir& dir = QDir(),
|
||||||
Playlist::Path path_type = Playlist::Path_Automatic) const;
|
Playlist::Path path_type = Playlist::Path_Automatic) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -63,6 +63,7 @@ SongList CueParser::Load(QIODevice* device, const QString& playlist_path,
|
||||||
|
|
||||||
// -- whole file
|
// -- whole file
|
||||||
while (!text_stream.atEnd()) {
|
while (!text_stream.atEnd()) {
|
||||||
|
|
||||||
QString album_artist;
|
QString album_artist;
|
||||||
QString album;
|
QString album;
|
||||||
QString album_composer;
|
QString album_composer;
|
||||||
|
@ -85,18 +86,22 @@ SongList CueParser::Load(QIODevice* device, const QString& playlist_path,
|
||||||
|
|
||||||
// PERFORMER
|
// PERFORMER
|
||||||
if (line_name == kPerformer) {
|
if (line_name == kPerformer) {
|
||||||
|
|
||||||
album_artist = line_value;
|
album_artist = line_value;
|
||||||
|
|
||||||
// TITLE
|
// TITLE
|
||||||
} else if (line_name == kTitle) {
|
} else if (line_name == kTitle) {
|
||||||
|
|
||||||
album = line_value;
|
album = line_value;
|
||||||
|
|
||||||
// SONGWRITER
|
// SONGWRITER
|
||||||
} else if (line_name == kSongWriter) {
|
} else if (line_name == kSongWriter) {
|
||||||
|
|
||||||
album_composer = line_value;
|
album_composer = line_value;
|
||||||
|
|
||||||
// FILE
|
// FILE
|
||||||
} else if (line_name == kFile) {
|
} else if (line_name == kFile) {
|
||||||
|
|
||||||
file = QDir::isAbsolutePath(line_value)
|
file = QDir::isAbsolutePath(line_value)
|
||||||
? line_value
|
? line_value
|
||||||
: dir.absoluteFilePath(line_value);
|
: dir.absoluteFilePath(line_value);
|
||||||
|
@ -122,6 +127,7 @@ SongList CueParser::Load(QIODevice* device, const QString& playlist_path,
|
||||||
|
|
||||||
// end of the header -> go into the track mode
|
// end of the header -> go into the track mode
|
||||||
} else if (line_name == kTrack) {
|
} else if (line_name == kTrack) {
|
||||||
|
|
||||||
files++;
|
files++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -160,6 +166,7 @@ SongList CueParser::Load(QIODevice* device, const QString& playlist_path,
|
||||||
splitted.size() > 2 ? splitted[2].toLower() : "";
|
splitted.size() > 2 ? splitted[2].toLower() : "";
|
||||||
|
|
||||||
if (line_name == kTrack) {
|
if (line_name == kTrack) {
|
||||||
|
|
||||||
// the beginning of another track's definition - we're saving the
|
// the beginning of another track's definition - we're saving the
|
||||||
// current one
|
// current one
|
||||||
// for later (if it's valid of course)
|
// for later (if it's valid of course)
|
||||||
|
@ -180,26 +187,33 @@ SongList CueParser::Load(QIODevice* device, const QString& playlist_path,
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (line_name == kIndex) {
|
} else if (line_name == kIndex) {
|
||||||
|
|
||||||
// we need the index's position field
|
// we need the index's position field
|
||||||
if (!line_additional.isEmpty()) {
|
if (!line_additional.isEmpty()) {
|
||||||
|
|
||||||
// if there's none "01" index, we'll just take the first one
|
// if there's none "01" index, we'll just take the first one
|
||||||
// also, we'll take the "01" index even if it's the last one
|
// also, we'll take the "01" index even if it's the last one
|
||||||
if (line_value == "01" || index.isEmpty()) {
|
if (line_value == "01" || index.isEmpty()) {
|
||||||
|
|
||||||
index = line_additional;
|
index = line_additional;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (line_name == kPerformer) {
|
} else if (line_name == kPerformer) {
|
||||||
|
|
||||||
artist = line_value;
|
artist = line_value;
|
||||||
|
|
||||||
} else if (line_name == kTitle) {
|
} else if (line_name == kTitle) {
|
||||||
|
|
||||||
title = line_value;
|
title = line_value;
|
||||||
|
|
||||||
} else if (line_name == kSongWriter) {
|
} else if (line_name == kSongWriter) {
|
||||||
|
|
||||||
composer = line_value;
|
composer = line_value;
|
||||||
|
|
||||||
// end of track's for the current file -> parse next one
|
// end of track's for the current file -> parse next one
|
||||||
} else if (line_name == kFile) {
|
} else if (line_name == kFile) {
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -337,7 +351,8 @@ qint64 CueParser::IndexToMarker(const QString& index) const {
|
||||||
return (frames * kNsecPerSec) / 75;
|
return (frames * kNsecPerSec) / 75;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CueParser::Save(const SongList& songs, QIODevice* device, const QDir& dir,
|
void CueParser::Save(const SongList& songs, QIODevice* device,
|
||||||
|
const QDir& dir,
|
||||||
Playlist::Path path_type) const {
|
Playlist::Path path_type) const {
|
||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,7 +53,8 @@ class CueParser : public ParserBase {
|
||||||
|
|
||||||
SongList Load(QIODevice* device, const QString& playlist_path = "",
|
SongList Load(QIODevice* device, const QString& playlist_path = "",
|
||||||
const QDir& dir = QDir()) const;
|
const QDir& dir = QDir()) const;
|
||||||
void Save(const SongList& songs, QIODevice* device, const QDir& dir = QDir(),
|
void Save(const SongList& songs, QIODevice* device,
|
||||||
|
const QDir& dir = QDir(),
|
||||||
Playlist::Path path_type = Playlist::Path_Automatic) const;
|
Playlist::Path path_type = Playlist::Path_Automatic) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -104,7 +104,8 @@ bool M3UParser::ParseMetadata(const QString& line,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void M3UParser::Save(const SongList& songs, QIODevice* device, const QDir& dir,
|
void M3UParser::Save(const SongList& songs, QIODevice* device,
|
||||||
|
const QDir& dir,
|
||||||
Playlist::Path path_type) const {
|
Playlist::Path path_type) const {
|
||||||
device->write("#EXTM3U\n");
|
device->write("#EXTM3U\n");
|
||||||
|
|
||||||
|
|
|
@ -41,7 +41,8 @@ class M3UParser : public ParserBase {
|
||||||
|
|
||||||
SongList Load(QIODevice* device, const QString& playlist_path = "",
|
SongList Load(QIODevice* device, const QString& playlist_path = "",
|
||||||
const QDir& dir = QDir()) const;
|
const QDir& dir = QDir()) const;
|
||||||
void Save(const SongList& songs, QIODevice* device, const QDir& dir = QDir(),
|
void Save(const SongList& songs, QIODevice* device,
|
||||||
|
const QDir& dir = QDir(),
|
||||||
Playlist::Path path_type = Playlist::Path_Automatic) const;
|
Playlist::Path path_type = Playlist::Path_Automatic) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -86,7 +86,8 @@ Song ParserBase::LoadSong(const QString& filename_or_url, qint64 beginning,
|
||||||
return song;
|
return song;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString ParserBase::URLOrFilename(const QUrl& url, const QDir& dir,
|
QString ParserBase::URLOrFilename(const QUrl& url,
|
||||||
|
const QDir& dir,
|
||||||
Playlist::Path path_type) const {
|
Playlist::Path path_type) const {
|
||||||
if (url.scheme() != "file") return url.toString();
|
if (url.scheme() != "file") return url.toString();
|
||||||
|
|
||||||
|
|
|
@ -51,9 +51,9 @@ class ParserBase : public QObject {
|
||||||
// from the parser's point of view).
|
// from the parser's point of view).
|
||||||
virtual SongList Load(QIODevice* device, const QString& playlist_path = "",
|
virtual SongList Load(QIODevice* device, const QString& playlist_path = "",
|
||||||
const QDir& dir = QDir()) const = 0;
|
const QDir& dir = QDir()) const = 0;
|
||||||
virtual void Save(
|
virtual void Save(const SongList& songs, QIODevice* device,
|
||||||
const SongList& songs, QIODevice* device, const QDir& dir = QDir(),
|
const QDir& dir = QDir(),
|
||||||
Playlist::Path path_type = Playlist::Path_Automatic) const = 0;
|
Playlist::Path path_type = Playlist::Path_Automatic) const = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Loads a song. If filename_or_url is a URL (with a scheme other than
|
// Loads a song. If filename_or_url is a URL (with a scheme other than
|
||||||
|
|
|
@ -130,7 +130,8 @@ SongList PlaylistParser::LoadFromDevice(QIODevice* device,
|
||||||
return parser->Load(device, path_hint, dir_hint);
|
return parser->Load(device, path_hint, dir_hint);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlaylistParser::Save(const SongList& songs, const QString& filename,
|
void PlaylistParser::Save(const SongList& songs,
|
||||||
|
const QString& filename,
|
||||||
Playlist::Path path_type) const {
|
Playlist::Path path_type) const {
|
||||||
QFileInfo info(filename);
|
QFileInfo info(filename);
|
||||||
|
|
||||||
|
|
|
@ -49,8 +49,7 @@ class PlaylistParser : public QObject {
|
||||||
SongList LoadFromDevice(QIODevice* device,
|
SongList LoadFromDevice(QIODevice* device,
|
||||||
const QString& path_hint = QString(),
|
const QString& path_hint = QString(),
|
||||||
const QDir& dir_hint = QDir()) const;
|
const QDir& dir_hint = QDir()) const;
|
||||||
void Save(const SongList& songs, const QString& filename,
|
void Save(const SongList& songs, const QString& filename, Playlist::Path) const;
|
||||||
Playlist::Path) const;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QString FilterForParser(const ParserBase* parser,
|
QString FilterForParser(const ParserBase* parser,
|
||||||
|
|
|
@ -61,8 +61,8 @@ SongList PLSParser::Load(QIODevice* device, const QString& playlist_path,
|
||||||
return songs.values();
|
return songs.values();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PLSParser::Save(const SongList& songs, QIODevice* device, const QDir& dir,
|
void PLSParser::Save(const SongList& songs, QIODevice* device,
|
||||||
Playlist::Path path_type) const {
|
const QDir& dir, Playlist::Path path_type) const {
|
||||||
QTextStream s(device);
|
QTextStream s(device);
|
||||||
s << "[playlist]" << endl;
|
s << "[playlist]" << endl;
|
||||||
s << "Version=2" << endl;
|
s << "Version=2" << endl;
|
||||||
|
@ -70,8 +70,7 @@ void PLSParser::Save(const SongList& songs, QIODevice* device, const QDir& dir,
|
||||||
|
|
||||||
int n = 1;
|
int n = 1;
|
||||||
for (const Song& song : songs) {
|
for (const Song& song : songs) {
|
||||||
s << "File" << n << "=" << URLOrFilename(song.url(), dir, path_type)
|
s << "File" << n << "=" << URLOrFilename(song.url(), dir, path_type) << endl;
|
||||||
<< endl;
|
|
||||||
s << "Title" << n << "=" << song.title() << endl;
|
s << "Title" << n << "=" << song.title() << endl;
|
||||||
s << "Length" << n << "=" << song.length_nanosec() / kNsecPerSec << endl;
|
s << "Length" << n << "=" << song.length_nanosec() / kNsecPerSec << endl;
|
||||||
++n;
|
++n;
|
||||||
|
|
|
@ -33,7 +33,8 @@ class PLSParser : public ParserBase {
|
||||||
|
|
||||||
SongList Load(QIODevice* device, const QString& playlist_path = "",
|
SongList Load(QIODevice* device, const QString& playlist_path = "",
|
||||||
const QDir& dir = QDir()) const;
|
const QDir& dir = QDir()) const;
|
||||||
void Save(const SongList& songs, QIODevice* device, const QDir& dir = QDir(),
|
void Save(const SongList& songs, QIODevice* device,
|
||||||
|
const QDir& dir = QDir(),
|
||||||
Playlist::Path path_type = Playlist::Path_Automatic) const;
|
Playlist::Path path_type = Playlist::Path_Automatic) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -76,8 +76,8 @@ void WplParser::ParseSeq(const QDir& dir, QXmlStreamReader* reader,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WplParser::Save(const SongList& songs, QIODevice* device, const QDir& dir,
|
void WplParser::Save(const SongList& songs, QIODevice* device,
|
||||||
Playlist::Path path_type) const {
|
const QDir& dir, Playlist::Path path_type) const {
|
||||||
QXmlStreamWriter writer(device);
|
QXmlStreamWriter writer(device);
|
||||||
writer.setAutoFormatting(true);
|
writer.setAutoFormatting(true);
|
||||||
writer.setAutoFormattingIndent(2);
|
writer.setAutoFormattingIndent(2);
|
||||||
|
|
|
@ -102,8 +102,8 @@ return_song:
|
||||||
return song;
|
return song;
|
||||||
}
|
}
|
||||||
|
|
||||||
void XSPFParser::Save(const SongList& songs, QIODevice* device, const QDir& dir,
|
void XSPFParser::Save(const SongList& songs, QIODevice* device,
|
||||||
Playlist::Path path_type) const {
|
const QDir& dir, Playlist::Path path_type) const {
|
||||||
QFileInfo file;
|
QFileInfo file;
|
||||||
QXmlStreamWriter writer(device);
|
QXmlStreamWriter writer(device);
|
||||||
writer.setAutoFormatting(true);
|
writer.setAutoFormatting(true);
|
||||||
|
@ -120,8 +120,7 @@ void XSPFParser::Save(const SongList& songs, QIODevice* device, const QDir& dir,
|
||||||
|
|
||||||
StreamElement tracklist("trackList", &writer);
|
StreamElement tracklist("trackList", &writer);
|
||||||
for (const Song& song : songs) {
|
for (const Song& song : songs) {
|
||||||
QString filename_or_url =
|
QString filename_or_url = URLOrFilename(song.url(), dir, path_type).toUtf8();
|
||||||
URLOrFilename(song.url(), dir, path_type).toUtf8();
|
|
||||||
|
|
||||||
StreamElement track("track", &writer);
|
StreamElement track("track", &writer);
|
||||||
writer.writeTextElement("location", filename_or_url);
|
writer.writeTextElement("location", filename_or_url);
|
||||||
|
|
|
@ -38,7 +38,8 @@ class XSPFParser : public XMLParser {
|
||||||
|
|
||||||
SongList Load(QIODevice* device, const QString& playlist_path = "",
|
SongList Load(QIODevice* device, const QString& playlist_path = "",
|
||||||
const QDir& dir = QDir()) const;
|
const QDir& dir = QDir()) const;
|
||||||
void Save(const SongList& songs, QIODevice* device, const QDir& dir = QDir(),
|
void Save(const SongList& songs, QIODevice* device,
|
||||||
|
const QDir& dir = QDir(),
|
||||||
Playlist::Path path_type = Playlist::Path_Automatic) const;
|
Playlist::Path path_type = Playlist::Path_Automatic) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -231,16 +231,16 @@ void TranscodeDialog::Add() {
|
||||||
|
|
||||||
void TranscodeDialog::Import() {
|
void TranscodeDialog::Import() {
|
||||||
QString path = QFileDialog::getExistingDirectory(
|
QString path = QFileDialog::getExistingDirectory(
|
||||||
this, tr("Open a directory to import music from"), last_import_dir_,
|
this, tr("Open a directory to import music from"),
|
||||||
QFileDialog::ShowDirsOnly);
|
last_import_dir_, QFileDialog::ShowDirsOnly);
|
||||||
|
|
||||||
if (path.isEmpty()) return;
|
if (path.isEmpty()) return;
|
||||||
|
|
||||||
QStringList filenames;
|
QStringList filenames;
|
||||||
QStringList audioTypes =
|
QStringList audioTypes = QString(FileView::kFileFilter).split(" ",
|
||||||
QString(FileView::kFileFilter).split(" ", QString::SkipEmptyParts);
|
QString::SkipEmptyParts);
|
||||||
QDirIterator files(path, audioTypes, QDir::Files | QDir::Readable,
|
QDirIterator files(path, audioTypes, QDir::Files | QDir::Readable,
|
||||||
QDirIterator::Subdirectories);
|
QDirIterator::Subdirectories);
|
||||||
|
|
||||||
while (files.hasNext()) {
|
while (files.hasNext()) {
|
||||||
filenames << files.next();
|
filenames << files.next();
|
||||||
|
|
|
@ -84,6 +84,7 @@
|
||||||
#include "internet/seafilesettingspage.h"
|
#include "internet/seafilesettingspage.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#include <QAbstractButton>
|
#include <QAbstractButton>
|
||||||
#include <QDesktopWidget>
|
#include <QDesktopWidget>
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
|
@ -193,6 +194,8 @@ SettingsDialog::SettingsDialog(Application* app, BackgroundStreams* streams,
|
||||||
AddPage(Page_Seafile, new SeafileSettingsPage(this), providers);
|
AddPage(Page_Seafile, new SeafileSettingsPage(this), providers);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
AddPage(Page_Magnatune, new MagnatuneSettingsPage(this), providers);
|
AddPage(Page_Magnatune, new MagnatuneSettingsPage(this), providers);
|
||||||
AddPage(Page_DigitallyImported, new DigitallyImportedSettingsPage(this),
|
AddPage(Page_DigitallyImported, new DigitallyImportedSettingsPage(this),
|
||||||
providers);
|
providers);
|
||||||
|
|
Loading…
Reference in New Issue