Newer
Older
/*
* Copyright (C) 2019 Kevin Whitaker <eyecreate@eyecreate.org>
*
* This program 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.
*ByteArray(jsonTrack)
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "minimediaplayer.h"
#include <QProcess>
#include <QJsonDocument>
#include <QJsonObject>
MiniMediaPlayer::MiniMediaPlayer(QObject *parent) : QObject(parent)
{
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
m_player = new QMediaPlayer(this,QMediaPlayer::StreamPlayback);
connect(m_player, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus)),this,SLOT(mediaStatusChanged(QMediaPlayer::MediaStatus)));
connect(m_player,SIGNAL(stateChanged(QMediaPlayer::State)),this,SLOT(mediaStateChanged(QMediaPlayer::State)));
connect(m_player,SIGNAL(durationChanged(qint64)),this,SLOT(durationChanged(qint64)));
connect(m_player,SIGNAL(positionChanged(qint64)),this,SLOT(positionChanged(qint64)));
}
bool MiniMediaPlayer::isPlaying()
{
return m_player->state() == QMediaPlayer::State::PlayingState;
}
bool MiniMediaPlayer::nextTrack()
{
if(playlist.size() > 1)
{
playlist.pop_front();
m_player->stop();
m_player->setMedia(getStreamUrlFromUrl(playlist.first().second));
emit playlistChanged(getTrackNames());
return true;
}
return false;
}
bool MiniMediaPlayer::playPauseTrack(bool playing)
{
if(m_player->state() == QMediaPlayer::State::PlayingState && !playing)
{
m_player->pause();
return true;
}
else if(m_player->state() == QMediaPlayer::State::PausedState && playing)
{
m_player->play();
return true;
}
return false;
}
QList<QString> MiniMediaPlayer::getTrackNames()
{
QList<QString> playlistTitles;
for(QPair<QString,QUrl> item: playlist)
{
playlistTitles.append(item.first);
}
return playlistTitles;
}
QMap<QString, qint64> MiniMediaPlayer::currentState()
{
QMap<QString,qint64> state;
state.insert("duration",m_player->duration());
state.insert("position",m_player->position());
state.insert("state",isPlaying());
return state;
}
void MiniMediaPlayer::durationChanged(qint64 length)
{
emit trackDurationChanged(length);
}
void MiniMediaPlayer::positionChanged(qint64 position)
{
emit trackPositionChanged(position);
bool MiniMediaPlayer::addURLToPlaylist(QUrl mediaUrl)
if(isValidMediaUrl(mediaUrl))
{
bool shouldStartPlaying = false;
if(playlist.size() == 0) shouldStartPlaying = true;
QList<QPair<QString,QUrl>> tracks = getStreamTitlesAndUrlsFromUrl(mediaUrl);
playlist.append(tracks);
emit playlistChanged(getTrackNames());
if(shouldStartPlaying && playlist.size() > 0)
{
m_player->setMedia(getStreamUrlFromUrl(playlist.first().second));
}
if(tracks.size() > 0)
{
return true;
}
}
return false;
QUrl MiniMediaPlayer::getStreamUrlFromUrl(QUrl mediaUrl)
//Run youtube-dl on Url and return Url given back.
QProcess youtubedl;
youtubedl.start("youtube-dl -f bestaudio -g "+mediaUrl.toString());
if(youtubedl.waitForFinished(-1))
{
QByteArray out = youtubedl.readAllStandardOutput();
QString outStr = QString::fromStdString(out.toStdString());
for(QString track:outStr.split('\n'))
{
qDebug() << "Found URL stream:" << track;
return QUrl(track);
}
}
return QUrl();
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
bool MiniMediaPlayer::isValidMediaUrl(QUrl mediaUrl)
{
//Only support youtube and bandcamp for now.
if(mediaUrl.host().endsWith("youtube.com") || mediaUrl.host().endsWith("bandcamp.com"))
{
//TODO: check more than host?
return true;
}
return false;
}
void MiniMediaPlayer::mediaStateChanged(QMediaPlayer::State state)
{
if(state == QMediaPlayer::State::PlayingState)
{
emit playStateChanged(true);
}
else
{
emit playStateChanged(false);
}
}
void MiniMediaPlayer::mediaStatusChanged(QMediaPlayer::MediaStatus status)
{
//Make sure to load next track once track has ended.
if(status == QMediaPlayer::MediaStatus::EndOfMedia)
{
//Load next track
nextTrack();
}
else if(status == QMediaPlayer::MediaStatus::InvalidMedia)
{
qWarning() << "Unable to play track.";
}
else if(status == QMediaPlayer::MediaStatus::LoadedMedia)
{
//Start playing media
m_player->play();
}
}
QList<QPair<QString,QUrl>> MiniMediaPlayer::getStreamTitlesAndUrlsFromUrl(QUrl mediaUrl)
{
QList<QPair<QString,QUrl>> tracks;
//Run youtube-dl on Url and return json given back.
QProcess youtubedl;
youtubedl.start("youtube-dl -f bestaudio -j "+mediaUrl.toString());
if(youtubedl.waitForFinished(-1))
{
//If there is anything in error output, error must have occured.
if(youtubedl.readAllStandardError().size()== 0)
{
QByteArray out = youtubedl.readAllStandardOutput();
QString outStr = QString::fromStdString(out.toStdString());
for(QString jsonTrack:outStr.split('\n'))
{
//Parse urls and titles from json list
QJsonDocument info = QJsonDocument::fromJson(jsonTrack.toUtf8());
if(!info.isNull() && info.isObject())
{
QPair<QString,QUrl> track;
QJsonObject jsonTrackInfo = info.object();
track.first = jsonTrackInfo["title"].toString();
track.second = QUrl(jsonTrackInfo["webpage_url"].toString());
tracks.append(track);
}
}
}
else
{
qWarning() << "Url may be invalid.";
}
}
return tracks;
}