Merge pull request #4580 from Chocobozzz/hide_internet_services

Hide internet services
This commit is contained in:
John Maguire 2014-10-31 12:02:29 +01:00
commit 4f4c8f6894
41 changed files with 405 additions and 173 deletions

View File

@ -425,5 +425,6 @@
<file>providers/vk.png</file>
<file>vk/link.png</file>
<file>providers/seafile.png</file>
<file>icons/32x32/internet-services.png</file>
</qresource>
</RCC>

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

View File

@ -106,12 +106,10 @@ bool MediaPipeline::Init(int sample_rate, int channels) {
#endif
// Set caps
GstCaps* caps = gst_caps_new_simple("audio/x-raw",
"format", G_TYPE_STRING, format,
"rate", G_TYPE_INT, sample_rate,
"channels", G_TYPE_INT, channels,
"layout", G_TYPE_STRING, "interleaved",
nullptr);
GstCaps* caps = gst_caps_new_simple(
"audio/x-raw", "format", G_TYPE_STRING, format, "rate", G_TYPE_INT,
sample_rate, "channels", G_TYPE_INT, channels, "layout", G_TYPE_STRING,
"interleaved", nullptr);
gst_app_src_set_caps(appsrc_, caps);
gst_caps_unref(caps);

View File

@ -604,7 +604,6 @@ void SpotifyClient::PlaylistStateChangedForGetPlaylists(sp_playlist* pl,
void SpotifyClient::AddTracksToPlaylist(
const pb::spotify::AddTracksToPlaylistRequest& req) {
// Get the playlist we want to update
int playlist_index = req.playlist_index();
sp_playlist* playlist =
@ -615,21 +614,22 @@ void SpotifyClient::AddTracksToPlaylist(
}
// Get the tracks we want to add
std::unique_ptr<sp_track*[]> tracks_array (new sp_track*[req.track_uri_size()]);
std::unique_ptr<sp_track* []> tracks_array(
new sp_track* [req.track_uri_size()]);
for (int i = 0; i < req.track_uri_size(); ++i) {
sp_link* track_link = sp_link_create_from_string(req.track_uri(i).c_str());
sp_track* track = sp_link_as_track(track_link);
sp_track_add_ref(track);
sp_link_release(track_link);
if (!track) {
qLog(Error) << "Track" << QString::fromStdString(req.track_uri(i)) << "not found";
qLog(Error) << "Track" << QString::fromStdString(req.track_uri(i))
<< "not found";
}
tracks_array[i] = track;
}
// Actually add the tracks to the playlist
if (sp_playlist_add_tracks(playlist, tracks_array.get(),
req.track_uri_size(),
if (sp_playlist_add_tracks(playlist, tracks_array.get(), req.track_uri_size(),
0 /* TODO: don't insert at a hardcoded position */,
session_) != SP_ERROR_OK) {
qLog(Error) << "Error when adding tracks!";
@ -643,7 +643,6 @@ void SpotifyClient::AddTracksToPlaylist(
void SpotifyClient::RemoveTracksFromPlaylist(
const pb::spotify::RemoveTracksFromPlaylistRequest& req) {
// Get the playlist we want to update
int playlist_index = req.playlist_index();
sp_playlist* playlist =
@ -654,18 +653,17 @@ void SpotifyClient::RemoveTracksFromPlaylist(
}
// Get the position of the tracks we want to remove
std::unique_ptr<int[]> tracks_indices_array (new int[req.track_index_size()]);
std::unique_ptr<int[]> tracks_indices_array(new int[req.track_index_size()]);
for (int i = 0; i < req.track_index_size(); ++i) {
tracks_indices_array[i] = req.track_index(i);
}
if (sp_playlist_remove_tracks(playlist, tracks_indices_array.get(),
req.track_index_size()) != SP_ERROR_OK) {
req.track_index_size()) != SP_ERROR_OK) {
qLog(Error) << "Error when removing tracks!";
}
}
void SpotifyClient::ConvertTrack(sp_track* track, pb::spotify::Track* pb) {
sp_album* album = sp_track_album(track);

View File

@ -123,7 +123,8 @@ class SpotifyClient : public AbstractMessageHandler<pb::spotify::Message> {
void LoadPlaylist(const pb::spotify::LoadPlaylistRequest& req);
void SyncPlaylist(const pb::spotify::SyncPlaylistRequest& req);
void AddTracksToPlaylist(const pb::spotify::AddTracksToPlaylistRequest& req);
void RemoveTracksFromPlaylist(const pb::spotify::RemoveTracksFromPlaylistRequest& req);
void RemoveTracksFromPlaylist(
const pb::spotify::RemoveTracksFromPlaylistRequest& req);
void StartPlayback(const pb::spotify::PlaybackRequest& req);
void Seek(qint64 offset_nsec);
void LoadImage(const QString& id_b64);
@ -194,7 +195,7 @@ class SpotifyClient : public AbstractMessageHandler<pb::spotify::Message> {
QMap<sp_toplistbrowse*, pb::spotify::BrowseToplistRequest>
pending_toplist_browses_;
QMap<sp_search*, QList<sp_albumbrowse*> > pending_search_album_browses_;
QMap<sp_search*, QList<sp_albumbrowse*>> pending_search_album_browses_;
QMap<sp_albumbrowse*, sp_search*> pending_search_album_browse_responses_;
QScopedPointer<MediaPipeline> media_pipeline_;

View File

@ -183,6 +183,7 @@ set(SOURCES
internet/internetmodel.cpp
internet/internetplaylistitem.cpp
internet/internetservice.cpp
internet/internetshowsettingspage.cpp
internet/internetview.cpp
internet/internetviewcontainer.cpp
internet/jamendodynamicplaylist.cpp
@ -488,6 +489,7 @@ set(HEADERS
internet/internetmimedata.h
internet/internetmodel.h
internet/internetservice.h
internet/internetshowsettingspage.h
internet/internetsongmimedata.h
internet/internetview.h
internet/internetviewcontainer.h
@ -694,6 +696,7 @@ set(UI
internet/digitallyimportedsettingspage.ui
internet/groovesharksettingspage.ui
internet/icecastfilterwidget.ui
internet/internetshowsettingspage.ui
internet/internetviewcontainer.ui
internet/magnatunedownloaddialog.ui
internet/magnatunesettingspage.ui

View File

@ -235,25 +235,20 @@ bool GstEnginePipeline::Init() {
!device_.toString().isEmpty()) {
switch (device_.type()) {
case QVariant::Int:
g_object_set(G_OBJECT(audiosink_),
"device", device_.toInt(),
nullptr);
g_object_set(G_OBJECT(audiosink_), "device", device_.toInt(), nullptr);
break;
case QVariant::String:
g_object_set(G_OBJECT(audiosink_),
"device", device_.toString().toUtf8().constData(),
nullptr);
g_object_set(G_OBJECT(audiosink_), "device",
device_.toString().toUtf8().constData(), nullptr);
break;
#ifdef Q_OS_WIN32
#ifdef Q_OS_WIN32
case QVariant::ByteArray: {
GUID guid = QUuid(device_.toByteArray());
g_object_set(G_OBJECT(audiosink_),
"device", &guid,
nullptr);
g_object_set(G_OBJECT(audiosink_), "device", &guid, nullptr);
break;
}
#endif // Q_OS_WIN32
#endif // Q_OS_WIN32
default:
qLog(Warning) << "Unknown device type" << device_;
@ -322,8 +317,8 @@ bool GstEnginePipeline::Init() {
// We do it here because we want pre-equalized and pre-volume samples
// so that our visualization are not be affected by them.
pad = gst_element_get_static_pad(event_probe, "src");
gst_pad_add_probe(
pad, GST_PAD_PROBE_TYPE_EVENT_UPSTREAM, &EventHandoffCallback, this, NULL);
gst_pad_add_probe(pad, GST_PAD_PROBE_TYPE_EVENT_UPSTREAM,
&EventHandoffCallback, this, NULL);
gst_object_unref(pad);
// Configure the fakesink properly
@ -334,8 +329,8 @@ bool GstEnginePipeline::Init() {
int last_band_frequency = 0;
for (int i = 0; i < kEqBandCount; ++i) {
GstObject* band = GST_OBJECT(gst_child_proxy_get_child_by_index(
GST_CHILD_PROXY(equalizer_), i));
GstObject* band = GST_OBJECT(
gst_child_proxy_get_child_by_index(GST_CHILD_PROXY(equalizer_), i));
const float frequency = kEqBandFrequencies[i];
const float bandwidth = frequency - last_band_frequency;
@ -369,9 +364,8 @@ bool GstEnginePipeline::Init() {
// Link the elements with special caps
// The scope path through the tee gets 16-bit ints.
GstCaps* caps16 = gst_caps_new_simple ("audio/x-raw",
"format", G_TYPE_STRING, "S16LE",
NULL);
GstCaps* caps16 = gst_caps_new_simple("audio/x-raw", "format", G_TYPE_STRING,
"S16LE", NULL);
gst_element_link_filtered(probe_converter, probe_sink, caps16);
gst_caps_unref(caps16);
@ -394,8 +388,7 @@ bool GstEnginePipeline::Init() {
// Add probes and handlers.
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_)),
BusCallbackSync, this, nullptr);
bus_cb_id_ = gst_bus_add_watch(gst_pipeline_get_bus(GST_PIPELINE(pipeline_)),
@ -456,9 +449,8 @@ bool GstEnginePipeline::InitFromUrl(const QUrl& url, qint64 end_nanosec) {
GstEnginePipeline::~GstEnginePipeline() {
if (pipeline_) {
gst_bus_set_sync_handler(
gst_pipeline_get_bus(GST_PIPELINE(pipeline_)),
nullptr, nullptr, nullptr);
gst_bus_set_sync_handler(gst_pipeline_get_bus(GST_PIPELINE(pipeline_)),
nullptr, nullptr, nullptr);
g_source_remove(bus_cb_id_);
gst_element_set_state(pipeline_, GST_STATE_NULL);
gst_object_unref(GST_OBJECT(pipeline_));
@ -719,20 +711,16 @@ void GstEnginePipeline::NewPadCallback(GstElement*, GstPad* pad,
// decodebin.
// "Running time" is the time since the last flushing seek.
GstClockTime running_time = gst_segment_to_running_time(
&instance->last_decodebin_segment_,
GST_FORMAT_TIME,
&instance->last_decodebin_segment_, GST_FORMAT_TIME,
instance->last_decodebin_segment_.position);
gst_pad_set_offset(pad, running_time);
// Add a probe to the pad so we can update last_decodebin_segment_.
gst_pad_add_probe(pad,
static_cast<GstPadProbeType>(
GST_PAD_PROBE_TYPE_BUFFER |
GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM |
GST_PAD_PROBE_TYPE_EVENT_FLUSH),
DecodebinProbe,
instance,
nullptr);
gst_pad_add_probe(
pad, static_cast<GstPadProbeType>(GST_PAD_PROBE_TYPE_BUFFER |
GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM |
GST_PAD_PROBE_TYPE_EVENT_FLUSH),
DecodebinProbe, instance, nullptr);
instance->pipeline_is_connected_ = true;
if (instance->pending_seek_nanosec_ != -1 &&
@ -985,21 +973,22 @@ GstState GstEnginePipeline::state() const {
QFuture<GstStateChangeReturn> GstEnginePipeline::SetState(GstState state) {
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) {
SpotifyService* spotify = InternetModel::Service<SpotifyService>();
if (state == GST_STATE_PAUSED && current_state == GST_STATE_PLAYING) {
SpotifyService* spotify = InternetModel::Service<SpotifyService>();
// Need to schedule this in the spotify service's thread
QMetaObject::invokeMethod(spotify, "SetPaused", Qt::QueuedConnection,
Q_ARG(bool, true));
} else if (state == GST_STATE_PLAYING && current_state == GST_STATE_PAUSED) {
SpotifyService* spotify = InternetModel::Service<SpotifyService>();
// Need to schedule this in the spotify service's thread
QMetaObject::invokeMethod(spotify, "SetPaused", Qt::QueuedConnection,
Q_ARG(bool, true));
} else if (state == GST_STATE_PLAYING &&
current_state == GST_STATE_PAUSED) {
SpotifyService* spotify = InternetModel::Service<SpotifyService>();
// Need to schedule this in the spotify service's thread
QMetaObject::invokeMethod(spotify, "SetPaused", Qt::QueuedConnection,
Q_ARG(bool, false));
}
// Need to schedule this in the spotify service's thread
QMetaObject::invokeMethod(spotify, "SetPaused", Qt::QueuedConnection,
Q_ARG(bool, false));
}
}
return ConcurrentRun::Run<GstStateChangeReturn, GstElement*, GstState>(
&set_state_threadpool_, &gst_element_set_state, pipeline_, state);

View File

@ -131,7 +131,8 @@ signals:
static gboolean BusCallback(GstBus*, GstMessage*, gpointer);
static void NewPadCallback(GstElement*, GstPad*, gpointer);
static GstPadProbeReturn HandoffCallback(GstPad*, GstPadProbeInfo*, gpointer);
static GstPadProbeReturn EventHandoffCallback(GstPad*, GstPadProbeInfo*, gpointer);
static GstPadProbeReturn EventHandoffCallback(GstPad*, GstPadProbeInfo*,
gpointer);
static GstPadProbeReturn DecodebinProbe(GstPad*, GstPadProbeInfo*, gpointer);
static void SourceDrainedCallback(GstURIDecodeBin*, gpointer);
static void SourceSetupCallback(GstURIDecodeBin*, GParamSpec* pspec,

View File

@ -63,6 +63,8 @@ using smart_playlists::GeneratorPtr;
QMap<QString, InternetService*>* InternetModel::sServices = nullptr;
const char* InternetModel::kSettingsGroup = "InternetModel";
InternetModel::InternetModel(Application* app, QObject* parent)
: QStandardItemModel(parent),
app_(app),
@ -108,7 +110,7 @@ InternetModel::InternetModel(Application* app, QObject* parent)
AddService(new VkService(app, this));
#endif
invisibleRootItem()->sortChildren(0, Qt::AscendingOrder);
UpdateServices();
}
void InternetModel::AddService(InternetService* service) {
@ -126,6 +128,12 @@ void InternetModel::AddService(InternetService* service) {
qLog(Debug) << "Adding internet service:" << service->name();
sServices->insert(service->name(), service);
ServiceItem service_item;
service_item.item = root;
service_item.shown = true;
shown_services_.insert(service, service_item);
connect(service, SIGNAL(StreamError(QString)), SIGNAL(StreamError(QString)));
connect(service, SIGNAL(StreamMetadataFound(QUrl, Song)),
SIGNAL(StreamMetadataFound(QUrl, Song)));
@ -154,6 +162,9 @@ void InternetModel::RemoveService(InternetService* service) {
// Remove the service from the list
sServices->remove(service->name());
// Don't forget to delete from shown_services too
shown_services_.remove(service);
// Disconnect the service
disconnect(service, 0, this, 0);
}
@ -315,3 +326,50 @@ void InternetModel::ReloadSettings() {
service->ReloadSettings();
}
}
void InternetModel::UpdateServices() {
QSettings s;
s.beginGroup(kSettingsGroup);
QStringList keys = s.childKeys();
for (QString service_name : keys) {
InternetService* internet_service = ServiceByName(service_name);
bool setting_val = s.value(service_name).toBool();
// Only update if values are different
if (setting_val == true &&
shown_services_[internet_service].shown == false) {
ShowService(internet_service);
} else if (setting_val == false &&
shown_services_[internet_service].shown == true) {
HideService(internet_service);
}
}
s.endGroup();
invisibleRootItem()->sortChildren(0, Qt::AscendingOrder);
}
void InternetModel::ShowService(InternetService* service) {
if (shown_services_[service].shown != true) {
invisibleRootItem()->appendRow(shown_services_[service].item);
shown_services_[service].shown = true;
}
}
void InternetModel::HideService(InternetService* service) {
// Find and remove the root item that this service created
for (int i = 0; i < invisibleRootItem()->rowCount(); ++i) {
QStandardItem* item = invisibleRootItem()->child(i);
if (!item ||
item->data(Role_Service).value<InternetService*>() == service) {
// Don't remove the standarditem behind the row
invisibleRootItem()->takeRow(i);
break;
}
}
shown_services_[service].shown = false;
}

View File

@ -114,8 +114,14 @@ class InternetModel : public QStandardItemModel {
PlayBehaviour_DoubleClickAction,
};
struct ServiceItem {
QStandardItem* item;
bool shown;
};
// Needs to be static for InternetPlaylistItem::restore
static InternetService* ServiceByName(const QString& name);
static const char* kSettingsGroup;
template <typename T>
static T* Service() {
@ -127,6 +133,10 @@ class InternetModel : public QStandardItemModel {
// removed from the model.
void AddService(InternetService* service);
void RemoveService(InternetService* service);
void HideService(InternetService* service);
void ShowService(InternetService* service);
// Add or remove the services according to the setting file
void UpdateServices();
// Returns the service that is a parent of this item. Works by walking up
// the tree until it finds an item with Role_Service set.
@ -155,6 +165,9 @@ class InternetModel : public QStandardItemModel {
const QModelIndex& current_index() const { return current_index_; }
const QModelIndexList& selected_indexes() const { return selected_indexes_; }
const QMap<InternetService*, ServiceItem> shown_services() const {
return shown_services_;
}
signals:
void StreamError(const QString& message);
@ -167,6 +180,8 @@ signals:
void ServiceDeleted();
private:
QMap<InternetService*, ServiceItem> shown_services_;
static QMap<QString, InternetService*>* sServices;
Application* app_;

View File

@ -0,0 +1,74 @@
/* This file is part of Clementine.
Copyright 2011, David Sansome <me@davidsansome.com>
Clementine 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.
Clementine 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 Clementine. If not, see <http://www.gnu.org/licenses/>.
*/
#include "internetshowsettingspage.h"
#include "core/application.h"
#include "ui/settingsdialog.h"
#include "internetservice.h"
#include "internetmodel.h"
#include <QSettings>
InternetShowSettingsPage::InternetShowSettingsPage(SettingsDialog* parent)
: SettingsPage(parent), ui_(new Ui::InternetShowSettingsPage) {
ui_->setupUi(this);
ui_->sources->header()->setResizeMode(0, QHeaderView::Stretch);
ui_->sources->header()->setResizeMode(1, QHeaderView::ResizeToContents);
}
void InternetShowSettingsPage::Load() {
QMap<InternetService*, InternetModel::ServiceItem> shown_services =
dialog()->app()->internet_model()->shown_services();
ui_->sources->clear();
for (auto service_it = shown_services.constBegin();
service_it != shown_services.constEnd(); service_it++) {
QTreeWidgetItem* item = new QTreeWidgetItem;
// Get the same text and the same icon as the service tree
item->setText(0, service_it.value().item->text());
item->setIcon(0, service_it.value().item->icon());
Qt::CheckState check_state =
service_it.value().shown == true ? Qt::Checked : Qt::Unchecked;
item->setData(0, Qt::CheckStateRole, check_state);
/* We have to store the constant name of the service */
item->setData(1, Qt::UserRole, service_it.key()->name());
ui_->sources->invisibleRootItem()->addChild(item);
}
ui_->sources->invisibleRootItem()->sortChildren(0, Qt::AscendingOrder);
}
void InternetShowSettingsPage::Save() {
QSettings s;
s.beginGroup(InternetModel::kSettingsGroup);
for (int i = 0; i < ui_->sources->invisibleRootItem()->childCount(); ++i) {
QTreeWidgetItem* item = ui_->sources->invisibleRootItem()->child(i);
s.setValue(item->data(1, Qt::UserRole).toString(),
(item->data(0, Qt::CheckStateRole).toBool()));
}
s.endGroup();
dialog()->app()->internet_model()->UpdateServices();
}

View File

@ -0,0 +1,42 @@
/* This file is part of Clementine.
Copyright 2011, David Sansome <me@davidsansome.com>
Clementine 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.
Clementine 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 Clementine. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef INTERNETSHOWSETTINGSPAGE_H
#define INTERNETSHOWSETTINGSPAGE_H
#include "ui/settingspage.h"
#include "ui_internetshowsettingspage.h"
#include <QIcon>
class QTreeWidgetItem;
class Ui_InternetShowSettingsPage;
class InternetShowSettingsPage : public SettingsPage {
Q_OBJECT
public:
InternetShowSettingsPage(SettingsDialog* dialog);
void Load();
void Save();
private:
std::unique_ptr<Ui_InternetShowSettingsPage> ui_;
};
#endif // INTERNETSHOWSETTINGSPAGE_H

View File

@ -0,0 +1,82 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>InternetShowSettingsPage</class>
<widget class="QWidget" name="InternetShowSettingsPage">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>654</width>
<height>506</height>
</rect>
</property>
<property name="windowTitle">
<string comment="Global search settings dialog title.">Internet services</string>
</property>
<property name="windowIcon">
<iconset resource="../../data/data.qrc">
<normaloff>:/icons/32x32/internet-services.png</normaloff>:/icons/32x32/internet-services.png</iconset>
</property>
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<widget class="QGroupBox" name="sources_group">
<property name="title">
<string>Sources</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Choose the internet services you want to show.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QTreeWidget" name="sources">
<property name="horizontalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOff</enum>
</property>
<property name="rootIsDecorated">
<bool>false</bool>
</property>
<property name="columnCount">
<number>2</number>
</property>
<attribute name="headerVisible">
<bool>false</bool>
</attribute>
<attribute name="headerStretchLastSection">
<bool>false</bool>
</attribute>
<column>
<property name="text">
<string notr="true">1</string>
</property>
</column>
<column>
<property name="text">
<string notr="true">2</string>
</property>
</column>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<tabstops>
<tabstop>sources</tabstop>
</tabstops>
<resources>
<include location="../../data/data.qrc"/>
</resources>
<connections/>
</ui>

View File

@ -420,7 +420,8 @@ void SpotifyService::PlaylistsUpdated(const pb::spotify::Playlists& response) {
QString playlist_title = QStringFromStdString(msg.name());
if (!msg.is_mine()) {
const std::string& owner = msg.owner();
playlist_title += tr(", by ") + QString::fromUtf8(owner.c_str(), owner.size());
playlist_title +=
tr(", by ") + QString::fromUtf8(owner.c_str(), owner.size());
}
QStandardItem* item = new QStandardItem(playlist_title);
item->setData(InternetModel::Type_UserPlaylist, InternetModel::Role_Type);
@ -611,8 +612,7 @@ void SpotifyService::EnsureMenuCreated() {
song_context_menu_ = new QMenu;
remove_from_playlist_ = song_context_menu_->addAction(
IconLoader::Load("list-remove"),
tr("Remove from playlist"), this,
IconLoader::Load("list-remove"), tr("Remove from playlist"), this,
SLOT(RemoveCurrentFromPlaylist()));
song_context_menu_->addAction(GetNewShowConfigAction());
@ -742,7 +742,8 @@ void SpotifyService::ShowContextMenu(const QPoint& global_pos) {
return;
} else if (type == InternetModel::Type_Track) {
// Is this track contained in a playlist we can modify?
bool is_playlist_modifiable = item->parent() &&
bool is_playlist_modifiable =
item->parent() &&
item->parent()->data(Role_UserPlaylistIsMine).toBool();
remove_from_playlist_->setVisible(is_playlist_modifiable);
@ -807,9 +808,8 @@ void SpotifyService::SyncPlaylistProgress(
}
QAction* SpotifyService::GetNewShowConfigAction() {
QAction* action = new QAction(
IconLoader::Load("configure"),
tr("Configure Spotify..."), this);
QAction* action = new QAction(IconLoader::Load("configure"),
tr("Configure Spotify..."), this);
connect(action, SIGNAL(triggered()), this, SLOT(ShowConfig()));
return action;
}
@ -820,14 +820,15 @@ void SpotifyService::ShowConfig() {
void SpotifyService::RemoveCurrentFromPlaylist() {
const QModelIndexList& indexes(model()->selected_indexes());
QMap<int, QList<int> > playlists_songs_indices;
QMap<int, QList<int>> playlists_songs_indices;
for (const QModelIndex& index : indexes) {
if (index.parent().data(InternetModel::Role_Type).toInt() !=
InternetModel::Type_UserPlaylist) {
continue;
}
if (index.data(InternetModel::Role_Type).toInt() != InternetModel::Type_Track) {
if (index.data(InternetModel::Role_Type).toInt() !=
InternetModel::Type_Track) {
continue;
}
@ -836,8 +837,8 @@ void SpotifyService::RemoveCurrentFromPlaylist() {
playlists_songs_indices[playlist_index] << song_index;
}
for (QMap<int, QList<int> >::const_iterator it =
playlists_songs_indices.constBegin();
for (QMap<int, QList<int>>::const_iterator it =
playlists_songs_indices.constBegin();
it != playlists_songs_indices.constEnd(); ++it) {
RemoveSongsFromPlaylist(it.key(), it.value());
}
@ -845,7 +846,6 @@ void SpotifyService::RemoveCurrentFromPlaylist() {
void SpotifyService::RemoveSongsFromPlaylist(
int playlist_index, const QList<int>& songs_indices_to_remove) {
server_->RemoveSongsFromPlaylist(playlist_index, songs_indices_to_remove);
}

View File

@ -30,7 +30,8 @@ class SpotifyService : public InternetService {
enum Role {
Role_UserPlaylistIndex = InternetModel::RoleCount,
Role_UserPlaylistIsMine, // Is this playlist owned by the user currently logged-in?
Role_UserPlaylistIsMine, // Is this playlist owned by the user currently
// logged-in?
};
// Values are persisted - don't change.

View File

@ -23,18 +23,14 @@
namespace {
static const int sBarkBands[] = {
100, 200, 300, 400, 510, 630, 770, 920,
1080, 1270, 1480, 1720, 2000, 2320, 2700, 3150,
3700, 4400, 5300, 6400, 7700, 9500, 12000, 15500 };
100, 200, 300, 400, 510, 630, 770, 920, 1080, 1270, 1480, 1720,
2000, 2320, 2700, 3150, 3700, 4400, 5300, 6400, 7700, 9500, 12000, 15500};
static const int sBarkBandCount = arraysize(sBarkBands);
} // namespace
MoodbarBuilder::MoodbarBuilder()
: bands_(0),
rate_hz_(0) {
}
MoodbarBuilder::MoodbarBuilder() : bands_(0), rate_hz_(0) {}
int MoodbarBuilder::BandFrequency(int band) const {
return ((rate_hz_ / 2) * band + rate_hz_ / 4) / bands_;
@ -151,9 +147,8 @@ void MoodbarBuilder::Normalize(QList<Rgb>* vals, double Rgb::*member) {
for (auto it = vals->begin(); it != vals->end(); ++it) {
double* value = &((*it).*member);
*value = std::isfinite(*value)
? qBound(0.0, (*value - mini) / delta, 1.0)
: 0;
*value =
std::isfinite(*value) ? qBound(0.0, (*value - mini) / delta, 1.0) : 0;
}
}
@ -161,8 +156,7 @@ QByteArray MoodbarBuilder::Finish(int width) {
QByteArray ret;
ret.resize(width * 3);
char* data = ret.data();
if (frames_.count() == 0)
return ret;
if (frames_.count() == 0) return ret;
Normalize(&frames_, &Rgb::r);
Normalize(&frames_, &Rgb::g);

View File

@ -102,17 +102,13 @@ void MoodbarPipeline::Start() {
builder_.reset(new MoodbarBuilder);
// Set properties
g_object_set(decodebin,
"uri", local_filename_.toEncoded().constData(),
nullptr);
g_object_set(spectrum,
"bands", kBands,
g_object_set(decodebin, "uri", local_filename_.toEncoded().constData(),
nullptr);
g_object_set(spectrum, "bands", kBands, nullptr);
GstFastSpectrum* fast_spectrum = GST_FASTSPECTRUM(spectrum);
fast_spectrum->output_callback = [this](double* magnitudes, int size) {
builder_->AddFrame(magnitudes, size);
};
fast_spectrum->output_callback = [this](
double* magnitudes, int size) { builder_->AddFrame(magnitudes, size); };
// Connect signals
CHECKED_GCONNECT(decodebin, "pad-added", &NewPadCallback, this);

View File

@ -167,7 +167,8 @@ void PlaylistManager::Load(const QString& filename) {
return;
}
Playlist* playlist = AddPlaylist(id, info.baseName(), QString(), QString(), false);
Playlist* playlist =
AddPlaylist(id, info.baseName(), QString(), QString(), false);
QList<QUrl> urls;
playlist->InsertUrls(urls << QUrl::fromLocalFile(filename));
@ -195,7 +196,6 @@ void PlaylistManager::Save(int id, const QString& filename,
void PlaylistManager::ItemsLoadedForSavePlaylist(QFutureWatcher<Song>* watcher,
const QString& filename,
Playlist::Path path_type) {
SongList song_list = watcher->future().results();
parser_->Save(song_list, filename, path_type);
}
@ -263,7 +263,6 @@ void PlaylistManager::Rename(int id, const QString& new_name) {
}
void PlaylistManager::Favorite(int id, bool favorite) {
if (playlists_.contains(id)) {
// If playlists_ contains this playlist, its means it's opened: star or
// unstar it.

View File

@ -76,7 +76,8 @@ class PlaylistManagerInterface : public QObject {
virtual void New(const QString& name, const SongList& songs = SongList(),
const QString& special_type = QString()) = 0;
virtual void Load(const QString& filename) = 0;
virtual void Save(int id, const QString& filename, Playlist::Path path_type) = 0;
virtual void Save(int id, const QString& filename,
Playlist::Path path_type) = 0;
virtual void Rename(int id, const QString& new_name) = 0;
virtual void Delete(int id) = 0;
virtual bool Close(int id) = 0;

View File

@ -48,5 +48,6 @@ void PlaylistSaveOptionsDialog::accept() {
}
Playlist::Path PlaylistSaveOptionsDialog::path_type() const {
return static_cast<Playlist::Path>(ui->filePaths->itemData(ui->filePaths->currentIndex()).toInt());
return static_cast<Playlist::Path>(
ui->filePaths->itemData(ui->filePaths->currentIndex()).toInt());
}

View File

@ -967,8 +967,9 @@ void PlaylistView::paintEvent(QPaintEvent* event) {
if (model()->rowCount() == 0)
drop_pos = 1;
else
drop_pos = 1 + visualRect(model()->index(model()->rowCount() - 1,
first_column)).bottom();
drop_pos = 1 +
visualRect(model()->index(model()->rowCount() - 1,
first_column)).bottom();
break;
}
@ -1112,10 +1113,10 @@ void PlaylistView::ReloadSettings() {
force_background_redraw_ = true;
}
if(!s.value("click_edit_inline", true).toBool())
setEditTriggers(editTriggers() & ~QAbstractItemView::SelectedClicked);
if (!s.value("click_edit_inline", true).toBool())
setEditTriggers(editTriggers() & ~QAbstractItemView::SelectedClicked);
else
setEditTriggers(editTriggers() | QAbstractItemView::SelectedClicked);
setEditTriggers(editTriggers() | QAbstractItemView::SelectedClicked);
}
void PlaylistView::SaveSettings() {

View File

@ -50,8 +50,7 @@ SongList AsxIniParser::Load(QIODevice* device, const QString& playlist_path,
}
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);
s << "[Reference]" << endl;

View File

@ -33,8 +33,7 @@ class AsxIniParser : public ParserBase {
SongList Load(QIODevice* device, const QString& playlist_path = "",
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;
};

View File

@ -117,8 +117,8 @@ return_song:
return song;
}
void ASXParser::Save(const SongList& songs, QIODevice* device,
const QDir&, Playlist::Path path_type) const {
void ASXParser::Save(const SongList& songs, QIODevice* device, const QDir&,
Playlist::Path path_type) const {
QXmlStreamWriter writer(device);
writer.setAutoFormatting(true);
writer.setAutoFormattingIndent(2);

View File

@ -33,8 +33,7 @@ class ASXParser : public XMLParser {
SongList Load(QIODevice* device, const QString& playlist_path = "",
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;
private:

View File

@ -63,7 +63,6 @@ SongList CueParser::Load(QIODevice* device, const QString& playlist_path,
// -- whole file
while (!text_stream.atEnd()) {
QString album_artist;
QString album;
QString album_composer;
@ -86,22 +85,18 @@ SongList CueParser::Load(QIODevice* device, const QString& playlist_path,
// PERFORMER
if (line_name == kPerformer) {
album_artist = line_value;
// TITLE
} else if (line_name == kTitle) {
album = line_value;
// SONGWRITER
} else if (line_name == kSongWriter) {
album_composer = line_value;
// FILE
} else if (line_name == kFile) {
file = QDir::isAbsolutePath(line_value)
? line_value
: dir.absoluteFilePath(line_value);
@ -127,7 +122,6 @@ SongList CueParser::Load(QIODevice* device, const QString& playlist_path,
// end of the header -> go into the track mode
} else if (line_name == kTrack) {
files++;
break;
}
@ -166,7 +160,6 @@ SongList CueParser::Load(QIODevice* device, const QString& playlist_path,
splitted.size() > 2 ? splitted[2].toLower() : "";
if (line_name == kTrack) {
// the beginning of another track's definition - we're saving the
// current one
// for later (if it's valid of course)
@ -187,33 +180,26 @@ SongList CueParser::Load(QIODevice* device, const QString& playlist_path,
}
} else if (line_name == kIndex) {
// we need the index's position field
if (!line_additional.isEmpty()) {
// 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
if (line_value == "01" || index.isEmpty()) {
index = line_additional;
}
}
} else if (line_name == kPerformer) {
artist = line_value;
} else if (line_name == kTitle) {
title = line_value;
} else if (line_name == kSongWriter) {
composer = line_value;
// end of track's for the current file -> parse next one
} else if (line_name == kFile) {
break;
}
@ -351,8 +337,7 @@ qint64 CueParser::IndexToMarker(const QString& index) const {
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 {
// TODO
}

View File

@ -53,8 +53,7 @@ class CueParser : public ParserBase {
SongList Load(QIODevice* device, const QString& playlist_path = "",
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;
private:

View File

@ -104,8 +104,7 @@ bool M3UParser::ParseMetadata(const QString& line,
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 {
device->write("#EXTM3U\n");

View File

@ -41,8 +41,7 @@ class M3UParser : public ParserBase {
SongList Load(QIODevice* device, const QString& playlist_path = "",
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;
private:

View File

@ -86,8 +86,7 @@ Song ParserBase::LoadSong(const QString& filename_or_url, qint64 beginning,
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 {
if (url.scheme() != "file") return url.toString();

View File

@ -51,9 +51,9 @@ class ParserBase : public QObject {
// from the parser's point of view).
virtual SongList Load(QIODevice* device, const QString& playlist_path = "",
const QDir& dir = QDir()) const = 0;
virtual void Save(const SongList& songs, QIODevice* device,
const QDir& dir = QDir(),
Playlist::Path path_type = Playlist::Path_Automatic) const = 0;
virtual void Save(
const SongList& songs, QIODevice* device, const QDir& dir = QDir(),
Playlist::Path path_type = Playlist::Path_Automatic) const = 0;
protected:
// Loads a song. If filename_or_url is a URL (with a scheme other than

View File

@ -130,8 +130,7 @@ SongList PlaylistParser::LoadFromDevice(QIODevice* device,
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 {
QFileInfo info(filename);

View File

@ -49,7 +49,8 @@ class PlaylistParser : public QObject {
SongList LoadFromDevice(QIODevice* device,
const QString& path_hint = QString(),
const QDir& dir_hint = QDir()) const;
void Save(const SongList& songs, const QString& filename, Playlist::Path) const;
void Save(const SongList& songs, const QString& filename,
Playlist::Path) const;
private:
QString FilterForParser(const ParserBase* parser,

View File

@ -61,8 +61,8 @@ SongList PLSParser::Load(QIODevice* device, const QString& playlist_path,
return songs.values();
}
void PLSParser::Save(const SongList& songs, QIODevice* device,
const QDir& dir, Playlist::Path path_type) const {
void PLSParser::Save(const SongList& songs, QIODevice* device, const QDir& dir,
Playlist::Path path_type) const {
QTextStream s(device);
s << "[playlist]" << endl;
s << "Version=2" << endl;
@ -70,7 +70,8 @@ void PLSParser::Save(const SongList& songs, QIODevice* device,
int n = 1;
for (const Song& song : songs) {
s << "File" << n << "=" << URLOrFilename(song.url(), dir, path_type) << endl;
s << "File" << n << "=" << URLOrFilename(song.url(), dir, path_type)
<< endl;
s << "Title" << n << "=" << song.title() << endl;
s << "Length" << n << "=" << song.length_nanosec() / kNsecPerSec << endl;
++n;

View File

@ -33,8 +33,7 @@ class PLSParser : public ParserBase {
SongList Load(QIODevice* device, const QString& playlist_path = "",
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;
};

View File

@ -76,8 +76,8 @@ void WplParser::ParseSeq(const QDir& dir, QXmlStreamReader* reader,
}
}
void WplParser::Save(const SongList& songs, QIODevice* device,
const QDir& dir, Playlist::Path path_type) const {
void WplParser::Save(const SongList& songs, QIODevice* device, const QDir& dir,
Playlist::Path path_type) const {
QXmlStreamWriter writer(device);
writer.setAutoFormatting(true);
writer.setAutoFormattingIndent(2);

View File

@ -102,8 +102,8 @@ return_song:
return song;
}
void XSPFParser::Save(const SongList& songs, QIODevice* device,
const QDir& dir, Playlist::Path path_type) const {
void XSPFParser::Save(const SongList& songs, QIODevice* device, const QDir& dir,
Playlist::Path path_type) const {
QFileInfo file;
QXmlStreamWriter writer(device);
writer.setAutoFormatting(true);
@ -120,7 +120,8 @@ void XSPFParser::Save(const SongList& songs, QIODevice* device,
StreamElement tracklist("trackList", &writer);
for (const Song& song : songs) {
QString filename_or_url = URLOrFilename(song.url(), dir, path_type).toUtf8();
QString filename_or_url =
URLOrFilename(song.url(), dir, path_type).toUtf8();
StreamElement track("track", &writer);
writer.writeTextElement("location", filename_or_url);

View File

@ -38,8 +38,7 @@ class XSPFParser : public XMLParser {
SongList Load(QIODevice* device, const QString& playlist_path = "",
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;
private:

View File

@ -231,23 +231,23 @@ void TranscodeDialog::Add() {
void TranscodeDialog::Import() {
QString path = QFileDialog::getExistingDirectory(
this, tr("Open a directory to import music from"),
last_import_dir_, QFileDialog::ShowDirsOnly);
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);
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);

View File

@ -37,6 +37,7 @@
#include "globalsearch/globalsearchsettingspage.h"
#include "internet/digitallyimportedsettingspage.h"
#include "internet/groovesharksettingspage.h"
#include "internet/internetshowsettingspage.h"
#include "internet/magnatunesettingspage.h"
#include "internet/soundcloudsettingspage.h"
#include "internet/spotifysettingspage.h"
@ -83,8 +84,6 @@
#include "internet/seafilesettingspage.h"
#endif
#include <QAbstractButton>
#include <QDesktopWidget>
#include <QPainter>
@ -156,6 +155,7 @@ SettingsDialog::SettingsDialog(Application* app, BackgroundStreams* streams,
AddPage(Page_Appearance, new AppearanceSettingsPage(this), iface);
AddPage(Page_SongInformation, new SongInfoSettingsPage(this), iface);
AddPage(Page_Notifications, new NotificationsSettingsPage(this), iface);
AddPage(Page_InternetShow, new InternetShowSettingsPage(this), iface);
// Internet providers
QTreeWidgetItem* providers = AddCategory(tr("Internet providers"));
@ -193,8 +193,6 @@ SettingsDialog::SettingsDialog(Application* app, BackgroundStreams* streams,
AddPage(Page_Seafile, new SeafileSettingsPage(this), providers);
#endif
AddPage(Page_Magnatune, new MagnatuneSettingsPage(this), providers);
AddPage(Page_DigitallyImported, new DigitallyImportedSettingsPage(this),
providers);

View File

@ -85,7 +85,8 @@ class SettingsDialog : public QDialog {
Page_Skydrive,
Page_Box,
Page_Vk,
Page_Seafile
Page_Seafile,
Page_InternetShow
};
enum Role { Role_IsSeparator = Qt::UserRole };