3 * Copyright (c) 2006 acmesystems.it - john@acmesystems.it
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA02111-1307USA
19 * Feedback, Bugs... info@acmesystems.it
30 #include <sys/types.h>
31 #include <netinet/in.h>
32 #include <sys/socket.h>
39 typedef struct _MP3_STREAM
{
40 unsigned char buf
[MAX_PACKET_SIZE
+ 1];
42 unsigned char mp3_buffer
[MAX_BUFFER_SIZE
];
43 unsigned long int mp3_buffer_write_pos
;
44 unsigned long int mp3_buffer_read_pos
;
45 unsigned long int mp3_data_in_buffer
;
46 unsigned char transmit_success
;
47 unsigned int buffer_error
;
49 unsigned int numbytes
;
50 unsigned int metainterval
;
53 static MP3_STREAM mp3_stream
;
55 int connect_timeout (int sfd
, struct sockaddr
*addr
, int addrlen
,
56 struct timeval
*timeout
) {
58 int svlen
= sizeof sv
;
62 return connect (sfd
, addr
, addrlen
);
64 if (getsockopt (sfd
, SOL_SOCKET
, SO_SNDTIMEO
, (char *)&sv
, &svlen
) < 0) {
67 if (setsockopt (sfd
, SOL_SOCKET
, SO_SNDTIMEO
, timeout
,sizeof *timeout
) < 0) {
70 ret
= connect (sfd
, addr
, addrlen
);
71 setsockopt (sfd
, SOL_SOCKET
, SO_SNDTIMEO
, (char *)&sv
, sizeof sv
);
76 int mp3_stream_parse_url(unsigned char *url
, unsigned char *ip
,
77 unsigned char *path
, unsigned int *port
){
78 int len
= strlen(url
) - 1;
79 while(((url
[len
] == '\n')||(url
[len
] == ' ')) && (len
> 0)){
84 printf("Parsing stream url : %s\n", url
);
85 unsigned char *http
= strstr(url
, "http://");
89 unsigned char *p
= strstr(url
, ":");
96 unsigned char *p2
= strstr((p
)?(p
):(url
), "/");
107 printf("ip -> %s\nport -> %d\npath -> %s\n", ip
, *port
, path
);
113 int mp3_stream_get_url(unsigned char *url
, unsigned int type
,
114 unsigned char *ip
, unsigned int *port
, unsigned char *path
){
115 if(type
== STREAM_PLS
){
116 if(mp3_pls_get_info(url
, ip
, path
, port
) == MP3_OK
){
119 } else if(type
== STREAM_URL
){
120 if(mp3_stream_parse_url(url
, ip
, path
, port
) == MP3_OK
){
127 int mp3_stream_setup(unsigned char *url
, unsigned int type
, unsigned char *ip
,
128 unsigned char *path
, unsigned int *port
){
130 struct sockaddr_in their_addr
;
131 unsigned int error
= 0;
132 if(mp3_stream_get_url(url
, type
, ip
, port
, path
) == MP3_ERROR
){
136 mp3_stream
.mp3_buffer_write_pos
= 0;
137 mp3_stream
.mp3_buffer_read_pos
= 0;
138 mp3_stream
.mp3_data_in_buffer
= 0;
139 mp3_stream
.transmit_success
= 1;
140 mp3_stream
.buffer_error
= 0;
141 mp3_stream
.metainterval
= 0;
145 if ((he
=gethostbyname(ip
)) == NULL
) {
146 perror("Error in gethostbyname. Wrong url/ip ?");
149 if ((mp3_stream
.sockfd
= socket(PF_INET
, SOCK_STREAM
, 0)) == -1) {
150 perror("Error opening stream socket");
154 their_addr
.sin_family
= AF_INET
;
155 their_addr
.sin_port
= htons(*port
);
156 their_addr
.sin_addr
= *((struct in_addr
*)he
->h_addr
);
157 memset(&(their_addr
.sin_zero
), '\0', 8);
163 if (connect_timeout(mp3_stream
.sockfd
, (struct sockaddr
*)&their_addr
,
164 sizeof(struct sockaddr
), &tv
) == -1) {
169 unsigned char icy_request
[1024];
171 "GET %s HTTP/1.0\r\nHost: %s\r\nUser-Agent: A.LP-MP3\r\nAccept: */*\r\nicy-metadata:0\r\n\r\n",
174 printf("Sending request :\n%s\n", icy_request
);
175 send(mp3_stream
.sockfd
, icy_request
, strlen(icy_request
), 0);
176 mp3_stream
.numbytes
= 0;
177 while(mp3_stream
.numbytes
< MAX_PACKET_SIZE
-1) {
178 if ((mp3_stream
.numbytes
+= recv(mp3_stream
.sockfd
, &mp3_stream
.buf
[mp3_stream
.numbytes
], MAX_PACKET_SIZE
- 1 - mp3_stream
.numbytes
, 0)) == -1) {
183 mp3_stream
.buf
[mp3_stream
.numbytes
] = '\0';
184 printf("numbytes = %d\n", mp3_stream
.numbytes
);
185 unsigned char *p
= strstr(mp3_stream
.buf
, "\r\n\r\n");
190 printf("funky p error in stream.c\n");
192 printf("Received: \n%s\n", mp3_stream
.buf
);
193 if(((unsigned char*)strstr(mp3_stream
.buf
, "ICY 200 OK") != mp3_stream
.buf
) &&
194 ((unsigned char*)strstr(mp3_stream
.buf
, "HTTP/1.1 200 OK") != mp3_stream
.buf
) &&
195 ((unsigned char*)strstr(mp3_stream
.buf
, "HTTP/1.0 200 OK") != mp3_stream
.buf
)) {
198 int p_buf
= p
- mp3_stream
.buf
;
200 p2
= strstr(mp3_stream
.buf
, "icy-metaint:");
202 p2
= strstr(p2
, ":");
204 unsigned char *p3
= strstr(p2
, "\r");
206 mp3_stream
.metainterval
= atoi(p2
);
207 printf("META INT == %d\n", mp3_stream
.metainterval
);
210 printf("starting to buffer\n");
211 memcpy(&mp3_stream
.mp3_buffer
[mp3_stream
.mp3_buffer_write_pos
],
213 mp3_stream
.mp3_buffer_write_pos
+= p_buf
;
214 mp3_stream
.mp3_data_in_buffer
+= p_buf
;
216 while(mp3_stream
.mp3_data_in_buffer
+ (unsigned long int)MAX_PACKET_SIZE
217 < (unsigned long int)MAX_BUFFER_SIZE
){
218 if ((mp3_stream
.numbytes
=recv(mp3_stream
.sockfd
, mp3_stream
.buf
,
219 MAX_PACKET_SIZE
-1, 0)) == -1) {
220 perror("disconnected");
221 printf("disconntected\n");
225 if(mp3_stream
.numbytes
== 0){
228 perror("disconnected");
229 printf("disconntected\n");
234 memcpy(&mp3_stream
.mp3_buffer
[mp3_stream
.mp3_buffer_write_pos
],
235 mp3_stream
.buf
, mp3_stream
.numbytes
);
236 mp3_stream
.mp3_buffer_write_pos
+= mp3_stream
.numbytes
;
237 mp3_stream
.mp3_data_in_buffer
+= mp3_stream
.numbytes
;
238 printf("%ld ", mp3_stream
.mp3_data_in_buffer
);
243 mp3_stream
.mp3_data
.state
= MP3_PLAYING
;
244 while(mp3_stream
.mp3_data_in_buffer
>= 2 * MP3_CHUNK_SIZE
){
245 memcpy(mp3_stream
.mp3_data
.mp3
,
246 &mp3_stream
.mp3_buffer
[mp3_stream
.mp3_buffer_read_pos
],
248 mp3_send_data_to_buffer(mp3_stream
.mp3_data
);
249 mp3_stream
.mp3_buffer_read_pos
+= MP3_CHUNK_SIZE
;
250 mp3_stream
.mp3_data_in_buffer
-= MP3_CHUNK_SIZE
;
253 printf("Starting to play stream\n");
257 static int max_recv_errors
= 10;
258 int mp3_stream_handle(void){
259 if(MAX_BUFFER_SIZE
>= mp3_stream
.mp3_data_in_buffer
+ MAX_PACKET_SIZE
){
261 ufds
.fd
= mp3_stream
.sockfd
;
262 ufds
.events
= POLLIN
|POLLHUP
;
264 if(poll(&ufds
, 1, 2000) > 0){
265 max_recv_errors
= 10;
266 if ((mp3_stream
.numbytes
=recv(mp3_stream
.sockfd
, mp3_stream
.buf
, MAX_PACKET_SIZE
-1, 0)) == -1) {
269 if((mp3_stream
.numbytes
!= EAGAIN
)&& (mp3_stream
.numbytes
!= -1)){
270 if(mp3_stream
.mp3_buffer_write_pos
+ mp3_stream
.numbytes
<= MAX_BUFFER_SIZE
){
271 memcpy(&mp3_stream
.mp3_buffer
[mp3_stream
.mp3_buffer_write_pos
],
272 mp3_stream
.buf
, mp3_stream
.numbytes
);
273 mp3_stream
.mp3_buffer_write_pos
+= mp3_stream
.numbytes
;
274 mp3_stream
.mp3_data_in_buffer
+= mp3_stream
.numbytes
;
275 if(mp3_stream
.mp3_buffer_write_pos
== MAX_BUFFER_SIZE
){
276 mp3_stream
.mp3_buffer_write_pos
= 0;
279 unsigned int buffer_offset
= MAX_BUFFER_SIZE
- mp3_stream
.mp3_buffer_write_pos
;
280 memcpy(&mp3_stream
.mp3_buffer
[mp3_stream
.mp3_buffer_write_pos
],
281 mp3_stream
.buf
, buffer_offset
);
282 mp3_stream
.mp3_buffer_write_pos
=
283 mp3_stream
.numbytes
- buffer_offset
;
284 memcpy(&mp3_stream
.mp3_buffer
[0], &mp3_stream
.buf
[buffer_offset
],
285 mp3_stream
.mp3_buffer_write_pos
);
286 mp3_stream
.mp3_data_in_buffer
+= mp3_stream
.numbytes
;
291 if(max_recv_errors
== 0){
292 printf("recv error\n");
298 if(mp3_stream
.mp3_data_in_buffer
< MP3_CHUNK_SIZE
){
299 printf("radio_buffer is empty\n");
300 mp3_stream
.buffer_error
++;
301 if(mp3_stream
.buffer_error
> MAX_BUFFER_ERROR
){
305 mp3_stream
.buffer_error
= 0;
307 if(mp3_stream
.transmit_success
){
308 if(MAX_BUFFER_SIZE
>= mp3_stream
.mp3_buffer_read_pos
+ MP3_CHUNK_SIZE
){
309 memcpy(mp3_stream
.mp3_data
.mp3
,
310 &mp3_stream
.mp3_buffer
[mp3_stream
.mp3_buffer_read_pos
], MP3_CHUNK_SIZE
);
311 mp3_stream
.mp3_buffer_read_pos
+= MP3_CHUNK_SIZE
;
312 mp3_stream
.mp3_data_in_buffer
-= MP3_CHUNK_SIZE
;
313 if(mp3_stream
.mp3_buffer_read_pos
== MAX_BUFFER_SIZE
){
314 mp3_stream
.mp3_buffer_read_pos
= 0;
318 unsigned int buffer_offset
= MAX_BUFFER_SIZE
- mp3_stream
.mp3_buffer_read_pos
;
319 memcpy(mp3_stream
.mp3_data
.mp3
,
320 &mp3_stream
.mp3_buffer
[mp3_stream
.mp3_buffer_read_pos
],
322 mp3_stream
.mp3_buffer_read_pos
= MP3_CHUNK_SIZE
- buffer_offset
;
323 memcpy(&mp3_stream
.mp3_data
.mp3
[buffer_offset
], mp3_stream
.mp3_buffer
,
324 mp3_stream
.mp3_buffer_read_pos
);
327 if(!mp3_send_data_to_buffer(mp3_stream
.mp3_data
)){
328 mp3_stream
.transmit_success
= 0;
330 mp3_stream
.transmit_success
= 1;
332 } while((mp3_stream
.transmit_success
)&&(mp3_stream
.mp3_data_in_buffer
> MP3_CHUNK_SIZE
));
337 int mp3_stream_cleanup(void){
338 close(mp3_stream
.sockfd
);
This page took 0.092945 seconds and 5 git commands to generate.