diff -urN mythmusic/mythmusic/mythmusic.pro mythmusic-local/mythmusic/mythmusic.pro --- mythmusic/mythmusic/mythmusic.pro 2003-10-05 13:17:51.000000000 +0200 +++ mythmusic-local/mythmusic/mythmusic.pro 2003-09-29 15:59:19.000000000 +0200 @@ -29,7 +29,7 @@ HEADERS += audiooutput.h buffer.h cddecoder.h cdrip.h constants.h databasebox.h HEADERS += decoder.h flacdecoder.h flacencoder.h maddecoder.h mainvisual.h HEADERS += metadata.h playbackbox.h playlist.h polygon.h output.h recycler.h -HEADERS += streaminput.h synaesthesia.h encoder.h visualize.h +HEADERS += streaminput.h shoutcaststream.h synaesthesia.h encoder.h visualize.h HEADERS += treecheckitem.h visual.h vorbisdecoder.h vorbisencoder.h polygon.h HEADERS += bumpscope.h globalsettings.h lameencoder.h HEADERS += goom/filters.h goom/goomconfig.h goom/goom_core.h goom/graphic.h @@ -39,7 +39,8 @@ SOURCES += audiooutput.cpp cddecoder.cpp cdrip.cpp databasebox.cpp decoder.cpp SOURCES += flacdecoder.cpp flacencoder.cpp maddecoder.cpp main.cpp SOURCES += mainvisual.cpp metadata.cpp playbackbox.cpp playlist.cpp output.cpp -SOURCES += recycler.cpp streaminput.cpp encoder.cpp resample.c +SOURCES += recycler.cpp streaminput.cpp shoutcaststream.cpp +SOURCES += encoder.cpp resample.c SOURCES += synaesthesia.cpp treecheckitem.cpp vorbisdecoder.cpp lameencoder.cpp SOURCES += vorbisencoder.cpp visualize.cpp bumpscope.cpp globalsettings.cpp SOURCES += goom/filters.c goom/goom_core.c goom/graphic.c goom/tentacle3d.c diff -urN mythmusic/mythmusic/playbackbox.cpp mythmusic-local/mythmusic/playbackbox.cpp --- mythmusic/mythmusic/playbackbox.cpp 2003-10-05 13:17:51.000000000 +0200 +++ mythmusic-local/mythmusic/playbackbox.cpp 2003-10-05 12:14:34.000000000 +0200 @@ -7,9 +7,9 @@ #include "metadata.h" #include "audiooutput.h" #include "constants.h" -#include "streaminput.h" #include "output.h" #include "decoder.h" +#include "streaminput.h" #include "playbackbox.h" #include "databasebox.h" #include "mainvisual.h" @@ -531,9 +531,6 @@ return; } - QUrl sourceurl(playfile); - QString sourcename(playfile); - bool startoutput = false; if (!output) @@ -558,25 +555,57 @@ return; } - if (!sourceurl.isLocalFile()) +/* + switch StreamInput::supports(playfile) { + case kLocalFile: + input = new QFile(playfile); + break; + case kShoutcast: + stream = new ShoutcastStream(); + // decoder is selected by file extension + playfile = "blah.mp3"; + break; + default: + break; + } +*/ +/* + if (stream) { + if (stream->initialize()) + { + cout << "stream inited" << endl; + if (stream->start()) + input = stream->getSocket(); + if (!input) + cout << "stream not started" << endl; + } + } +*/ + input = new StreamInput(playfile); + + cout << "'" << playfile.ascii() << "'" << endl; // DEBUG + + if (! input->type()) { - StreamInput streaminput(sourceurl); - streaminput.setup(); - input = streaminput.socket(); - } - else - input = new QFile(playfile); + VERBOSE(VB_PLAYBACK, QString("mythmusic: error reading input " + "file/stream: '%1'").arg(playfile)); + stopAll(); + return; + } + + // filename extension of playfile selects decoder + playfile = input->name(); - if (decoder && !decoder->factory()->supports(sourcename)) + if (decoder && !decoder->factory()->supports(playfile)) decoder = 0; if (!decoder) { - decoder = Decoder::create(sourcename, input, output); + decoder = Decoder::create(playfile, input, output); if (!decoder) { - printf("mythmusic: unsupported fileformat\n"); + VERBOSE(VB_PLAYBACK, "mythmusic: unsupported audioformat"); stopAll(); return; } diff -urN mythmusic/mythmusic/playbackbox.h mythmusic-local/mythmusic/playbackbox.h --- mythmusic/mythmusic/playbackbox.h 2003-08-26 17:45:18.000000000 +0200 +++ mythmusic-local/mythmusic/playbackbox.h 2003-10-04 18:55:52.000000000 +0200 @@ -15,6 +15,7 @@ class Output; class Decoder; +class StreamInput; class PlaybackBox : public MythThemedDialog { @@ -80,7 +81,7 @@ void CycleVisualizer(void); - QIODevice *input; + StreamInput *input; Output *output; Decoder *decoder; diff -urN mythmusic/mythmusic/shoutcaststream.cpp mythmusic-local/mythmusic/shoutcaststream.cpp --- mythmusic/mythmusic/shoutcaststream.cpp 1970-01-01 01:00:00.000000000 +0100 +++ mythmusic-local/mythmusic/shoutcaststream.cpp 2003-10-05 13:00:56.000000000 +0200 @@ -0,0 +1,151 @@ +#include +#include +#include +#include + +#include +using namespace std; + +#include "streaminput.h" +#include "shoutcaststream.h" +#include "mythtv/mythcontext.h" + +ShoutcastStream::ShoutcastStream(QUrl *url) + : QSocket() +{ + kconnected = 0; + streamurl = *url; + cout << "new shoutcast\n"; //DEBUG +} + +bool ShoutcastStream::initialize() +{ + cout << "shoutcast: initialize\n"; //DEBUG + if (!streamurl.isValid()) + { + return false; + } + else + { + if (streamurl.protocol() == "shoutcast") + { + streamurl.setProtocol("http"); + } + else + return false; + if (!streamurl.hasPort()) + streamurl.setPort(80); + } + return true; +} + +bool ShoutcastStream::start() +{ + QString request; + + request = "GET " + streamurl.path().utf8() + " HTTP/1.0" + "\r\n"; + request += "Host: " + streamurl.host().utf8() + "\r\n"; + request += "User-Agent: xmms/1.2.7\r\n"; + request += "\r\n"; + + cout << "shoutcast: start '" << request.ascii() << "'\n"; //DEBUG + + for (int i = 0; i < 3; i++) + { + if (openSocket()) + break; + } + if (state() != QSocket::Connected) + { + VERBOSE(VB_NETWORK, QString("Couldn't connect to: '%1'").arg(streamurl.host())); + return false; + } + VERBOSE(VB_NETWORK, QString("Connected to: '%1'").arg(streamurl.host())); + sendRequest(request); + if (readlineSocket(request)) + { + cout << request.ascii() << endl; + if (request != "ICY 200 OK\r\n") + return false; + else + { + while (bytesAvailable() < 65536) + usleep(100); + } + } + else + return false; + + kconnected = 1; + return true ; +} + +bool ShoutcastStream::openSocket() +{ + QString host = streamurl.host(); + int port = streamurl.port(); + + qApp->lock(); + //socket = new QSocket(); + connectToHost(host, port); + qApp->unlock(); + + int i = 0; + while (state() == QSocket::HostLookup || + state() == QSocket::Connecting) + { + qApp->processEvents(); + + i++; + if (i > 500) + break; + usleep(50); + } + + if (state() != QSocket::Connected) + return false; + return true; +} + +void ShoutcastStream::sendRequest(const QString request) +{ + writeBlock(request, request.length()); + flush(); + printf("\'%s\'",request.ascii()); //DEBUG +} + +bool ShoutcastStream::readlineSocket(QString &request) +{ + int i = 0; + while (state() == QSocket::Connected) + { + if (canReadLine()) + { + request = readLine(); + return true; + } + i++; + if (i > 500) + break; + usleep(50); + } + return false; +} + +Q_LONG ShoutcastStream::readBlock(char *data, long unsigned maxlen) +{ + cout << "shoutcast: readBlock\n"; //DEBUG + if (! kconnected) + { + cout << "shoutcast: readBlock N/C\n"; //DEBUG + if (initialize()) + { + if (! start()) + return -1; + } + else + return -1; + } + return QSocket::readBlock(data, maxlen); +} + diff -urN mythmusic/mythmusic/shoutcaststream.h mythmusic-local/mythmusic/shoutcaststream.h --- mythmusic/mythmusic/shoutcaststream.h 1970-01-01 01:00:00.000000000 +0100 +++ mythmusic-local/mythmusic/shoutcaststream.h 2003-10-05 12:49:31.000000000 +0200 @@ -0,0 +1,29 @@ +#ifndef SHOUTCASTSTREAM_H +#define SHOUTCASTSTREAM_H + +#include +#include +#include + +class ShoutcastStream : public QSocket +{ + public: + ShoutcastStream(QUrl *url); + + Q_LONG readBlock(char *data, Q_ULONG maxlen); + + private: + bool initialize(); + bool start(); + + bool openSocket(); + void closeSocket(); + void sendRequest(const QString request); + bool readlineSocket(QString &request); + + bool kconnected; + QUrl streamurl; + //QSocket *socket; + +}; +#endif diff -urN mythmusic/mythmusic/streaminput.cpp mythmusic-local/mythmusic/streaminput.cpp --- mythmusic/mythmusic/streaminput.cpp 2003-10-05 13:17:51.000000000 +0200 +++ mythmusic-local/mythmusic/streaminput.cpp 2003-10-05 12:36:07.000000000 +0200 @@ -4,118 +4,171 @@ // warranty, or liability of any kind. // -#include "streaminput.h" +// modified 09/2003 by Stefan Frank +// - added shoutcast streaming audio support -#include +//#include +//#include +#include #include +#include +#include +#include +using namespace std; +#include "streaminput.h" +#include "shoutcaststream.h" -StreamInput::StreamInput(const QUrl &source) - : request(0), url(source), sock(0), stage(0) +StreamInput::StreamInput(QString playfile) { -} + mediatype = ""; + medianame = ""; + device = NULL; + QUrl url(playfile); -void StreamInput::setup() -{ - if (! url.isValid()) - return; + cout << "new streaminput '" << playfile.ascii() << "'\n"; //DEBUG + if ( url.isValid()) + { + streamurl = url; + QString proto = url.protocol(); + medianame = playfile; + mediatype = "remote"; - QString protocol = url.protocol(); - QString host = url.host(); - QString path = url.path(); - int port = url.port(); + if (url.isLocalFile()) + { + mediatype = "local"; + device = new QFile(playfile); + } + else if (proto == "shoutcast") + { + medianame = "blah.mp3"; + device = new ShoutcastStream(&url); + } +/* + else if (proto == "icecast") + { + medianame = "blah.ogg"; + device = new IcecastStream(playfile); + } +*/ + } +} - if (protocol != "mqp" || host.isNull()) - return; +StreamInput::~StreamInput() +{ + delete device; +} +/* +bool StreamInput::openSocket(QUrl *source) +{ + QString host = source->host(); + int port = source->port(); + + qApp->lock(); + socket = new QSocket(); + socket->connectToHost(host, port); + qApp->unlock(); - if (port == -1) - port = 42666; + int i = 0; + while (socket->state() == QSocket::HostLookup || + socket->state() == QSocket::Connecting) + { + qApp->processEvents(); - request = ".song " + path.utf8() + "\r\n"; + i++; + if (i > 500) + break; + usleep(50); + } + + if (socket->state() != QSocket::Connected) + return false; + return true; +} +void StreamInput::closeSocket() +{ + socket->close(); + delete socket; - sock = new QSocket; - connect(sock, SIGNAL(error(int)), this, SLOT(error(int))); - connect(sock, SIGNAL(hostFound()), this, SLOT(hostfound())); - connect(sock, SIGNAL(connected()), this, SLOT(connected())); - connect(sock, SIGNAL(readyRead()), this, SLOT(readyread())); +} - sock->connectToHost(host, port); - while (stage != -1 && stage < 4) { - qDebug("processing one event: stage %d %d %ld", - stage, sock->canReadLine(), sock->bytesAvailable()); - qApp->processOneEvent(); - } +void StreamInput::sendRequest(const QString request) +{ + socket->writeBlock(request, request.length()); + socket->flush(); + printf("\'%s\'",request.ascii()); //DEBUG +} - qDebug("disconnecting from socket"); - disconnect(sock, SIGNAL(error(int)), this, SLOT(error(int))); - disconnect(sock, SIGNAL(hostFound()), this, SLOT(hostfound())); - disconnect(sock, SIGNAL(connected()), this, SLOT(connected())); - disconnect(sock, SIGNAL(readyRead()), this, SLOT(readyread())); - - if (stage == -1) { - // some sort of error - delete sock; - sock = 0; +bool StreamInput::readlineSocket(QString &request) +{ + int i = 0; + while (socket->state() == QSocket::Connected) + { + if (socket->canReadLine()) + { + request = socket->readLine(); + return true; + } + i++; + if (i > 500) + break; + usleep(50); } + return false; } - - -void StreamInput::hostfound() +*/ +bool StreamInput::open(int mode) { - qDebug("host found"); - stage = 1; + if (mediatype == "local") + return device->open(mode); + return true; } - -void StreamInput::connected() +void StreamInput::close() { - qDebug("connected... sending request '%s' %d", request.data(), request.length()); - - sock->writeBlock(request.data(), request.length()); - sock->flush(); - - stage = 2; + device->close(); } - -void StreamInput::readyread() +void StreamInput::flush() { - if (stage == 2) { - qDebug("readyread... checking response"); - - if (! sock->canReadLine()) { - stage = -1; - qDebug("can't read line"); - return; - } + device->flush(); +} - QString line = sock->readLine(); - if (line.isEmpty()) { - stage = -1; - qDebug("line is empty"); - return; - } +Q_ULONG StreamInput::size() const +{ + return device->size(); +} - if (line.left(5) != "*GOOD") { - qDebug("server error response: %s", line.latin1()); - stage = -1; - return; - } +Q_LONG StreamInput::readBlock(char *data, Q_ULONG maxlen ) +{ + cout << "streaminput: readBlock\n"; //DEBUG + return device->readBlock(data, maxlen); +} - stage = 3; - } else if (sock->bytesAvailable() > 65536 || sock->atEnd()) { - stage = 4; - } +Q_LONG StreamInput::writeBlock(const char *data, Q_ULONG len) +{ + return device->writeBlock(data, len); } +Q_LONG StreamInput::readLine(char *data, Q_ULONG maxlen) +{ + return device->readLine(data, maxlen); +} -void StreamInput::error(int err) +int StreamInput::getch() { - qDebug("socket error: %d", err); + return device->getch(); +} - stage = -1; +int StreamInput::putch(int ch) +{ + return device->putch(ch); } +int StreamInput::ungetch(int ch) +{ + return device->ungetch(ch); +} diff -urN mythmusic/mythmusic/streaminput.h mythmusic-local/mythmusic/streaminput.h --- mythmusic/mythmusic/streaminput.h 2003-10-05 13:17:51.000000000 +0200 +++ mythmusic-local/mythmusic/streaminput.h 2003-10-05 12:16:36.000000000 +0200 @@ -7,35 +7,46 @@ #ifndef INPUT_H #define INPUT_H -class StreamInput; - +#include #include #include - -class StreamInput : public QObject +class StreamInput : public QIODevice { - Q_OBJECT -public: - StreamInput(const QUrl &); - - QIODevice *socket() { return sock; } - - void setup(); - - -private slots: - void hostfound(); - void connected(); - void readyread(); - void error(int); - - -private: - QCString request; - QUrl url; - QSocket *sock; - int stage; + public: + StreamInput(QString playfile); + ~StreamInput(); + + bool open( int mode ); + void close(); + void flush(); + + Q_ULONG size() const; + + Q_LONG readBlock( char *data, Q_ULONG maxlen ); + Q_LONG writeBlock( const char *data, Q_ULONG len ); + Q_LONG readLine( char *data, Q_ULONG maxlen ); + + int getch(); + int putch( int ch); + int ungetch( int ch); + + QString type() { return mediatype; } + QString name() { return medianame; } + //virtual bool initialize() = 0; + //virtual bool start() = 0; + + private: +/* + bool openSocket(QUrl *source); + void closeSocket(); + void sendRequest(const QString request); + bool readlineSocket(QString &request); +*/ + QIODevice *device; + QUrl streamurl; + QString mediatype; + QString medianame; };