2010-11-23 23:36:00 +01:00
|
|
|
/* This file is part of Clementine.
|
|
|
|
Copyright 2010, 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 "icecastbackend.h"
|
|
|
|
#include "core/database.h"
|
|
|
|
#include "core/scopedtransaction.h"
|
|
|
|
|
|
|
|
#include <QSqlQuery>
|
|
|
|
#include <QVariant>
|
|
|
|
|
|
|
|
const char* IcecastBackend::kTableName = "icecast_stations";
|
|
|
|
|
|
|
|
IcecastBackend::IcecastBackend(QObject* parent)
|
|
|
|
: QObject(parent)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2012-02-12 14:41:50 +01:00
|
|
|
void IcecastBackend::Init(Database* db) {
|
2010-11-23 23:36:00 +01:00
|
|
|
db_ = db;
|
|
|
|
}
|
|
|
|
|
2010-11-24 00:05:42 +01:00
|
|
|
QStringList IcecastBackend::GetGenresAlphabetical(const QString& filter) {
|
2010-11-23 23:36:00 +01:00
|
|
|
QStringList ret;
|
|
|
|
QMutexLocker l(db_->Mutex());
|
|
|
|
QSqlDatabase db = db_->Connect();
|
|
|
|
|
2010-11-24 00:05:42 +01:00
|
|
|
QString where = filter.isEmpty() ? "" : "WHERE name LIKE :filter";
|
|
|
|
|
|
|
|
QString sql = QString("SELECT DISTINCT genre FROM %1 %2 ORDER BY genre")
|
|
|
|
.arg(kTableName, where);
|
|
|
|
|
|
|
|
QSqlQuery q(sql, db);
|
|
|
|
if (!filter.isEmpty()) {
|
2012-02-19 14:44:33 +01:00
|
|
|
q.bindValue(":filter", QString("%" + filter + "%"));
|
2010-11-24 00:05:42 +01:00
|
|
|
}
|
|
|
|
|
2010-11-23 23:36:00 +01:00
|
|
|
q.exec();
|
2011-02-05 14:43:04 +01:00
|
|
|
if (db_->CheckErrors(q)) return ret;
|
2010-11-23 23:36:00 +01:00
|
|
|
|
|
|
|
while (q.next()) {
|
|
|
|
ret << q.value(0).toString();
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2010-11-24 00:05:42 +01:00
|
|
|
QStringList IcecastBackend::GetGenresByPopularity(const QString& filter) {
|
2010-11-23 23:36:00 +01:00
|
|
|
QStringList ret;
|
|
|
|
QMutexLocker l(db_->Mutex());
|
|
|
|
QSqlDatabase db = db_->Connect();
|
|
|
|
|
2010-11-24 00:05:42 +01:00
|
|
|
QString where = filter.isEmpty() ? "" : "WHERE name LIKE :filter";
|
|
|
|
|
|
|
|
QString sql = QString("SELECT genre, COUNT(*) AS count FROM %1 "
|
|
|
|
" %2"
|
|
|
|
" GROUP BY genre"
|
|
|
|
" ORDER BY count DESC").arg(kTableName, where);
|
|
|
|
QSqlQuery q(sql, db);
|
|
|
|
if (!filter.isEmpty()) {
|
2012-02-19 14:44:33 +01:00
|
|
|
q.bindValue(":filter", QString("%" + filter + "%"));
|
2010-11-24 00:05:42 +01:00
|
|
|
}
|
|
|
|
|
2010-11-23 23:36:00 +01:00
|
|
|
q.exec();
|
2011-02-05 14:43:04 +01:00
|
|
|
if (db_->CheckErrors(q)) return ret;
|
2010-11-23 23:36:00 +01:00
|
|
|
|
|
|
|
while (q.next()) {
|
|
|
|
ret << q.value(0).toString();
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2010-11-24 00:05:42 +01:00
|
|
|
IcecastBackend::StationList IcecastBackend::GetStations(const QString& filter,
|
|
|
|
const QString& genre) {
|
2010-11-23 23:36:00 +01:00
|
|
|
StationList ret;
|
|
|
|
QMutexLocker l(db_->Mutex());
|
|
|
|
QSqlDatabase db = db_->Connect();
|
|
|
|
|
2010-11-24 00:05:42 +01:00
|
|
|
QStringList where_clauses;
|
|
|
|
QStringList bound_items;
|
|
|
|
|
|
|
|
if (!genre.isEmpty()) {
|
|
|
|
where_clauses << "genre = :genre";
|
|
|
|
bound_items << genre;
|
|
|
|
}
|
|
|
|
if (!filter.isEmpty()) {
|
|
|
|
where_clauses << "name LIKE :filter";
|
|
|
|
bound_items << "%" + filter + "%";
|
|
|
|
}
|
|
|
|
|
2010-11-23 23:36:00 +01:00
|
|
|
QString sql = QString("SELECT name, url, mime_type, bitrate, channels,"
|
|
|
|
" samplerate, genre"
|
|
|
|
" FROM %1").arg(kTableName);
|
2010-11-24 00:05:42 +01:00
|
|
|
|
|
|
|
if (!where_clauses.isEmpty()) {
|
|
|
|
sql += " WHERE " + where_clauses.join(" AND ");
|
2010-11-23 23:36:00 +01:00
|
|
|
}
|
|
|
|
QSqlQuery q(sql, db);
|
2010-11-24 00:05:42 +01:00
|
|
|
foreach (const QString& value, bound_items) {
|
|
|
|
q.addBindValue(value);
|
2010-11-23 23:36:00 +01:00
|
|
|
}
|
2010-11-24 00:05:42 +01:00
|
|
|
|
2010-11-23 23:36:00 +01:00
|
|
|
q.exec();
|
2011-02-05 14:43:04 +01:00
|
|
|
if (db_->CheckErrors(q)) return ret;
|
2010-11-23 23:36:00 +01:00
|
|
|
|
|
|
|
while (q.next()) {
|
|
|
|
Station station;
|
|
|
|
station.name = q.value(0).toString();
|
2012-09-26 17:09:13 +02:00
|
|
|
station.url = QUrl(q.value(1).toString());
|
2010-11-23 23:36:00 +01:00
|
|
|
station.mime_type = q.value(2).toString();
|
|
|
|
station.bitrate = q.value(3).toInt();
|
|
|
|
station.channels = q.value(4).toInt();
|
|
|
|
station.samplerate = q.value(5).toInt();
|
|
|
|
station.genre = q.value(6).toString();
|
|
|
|
ret << station;
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool IcecastBackend::IsEmpty() {
|
|
|
|
QMutexLocker l(db_->Mutex());
|
|
|
|
QSqlDatabase db = db_->Connect();
|
|
|
|
QSqlQuery q(QString("SELECT ROWID FROM %1 LIMIT 1").arg(kTableName), db);
|
|
|
|
q.exec();
|
|
|
|
return !q.next();
|
|
|
|
}
|
|
|
|
|
|
|
|
void IcecastBackend::ClearAndAddStations(const StationList& stations) {
|
2010-11-24 00:10:53 +01:00
|
|
|
{
|
|
|
|
QMutexLocker l(db_->Mutex());
|
|
|
|
QSqlDatabase db = db_->Connect();
|
|
|
|
ScopedTransaction t(&db);
|
2010-11-23 23:36:00 +01:00
|
|
|
|
2010-11-24 00:10:53 +01:00
|
|
|
// Remove all existing items
|
|
|
|
QSqlQuery q(QString("DELETE FROM %1").arg(kTableName), db);
|
2010-11-23 23:36:00 +01:00
|
|
|
q.exec();
|
2011-02-05 14:43:04 +01:00
|
|
|
if (db_->CheckErrors(q)) return;
|
2010-11-23 23:36:00 +01:00
|
|
|
|
2010-11-24 00:10:53 +01:00
|
|
|
q = QSqlQuery(QString("INSERT INTO %1 (name, url, mime_type, bitrate,"
|
|
|
|
" channels, samplerate, genre)"
|
|
|
|
" VALUES (:name, :url, :mime_type, :bitrate,"
|
|
|
|
" :channels, :samplerate, :genre)")
|
|
|
|
.arg(kTableName), db);
|
|
|
|
|
|
|
|
// Add these ones
|
|
|
|
foreach (const Station& station, stations) {
|
|
|
|
q.bindValue(":name", station.name);
|
|
|
|
q.bindValue(":url", station.url);
|
|
|
|
q.bindValue(":mime_type", station.mime_type);
|
|
|
|
q.bindValue(":bitrate", station.bitrate);
|
|
|
|
q.bindValue(":channels", station.channels);
|
|
|
|
q.bindValue(":samplerate", station.samplerate);
|
|
|
|
q.bindValue(":genre", station.genre);
|
|
|
|
q.exec();
|
2011-02-05 14:43:04 +01:00
|
|
|
if (db_->CheckErrors(q)) return;
|
2010-11-24 00:10:53 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
t.Commit();
|
|
|
|
}
|
2010-11-23 23:36:00 +01:00
|
|
|
|
|
|
|
emit DatabaseReset();
|
|
|
|
}
|
2010-11-24 20:25:41 +01:00
|
|
|
|
|
|
|
Song IcecastBackend::Station::ToSong() const {
|
|
|
|
Song ret;
|
|
|
|
ret.set_valid(true);
|
|
|
|
ret.set_title(name);
|
2011-04-28 14:27:53 +02:00
|
|
|
ret.set_url(url);
|
2010-11-24 20:25:41 +01:00
|
|
|
ret.set_bitrate(bitrate);
|
|
|
|
ret.set_samplerate(samplerate);
|
|
|
|
ret.set_genre(genre);
|
2011-03-22 23:04:10 +01:00
|
|
|
ret.set_filetype(Song::Type_Stream);
|
2010-11-24 20:25:41 +01:00
|
|
|
return ret;
|
|
|
|
}
|