00001
00002
00003
00004
00005
00006
00007 #ifndef SHOUTCAST_H_
00008 #define SHOUTCAST_H_
00009
00010
00011 #include <sys/time.h>
00012 #include <time.h>
00013
00014
00015 #include <QObject>
00016 #include <QTcpSocket>
00017 #include <QBuffer>
00018 #include <QUrl>
00019 #include <QMutex>
00020
00021
00022 #include "config.h"
00023
00024
00025 #include "decoder.h"
00026 #include "decoderhandler.h"
00027
00028 class ShoutCastRequest;
00029 class ShoutCastResponse;
00030
00031 typedef QMap<QString,QString> ShoutCastMetaMap;
00032
00033 class ShoutCastIODevice : public MusicIODevice
00034 {
00035 Q_OBJECT
00036
00037 public:
00038 enum State
00039 {
00040 NOT_CONNECTED,
00041 RESOLVING,
00042 CONNECTING,
00043 CANT_RESOLVE,
00044 CANT_CONNECT,
00045 CONNECTED,
00046 WRITING_HEADER,
00047 READING_HEADER,
00048 PLAYING,
00049 STREAMING,
00050 STREAMING_META,
00051 STOPPED
00052 };
00053 static const char* stateString(const State &s);
00054
00055 ShoutCastIODevice(void);
00056 ~ShoutCastIODevice(void);
00057
00058 void connectToUrl(const QUrl &url);
00059 void close(void);
00060 bool flush(void);
00061
00062 qint64 size(void) const;
00063 qint64 pos(void) const { return 0; }
00064 qint64 bytesAvailable(void) const;
00065 bool isSequential(void) const { return true; }
00066
00067 qint64 readData(char *data, qint64 sz);
00068 qint64 writeData(const char *data, qint64 sz);
00069
00070 bool getResponse(ShoutCastResponse &response);
00071
00072 signals:
00073 void meta(const QString &metadata);
00074 void changedState(ShoutCastIODevice::State newstate);
00075
00076 private slots:
00077 void socketHostFound(void);
00078 void socketConnected(void);
00079 void socketConnectionClosed(void);
00080 void socketReadyRead(void);
00081 void socketBytesWritten(qint64 );
00082 void socketError(QAbstractSocket::SocketError error);
00083
00084 private:
00085 void switchToState(const State &s);
00086 bool parseHeader(void);
00087 bool parseMeta(void);
00088
00089
00090 ShoutCastResponse *m_response;
00091 int m_redirects;
00092 QTcpSocket *m_socket;
00093
00094
00095 QByteArray m_scratchpad;
00096 qint64 m_scratchpad_pos;
00097
00098
00099 QUrl m_url;
00100 qint64 m_bytesTillNextMeta;
00101 State m_state;
00102 QString m_last_metadata;
00103 qint64 m_bytesDownloaded;
00104 bool m_response_gotten;
00105 bool m_started;
00106 };
00107
00108 class DecoderIOFactoryShoutCast : public DecoderIOFactory
00109 {
00110 Q_OBJECT
00111
00112 public:
00113 DecoderIOFactoryShoutCast(DecoderHandler *parent);
00114 ~DecoderIOFactoryShoutCast(void);
00115
00116 void start(void);
00117 void stop(void);
00118 QIODevice *takeInput(void);
00119
00120 protected slots:
00121 void periodicallyCheckResponse(void);
00122 void periodicallyCheckBuffered(void);
00123 void shoutcastMeta(const QString &metadata);
00124 void shoutcastChangedState(ShoutCastIODevice::State newstate);
00125
00126 private:
00127 int checkResponseOK(void);
00128
00129 void makeIODevice(void);
00130 void closeIODevice(void);
00131
00132 QTimer *m_timer;
00133
00134 ShoutCastIODevice *m_input;
00135 uint m_prebuffer;
00136 };
00137
00138 #endif