Robin Thoni 9 år sedan
incheckning
ede55480d5
19 ändrade filer med 1224 tillägg och 0 borttagningar
  1. 37
    0
      .gitignore
  2. Binär
      favicon.ico
  3. 11
    0
      main.cpp
  4. 75
    0
      mainwindow.cpp
  5. 38
    0
      mainwindow.h
  6. 77
    0
      mainwindow.ui
  7. 130
    0
      nrj.cpp
  8. 44
    0
      nrj.h
  9. 37
    0
      nrj.pro
  10. 248
    0
      radio.cpp
  11. 92
    0
      radio.h
  12. 81
    0
      radiowidget.cpp
  13. 45
    0
      radiowidget.h
  14. 126
    0
      radiowidget.ui
  15. 5
    0
      rc.qrc
  16. 83
    0
      song.cpp
  17. 52
    0
      song.h
  18. 22
    0
      verticalscrollarea.cpp
  19. 21
    0
      verticalscrollarea.h

+ 37
- 0
.gitignore Visa fil

@@ -0,0 +1,37 @@
1
+*.swp
2
+nrj
3
+
4
+# C++ objects and libs
5
+
6
+*.slo
7
+*.lo
8
+*.o
9
+*.a
10
+*.la
11
+*.lai
12
+*.so
13
+*.dll
14
+*.dylib
15
+
16
+# Qt-es
17
+
18
+/.qmake.cache
19
+/.qmake.stash
20
+*.pro.user
21
+*.pro.user.*
22
+*.qbs.user
23
+*.qbs.user.*
24
+*.moc
25
+moc_*.cpp
26
+qrc_*.cpp
27
+ui_*.h
28
+Makefile*
29
+*-build-*
30
+
31
+# QtCreator
32
+
33
+*.autosave
34
+
35
+#QtCtreator Qml
36
+*.qmlproject.user
37
+*.qmlproject.user.*

Binär
favicon.ico Visa fil


+ 11
- 0
main.cpp Visa fil

@@ -0,0 +1,11 @@
1
+#include <QApplication>
2
+#include "mainwindow.h"
3
+
4
+int main(int argc, char *argv[])
5
+{
6
+    QApplication a(argc, argv);
7
+    MainWindow w;
8
+    w.show();
9
+    
10
+    return a.exec();
11
+}

+ 75
- 0
mainwindow.cpp Visa fil

@@ -0,0 +1,75 @@
1
+#include "mainwindow.h"
2
+#include "ui_mainwindow.h"
3
+#include <yaml-cpp/yaml.h>
4
+
5
+MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow)//, buf(&tmp)
6
+{
7
+    ui->setupUi(this);
8
+
9
+    //avcodec_register_all();
10
+
11
+    QAudioFormat format;
12
+    format.setSampleRate(44100);
13
+    format.setChannelCount(2);
14
+    //format.setFrequency(48000);
15
+    //format.setChannels(2);
16
+    format.setSampleSize(128000);
17
+    format.setCodec("audio/pcm");
18
+    format.setByteOrder(QAudioFormat::LittleEndian);
19
+    format.setSampleType(QAudioFormat::SignedInt);
20
+
21
+    QAudioDeviceInfo info(QAudioDeviceInfo::defaultOutputDevice());
22
+    if (!info.isFormatSupported(format))
23
+        format = info.nearestFormat(format);
24
+
25
+    qDebug() << format;
26
+
27
+    output=new QAudioOutput(format, this);
28
+    out=output->start();
29
+
30
+    currentRadio = 0;
31
+    nrj = new NRJ(this);
32
+    connect(nrj, SIGNAL(setupFinished()), this, SLOT(setupFinished()));
33
+    nrj->setupPlayer();
34
+
35
+}
36
+
37
+MainWindow::~MainWindow()
38
+{
39
+    delete ui;
40
+}
41
+
42
+void MainWindow::setupFinished()
43
+{
44
+    int i = 0;
45
+    foreach(Radio* r, nrj->getRadios())
46
+    {
47
+        RadioWidget* w = new RadioWidget();
48
+        ui->layRadios->addWidget(w, i / 2, i % 2);
49
+        connect(w, SIGNAL(clicked(Radio*)), this, SLOT(radioChanged(Radio*)));
50
+        w->setRadio(r);
51
+        ++i;
52
+    }
53
+    nrj->getAllCur();
54
+}
55
+
56
+void MainWindow::radioChanged(Radio *r)
57
+{
58
+    if(currentRadio != 0)
59
+    {
60
+        currentRadio->stopStream();
61
+        currentRadio->disconnect(this);
62
+    }
63
+    currentRadio = r;
64
+    if(currentRadio != 0)
65
+    {
66
+        connect(currentRadio, SIGNAL(streamData(QByteArray)), this, SLOT(radioData(QByteArray)));
67
+        currentRadio->startStream();
68
+    }
69
+}
70
+
71
+void MainWindow::radioData(QByteArray data)
72
+{
73
+    out->write(data);
74
+    //streamData.append(data);
75
+}

+ 38
- 0
mainwindow.h Visa fil

@@ -0,0 +1,38 @@
1
+#ifndef MAINWINDOW_H
2
+#define MAINWINDOW_H
3
+
4
+#include <QMainWindow>
5
+#include <QBuffer>
6
+#include "nrj.h"
7
+#include "radiowidget.h"
8
+#include "radio.h"
9
+#include <QDebug>
10
+#include <QAudioOutput>
11
+
12
+namespace Ui {
13
+class MainWindow;
14
+}
15
+
16
+class MainWindow : public QMainWindow
17
+{
18
+    Q_OBJECT
19
+
20
+public:
21
+    explicit MainWindow(QWidget *parent = 0);
22
+    ~MainWindow();
23
+
24
+private slots:
25
+    void setupFinished();
26
+    void radioChanged(Radio* r);
27
+    void radioData(QByteArray data);
28
+
29
+private:
30
+    Ui::MainWindow *ui;
31
+    NRJ* nrj;
32
+    Radio* currentRadio;
33
+    QAudioOutput* output;
34
+    QIODevice* out;
35
+
36
+};
37
+
38
+#endif // MAINWINDOW_H

+ 77
- 0
mainwindow.ui Visa fil

@@ -0,0 +1,77 @@
1
+<?xml version="1.0" encoding="UTF-8"?>
2
+<ui version="4.0">
3
+ <class>MainWindow</class>
4
+ <widget class="QMainWindow" name="MainWindow">
5
+  <property name="geometry">
6
+   <rect>
7
+    <x>0</x>
8
+    <y>0</y>
9
+    <width>658</width>
10
+    <height>339</height>
11
+   </rect>
12
+  </property>
13
+  <property name="windowTitle">
14
+   <string>NRJ</string>
15
+  </property>
16
+  <property name="windowIcon">
17
+   <iconset resource="rc.qrc">
18
+    <normaloff>:/favicon.ico</normaloff>:/favicon.ico</iconset>
19
+  </property>
20
+  <widget class="QWidget" name="centralWidget">
21
+   <layout class="QGridLayout" name="gridLayout">
22
+    <item row="0" column="0">
23
+     <widget class="VerticalScrollArea" name="radiosArea">
24
+      <property name="verticalScrollBarPolicy">
25
+       <enum>Qt::ScrollBarAlwaysOn</enum>
26
+      </property>
27
+      <property name="horizontalScrollBarPolicy">
28
+       <enum>Qt::ScrollBarAlwaysOff</enum>
29
+      </property>
30
+      <property name="widgetResizable">
31
+       <bool>true</bool>
32
+      </property>
33
+      <widget class="QWidget" name="widRadios">
34
+       <property name="geometry">
35
+        <rect>
36
+         <x>0</x>
37
+         <y>0</y>
38
+         <width>605</width>
39
+         <height>299</height>
40
+        </rect>
41
+       </property>
42
+       <layout class="QGridLayout" name="layRadios">
43
+        <property name="spacing">
44
+         <number>2</number>
45
+        </property>
46
+       </layout>
47
+      </widget>
48
+     </widget>
49
+    </item>
50
+    <item row="0" column="1">
51
+     <widget class="QFrame" name="radioFrame">
52
+      <property name="frameShape">
53
+       <enum>QFrame::StyledPanel</enum>
54
+      </property>
55
+      <property name="frameShadow">
56
+       <enum>QFrame::Raised</enum>
57
+      </property>
58
+     </widget>
59
+    </item>
60
+   </layout>
61
+  </widget>
62
+  <widget class="QStatusBar" name="statusBar"/>
63
+ </widget>
64
+ <layoutdefault spacing="6" margin="11"/>
65
+ <customwidgets>
66
+  <customwidget>
67
+   <class>VerticalScrollArea</class>
68
+   <extends>QScrollArea</extends>
69
+   <header>verticalscrollarea.h</header>
70
+   <container>1</container>
71
+  </customwidget>
72
+ </customwidgets>
73
+ <resources>
74
+  <include location="rc.qrc"/>
75
+ </resources>
76
+ <connections/>
77
+</ui>

+ 130
- 0
nrj.cpp Visa fil

@@ -0,0 +1,130 @@
1
+#include "nrj.h"
2
+#include "yaml-cpp/yaml.h"
3
+#include <QDebug>
4
+#include <QColor>
5
+#include <QUrlQuery>
6
+
7
+NRJ::NRJ(QObject *parent) : QObject(parent)
8
+{
9
+    mgr = new QNetworkAccessManager(this);
10
+    tries = 0;
11
+}
12
+
13
+QList<Radio *> NRJ::getRadios()
14
+{
15
+    return radios;
16
+}
17
+
18
+void NRJ::setupPlayer()
19
+{
20
+    tries = 0;
21
+    QNetworkReply* reply = mgr->get(QNetworkRequest(QUrl("http://players.nrjaudio.fm/live-metadata/player/nrj/v1.0/player_setup.yml")));
22
+    connect(reply, SIGNAL(finished()), this, SLOT(onSetupFinished()));
23
+    connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(onSetupError(QNetworkReply::NetworkError)));
24
+}
25
+
26
+void NRJ::getAllCur()
27
+{
28
+    if(apiBase.isEmpty())
29
+        return;
30
+    tries = 0;
31
+    QUrl url = apiBase;
32
+    QUrlQuery query;
33
+    query.addQueryItem("act", "get_allcur");
34
+    url.setQuery(query);
35
+
36
+    QNetworkReply* reply = mgr->get(QNetworkRequest(url));
37
+    connect(reply, SIGNAL(finished()), this, SLOT(onGetAllCurFinished()));
38
+    connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(onGetAllCurError(QNetworkReply::NetworkError)));
39
+}
40
+
41
+void NRJ::onSetupFinished()
42
+{
43
+    QNetworkReply* reply = (QNetworkReply*)sender();
44
+    YAML::Node root = YAML::Load(reply->readAll().constData());
45
+    apiBase = QUrl(root["player_api"].as<std::string>().c_str());
46
+    QUrlQuery query;
47
+    query.addQueryItem("id_radio", root["id_webradio"].as<std::string>().c_str());
48
+    apiBase.setQuery(query);
49
+    coverBase = QUrl(root["radio_pics"].as<std::string>().c_str());
50
+    YAML::Node webradios = root["webradios"];
51
+
52
+    QString logosRootUrl = root["radio_pics"].as<std::string>().c_str();
53
+    logosRootUrl += "80x80/";
54
+
55
+    for(unsigned i = 0;i < webradios.size(); ++i)
56
+    {
57
+        YAML::Node node = webradios[i];
58
+        Radio* radio = new Radio(this);
59
+        radios.append(radio);
60
+        radio->setApiBase(apiBase);
61
+        radio->setCoverBase(coverBase);
62
+        radio->setNetworkManager(mgr);
63
+
64
+        radio->setId(node["id"].as<int>());
65
+        radio->setName(QString::fromUtf8(node["name"].as<std::string>().c_str()));
66
+        radio->setClaim(QString::fromUtf8(node["claim"].as<std::string>().c_str()));
67
+        radio->setTextColor(QColor("#" + QString(node["color"].as<std::string>().c_str())));
68
+        radio->setLogoUrl(QUrl(logosRootUrl + node["logo"].as<std::string>().c_str()));
69
+        radio->setStreamUrl(QUrl(node["url_128k_mp3"].as<std::string>().c_str()));
70
+    }
71
+    emit setupFinished();
72
+}
73
+
74
+void NRJ::onSetupError(QNetworkReply::NetworkError)
75
+{
76
+    if(tries < 3)
77
+    {
78
+        ++tries;
79
+        setupPlayer();
80
+    }
81
+    else
82
+    {
83
+        tries = 0;
84
+        emit setupError();
85
+    }
86
+}
87
+
88
+void NRJ::onGetAllCurFinished()
89
+{
90
+    QNetworkReply* reply = (QNetworkReply*)sender();
91
+    YAML::Node itms = YAML::Load(reply->readAll().constData())["itms"];
92
+
93
+    for(unsigned i = 0;i < itms.size(); ++i)
94
+    {
95
+        YAML::Node itm = itms[i];
96
+        int id = itm["id_plst"].as<int>();
97
+        for(int it = 0;it < radios.size(); ++it)
98
+        {
99
+            Radio* r = radios.at(it);
100
+            if(r->getId() == id)
101
+            {
102
+                it = radios.size();
103
+                Song* song = new Song(r);
104
+                song->setDuration(qMax((int)(itm["t_dur"].as<int>() - (1000 * (QDateTime::currentDateTime().toTime_t() - itm["ts"].as<int>()))), 0));
105
+                song->setArtist(itm["art"].as<std::string>().c_str());
106
+                song->setTitle(itm["tit"].as<std::string>().c_str());
107
+                //qDebug()<<(QDateTime::currentDateTime().toTime_t() - itm["ts"].as<int>());
108
+                //song->setStartTime(itm["ts"].as<int>() * 1000);
109
+                QUrl url = coverBase;
110
+                url.setPath(url.path() + itm["cov"].as<std::string>().c_str());
111
+                song->setCoverUrl(url);
112
+                r->setCurrentSong(song);
113
+            }
114
+        }
115
+    }
116
+}
117
+
118
+void NRJ::onGetAllCurError(QNetworkReply::NetworkError)
119
+{
120
+    if(tries < 3)
121
+    {
122
+        ++tries;
123
+        getAllCur();
124
+    }
125
+    else
126
+    {
127
+        tries = 0;
128
+        emit getAllCurError();
129
+    }
130
+}

+ 44
- 0
nrj.h Visa fil

@@ -0,0 +1,44 @@
1
+#ifndef NRJ_H
2
+#define NRJ_H
3
+
4
+#include <QObject>
5
+#include <QNetworkAccessManager>
6
+#include <QNetworkRequest>
7
+#include <QNetworkReply>
8
+#include "radio.h"
9
+
10
+class NRJ : public QObject
11
+{
12
+    Q_OBJECT
13
+public:
14
+    explicit NRJ(QObject *parent = 0);
15
+
16
+    QList<Radio*> getRadios();
17
+    
18
+signals:
19
+    void setupFinished();
20
+    void setupError();
21
+
22
+    void getAllCurError();
23
+    
24
+public slots:
25
+    void setupPlayer();
26
+    void getAllCur();
27
+
28
+private slots:
29
+    void onSetupFinished();
30
+    void onSetupError(QNetworkReply::NetworkError);
31
+
32
+    void onGetAllCurFinished();
33
+    void onGetAllCurError(QNetworkReply::NetworkError);
34
+
35
+private:
36
+    QNetworkAccessManager* mgr;
37
+    QList<Radio*> radios;
38
+    QUrl apiBase;
39
+    QUrl coverBase;
40
+    int tries;
41
+    
42
+};
43
+
44
+#endif // NRJ_H

+ 37
- 0
nrj.pro Visa fil

@@ -0,0 +1,37 @@
1
+#-------------------------------------------------
2
+#
3
+# Project created by QtCreator 2013-06-05T22:35:34
4
+#
5
+#-------------------------------------------------
6
+
7
+QT       += core gui network multimedia widgets
8
+
9
+TARGET = nrj
10
+TEMPLATE = app
11
+
12
+INCLUDEPATH += C:/boost_1_53_0/
13
+
14
+SOURCES += main.cpp\
15
+        mainwindow.cpp \
16
+    nrj.cpp \
17
+    radio.cpp \
18
+    radiowidget.cpp \
19
+    verticalscrollarea.cpp \
20
+    song.cpp
21
+
22
+HEADERS  += mainwindow.h \
23
+    nrj.h \
24
+    radio.h \
25
+    radiowidget.h \
26
+    verticalscrollarea.h \
27
+    song.h
28
+
29
+FORMS    += mainwindow.ui \
30
+    radiowidget.ui
31
+
32
+
33
+LIBS += -lyaml-cpp
34
+#-lavcodec
35
+
36
+RESOURCES += \
37
+    rc.qrc

+ 248
- 0
radio.cpp Visa fil

@@ -0,0 +1,248 @@
1
+#include "radio.h"
2
+#include "yaml-cpp/yaml.h"
3
+#include <QDebug>
4
+#include <QUrlQuery>
5
+
6
+Radio::Radio(QObject *parent) : QObject(parent), logo(0, 0)
7
+{
8
+    mgr = 0;
9
+    logoTries = 0;
10
+    currentSong = 0;
11
+    songsTries = 0;
12
+    streamTries = 0;
13
+    stream = 0;
14
+    songTimer = new QTimer(this);
15
+    songTimer->setSingleShot(true);
16
+    connect(songTimer, SIGNAL(timeout()), this, SLOT(songEnded()));
17
+}
18
+
19
+QString Radio::getName()
20
+{
21
+    return name;
22
+}
23
+
24
+QString Radio::getClaim()
25
+{
26
+    return claim;
27
+}
28
+
29
+QColor Radio::getTextColor()
30
+{
31
+    return textColor;
32
+}
33
+
34
+QUrl Radio::getLogoUrl()
35
+{
36
+    return logoUrl;
37
+}
38
+
39
+QUrl Radio::getStreamUrl()
40
+{
41
+    return streamUrl;
42
+}
43
+
44
+int Radio::getId()
45
+{
46
+    return id;
47
+}
48
+
49
+QUrl Radio::getApiBase()
50
+{
51
+    return apiBase;
52
+}
53
+
54
+QUrl Radio::getCoverBase()
55
+{
56
+    return coverBase;
57
+}
58
+
59
+Song *Radio::getCurrentSong()
60
+{
61
+    return currentSong;
62
+}
63
+
64
+QNetworkReply *Radio::getStream()
65
+{
66
+    return stream;
67
+}
68
+
69
+void Radio::setName(QString n)
70
+{
71
+    name = n;
72
+}
73
+
74
+void Radio::setClaim(QString c)
75
+{
76
+    claim = c;
77
+}
78
+
79
+void Radio::setTextColor(QColor c)
80
+{
81
+    textColor = c;
82
+}
83
+
84
+void Radio::setLogoUrl(QUrl u)
85
+{
86
+    logoUrl = u;
87
+}
88
+
89
+void Radio::setStreamUrl(QUrl u)
90
+{
91
+    streamUrl = u;
92
+}
93
+
94
+void Radio::setId(int i)
95
+{
96
+    id = i;
97
+}
98
+
99
+void Radio::setApiBase(QUrl u)
100
+{
101
+    apiBase = u;
102
+}
103
+
104
+void Radio::setCoverBase(QUrl u)
105
+{
106
+    coverBase = u;
107
+}
108
+
109
+void Radio::setCurrentSong(Song *s)
110
+{
111
+    if(currentSong != 0)
112
+        currentSong->deleteLater();
113
+    currentSong = s;
114
+    songTimer->stop();
115
+    if(s->getDuration() < 0)
116
+        qDebug()<<s->getDuration()<<name;
117
+    songTimer->setInterval(s->getDuration());
118
+    songTimer->start();
119
+    nextSongs.removeOne(currentSong);
120
+    updateNextSongs();
121
+    emit songChanged(currentSong);
122
+}
123
+
124
+void Radio::updateNextSongs()
125
+{
126
+    songsTries = 0;
127
+    QUrl url = apiBase;
128
+    QUrlQuery query;
129
+    query.addQueryItem("act", "get_plist");
130
+    query.addQueryItem("id_wr", QString::number(id));
131
+    url.setQuery(query);
132
+    QNetworkReply* reply = mgr->get(QNetworkRequest(url));
133
+    connect(reply, SIGNAL(finished()), this, SLOT(songsFinished()));
134
+    connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(songsError(QNetworkReply::NetworkError)));
135
+}
136
+
137
+void Radio::downloadLogo()
138
+{
139
+    if(logo.isNull())
140
+    {
141
+        logoTries = 0;
142
+        QNetworkReply* reply = mgr->get(QNetworkRequest(logoUrl));
143
+        connect(reply, SIGNAL(finished()), this, SLOT(logoFinished()));
144
+        connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(logoError(QNetworkReply::NetworkError)));
145
+    }
146
+    else
147
+        emit logoDownloaded(logo);
148
+}
149
+
150
+void Radio::startStream()
151
+{
152
+    stopStream();
153
+    streamTries = 0;
154
+    stream = mgr->get(QNetworkRequest(streamUrl));
155
+    stream->setReadBufferSize(128);
156
+    connect(stream, SIGNAL(readyRead()), this, SLOT(streamRead()));
157
+    emit streamChanged(stream);
158
+}
159
+
160
+void Radio::stopStream()
161
+{
162
+    if(stream != 0)
163
+    {
164
+        stream->abort();
165
+        stream->deleteLater();
166
+        stream = 0;
167
+    }
168
+}
169
+
170
+void Radio::logoFinished()
171
+{
172
+    QNetworkReply* reply = (QNetworkReply*)sender();
173
+
174
+    if(logo.loadFromData(reply->readAll()) && !logo.isNull())
175
+        emit logoDownloaded(logo);
176
+}
177
+
178
+void Radio::logoError(QNetworkReply::NetworkError)
179
+{
180
+    if(logoTries < 3)
181
+    {
182
+        ++logoTries;
183
+        downloadLogo();
184
+    }
185
+}
186
+
187
+void Radio::songsFinished()
188
+{
189
+    QNetworkReply* reply = (QNetworkReply*)sender();
190
+    YAML::Node itms = YAML::Load(reply->readAll().constData())["itms"];
191
+    qDeleteAll(nextSongs);
192
+    for(unsigned i = 1;i < itms.size(); ++i)
193
+    {
194
+        YAML::Node itm = itms[i];
195
+        if(itm["id"].as<int>() == -1)
196
+            continue;
197
+        Song* song = new Song(this);
198
+        song->setDuration(itm["t_dur"].as<int>());
199
+        song->setArtist(itm["art"].as<std::string>().c_str());
200
+        song->setTitle(itm["tit"].as<std::string>().c_str());
201
+        QUrl url = coverBase;
202
+        url.setPath(url.path() + itm["cov"].as<std::string>().c_str());
203
+        song->setCoverUrl(url);
204
+        nextSongs.append(song);
205
+    }
206
+}
207
+
208
+void Radio::songsError(QNetworkReply::NetworkError)
209
+{
210
+    if(songsTries < 3)
211
+    {
212
+        ++songsTries;
213
+        updateNextSongs();
214
+    }
215
+}
216
+
217
+void Radio::streamRead()
218
+{
219
+    if(stream->header(QNetworkRequest::LocationHeader).toUrl().isEmpty())
220
+        emit streamData(stream->readAll());
221
+    else
222
+    {
223
+        streamUrl = stream->header(QNetworkRequest::LocationHeader).toUrl();
224
+        stopStream();
225
+        startStream();
226
+    }
227
+}
228
+
229
+void Radio::streamError()
230
+{
231
+    if(streamTries < 3)
232
+    {
233
+        ++streamTries;
234
+        stopStream();
235
+        startStream();
236
+    }
237
+}
238
+
239
+void Radio::songEnded()
240
+{
241
+    if(!nextSongs.isEmpty())
242
+        setCurrentSong(nextSongs.at(0));
243
+}
244
+
245
+void Radio::setNetworkManager(QNetworkAccessManager *m)
246
+{
247
+    mgr = m;
248
+}

+ 92
- 0
radio.h Visa fil

@@ -0,0 +1,92 @@
1
+#ifndef RADIO_H
2
+#define RADIO_H
3
+
4
+#include <QObject>
5
+#include <QColor>
6
+#include <QUrl>
7
+#include <QPixmap>
8
+#include <QNetworkAccessManager>
9
+#include <QNetworkReply>
10
+#include <QList>
11
+#include <QTimer>
12
+#include "song.h"
13
+
14
+class Radio : public QObject
15
+{
16
+    Q_OBJECT
17
+public:
18
+    explicit Radio(QObject *parent = 0);
19
+
20
+    QString getName();
21
+    QString getClaim();
22
+    QColor getTextColor();
23
+    QUrl getLogoUrl();
24
+    QUrl getStreamUrl();
25
+    int getId();
26
+    QUrl getApiBase();
27
+    QUrl getCoverBase();
28
+
29
+    Song* getCurrentSong();
30
+    QNetworkReply* getStream();
31
+    
32
+signals:
33
+    void logoDownloaded(QPixmap);
34
+    void songChanged(Song*);
35
+    void nextSongsUpdated();
36
+    void streamData(QByteArray);
37
+    void streamChanged(QNetworkReply*);
38
+    
39
+public slots:
40
+    void setNetworkManager(QNetworkAccessManager* m);
41
+
42
+    void setName(QString n);
43
+    void setClaim(QString c);
44
+    void setTextColor(QColor c);
45
+    void setLogoUrl(QUrl u);
46
+    void setStreamUrl(QUrl u);
47
+    void setId(int i);
48
+    void setApiBase(QUrl u);
49
+    void setCoverBase(QUrl u);
50
+
51
+    void setCurrentSong(Song* s);
52
+    void updateNextSongs();
53
+    void downloadLogo();
54
+    void startStream();
55
+    void stopStream();
56
+
57
+private slots:
58
+    void logoFinished();
59
+    void logoError(QNetworkReply::NetworkError);
60
+
61
+    void songsFinished();
62
+    void songsError(QNetworkReply::NetworkError);
63
+
64
+    void streamRead();
65
+    void streamError();
66
+
67
+    void songEnded();
68
+
69
+private:
70
+    QString name;
71
+    QString claim;
72
+    QColor textColor;
73
+    QUrl logoUrl;
74
+    QUrl streamUrl;
75
+    int id;
76
+    QPixmap logo;
77
+    QUrl apiBase;
78
+    QUrl coverBase;
79
+
80
+    QList<Song*> nextSongs;
81
+    Song* currentSong;
82
+    QTimer* songTimer;
83
+
84
+    QNetworkAccessManager* mgr;
85
+    int logoTries;
86
+    int songsTries;
87
+    int streamTries;
88
+    QNetworkReply* stream;
89
+    
90
+};
91
+
92
+#endif // RADIO_H

+ 81
- 0
radiowidget.cpp Visa fil

@@ -0,0 +1,81 @@
1
+#include "radiowidget.h"
2
+#include "ui_radiowidget.h"
3
+#include <QDebug>
4
+
5
+RadioWidget::RadioWidget(QWidget *parent) : QFrame(parent), ui(new Ui::RadioWidget)
6
+{
7
+    ui->setupUi(this);
8
+    remaining = 0;
9
+    timer = new QTimer(this);
10
+    connect(timer, SIGNAL(timeout()), this, SLOT(countdown()));
11
+    timer->setInterval(1000);
12
+}
13
+
14
+RadioWidget::~RadioWidget()
15
+{
16
+    delete ui;
17
+}
18
+
19
+Radio *RadioWidget::getRadio()
20
+{
21
+    return radio;
22
+}
23
+
24
+void RadioWidget::setRadio(Radio *r)
25
+{
26
+    radio = r;
27
+    ui->lblClaim->setText(radio->getClaim());
28
+    QPalette p = ui->lblClaim->palette();
29
+    p.setColor(QPalette::Foreground, radio->getTextColor());
30
+    ui->lblClaim->setPalette(p);
31
+    songChanged(0);
32
+    ui->lblLogo->setText(radio->getName());
33
+    connect(radio, SIGNAL(logoDownloaded(QPixmap)), this, SLOT(logoDownloaded(QPixmap)));
34
+    connect(radio, SIGNAL(songChanged(Song*)), this, SLOT(songChanged(Song*)));
35
+    radio->downloadLogo();
36
+}
37
+
38
+void RadioWidget::logoDownloaded(QPixmap l)
39
+{
40
+    ui->lblLogo->setText("");
41
+    ui->lblLogo->setPixmap(l);
42
+}
43
+
44
+void RadioWidget::songChanged(Song *s)
45
+{
46
+    if(s == 0)
47
+    {
48
+        ui->lblSong->setText("--");
49
+        ui->lblTime->setText("");
50
+    }
51
+    else
52
+    {
53
+        ui->lblSong->setText(s->getArtist() + "\n" + s->getTitle());
54
+        remaining = s->getDuration()/1000;
55
+
56
+        ui->lblTime->setText(QString::number(remaining));
57
+        timer->start();
58
+    }
59
+}
60
+
61
+void RadioWidget::countdown()
62
+{
63
+    --remaining;
64
+    ui->lblTime->setText(QString::number(remaining));
65
+}
66
+
67
+void RadioWidget::enterEvent(QEvent *)
68
+{
69
+    setStyleSheet("background-color: rgb(225, 225, 225);");
70
+}
71
+
72
+void RadioWidget::leaveEvent(QEvent *)
73
+{
74
+    setStyleSheet("background-color: none;");
75
+}
76
+
77
+void RadioWidget::mouseReleaseEvent(QMouseEvent *e)
78
+{
79
+    if(e->button() == Qt::LeftButton)
80
+        emit clicked(radio);
81
+}

+ 45
- 0
radiowidget.h Visa fil

@@ -0,0 +1,45 @@
1
+#ifndef RADIOWIDGET_H
2
+#define RADIOWIDGET_H
3
+
4
+#include <QMouseEvent>
5
+#include <QFrame>
6
+#include "radio.h"
7
+
8
+namespace Ui {
9
+class RadioWidget;
10
+}
11
+
12
+class RadioWidget : public QFrame
13
+{
14
+    Q_OBJECT
15
+    
16
+public:
17
+    explicit RadioWidget(QWidget *parent = 0);
18
+    ~RadioWidget();
19
+    
20
+    Radio* getRadio();
21
+
22
+signals:
23
+    void clicked(Radio*);
24
+
25
+public slots:
26
+    void setRadio(Radio* r);
27
+
28
+private slots:
29
+    void logoDownloaded(QPixmap l);
30
+    void songChanged(Song* s);
31
+    void countdown();
32
+
33
+protected:
34
+    void enterEvent(QEvent *);
35
+    void leaveEvent(QEvent *);
36
+    void mouseReleaseEvent(QMouseEvent* e);
37
+
38
+private:
39
+    Ui::RadioWidget *ui;
40
+    Radio* radio;
41
+    int remaining;
42
+    QTimer* timer;
43
+};
44
+
45
+#endif // RADIOWIDGET_H

+ 126
- 0
radiowidget.ui Visa fil

@@ -0,0 +1,126 @@
1
+<?xml version="1.0" encoding="UTF-8"?>
2
+<ui version="4.0">
3
+ <class>RadioWidget</class>
4
+ <widget class="QFrame" name="RadioWidget">
5
+  <property name="geometry">
6
+   <rect>
7
+    <x>0</x>
8
+    <y>0</y>
9
+    <width>194</width>
10
+    <height>104</height>
11
+   </rect>
12
+  </property>
13
+  <property name="sizePolicy">
14
+   <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
15
+    <horstretch>0</horstretch>
16
+    <verstretch>0</verstretch>
17
+   </sizepolicy>
18
+  </property>
19
+  <property name="cursor">
20
+   <cursorShape>PointingHandCursor</cursorShape>
21
+  </property>
22
+  <property name="windowTitle">
23
+   <string>Form</string>
24
+  </property>
25
+  <property name="styleSheet">
26
+   <string notr="true"/>
27
+  </property>
28
+  <layout class="QGridLayout" name="gridLayout">
29
+   <property name="margin">
30
+    <number>0</number>
31
+   </property>
32
+   <property name="spacing">
33
+    <number>0</number>
34
+   </property>
35
+   <item row="1" column="1">
36
+    <widget class="QLabel" name="lblSong">
37
+     <property name="sizePolicy">
38
+      <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
39
+       <horstretch>0</horstretch>
40
+       <verstretch>0</verstretch>
41
+      </sizepolicy>
42
+     </property>
43
+     <property name="maximumSize">
44
+      <size>
45
+       <width>200</width>
46
+       <height>16777215</height>
47
+      </size>
48
+     </property>
49
+     <property name="text">
50
+      <string>Artist name
51
+Song name</string>
52
+     </property>
53
+     <property name="alignment">
54
+      <set>Qt::AlignCenter</set>
55
+     </property>
56
+     <property name="wordWrap">
57
+      <bool>true</bool>
58
+     </property>
59
+    </widget>
60
+   </item>
61
+   <item row="0" column="1">
62
+    <widget class="QLabel" name="lblClaim">
63
+     <property name="sizePolicy">
64
+      <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
65
+       <horstretch>0</horstretch>
66
+       <verstretch>0</verstretch>
67
+      </sizepolicy>
68
+     </property>
69
+     <property name="maximumSize">
70
+      <size>
71
+       <width>200</width>
72
+       <height>16777215</height>
73
+      </size>
74
+     </property>
75
+     <property name="font">
76
+      <font>
77
+       <pointsize>8</pointsize>
78
+       <weight>75</weight>
79
+       <bold>true</bold>
80
+      </font>
81
+     </property>
82
+     <property name="text">
83
+      <string>Radio claim</string>
84
+     </property>
85
+     <property name="wordWrap">
86
+      <bool>true</bool>
87
+     </property>
88
+    </widget>
89
+   </item>
90
+   <item row="2" column="1">
91
+    <widget class="QLabel" name="lblTime">
92
+     <property name="text">
93
+      <string>2:00</string>
94
+     </property>
95
+     <property name="alignment">
96
+      <set>Qt::AlignCenter</set>
97
+     </property>
98
+    </widget>
99
+   </item>
100
+   <item row="0" column="0" rowspan="3">
101
+    <widget class="QLabel" name="lblLogo">
102
+     <property name="sizePolicy">
103
+      <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
104
+       <horstretch>0</horstretch>
105
+       <verstretch>0</verstretch>
106
+      </sizepolicy>
107
+     </property>
108
+     <property name="maximumSize">
109
+      <size>
110
+       <width>100</width>
111
+       <height>150</height>
112
+      </size>
113
+     </property>
114
+     <property name="text">
115
+      <string>Radio name</string>
116
+     </property>
117
+     <property name="wordWrap">
118
+      <bool>true</bool>
119
+     </property>
120
+    </widget>
121
+   </item>
122
+  </layout>
123
+ </widget>
124
+ <resources/>
125
+ <connections/>
126
+</ui>

+ 5
- 0
rc.qrc Visa fil

@@ -0,0 +1,5 @@
1
+<RCC>
2
+    <qresource prefix="/" lang="fr">
3
+        <file>favicon.ico</file>
4
+    </qresource>
5
+</RCC>

+ 83
- 0
song.cpp Visa fil

@@ -0,0 +1,83 @@
1
+#include "song.h"
2
+
3
+Song::Song(QObject *parent) : QObject(parent), cover(0, 0)
4
+{
5
+    tries = 0;
6
+}
7
+
8
+QString Song::getArtist() const
9
+{
10
+    return artist;
11
+}
12
+
13
+QString Song::getTitle() const
14
+{
15
+    return title;
16
+}
17
+
18
+QUrl Song::getCoverUrl() const
19
+{
20
+    return coverUrl;
21
+}
22
+
23
+int Song::getDuration() const
24
+{
25
+    return duration;
26
+}
27
+
28
+void Song::setArtist(QString a)
29
+{
30
+    artist = a;
31
+}
32
+
33
+void Song::setTitle(QString t)
34
+{
35
+    title = t;
36
+}
37
+
38
+void Song::setCoverUrl(QUrl u)
39
+{
40
+    coverUrl = u;
41
+}
42
+
43
+void Song::setDuration(int d)
44
+{
45
+    duration = d;
46
+}
47
+
48
+void Song::downloadCover()
49
+{
50
+    if(cover.isNull())
51
+    {
52
+        if(mgr != 0)
53
+        {
54
+            tries = 0;
55
+            QNetworkReply* reply = mgr->get(QNetworkRequest(coverUrl));
56
+            connect(reply, SIGNAL(finished()), this, SLOT(onCoverFinished()));
57
+            connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(onCoverError(QNetworkReply::NetworkError)));
58
+        }
59
+    }
60
+    else
61
+        emit coverDownloaded(cover);
62
+}
63
+
64
+void Song::setNetworkManager(QNetworkAccessManager *m)
65
+{
66
+    mgr = m;
67
+}
68
+
69
+void Song::onCoverFinished()
70
+{
71
+    QNetworkReply* reply = (QNetworkReply*)sender();
72
+    if(cover.loadFromData(reply->readAll()) && !cover.isNull())
73
+        emit coverDownloaded(cover);
74
+}
75
+
76
+void Song::onCoverError(QNetworkReply::NetworkError)
77
+{
78
+    if(tries < 3)
79
+    {
80
+        ++tries;
81
+        downloadCover();
82
+    }
83
+}

+ 52
- 0
song.h Visa fil

@@ -0,0 +1,52 @@
1
+#ifndef SONG_H
2
+#define SONG_H
3
+
4
+#include <QObject>
5
+#include <QString>
6
+#include <QTime>
7
+#include <QUrl>
8
+#include <QNetworkAccessManager>
9
+#include <QNetworkReply>
10
+#include <QNetworkRequest>
11
+#include <QPixmap>
12
+
13
+class Song : public QObject
14
+{
15
+    Q_OBJECT
16
+public:
17
+    explicit Song(QObject *parent = 0);
18
+
19
+    QString getArtist() const;
20
+    QString getTitle() const;
21
+    QUrl getCoverUrl() const;
22
+    int getDuration() const;
23
+    
24
+signals:
25
+    void coverDownloaded(QPixmap);
26
+    
27
+public slots:
28
+    void setArtist(QString a);
29
+    void setTitle(QString t);
30
+    void setCoverUrl(QUrl u);
31
+    void setDuration(int d);
32
+
33
+    void downloadCover();
34
+
35
+    void setNetworkManager(QNetworkAccessManager* m);
36
+
37
+private slots:
38
+    void onCoverFinished();
39
+    void onCoverError(QNetworkReply::NetworkError);
40
+    
41
+private:
42
+    QString artist;
43
+    QString title;
44
+    QUrl coverUrl;
45
+    int duration;
46
+    QPixmap cover;
47
+
48
+    QNetworkAccessManager* mgr;
49
+    int tries;
50
+};
51
+
52
+#endif // SONG_H

+ 22
- 0
verticalscrollarea.cpp Visa fil

@@ -0,0 +1,22 @@
1
+#include "verticalscrollarea.h"
2
+#include <QVBoxLayout>
3
+
4
+VerticalScrollArea::VerticalScrollArea(QWidget *parent) : QScrollArea(parent)
5
+{
6
+    setWidgetResizable(true);
7
+}
8
+
9
+void VerticalScrollArea::setWidget(QWidget *widget)
10
+{
11
+    if(widget != 0)
12
+        widget->installEventFilter(this);
13
+    QScrollArea::setWidget(widget);
14
+}
15
+
16
+bool VerticalScrollArea::eventFilter(QObject *o, QEvent *e)
17
+{
18
+    if(o == widget() && e->type() == QEvent::Resize)
19
+        setMinimumWidth(widget()->minimumSizeHint().width() + verticalScrollBar()->width());
20
+
21
+    return false;
22
+}

+ 21
- 0
verticalscrollarea.h Visa fil

@@ -0,0 +1,21 @@
1
+#ifndef VERTICALSCROLLAREA_H
2
+#define VERTICALSCROLLAREA_H
3
+
4
+#include <QScrollArea>
5
+#include <QEvent>
6
+#include <QScrollBar>
7
+
8
+class VerticalScrollArea : public QScrollArea
9
+{
10
+    Q_OBJECT
11
+public:
12
+    explicit VerticalScrollArea(QWidget *parent = 0);
13
+    
14
+    void setWidget(QWidget *widget);
15
+
16
+protected:
17
+    bool eventFilter(QObject *o, QEvent *e);
18
+    
19
+};
20
+
21
+#endif // VERTICALSCROLLAREA_H

Laddar…
Avbryt
Spara