From 83b88220e69ab88edb7808397661f20f3311d55c Mon Sep 17 00:00:00 2001 From: 0xFEEDC0DE64 <0xFEEDC0DE64@gmail.com> Date: Sun, 16 Sep 2018 05:30:24 +0200 Subject: [PATCH] Imported existing sources --- DbRadioDumper.pro | 22 +++++++++ dumpjob.cpp | 123 ++++++++++++++++++++++++++++++++++++++++++++++ dumpjob.h | 45 +++++++++++++++++ main.cpp | 21 ++++++++ 4 files changed, 211 insertions(+) create mode 100644 DbRadioDumper.pro create mode 100644 dumpjob.cpp create mode 100644 dumpjob.h create mode 100644 main.cpp diff --git a/DbRadioDumper.pro b/DbRadioDumper.pro new file mode 100644 index 0000000..476beaf --- /dev/null +++ b/DbRadioDumper.pro @@ -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) diff --git a/dumpjob.cpp b/dumpjob.cpp new file mode 100644 index 0000000..332290b --- /dev/null +++ b/dumpjob.cpp @@ -0,0 +1,123 @@ +#include "dumpjob.h" + +#include +#include +#include +#include + +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; + } + } + } + + +} diff --git a/dumpjob.h b/dumpjob.h new file mode 100644 index 0000000..2101539 --- /dev/null +++ b/dumpjob.h @@ -0,0 +1,45 @@ +#ifndef DUMPJOB_H +#define DUMPJOB_H + +#include +#include +#include +#include + +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 diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..ea0a7c1 --- /dev/null +++ b/main.cpp @@ -0,0 +1,21 @@ +#include + +#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(); +}