2 * ezstream - source client for Icecast with external en-/decoder support
3 * Copyright (C) 2003, 2004, 2005, 2006 Ed Zaleski <oddsock@oddsock.org>
4 * Copyright (C) 2007 Moritz Grimm <mdgrimm@gmx.net>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
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, MA 02111-1307 USA
21 * This file contains utility functions, as well as a few other unexciting
22 * but verbose functions outsourced from ezstream.c to make it more readable.
29 #ifdef HAVE_SYS_TYPES_H
30 # include <sys/types.h>
32 #ifdef HAVE_SYS_TIME_H
33 # include <sys/time.h>
40 #ifdef HAVE_LANGINFO_H
41 # include <langinfo.h>
52 #include <shout/shout.h>
56 #include "configfile.h"
63 extern EZCONFIG
*pezConfig
;
64 extern char *__progname
;
66 char * iconvert(const char *, const char *, const char *, int);
69 strrcmp(const char *s
, const char *sub
)
71 size_t slen
= strlen(s
);
72 size_t sublen
= strlen(sub
);
77 return (memcmp(s
+ slen
- sublen
, sub
, sublen
));
81 strrcasecmp(const char *s
, const char *sub
)
83 char *s_cpy
= xstrdup(s
);
84 char *sub_cpy
= xstrdup(sub
);
88 for (p
= s_cpy
; *p
!= '\0'; p
++)
89 *p
= tolower((int)*p
);
91 for (p
= sub_cpy
; *p
!= '\0'; p
++)
92 *p
= tolower((int)*p
);
94 ret
= strrcmp(s_cpy
, sub_cpy
);
103 stream_setup(const char *host
, const int port
, const char *mount
)
105 shout_t
*shout
= NULL
;
107 if ((shout
= shout_new()) == NULL
) {
108 printf("%s: shout_new(): %s", __progname
, strerror(ENOMEM
));
112 if (shout_set_host(shout
, host
) != SHOUTERR_SUCCESS
) {
113 printf("%s: shout_set_host(): %s\n", __progname
,
114 shout_get_error(shout
));
118 if (shout_set_protocol(shout
, SHOUT_PROTOCOL_HTTP
) != SHOUTERR_SUCCESS
) {
119 printf("%s: shout_set_protocol(): %s\n", __progname
,
120 shout_get_error(shout
));
124 if (shout_set_port(shout
, port
) != SHOUTERR_SUCCESS
) {
125 printf("%s: shout_set_port: %s\n", __progname
,
126 shout_get_error(shout
));
130 if (shout_set_password(shout
, pezConfig
->password
) != SHOUTERR_SUCCESS
) {
131 printf("%s: shout_set_password(): %s\n", __progname
,
132 shout_get_error(shout
));
136 if (shout_set_mount(shout
, mount
) != SHOUTERR_SUCCESS
) {
137 printf("%s: shout_set_mount(): %s\n", __progname
,
138 shout_get_error(shout
));
142 if (shout_set_user(shout
, "source") != SHOUTERR_SUCCESS
) {
143 printf("%s: shout_set_user(): %s\n", __progname
,
144 shout_get_error(shout
));
149 if (!strcmp(pezConfig
->format
, MP3_FORMAT
) &&
150 shout_set_format(shout
, SHOUT_FORMAT_MP3
) != SHOUTERR_SUCCESS
) {
151 printf("%s: shout_set_format(MP3): %s\n",
152 __progname
, shout_get_error(shout
));
156 if ((!strcmp(pezConfig
->format
, VORBIS_FORMAT
) ||
157 !strcmp(pezConfig
->format
, THEORA_FORMAT
)) &&
158 shout_set_format(shout
, SHOUT_FORMAT_OGG
) != SHOUTERR_SUCCESS
) {
159 printf("%s: shout_set_format(OGG): %s\n",
160 __progname
, shout_get_error(shout
));
165 if (pezConfig
->serverName
&&
166 shout_set_name(shout
, pezConfig
->serverName
) != SHOUTERR_SUCCESS
) {
167 printf("%s: shout_set_name(): %s\n",
168 __progname
, shout_get_error(shout
));
172 if (pezConfig
->serverURL
&&
173 shout_set_url(shout
, pezConfig
->serverURL
) != SHOUTERR_SUCCESS
) {
174 printf("%s: shout_set_url(): %s\n",
175 __progname
, shout_get_error(shout
));
179 if (pezConfig
->serverGenre
&&
180 shout_set_genre(shout
, pezConfig
->serverGenre
) != SHOUTERR_SUCCESS
) {
181 printf("%s: shout_set_genre(): %s\n",
182 __progname
, shout_get_error(shout
));
186 if (pezConfig
->serverDescription
&&
187 shout_set_description(shout
, pezConfig
->serverDescription
) != SHOUTERR_SUCCESS
) {
188 printf("%s: shout_set_description(): %s\n",
189 __progname
, shout_get_error(shout
));
193 if (pezConfig
->serverBitrate
&&
194 shout_set_audio_info(shout
, SHOUT_AI_BITRATE
, pezConfig
->serverBitrate
) != SHOUTERR_SUCCESS
) {
195 printf("%s: shout_set_audio_info(AI_BITRATE): %s\n",
196 __progname
, shout_get_error(shout
));
200 if (pezConfig
->serverChannels
&&
201 shout_set_audio_info(shout
, SHOUT_AI_CHANNELS
, pezConfig
->serverChannels
) != SHOUTERR_SUCCESS
) {
202 printf("%s: shout_set_audio_info(AI_CHANNELS): %s\n",
203 __progname
, shout_get_error(shout
));
207 if (pezConfig
->serverSamplerate
&&
208 shout_set_audio_info(shout
, SHOUT_AI_SAMPLERATE
, pezConfig
->serverSamplerate
) != SHOUTERR_SUCCESS
) {
209 printf("%s: shout_set_audio_info(AI_SAMPLERATE): %s\n",
210 __progname
, shout_get_error(shout
));
214 if (pezConfig
->serverQuality
&&
215 shout_set_audio_info(shout
, SHOUT_AI_QUALITY
, pezConfig
->serverQuality
) != SHOUTERR_SUCCESS
) {
216 printf("%s: shout_set_audio_info(AI_QUALITY): %s\n",
217 __progname
, shout_get_error(shout
));
222 if (shout_set_public(shout
, pezConfig
->serverPublic
) != SHOUTERR_SUCCESS
) {
223 printf("%s: shout_set_public(): %s\n",
224 __progname
, shout_get_error(shout
));
233 CHARtoUTF8(const char *in_str
, int mode
)
238 # if defined(HAVE_NL_LANGINFO) && defined(HAVE_SETLOCALE) && defined(CODESET)
239 setlocale(LC_CTYPE
, "");
240 codeset
= nl_langinfo(CODESET
);
241 setlocale(LC_CTYPE
, "C");
243 codeset
= (char *)"";
244 # endif /* HAVE_NL_LANGINFO && HAVE_SETLOCALE && CODESET */
248 snprintf(codeset
, sizeof(codeset
), "CP%u", GetACP());
251 if (in_str
== NULL
|| strlen(in_str
) == 0)
254 return (iconvert(in_str
, codeset
, "UTF-8", mode
));
258 UTF8toCHAR(const char *in_str
, int mode
)
263 # if defined(HAVE_NL_LANGINFO) && defined(HAVE_SETLOCALE) && defined(CODESET)
264 setlocale(LC_CTYPE
, "");
265 codeset
= nl_langinfo(CODESET
);
266 setlocale(LC_CTYPE
, "C");
268 codeset
= (char *)"";
269 # endif /* HAVE_NL_LANGINFO && HAVE_SETLOCALE && CODESET */
273 snprintf(codeset
, sizeof(codeset
), "CP%u", GetACP());
276 if (in_str
== NULL
|| strlen(in_str
) == 0)
279 return (iconvert(in_str
, "UTF-8", codeset
, mode
));
283 iconvert(const char *in_str
, const char *from
, const char *to
, int mode
)
287 ICONV_CONST
char *input
, *ip
;
291 char buf
[BUFSIZ
], *bp
;
300 siz
= strlen(to
) + strlen("//TRANSLIT") + 1;
301 tocode
= xcalloc(siz
, sizeof(char));
302 snprintf(tocode
, siz
, "%s//TRANSLIT", to
);
305 siz
= strlen(to
) + strlen("//IGNORE") + 1;
306 tocode
= xcalloc(siz
, sizeof(char));
307 snprintf(tocode
, siz
, "%s//IGNORE", to
);
312 tocode
= xstrdup(to
);
316 if ((cd
= iconv_open(tocode
, from
)) == (iconv_t
)-1 &&
317 (cd
= iconv_open("", from
)) == (iconv_t
)-1 &&
318 (cd
= iconv_open(tocode
, "")) == (iconv_t
)-1) {
320 printf("%s: iconv_open(): %s\n", __progname
, strerror(errno
));
324 ip
= input
= (ICONV_CONST
char *)in_str
;
325 input_len
= strlen(input
);
327 output
= xcalloc(output_size
, sizeof(char));
329 output
[out_pos
] = '\0';
330 while (input_len
> 0) {
336 bufavail
= sizeof(buf
) - 1;
338 if (iconv(cd
, &ip
, &input_len
, &bp
, &bufavail
) == (size_t)-1 &&
347 count
= sizeof(buf
) - bufavail
- 1;
349 output_size
+= count
;
350 op
= output
= xrealloc(output
, output_size
, sizeof(char));
352 memcpy(op
, buf
, count
);
358 if (iconv_close(cd
) == -1) {
359 printf("%s: iconv_close(): %s\n", __progname
, strerror(errno
));
368 return (xstrdup(in_str
));
369 #endif /* HAVE_ICONV */
373 ez_gettimeofday(void *tp_arg
)
375 struct timeval
*tp
= (struct timeval
*)tp_arg
;
378 #ifdef HAVE_GETTIMEOFDAY
379 ret
= gettimeofday(tp
, NULL
);
380 #else /* HAVE_GETTIMEOFDAY */
383 * Idea for this way of implementing gettimeofday()-like functionality
384 * on Windows taken from cURL, (C) 1998 - 2007 Daniel Steinberg, et al.
385 * http://curl.haxx.se/docs/copyright.html
391 tm
.tm_sec
= st
.wSecond
;
392 tm
.tm_min
= st
.wMinute
;
393 tm
.tm_hour
= st
.wHour
;
394 tm
.tm_mday
= st
.wDay
;
395 tm
.tm_mon
= st
.wMonth
- 1;
396 tm
.tm_year
= st
.wYear
- 1900;
398 tp
->tv_sec
= (long)mktime(&tm
);
399 tp
->tv_usec
= st
.wMilliseconds
* 1000;
402 /* Fallback to time(): */
403 tp
->tv_sec
= (long)time(NULL
);
407 #endif /* HAVE_GETTIMEOFDAY */