Imported existing sources
This commit is contained in:
22
DbRadioDumper.pro
Normal file
22
DbRadioDumper.pro
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
QT += core network
|
||||||
|
QT -= gui widgets
|
||||||
|
|
||||||
|
DBLIBS +=
|
||||||
|
|
||||||
|
TARGET = radiodumper
|
||||||
|
|
||||||
|
PROJECT_ROOT = ..
|
||||||
|
|
||||||
|
SOURCES += main.cpp \
|
||||||
|
dumpjob.cpp
|
||||||
|
|
||||||
|
HEADERS += \
|
||||||
|
dumpjob.h
|
||||||
|
|
||||||
|
FORMS +=
|
||||||
|
|
||||||
|
RESOURCES +=
|
||||||
|
|
||||||
|
TRANSLATIONS +=
|
||||||
|
|
||||||
|
include($${PROJECT_ROOT}/app.pri)
|
123
dumpjob.cpp
Normal file
123
dumpjob.cpp
Normal file
@@ -0,0 +1,123 @@
|
|||||||
|
#include "dumpjob.h"
|
||||||
|
|
||||||
|
#include <QTcpSocket>
|
||||||
|
#include <QFile>
|
||||||
|
#include <QTimer>
|
||||||
|
#include <QDateTime>
|
||||||
|
|
||||||
|
const QByteArray DumpJob::m_userAgent = QByteArrayLiteral("Wieder ein Stream-Dumper!");
|
||||||
|
QDir DumpJob::m_outputDir("radio");
|
||||||
|
|
||||||
|
DumpJob::DumpJob(const QByteArray &jobName, const QByteArray &hostName, quint16 port, const QByteArray &path, QObject *parent) :
|
||||||
|
QObject(parent),
|
||||||
|
m_jobName(jobName),
|
||||||
|
m_hostName(hostName),
|
||||||
|
m_port(port),
|
||||||
|
m_path(path),
|
||||||
|
m_socket(Q_NULLPTR),
|
||||||
|
m_file(Q_NULLPTR),
|
||||||
|
m_jobDir(m_outputDir.absoluteFilePath(jobName))
|
||||||
|
{
|
||||||
|
reconnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DumpJob::reconnect()
|
||||||
|
{
|
||||||
|
if(m_socket)
|
||||||
|
{
|
||||||
|
disconnect(m_socket, &QAbstractSocket::stateChanged, this, &DumpJob::stateChanged);
|
||||||
|
m_socket->deleteLater();
|
||||||
|
}
|
||||||
|
if(m_file)
|
||||||
|
m_file->deleteLater();
|
||||||
|
m_file = Q_NULLPTR;
|
||||||
|
|
||||||
|
qDebug() << "[" << m_jobName << "] connecting to" << m_hostName << m_port;
|
||||||
|
|
||||||
|
m_socket = new QTcpSocket(this);
|
||||||
|
connect(m_socket, &QAbstractSocket::connected, this, &DumpJob::connected);
|
||||||
|
connect(m_socket, &QAbstractSocket::stateChanged, this, &DumpJob::stateChanged);
|
||||||
|
m_socket->connectToHost(m_hostName, m_port);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DumpJob::connected()
|
||||||
|
{
|
||||||
|
qDebug() << "[" << m_jobName << "] connected!";
|
||||||
|
|
||||||
|
m_firstHeader = true;
|
||||||
|
|
||||||
|
connect(m_socket, &QTcpSocket::readyRead, this, &DumpJob::readyRead);
|
||||||
|
|
||||||
|
m_socket->write(QByteArrayLiteral("GET "));
|
||||||
|
m_socket->write(m_path);
|
||||||
|
m_socket->write(QByteArrayLiteral(" HTTP/1.1\r\nHost: "));
|
||||||
|
m_socket->write(m_hostName);
|
||||||
|
m_socket->write(QByteArrayLiteral("\r\nUser-Agent: "));
|
||||||
|
m_socket->write(m_userAgent);
|
||||||
|
m_socket->write(QByteArrayLiteral("\r\nConnection: close\r\n\r\n"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void DumpJob::stateChanged(QAbstractSocket::SocketState state)
|
||||||
|
{
|
||||||
|
if(state == QAbstractSocket::UnconnectedState)
|
||||||
|
{
|
||||||
|
qDebug() << "[" << m_jobName << "] lost connection";
|
||||||
|
QTimer::singleShot(1000, this, &DumpJob::reconnect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DumpJob::readyRead()
|
||||||
|
{
|
||||||
|
if(m_file)
|
||||||
|
{
|
||||||
|
m_file->write(m_socket->readAll());
|
||||||
|
|
||||||
|
quint64 ts = QDateTime::currentMSecsSinceEpoch();
|
||||||
|
ts -= ts % 3600000;
|
||||||
|
if(m_lastTs != ts)
|
||||||
|
{
|
||||||
|
qDebug() << "[" << m_jobName << "] split file";
|
||||||
|
reconnect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_buffer.append(m_socket->readAll());
|
||||||
|
int index;
|
||||||
|
while((index = m_buffer.indexOf(QByteArrayLiteral("\r\n"))) != -1)
|
||||||
|
{
|
||||||
|
auto line = QString(m_buffer.left(index));
|
||||||
|
m_buffer.remove(0, index+2);
|
||||||
|
|
||||||
|
if(line.isEmpty())
|
||||||
|
{
|
||||||
|
if(!m_jobDir.mkpath(m_jobDir.absolutePath()))
|
||||||
|
qFatal("could not create directory!");
|
||||||
|
|
||||||
|
m_lastTs = QDateTime::currentMSecsSinceEpoch();
|
||||||
|
m_lastTs -= m_lastTs % 3600000;
|
||||||
|
|
||||||
|
m_file = new QFile(m_jobDir.absoluteFilePath(QString("%0_%1.mp3")
|
||||||
|
.arg(QString(m_jobName))
|
||||||
|
.arg(QDateTime::fromMSecsSinceEpoch(m_lastTs).toString(Qt::ISODate).replace("T", "_").replace(":", "-"))
|
||||||
|
), this);
|
||||||
|
if(!m_file->open(QIODevice::WriteOnly))
|
||||||
|
qCritical() << m_file->errorString();
|
||||||
|
|
||||||
|
m_file->write(m_buffer);
|
||||||
|
m_buffer.clear();
|
||||||
|
|
||||||
|
qDebug() << "[" << m_jobName << "] started dump";
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if(m_firstHeader)
|
||||||
|
{
|
||||||
|
qDebug() << "[" << m_jobName << "] " << line;
|
||||||
|
m_firstHeader = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
45
dumpjob.h
Normal file
45
dumpjob.h
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
#ifndef DUMPJOB_H
|
||||||
|
#define DUMPJOB_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QByteArray>
|
||||||
|
#include <QDir>
|
||||||
|
#include <QAbstractSocket>
|
||||||
|
|
||||||
|
class QTcpSocket;
|
||||||
|
class QFile;
|
||||||
|
|
||||||
|
class DumpJob : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit DumpJob(const QByteArray &jobName, const QByteArray &hostName, quint16 port, const QByteArray &path, QObject *parent = 0);
|
||||||
|
|
||||||
|
public Q_SLOTS:
|
||||||
|
void reconnect();
|
||||||
|
|
||||||
|
private Q_SLOTS:
|
||||||
|
void connected();
|
||||||
|
void stateChanged(QAbstractSocket::SocketState state);
|
||||||
|
void readyRead();
|
||||||
|
|
||||||
|
private:
|
||||||
|
const QByteArray m_jobName;
|
||||||
|
const QByteArray m_hostName;
|
||||||
|
const quint16 m_port;
|
||||||
|
const QByteArray m_path;
|
||||||
|
|
||||||
|
QTcpSocket *m_socket;
|
||||||
|
QFile *m_file;
|
||||||
|
|
||||||
|
bool m_firstHeader;
|
||||||
|
QByteArray m_buffer;
|
||||||
|
QDir m_jobDir;
|
||||||
|
|
||||||
|
quint64 m_lastTs;
|
||||||
|
|
||||||
|
static const QByteArray m_userAgent;
|
||||||
|
static QDir m_outputDir;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // DUMPJOB_H
|
21
main.cpp
Normal file
21
main.cpp
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
#include <QCoreApplication>
|
||||||
|
|
||||||
|
#include "dumpjob.h"
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
QCoreApplication app(argc, argv);
|
||||||
|
|
||||||
|
new DumpJob("TechnoBase.FM", "lw1.mp3.tb-group.fm", 80, "/tb.mp3");
|
||||||
|
new DumpJob("HouseTime.FM", "lw1.mp3.tb-group.fm", 80, "/ht.mp3");
|
||||||
|
new DumpJob("HardBase.FM", "lw1.mp3.tb-group.fm", 80, "/hb.mp3");
|
||||||
|
new DumpJob("TranceBase.FM", "lw1.mp3.tb-group.fm", 80, "/trb.mp3");
|
||||||
|
new DumpJob("CoreTime.FM", "lw1.mp3.tb-group.fm", 80, "/ct.mp3");
|
||||||
|
new DumpJob("ClubTime.FM", "lw1.mp3.tb-group.fm", 80, "/clt.mp3");
|
||||||
|
new DumpJob("TeaTime.FM", "lw1.mp3.tb-group.fm", 80, "/tt.mp3");
|
||||||
|
new DumpJob("Trap.FM", "stream.trap.fm", 6002, "/");
|
||||||
|
new DumpJob("Dubbase.FM", "stream.dubbase.fm", 7002, "/");
|
||||||
|
new DumpJob("DrumAndBass.FM", "stream.drumandbass.fm", 9002, "/");
|
||||||
|
|
||||||
|
return app.exec();
|
||||||
|
}
|
Reference in New Issue
Block a user