-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 @@ | |||
33 | #include <assert.h> | 33 | #include <assert.h> |
34 | #include <qapplication.h> | 34 | #include <qapplication.h> |
35 | #include <qpe/config.h> | 35 | #include <qpe/config.h> |
36 | 36 | ||
37 | // for network handling | ||
38 | #include <netinet/in.h> | ||
39 | #include <netdb.h> | ||
40 | #include <sys/socket.h> | ||
41 | #include <arpa/inet.h> | ||
42 | #include <unistd.h> | ||
43 | |||
44 | |||
37 | //#define HAVE_MMAP | 45 | //#define HAVE_MMAP |
38 | 46 | ||
39 | #if defined(HAVE_MMAP) | 47 | #if defined(HAVE_MMAP) |
40 | # include <sys/mman.h> | 48 | # include <sys/mman.h> |
@@ -159,13 +167,182 @@ bool LibMadPlugin::isFileSupported( const QString& path ) { | |||
159 | return TRUE; | 167 | return TRUE; |
160 | if ( strncasecmp(ext, ".mp3", 4) == 0 ) | 168 | if ( strncasecmp(ext, ".mp3", 4) == 0 ) |
161 | return TRUE; | 169 | return TRUE; |
162 | } | 170 | } |
171 | // UGLY - just for fast testing | ||
172 | if ( path.left(4) == "http") { | ||
173 | return TRUE; | ||
174 | } | ||
175 | |||
163 | 176 | ||
164 | return FALSE; | 177 | return FALSE; |
165 | } | 178 | } |
166 | 179 | ||
167 | 180 | ||
181 | int LibMadPlugin::tcp_open(char *address, int port) { | ||
182 | struct sockaddr_in stAddr; | ||
183 | struct hostent *host; | ||
184 | int sock; | ||
185 | struct linger l; | ||
186 | |||
187 | memset(&stAddr, 0, sizeof(stAddr)); | ||
188 | stAddr.sin_family = AF_INET; | ||
189 | stAddr.sin_port = htons(port); | ||
190 | |||
191 | if ((host = gethostbyname(address)) == NULL) | ||
192 | return (0); | ||
193 | |||
194 | stAddr.sin_addr = *((struct in_addr *)host->h_addr_list[0]); | ||
195 | |||
196 | if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) | ||
197 | return (0); | ||
198 | |||
199 | l.l_onoff = 1; | ||
200 | l.l_linger = 5; | ||
201 | if (setsockopt(sock, SOL_SOCKET, SO_LINGER, (char *)&l, sizeof(l)) < 0) | ||
202 | return (0); | ||
203 | |||
204 | if (connect(sock, (struct sockaddr *)&stAddr, sizeof(stAddr)) < 0) | ||
205 | return (0); | ||
206 | |||
207 | return (sock); | ||
208 | } | ||
209 | |||
210 | |||
211 | /** | ||
212 | * Read a http line header. | ||
213 | * This function read character by character. | ||
214 | * @param tcp_sock the socket use to read the stream | ||
215 | * @param buf a buffer to receive the data | ||
216 | * @param size size of the buffer | ||
217 | * @return the size of the stream read or -1 if an error occured | ||
218 | */ | ||
219 | int LibMadPlugin::http_read_line(int tcp_sock, char *buf, int size) { | ||
220 | int offset = 0; | ||
221 | |||
222 | do | ||
223 | { | ||
224 | if (std::read(tcp_sock, buf + offset, 1) < 0) | ||
225 | return -1; | ||
226 | if (buf[offset] != '\r') /* Strip \r from answer */ | ||
227 | offset++; | ||
228 | } | ||
229 | while (offset < size - 1 && buf[offset - 1] != '\n'); | ||
230 | |||
231 | buf[offset] = 0; | ||
232 | return offset; | ||
233 | } | ||
234 | |||
235 | int LibMadPlugin::http_open(const QString& path ) { | ||
236 | char *host; | ||
237 | int port; | ||
238 | char *request; | ||
239 | int tcp_sock; | ||
240 | char http_request[PATH_MAX]; | ||
241 | char filename[PATH_MAX]; | ||
242 | char c; | ||
243 | char *arg =strdup(path.latin1()); | ||
244 | |||
245 | /* Check for URL syntax */ | ||
246 | if (strncmp(arg, "http://", strlen("http://"))) | ||
247 | return (0); | ||
248 | |||
249 | /* Parse URL */ | ||
250 | port = 80; | ||
251 | host = arg + strlen("http://"); | ||
252 | if ((request = strchr(host, '/')) == NULL) | ||
253 | return (0); | ||
254 | *request++ = 0; | ||
255 | |||
256 | if (strchr(host, ':') != NULL) /* port is specified */ | ||
257 | { | ||
258 | port = atoi(strchr(host, ':') + 1); | ||
259 | *strchr(host, ':') = 0; | ||
260 | } | ||
261 | |||
262 | /* Open a TCP socket */ | ||
263 | if (!(tcp_sock = tcp_open(host, port))) | ||
264 | { | ||
265 | perror("http_open"); | ||
266 | return (0); | ||
267 | } | ||
268 | |||
269 | snprintf(filename, sizeof(filename) - strlen(host) - 75, "%s", request); | ||
270 | |||
271 | /* Send HTTP GET request */ | ||
272 | /* Please don't use a Agent know by shoutcast (Lynx, Mozilla) seems to be reconized and print | ||
273 | * a html page and not the stream */ | ||
274 | snprintf(http_request, sizeof(http_request), "GET /%s HTTP/1.0\r\n" | ||
275 | /* "User-Agent: Mozilla/2.0 (Win95; I)\r\n" */ | ||
276 | "Pragma: no-cache\r\n" "Host: %s\r\n" "Accept: */*\r\n" "\r\n", filename, host); | ||
277 | |||
278 | send(tcp_sock, http_request, strlen(http_request), 0); | ||
279 | |||
280 | /* Parse server reply */ | ||
281 | #if 0 | ||
282 | do | ||
283 | read(tcp_sock, &c, sizeof(char)); | ||
284 | while (c != ' '); | ||
285 | read(tcp_sock, http_request, 4 * sizeof(char)); | ||
286 | http_request[4] = 0; | ||
287 | if (strcmp(http_request, "200 ")) | ||
288 | { | ||
289 | fprintf(stderr, "http_open: "); | ||
290 | do | ||
291 | { | ||
292 | read(tcp_sock, &c, sizeof(char)); | ||
293 | fprintf(stderr, "%c", c); | ||
294 | } | ||
295 | while (c != '\r'); | ||
296 | fprintf(stderr, "\n"); | ||
297 | return (0); | ||
298 | } | ||
299 | #endif | ||
300 | |||
301 | do | ||
302 | { | ||
303 | int len; | ||
304 | |||
305 | len = http_read_line(tcp_sock, http_request, sizeof(http_request)); | ||
306 | |||
307 | if (len == -1) | ||
308 | { | ||
309 | fprintf(stderr, "http_open: %s\n", strerror(errno)); | ||
310 | return 0; | ||
311 | } | ||
312 | |||
313 | if (strncmp(http_request, "Location:", 9) == 0) | ||
314 | { | ||
315 | /* redirect */ | ||
316 | std::close(tcp_sock); | ||
317 | |||
318 | http_request[strlen(http_request) - 1] = '\0'; | ||
319 | |||
320 | return http_open(&http_request[10]); | ||
321 | } | ||
322 | |||
323 | if (strncmp(http_request, "ICY ", 4) == 0) | ||
324 | { | ||
325 | /* This is icecast streaming */ | ||
326 | if (strncmp(http_request + 4, "200 ", 4)) | ||
327 | { | ||
328 | fprintf(stderr, "http_open: %s\n", http_request); | ||
329 | return 0; | ||
330 | } | ||
331 | } | ||
332 | else if (strncmp(http_request, "icy-", 4) == 0) | ||
333 | { | ||
334 | /* we can have: icy-noticeX, icy-name, icy-genre, icy-url, icy-pub, icy-metaint, icy-br */ | ||
335 | /* Don't print these - mpg123 doesn't */ | ||
336 | /* fprintf(stderr,"%s\n",http_request); */ | ||
337 | } | ||
338 | } | ||
339 | while (strcmp(http_request, "\n") != 0); | ||
340 | |||
341 | return (tcp_sock); | ||
342 | } | ||
343 | |||
344 | |||
168 | bool LibMadPlugin::open( const QString& path ) { | 345 | bool LibMadPlugin::open( const QString& path ) { |
169 | debugMsg( "LibMadPlugin::open" ); | 346 | debugMsg( "LibMadPlugin::open" ); |
170 | Config cfg("MediaPlayer"); | 347 | Config cfg("MediaPlayer"); |
171 | cfg.setGroup("Options"); | 348 | cfg.setGroup("Options"); |
@@ -176,10 +353,16 @@ bool LibMadPlugin::open( const QString& path ) { | |||
176 | info = QString( "" ); | 353 | info = QString( "" ); |
177 | 354 | ||
178 | //qDebug( "Opening %s", path.latin1() ); | 355 | //qDebug( "Opening %s", path.latin1() ); |
179 | 356 | ||
180 | d->input.path = path.latin1(); | 357 | |
181 | d->input.fd = ::open( d->input.path, O_RDONLY ); | 358 | if (path.left( 4 ) == "http" ) { |
359 | d->input.fd = http_open(path); | ||
360 | |||
361 | } else { | ||
362 | d->input.path = path.latin1(); | ||
363 | d->input.fd = ::open( d->input.path, O_RDONLY ); | ||
364 | } | ||
182 | if (d->input.fd == -1) { | 365 | if (d->input.fd == -1) { |
183 | qDebug("error opening %s", d->input.path ); | 366 | qDebug("error opening %s", d->input.path ); |
184 | return FALSE; | 367 | return FALSE; |
185 | } | 368 | } |
@@ -495,9 +678,9 @@ bool LibMadPlugin::audioReadStereoSamples( short *output, long samples, long& sa | |||
495 | bool LibMadPlugin::audioReadSamples( short *output, int /*channels*/, long samples, long& samplesMade, int ) { | 678 | bool LibMadPlugin::audioReadSamples( short *output, int /*channels*/, long samples, long& samplesMade, int ) { |
496 | debugMsg( "LibMadPlugin::audioReadStereoSamples" ); | 679 | debugMsg( "LibMadPlugin::audioReadStereoSamples" ); |
497 | 680 | ||
498 | static bool needInput = TRUE; | 681 | static bool needInput = TRUE; |
499 | 682 | ||
500 | if ( samples == 0 ) | 683 | if ( samples == 0 ) |
501 | return FALSE; | 684 | return FALSE; |
502 | 685 | ||
503 | do { | 686 | 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 @@ | |||
16 | ** Contact info@trolltech.com if any conditions of this licensing are | 16 | ** Contact info@trolltech.com if any conditions of this licensing are |
17 | ** not clear to you. | 17 | ** not clear to you. |
18 | ** | 18 | ** |
19 | **********************************************************************/ | 19 | **********************************************************************/ |
20 | #ifndef LIBMAD_PLUGIN_H | 20 | #ifndef LIBMAD_PLUGIN_H |
21 | #define LIBMAD_PLUGIN_H | 21 | #define LIBMAD_PLUGIN_H |
22 | 22 | ||
23 | #include <qstring.h> | 23 | #include <qstring.h> |
24 | #include <qpe/mediaplayerplugininterface.h> | 24 | #include <qpe/mediaplayerplugininterface.h> |
@@ -42,15 +42,16 @@ public: | |||
42 | double pluginVersion() { return 1.0; } | 42 | double pluginVersion() { return 1.0; } |
43 | 43 | ||
44 | bool isFileSupported( const QString& ); | 44 | bool isFileSupported( const QString& ); |
45 | bool open( const QString& ); | 45 | bool open( const QString& ); |
46 | |||
46 | bool close(); | 47 | bool close(); |
47 | bool isOpen(); | 48 | bool isOpen(); |
48 | const QString &fileInfo() { return info; } | 49 | const QString &fileInfo() { return info; } |
49 | 50 | ||
50 | // If decoder doesn't support audio then return 0 here | 51 | // If decoder doesn't support audio then return 0 here |
51 | int audioStreams(); | 52 | int audioStreams(); |
52 | int audioChannels( int stream ); | 53 | int audioChannels( int stream ); |
53 | int audioFrequency( int stream ); | 54 | int audioFrequency( int stream ); |
54 | int audioSamples( int stream ); | 55 | int audioSamples( int stream ); |
55 | bool audioSetSample( long sample, int stream ); | 56 | bool audioSetSample( long sample, int stream ); |
56 | /* int audioBitsPerSample(int) {return 0;} */ | 57 | /* int audioBitsPerSample(int) {return 0;} */ |
@@ -100,8 +101,12 @@ public: | |||
100 | 101 | ||
101 | long getPlayTime() { return -1; } | 102 | long getPlayTime() { return -1; } |
102 | 103 | ||
103 | private: | 104 | private: |
105 | int tcp_open(char *address, int port); | ||
106 | int http_read_line(int tcp_sock, char *buf, int size) ; | ||
107 | int http_open(const QString& path ); | ||
108 | |||
104 | LibMadPluginData *d; | 109 | LibMadPluginData *d; |
105 | QString info; | 110 | QString info; |
106 | int bufferSize; | 111 | int bufferSize; |
107 | }; | 112 | }; |