format_mp3.c 3.61 KB
Newer Older
Michael Smith's avatar
Michael Smith committed
1
2
/* format_mp3.c
**
Michael Smith's avatar
Michael Smith committed
3
** format plugin for mp3
Michael Smith's avatar
Michael Smith committed
4
5
6
7
8
9
10
11
**
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "refbuf.h"
Michael Smith's avatar
Michael Smith committed
12
13
#include "source.h"
#include "client.h"
Michael Smith's avatar
Michael Smith committed
14
15
16

#include "stats.h"
#include "format.h"
Michael Smith's avatar
Michael Smith committed
17
18
19
20
21
22
23
24
25
26
#include "httpp/httpp.h"

#include "log.h"
#include "logging.h"

#include "format_mp3.h"

#define CATMODULE "format-mp3"

#define ICY_METADATA_INTERVAL 16000
Michael Smith's avatar
Michael Smith committed
27

28
29
30
31
static void format_mp3_free_plugin(format_plugin_t *self);
static int format_mp3_get_buffer(format_plugin_t *self, char *data, 
        unsigned long len, refbuf_t **buffer);
static refbuf_queue_t *format_mp3_get_predata(format_plugin_t *self);
Michael Smith's avatar
Michael Smith committed
32
33
34
35
36
37
38
39
40
41
42
43
static void *format_mp3_create_client_data(format_plugin_t *self,
        source_t *source, client_t *client);
static int format_mp3_write_buf_to_client(format_plugin_t *self,
        client_t *client, unsigned char *buf, int len);
static void format_mp3_send_headers(format_plugin_t *self, 
        source_t *source, client_t *client);

typedef struct {
   int interval;
   int offset;
   int metadata;
} mp3_client_data;
Michael Smith's avatar
Michael Smith committed
44
45
46
47
48
49
50
51
52
53
54

format_plugin_t *format_mp3_get_plugin(void)
{
	format_plugin_t *plugin;

	plugin = (format_plugin_t *)malloc(sizeof(format_plugin_t));

	plugin->type = FORMAT_TYPE_MP3;
	plugin->has_predata = 0;
	plugin->get_buffer = format_mp3_get_buffer;
	plugin->get_predata = format_mp3_get_predata;
Michael Smith's avatar
Michael Smith committed
55
    plugin->write_buf_to_client = format_mp3_write_buf_to_client;
56
    plugin->create_client_data = format_mp3_create_client_data;
Michael Smith's avatar
Michael Smith committed
57
    plugin->client_send_headers = format_mp3_send_headers;
Michael Smith's avatar
Michael Smith committed
58
	plugin->free_plugin = format_mp3_free_plugin;
59
    plugin->format_description = "MP3 audio";
Michael Smith's avatar
Michael Smith committed
60

Michael Smith's avatar
Michael Smith committed
61
	plugin->_state = calloc(1, sizeof(mp3_state));
Michael Smith's avatar
Michael Smith committed
62
63
64
65

	return plugin;
}

Michael Smith's avatar
Michael Smith committed
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
static int format_mp3_write_buf_to_client(format_plugin_t *self, 
    client_t *client, unsigned char *buf, int len) 
{
    int ret;

    ret = sock_write_bytes(client->con->sock, buf, len);

    if(ret < 0) {
        if(sock_recoverable(ret)) {
            DEBUG1("Client had recoverable error %ld", ret);
            ret = 0;
        }
    }
    else
        client->con->sent_bytes += ret;

    return ret;
}

static void format_mp3_free_plugin(format_plugin_t *self)
Michael Smith's avatar
Michael Smith committed
86
87
88
89
90
{
	/* free the plugin instance */
	free(self);
}

Michael Smith's avatar
Michael Smith committed
91
92
static int format_mp3_get_buffer(format_plugin_t *self, char *data, 
    unsigned long len, refbuf_t **buffer)
Michael Smith's avatar
Michael Smith committed
93
94
95
96
97
98
99
100
101
102
103
104
105
106
{
	refbuf_t *refbuf;
    if(!data) {
        *buffer = NULL;
        return 0;
    }
    refbuf = refbuf_new(len);

    memcpy(refbuf->data, data, len);

    *buffer = refbuf;
	return 0;
}

Michael Smith's avatar
Michael Smith committed
107
static refbuf_queue_t *format_mp3_get_predata(format_plugin_t *self)
Michael Smith's avatar
Michael Smith committed
108
109
110
111
{
    return NULL;
}

Michael Smith's avatar
Michael Smith committed
112
113
114
115
116
117
118
119
120
121
122
123
124
125
static void *format_mp3_create_client_data(format_plugin_t *self, 
        source_t *source, client_t *client) 
{
    mp3_client_data *data = calloc(1,sizeof(mp3_client_data));
    char *metadata;

    data->interval = ICY_METADATA_INTERVAL;
    data->offset = 0;

    metadata = httpp_getvar(source->parser, "icy-metadata");
    if(metadata)
    data->metadata = atoi(metadata)>0?1:0;

    return data;
126
}
Michael Smith's avatar
Michael Smith committed
127

Michael Smith's avatar
Michael Smith committed
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
static void format_mp3_send_headers(format_plugin_t *self,
        source_t *source, client_t *client)
{
    int bytes;
    
    client->respcode = 200;
    bytes = sock_write(client->con->sock, 
            "HTTP/1.0 200 OK\r\n" 
            "Content-Type: %s\r\n", 
            format_get_mimetype(source->format->type));

    if(bytes > 0) client->con->sent_bytes += bytes;

    format_send_general_headers(self, source, client);

    if(0 && ((mp3_client_data *)(client->format_data))->metadata) {
        int bytes = sock_write(client->con->sock, "icy-metaint: %d\r\n", 
                ICY_METADATA_INTERVAL);
        if(bytes > 0)
            client->con->sent_bytes += bytes;
    }
}



Michael Smith's avatar
Michael Smith committed
153