format.c 4.66 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
/* Icecast
 *
 * This program is distributed under the GNU General Public License, version 2.
 * A copy of this license is included with this source.
 *
 * Copyright 2000-2004, Jack Moffitt <jack@xiph.org, 
 *                      Michael Smith <msmith@xiph.org>,
 *                      oddsock <oddsock@xiph.org>,
 *                      Karl Heyes <karl@xiph.org>
 *                      and others (see AUTHORS for details).
 */

13
/* -*- c-basic-offset: 4; -*- */
Jack Moffitt's avatar
Jack Moffitt committed
14
15
16
17
18
19
/* format.c
**
** format plugin implementation
**
*/

20
21
22
23
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

Jack Moffitt's avatar
Jack Moffitt committed
24
25
#include <stdlib.h>
#include <string.h>
Karl Heyes's avatar
Karl Heyes committed
26
27
28
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
29
#include <time.h>
Jack Moffitt's avatar
Jack Moffitt committed
30
31
32
33

#include "connection.h"
#include "refbuf.h"

Michael Smith's avatar
Michael Smith committed
34
#include "source.h"
Jack Moffitt's avatar
Jack Moffitt committed
35
#include "format.h"
36
#include "global.h"
Karl Heyes's avatar
Karl Heyes committed
37
#include "httpp/httpp.h"
Jack Moffitt's avatar
Jack Moffitt committed
38
39

#include "format_vorbis.h"
Michael Smith's avatar
Michael Smith committed
40
#include "format_mp3.h"
Jack Moffitt's avatar
Jack Moffitt committed
41

42
43
#include "logging.h"
#define CATMODULE "format"
Ed "oddsock" Zaleski's avatar
Ed "oddsock" Zaleski committed
44
45
46
47
48

#ifdef WIN32
#define strcasecmp stricmp
#define strncasecmp strnicmp
#endif
49

Michael Smith's avatar
Michael Smith committed
50
51
52
format_type_t format_get_type(char *contenttype)
{
    if(strcmp(contenttype, "application/x-ogg") == 0)
53
54
55
        return FORMAT_TYPE_VORBIS; /* Backwards compatibility */
    else if(strcmp(contenttype, "application/ogg") == 0)
        return FORMAT_TYPE_VORBIS; /* Now blessed by IANA */
Michael Smith's avatar
Michael Smith committed
56
57
    else if(strcmp(contenttype, "audio/mpeg") == 0)
        return FORMAT_TYPE_MP3; 
58
59
    else if(strcmp(contenttype, "audio/x-mpeg") == 0)
        return FORMAT_TYPE_MP3; /* Relay-compatibility for some servers */
Michael Smith's avatar
Michael Smith committed
60
    else
61
        return FORMAT_ERROR;
Michael Smith's avatar
Michael Smith committed
62
63
}

64
65
66
67
char *format_get_mimetype(format_type_t type)
{
    switch(type) {
        case FORMAT_TYPE_VORBIS:
68
            return "application/ogg";
69
70
71
72
73
74
75
76
77
            break;
        case FORMAT_TYPE_MP3:
            return "audio/mpeg";
            break;
        default:
            return NULL;
    }
}

78
79
format_plugin_t *format_get_plugin(format_type_t type, char *mount, 
        http_parser_t *parser)
Jack Moffitt's avatar
Jack Moffitt committed
80
{
81
    format_plugin_t *plugin;
Jack Moffitt's avatar
Jack Moffitt committed
82

83
84
85
86
87
    switch (type) {
    case FORMAT_TYPE_VORBIS:
        plugin = format_vorbis_get_plugin();
        if (plugin) plugin->mount = mount;
        break;
Michael Smith's avatar
Michael Smith committed
88
    case FORMAT_TYPE_MP3:
89
        plugin = format_mp3_get_plugin(parser);
Michael Smith's avatar
Michael Smith committed
90
91
        if (plugin) plugin->mount = mount;
        break;
92
93
94
95
    default:
        plugin = NULL;
        break;
    }
Jack Moffitt's avatar
Jack Moffitt committed
96

97
    return plugin;
Jack Moffitt's avatar
Jack Moffitt committed
98
}
99
100
101
102

int format_generic_write_buf_to_client(format_plugin_t *format, 
        client_t *client, unsigned char *buf, int len)
{
103
    return client_send_bytes (client, buf, len);
104
105
}

Michael Smith's avatar
Michael Smith committed
106
107
108
109
110
111
112
void format_send_general_headers(format_plugin_t *format,
        source_t *source, client_t *client)
{
    http_var_t *var;
    avl_node *node;
    int bytes;

113
114
115
    /* iterate through source http headers and send to client */
    avl_tree_rlock(source->parser->vars);
    node = avl_get_first(source->parser->vars);
Karl Heyes's avatar
Karl Heyes committed
116
117
    while (node)
    {
118
        var = (http_var_t *)node->key;
Karl Heyes's avatar
Karl Heyes committed
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
        if (!strcasecmp(var->name, "ice-audio-info")) {
            /* convert ice-audio-info to icy-br */
            char *brfield;
            unsigned int bitrate;

            brfield = strstr(var->value, "bitrate=");
            if (brfield && sscanf(var->value, "bitrate=%u", &bitrate)) {
                bytes = sock_write(client->con->sock, "icy-br:%u\r\n", bitrate);
                if (bytes > 0)
                    client->con->sent_bytes += bytes;
            }
        }
        else
        {
            if (strcasecmp(var->name, "ice-password") &&
                strcasecmp(var->name, "icy-metaint"))
            {
                bytes = 0;
                if (!strncasecmp("ice-", var->name, 4))
                {
                    if (!strcasecmp("ice-bitrate", var->name))
                        bytes += sock_write(client->con->sock, "icy-br:%s\r\n", var->value);
                    else
142
143
144
145
146
147
                        if (!strcasecmp("ice-public", var->name))
                            bytes += sock_write(client->con->sock, 
                                "icy-pub:%s\r\n", var->value);
                        else
                            bytes = sock_write(client->con->sock, "icy%s:%s\r\n",
                                var->name + 3, var->value);
Karl Heyes's avatar
Karl Heyes committed
148
149
150
151
152
153
154
155
156
157
                            
                }
                if (!strncasecmp("icy-", var->name, 4))
                {
                    bytes = sock_write(client->con->sock, "icy%s:%s\r\n",
                            var->name + 3, var->value);
                }
                if (bytes > 0)
                    client->con->sent_bytes += bytes;
            }
158
159
160
161
        }
        node = avl_get_next(node);
    }
    avl_tree_unlock(source->parser->vars);
162
163
164
    bytes = sock_write(client->con->sock,
            "Server: %s\r\n", ICECAST_VERSION_STRING);
    if(bytes > 0) client->con->sent_bytes += bytes;
Michael Smith's avatar
Michael Smith committed
165
166
}