-rw-r--r-- | core/multimedia/opieplayer/libmad/libmadplugin.cpp | 189 | ||||
-rw-r--r-- | core/multimedia/opieplayer/libmad/libmadplugin.h | 9 |
2 files changed, 193 insertions, 5 deletions
diff --git a/core/multimedia/opieplayer/libmad/libmadplugin.cpp b/core/multimedia/opieplayer/libmad/libmadplugin.cpp index 8ede537..0fcc230 100644 --- a/core/multimedia/opieplayer/libmad/libmadplugin.cpp +++ b/core/multimedia/opieplayer/libmad/libmadplugin.cpp @@ -33,8 +33,16 @@ #include <assert.h> #include <qapplication.h> #include <qpe/config.h> +// for network handling +#include <netinet/in.h> +#include <netdb.h> +#include <sys/socket.h> +#include <arpa/inet.h> +#include <unistd.h> + + //#define HAVE_MMAP #if defined(HAVE_MMAP) # include <sys/mman.h> @@ -159,13 +167,182 @@ bool LibMadPlugin::isFileSupported( const QString& path ) { return TRUE; if ( strncasecmp(ext, ".mp3", 4) == 0 ) return TRUE; } + // UGLY - just for fast testing + if ( path.left(4) == "http") { + return TRUE; + } + return FALSE; } +int LibMadPlugin::tcp_open(char *address, int port) { + struct sockaddr_in stAddr; + struct hostent *host; + int sock; + struct linger l; + + memset(&stAddr, 0, sizeof(stAddr)); + stAddr.sin_family = AF_INET; + stAddr.sin_port = htons(port); + + if ((host = gethostbyname(address)) == NULL) + return (0); + + stAddr.sin_addr = *((struct in_addr *)host->h_addr_list[0]); + + if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) + return (0); + + l.l_onoff = 1; + l.l_linger = 5; + if (setsockopt(sock, SOL_SOCKET, SO_LINGER, (char *)&l, sizeof(l)) < 0) + return (0); + + if (connect(sock, (struct sockaddr *)&stAddr, sizeof(stAddr)) < 0) + return (0); + + return (sock); +} + + +/** + * Read a http line header. + * This function read character by character. + * @param tcp_sock the socket use to read the stream + * @param buf a buffer to receive the data + * @param size size of the buffer + * @return the size of the stream read or -1 if an error occured + */ +int LibMadPlugin::http_read_line(int tcp_sock, char *buf, int size) { + int offset = 0; + + do + { + if (std::read(tcp_sock, buf + offset, 1) < 0) + return -1; + if (buf[offset] != '\r') /* Strip \r from answer */ + offset++; + } + while (offset < size - 1 && buf[offset - 1] != '\n'); + + buf[offset] = 0; + return offset; +} + +int LibMadPlugin::http_open(const QString& path ) { + char *host; + int port; + char *request; + int tcp_sock; + char http_request[PATH_MAX]; + char filename[PATH_MAX]; + char c; + char *arg =strdup(path.latin1()); + + /* Check for URL syntax */ + if (strncmp(arg, "http://", strlen("http://"))) + return (0); + + /* Parse URL */ + port = 80; + host = arg + strlen("http://"); + if ((request = strchr(host, '/')) == NULL) + return (0); + *request++ = 0; + + if (strchr(host, ':') != NULL) /* port is specified */ + { + port = atoi(strchr(host, ':') + 1); + *strchr(host, ':') = 0; + } + + /* Open a TCP socket */ + if (!(tcp_sock = tcp_open(host, port))) + { + perror("http_open"); + return (0); + } + + snprintf(filename, sizeof(filename) - strlen(host) - 75, "%s", request); + + /* Send HTTP GET request */ + /* Please don't use a Agent know by shoutcast (Lynx, Mozilla) seems to be reconized and print + * a html page and not the stream */ + snprintf(http_request, sizeof(http_request), "GET /%s HTTP/1.0\r\n" +/* "User-Agent: Mozilla/2.0 (Win95; I)\r\n" */ + "Pragma: no-cache\r\n" "Host: %s\r\n" "Accept: */*\r\n" "\r\n", filename, host); + + send(tcp_sock, http_request, strlen(http_request), 0); + + /* Parse server reply */ +#if 0 + do + read(tcp_sock, &c, sizeof(char)); + while (c != ' '); + read(tcp_sock, http_request, 4 * sizeof(char)); + http_request[4] = 0; + if (strcmp(http_request, "200 ")) + { + fprintf(stderr, "http_open: "); + do + { + read(tcp_sock, &c, sizeof(char)); + fprintf(stderr, "%c", c); + } + while (c != '\r'); + fprintf(stderr, "\n"); + return (0); + } +#endif + + do + { + int len; + + len = http_read_line(tcp_sock, http_request, sizeof(http_request)); + + if (len == -1) + { + fprintf(stderr, "http_open: %s\n", strerror(errno)); + return 0; + } + + if (strncmp(http_request, "Location:", 9) == 0) + { + /* redirect */ + std::close(tcp_sock); + + http_request[strlen(http_request) - 1] = '\0'; + + return http_open(&http_request[10]); + } + + if (strncmp(http_request, "ICY ", 4) == 0) + { + /* This is icecast streaming */ + if (strncmp(http_request + 4, "200 ", 4)) + { + fprintf(stderr, "http_open: %s\n", http_request); + return 0; + } + } + else if (strncmp(http_request, "icy-", 4) == 0) + { + /* we can have: icy-noticeX, icy-name, icy-genre, icy-url, icy-pub, icy-metaint, icy-br */ + /* Don't print these - mpg123 doesn't */ + /* fprintf(stderr,"%s\n",http_request); */ + } + } + while (strcmp(http_request, "\n") != 0); + + return (tcp_sock); +} + + bool LibMadPlugin::open( const QString& path ) { debugMsg( "LibMadPlugin::open" ); Config cfg("MediaPlayer"); cfg.setGroup("Options"); @@ -176,10 +353,16 @@ bool LibMadPlugin::open( const QString& path ) { info = QString( "" ); //qDebug( "Opening %s", path.latin1() ); - d->input.path = path.latin1(); - d->input.fd = ::open( d->input.path, O_RDONLY ); + + if (path.left( 4 ) == "http" ) { + d->input.fd = http_open(path); + + } else { + d->input.path = path.latin1(); + d->input.fd = ::open( d->input.path, O_RDONLY ); + } if (d->input.fd == -1) { qDebug("error opening %s", d->input.path ); return FALSE; } @@ -495,9 +678,9 @@ bool LibMadPlugin::audioReadStereoSamples( short *output, long samples, long& sa bool LibMadPlugin::audioReadSamples( short *output, int /*channels*/, long samples, long& samplesMade, int ) { debugMsg( "LibMadPlugin::audioReadStereoSamples" ); static bool needInput = TRUE; - + if ( samples == 0 ) return FALSE; do { diff --git a/core/multimedia/opieplayer/libmad/libmadplugin.h b/core/multimedia/opieplayer/libmad/libmadplugin.h index 46cd4a1..ee1ca9d 100644 --- a/core/multimedia/opieplayer/libmad/libmadplugin.h +++ b/core/multimedia/opieplayer/libmad/libmadplugin.h @@ -16,9 +16,9 @@ ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ -#ifndef LIBMAD_PLUGIN_H +#ifndef LIBMAD_PLUGIN_H #define LIBMAD_PLUGIN_H #include <qstring.h> #include <qpe/mediaplayerplugininterface.h> @@ -42,15 +42,16 @@ public: double pluginVersion() { return 1.0; } bool isFileSupported( const QString& ); bool open( const QString& ); + bool close(); bool isOpen(); const QString &fileInfo() { return info; } // If decoder doesn't support audio then return 0 here int audioStreams(); - int audioChannels( int stream ); + int audioChannels( int stream ); int audioFrequency( int stream ); int audioSamples( int stream ); bool audioSetSample( long sample, int stream ); /* int audioBitsPerSample(int) {return 0;} */ @@ -100,8 +101,12 @@ public: long getPlayTime() { return -1; } private: + int tcp_open(char *address, int port); + int http_read_line(int tcp_sock, char *buf, int size) ; + int http_open(const QString& path ); + LibMadPluginData *d; QString info; int bufferSize; }; |