1 /* This file is part of Clementine.
2    Copyright 2010-2011, 2013, David Sansome <me@davidsansome.com>
3    Copyright 2010, 2012, 2014, John Maguire <john.maguire@gmail.com>
4    Copyright 2014, Krzysztof Sobiecki <sobkas@gmail.com>
5 
6    Clementine is free software: you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation, either version 3 of the License, or
9    (at your option) any later version.
10 
11    Clementine is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15 
16    You should have received a copy of the GNU General Public License
17    along with Clementine.  If not, see <http://www.gnu.org/licenses/>.
18 */
19 
20 #include "backgroundstreams.h"
21 
22 #include <QAction>
23 #include <QSettings>
24 #include <QtDebug>
25 
26 #include "core/logging.h"
27 #include "engines/enginebase.h"
28 
29 const char* BackgroundStreams::kSettingsGroup = "BackgroundStreams";
30 const char* BackgroundStreams::kHypnotoadUrl = "hypnotoad:///";
31 const char* BackgroundStreams::kRainUrl =
32     "http://data.clementine-player.org/rainymood";
33 const char* BackgroundStreams::kEnterpriseUrl = "enterprise:///";
34 
BackgroundStreams(EngineBase * engine,QObject * parent)35 BackgroundStreams::BackgroundStreams(EngineBase* engine, QObject* parent)
36     : QObject(parent), engine_(engine) {}
37 
~BackgroundStreams()38 BackgroundStreams::~BackgroundStreams() { SaveStreams(); }
39 
LoadStreams()40 void BackgroundStreams::LoadStreams() {
41   QSettings s;
42   s.beginGroup(kSettingsGroup);
43 
44   int version = s.value("version", 0).toInt();
45   if (version < 1) {
46     AddStream(QT_TR_NOOP("Hypnotoad"), QUrl(kHypnotoadUrl));
47     AddStream(QT_TR_NOOP("Rain"), QUrl(kRainUrl));
48   }
49 
50   if (version < kVersion) {
51     s.setValue("version", kVersion);
52     AddStream(QT_TR_NOOP("Make it so!"), QUrl(kEnterpriseUrl));
53   }
54 
55   int size = s.beginReadArray("streams");
56   for (int i = 0; i < size; ++i) {
57     s.setArrayIndex(i);
58     AddStream(s.value("name").toString(), s.value("url").toUrl(),
59               s.value("volume").toInt());
60   }
61 
62   SaveStreams();
63 }
64 
SaveStreams()65 void BackgroundStreams::SaveStreams() {
66   QSettings s;
67   s.beginGroup(kSettingsGroup);
68 
69   QList<Stream*> values = streams_.values();
70   s.beginWriteArray("streams");
71   for (int i = 0; i < values.size(); ++i) {
72     s.setArrayIndex(i);
73     Stream* stream = values[i];
74     s.setValue("name", stream->name);
75     s.setValue("url", stream->url);
76     s.setValue("volume", stream->volume);
77   }
78   s.endArray();
79 }
80 
AddStream(const QString & name,const QUrl & url,int volume)81 void BackgroundStreams::AddStream(const QString& name, const QUrl& url,
82                                   int volume) {
83   if (streams_.contains(name)) {
84     return;
85   }
86 
87   Stream* s = new Stream;
88   s->name = name;
89   s->url = url;
90   s->volume = volume;
91   s->id = -1;
92   streams_[name] = s;
93 }
94 
EnableStream(const QString & name,bool enable)95 void BackgroundStreams::EnableStream(const QString& name, bool enable) {
96   if (!streams_.contains(name)) {
97     qLog(Warning) << "Tried to toggle a stream" << name << "which didn't exist";
98     return;
99   }
100 
101   Stream* stream = streams_[name];
102   if (enable == (stream->id != -1)) {
103     return;
104   }
105   if (enable) {
106     PlayStream(stream);
107   } else {
108     StopStream(stream);
109   }
110   SaveStreams();
111 }
112 
SetStreamVolume(const QString & name,int volume)113 void BackgroundStreams::SetStreamVolume(const QString& name, int volume) {
114   Stream* stream = streams_[name];
115   stream->volume = volume;
116   if (stream->id != -1) {
117     engine_->SetBackgroundStreamVolume(stream->id, stream->volume);
118   }
119 }
120 
PlayStream(Stream * stream)121 void BackgroundStreams::PlayStream(Stream* stream) {
122   stream->id = engine_->AddBackgroundStream(stream->url);
123   engine_->SetBackgroundStreamVolume(stream->id, stream->volume);
124   emit StreamStarted(stream->name);
125 
126   if (stream->action) {
127     stream->action->setChecked(true);
128   }
129 }
130 
StopStream(Stream * stream)131 void BackgroundStreams::StopStream(Stream* stream) {
132   engine_->StopBackgroundStream(stream->id);
133   stream->id = -1;
134   emit StreamStopped(stream->name);
135 
136   if (stream->action) {
137     stream->action->setChecked(false);
138   }
139 }
140 
GetStreamVolume(const QString & name) const141 int BackgroundStreams::GetStreamVolume(const QString& name) const {
142   return streams_[name]->volume;
143 }
144 
IsPlaying(const QString & name) const145 bool BackgroundStreams::IsPlaying(const QString& name) const {
146   return streams_[name]->id != -1;
147 }
148 
AddAction(const QString & name,QAction * action)149 void BackgroundStreams::AddAction(const QString& name, QAction* action) {
150   if (!streams_.contains(name)) {
151     qLog(Error) << "Tried to add action for stream" << name
152                 << "which doesn't exist";
153     return;
154   }
155 
156   Stream* stream = streams_[name];
157   if (stream->action) {
158     qLog(Error) << "Tried to add multiple actions for stream" << name;
159     return;
160   }
161 
162   stream->action = action;
163   action->setChecked(IsPlaying(name));
164   connect(action, SIGNAL(toggled(bool)), SLOT(StreamActionToggled(bool)));
165   connect(action, SIGNAL(destroyed()), SLOT(StreamActionDestroyed()));
166 }
167 
StreamActionDestroyed()168 void BackgroundStreams::StreamActionDestroyed() {
169   QAction* action = static_cast<QAction*>(sender());
170   if (!action) {
171     return;
172   }
173 
174   for (Stream* stream : streams_.values()) {
175     if (stream->action == action) {
176       stream->action = nullptr;
177     }
178   }
179 }
180 
StreamActionToggled(bool checked)181 void BackgroundStreams::StreamActionToggled(bool checked) {
182   QAction* action = static_cast<QAction*>(sender());
183   if (!action) {
184     return;
185   }
186 
187   for (Stream* stream : streams_.values()) {
188     if (stream->action == action) {
189       EnableStream(stream->name, checked);
190     }
191   }
192 }
193