Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
What's new
10
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Open sidebar
Xiph.Org
Icecast-Server
Commits
9c44a7d1
Commit
9c44a7d1
authored
Aug 20, 2004
by
Karl Heyes
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
merged singleq branch 7177:7591
svn path=/icecast/trunk/icecast/; revision=7592
parent
490e6466
Changes
16
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
954 additions
and
727 deletions
+954
-727
src/admin.c
src/admin.c
+1
-5
src/cfgfile.c
src/cfgfile.c
+14
-2
src/cfgfile.h
src/cfgfile.h
+6
-4
src/client.c
src/client.c
+15
-7
src/client.h
src/client.h
+4
-3
src/connection.c
src/connection.c
+3
-4
src/format.c
src/format.c
+5
-15
src/format.h
src/format.h
+5
-11
src/format_mp3.c
src/format_mp3.c
+431
-242
src/format_mp3.h
src/format_mp3.h
+13
-8
src/format_vorbis.c
src/format_vorbis.c
+221
-82
src/format_vorbis.h
src/format_vorbis.h
+1
-1
src/refbuf.c
src/refbuf.c
+20
-92
src/refbuf.h
src/refbuf.h
+2
-25
src/source.c
src/source.c
+198
-222
src/source.h
src/source.h
+15
-4
No files found.
src/admin.c
View file @
9c44a7d1
...
...
@@ -799,11 +799,7 @@ static void command_metadata(client_t *client, source_t *source)
state
=
source
->
format
->
_state
;
thread_mutex_lock
(
&
(
state
->
lock
));
free
(
state
->
metadata
);
state
->
metadata
=
strdup
(
value
);
state
->
metadata_age
++
;
thread_mutex_unlock
(
&
(
state
->
lock
));
mp3_set_tag
(
source
->
format
,
"title"
,
value
);
DEBUG2
(
"Metadata on mountpoint %s changed to
\"
%s
\"
"
,
source
->
mount
,
value
);
...
...
src/cfgfile.c
View file @
9c44a7d1
...
...
@@ -339,7 +339,8 @@ static void _set_defaults(ice_config_t *configuration)
configuration
->
num_yp_directories
=
0
;
configuration
->
relay_username
=
NULL
;
configuration
->
relay_password
=
NULL
;
configuration
->
burst_on_connect
=
1
;
/* default to a typical prebuffer size used by clients */
configuration
->
burst_size
=
65536
;
}
static
void
_parse_root
(
xmlDocPtr
doc
,
xmlNodePtr
node
,
...
...
@@ -463,7 +464,12 @@ static void _parse_limits(xmlDocPtr doc, xmlNodePtr node,
if
(
tmp
)
xmlFree
(
tmp
);
}
else
if
(
strcmp
(
node
->
name
,
"burst-on-connect"
)
==
0
)
{
tmp
=
(
char
*
)
xmlNodeListGetString
(
doc
,
node
->
xmlChildrenNode
,
1
);
configuration
->
burst_on_connect
=
atoi
(
tmp
);
if
(
atoi
(
tmp
)
==
0
)
configuration
->
burst_size
=
0
;
if
(
tmp
)
xmlFree
(
tmp
);
}
else
if
(
strcmp
(
node
->
name
,
"burst-size"
)
==
0
)
{
tmp
=
(
char
*
)
xmlNodeListGetString
(
doc
,
node
->
xmlChildrenNode
,
1
);
configuration
->
burst_size
=
atoi
(
tmp
);
if
(
tmp
)
xmlFree
(
tmp
);
}
}
while
((
node
=
node
->
next
));
...
...
@@ -489,7 +495,9 @@ static void _parse_mount(xmlDocPtr doc, xmlNodePtr node,
else
configuration
->
mounts
=
mount
;
/* default <mount> settings */
mount
->
max_listeners
=
-
1
;
mount
->
burst_size
=
-
1
;
mount
->
next
=
NULL
;
do
{
...
...
@@ -574,6 +582,10 @@ static void _parse_mount(xmlDocPtr doc, xmlNodePtr node,
mount
->
source_timeout
=
atoi
(
tmp
);
xmlFree
(
tmp
);
}
}
else
if
(
strcmp
(
node
->
name
,
"burst-size"
)
==
0
)
{
tmp
=
(
char
*
)
xmlNodeListGetString
(
doc
,
node
->
xmlChildrenNode
,
1
);
mount
->
burst_size
=
atoi
(
tmp
);
if
(
tmp
)
xmlFree
(
tmp
);
}
}
while
((
node
=
node
->
next
));
}
...
...
src/cfgfile.h
View file @
9c44a7d1
...
...
@@ -54,8 +54,10 @@ typedef struct _mount_proxy {
clients from the fallback? */
int
no_mount
;
/* Do we permit direct requests of this mountpoint? (or only
indirect, through fallbacks) */
unsigned
queue_size_limit
;
unsigned
source_timeout
;
/* source timeout in seconds */
int
burst_size
;
/* amount to send to a new client if possible, -1 take
* from global setting */
unsigned
int
queue_size_limit
;
unsigned
int
source_timeout
;
/* source timeout in seconds */
char
*
auth_type
;
/* Authentication type */
config_options_t
*
auth_options
;
/* Options for this type */
...
...
@@ -84,8 +86,9 @@ typedef struct ice_config_tag
int
client_limit
;
int
source_limit
;
unsigned
queue_size_limit
;
unsigned
int
queue_size_limit
;
int
threadpool_size
;
unsigned
int
burst_size
;
int
client_timeout
;
int
header_timeout
;
int
source_timeout
;
...
...
@@ -133,7 +136,6 @@ typedef struct ice_config_tag
char
*
yp_url
[
MAX_YP_DIRECTORIES
];
int
yp_url_timeout
[
MAX_YP_DIRECTORIES
];
int
num_yp_directories
;
int
burst_on_connect
;
}
ice_config_t
;
typedef
struct
{
...
...
src/client.c
View file @
9c44a7d1
...
...
@@ -42,17 +42,14 @@ client_t *client_create(connection_t *con, http_parser_t *parser)
client
->
con
=
con
;
client
->
parser
=
parser
;
client
->
queue
=
NULL
;
client
->
refbuf
=
NULL
;
client
->
pos
=
0
;
client
->
burst_sent
=
0
;
return
client
;
}
void
client_destroy
(
client_t
*
client
)
{
refbuf_t
*
refbuf
;
if
(
client
==
NULL
)
return
;
/* write log entry if ip is set (some things don't set it, like outgoing
...
...
@@ -64,9 +61,9 @@ void client_destroy(client_t *client)
connection_close
(
client
->
con
);
httpp_destroy
(
client
->
parser
);
while
((
refbuf
=
refbuf_queue_remove
(
&
client
->
queue
)))
refbuf_release
(
refbuf
)
;
/* drop ref counts if need be */
if
(
client
->
refbuf
)
refbuf_release
(
client
->
refbuf
);
/* we need to free client specific format data (if any) */
if
(
client
->
free_client_data
)
client
->
free_client_data
(
client
);
...
...
@@ -144,3 +141,14 @@ int client_send_bytes (client_t *client, const void *buf, unsigned len)
return
ret
;
}
void
client_set_queue
(
client_t
*
client
,
refbuf_t
*
refbuf
)
{
refbuf_t
*
to_release
=
client
->
refbuf
;
client
->
refbuf
=
refbuf
;
refbuf_addref
(
client
->
refbuf
);
client
->
pos
=
0
;
if
(
to_release
)
refbuf_release
(
to_release
);
}
src/client.h
View file @
9c44a7d1
...
...
@@ -32,8 +32,9 @@ typedef struct _client_tag
/* http response code for this client */
int
respcode
;
/* buffer queue */
refbuf_queue_t
*
queue
;
/* where in the queue the client is */
refbuf_t
*
refbuf
;
/* position in first buffer */
unsigned
long
pos
;
...
...
@@ -45,7 +46,6 @@ typedef struct _client_tag
/* function to call to release format specific resources */
void
(
*
free_client_data
)(
struct
_client_tag
*
client
);
int
burst_sent
;
}
client_t
;
client_t
*
client_create
(
connection_t
*
con
,
http_parser_t
*
parser
);
...
...
@@ -56,5 +56,6 @@ void client_send_401(client_t *client);
void
client_send_403
(
client_t
*
client
);
void
client_send_400
(
client_t
*
client
,
char
*
message
);
int
client_send_bytes
(
client_t
*
client
,
const
void
*
buf
,
unsigned
len
);
void
client_set_queue
(
client_t
*
client
,
refbuf_t
*
refbuf
);
#endif
/* __CLIENT_H__ */
src/connection.c
View file @
9c44a7d1
...
...
@@ -465,9 +465,8 @@ int connection_complete_source (source_t *source)
"for icecast 1.x relays. Assuming content is mp3."
);
format_type
=
FORMAT_TYPE_MP3
;
}
source
->
format
=
format_get_plugin
(
format_type
,
source
->
mount
,
source
->
parser
);
if
(
source
->
format
==
NULL
)
if
(
format_get_plugin
(
format_type
,
source
)
<
0
)
{
global_unlock
();
config_release_config
();
...
...
@@ -483,6 +482,7 @@ int connection_complete_source (source_t *source)
/* set global settings first */
source
->
queue_size_limit
=
config
->
queue_size_limit
;
source
->
timeout
=
config
->
source_timeout
;
source
->
burst_size
=
config
->
burst_size
;
/* for relays, we don't yet have a client, however we do require one
* to retrieve the stream from. This is created here, quite late,
...
...
@@ -932,8 +932,7 @@ static void _handle_get_request(connection_t *con,
global
.
clients
++
;
global_unlock
();
client
->
format_data
=
source
->
format
->
create_client_data
(
source
->
format
,
source
,
client
);
source
->
format
->
create_client_data
(
source
,
client
);
source
->
format
->
client_send_headers
(
source
->
format
,
source
,
client
);
...
...
src/format.c
View file @
9c44a7d1
...
...
@@ -75,32 +75,22 @@ char *format_get_mimetype(format_type_t type)
}
}
format_plugin_t
*
format_get_plugin
(
format_type_t
type
,
char
*
mount
,
http_parser_t
*
parser
)
int
format_get_plugin
(
format_type_t
type
,
source_t
*
source
)
{
format_plugin_t
*
plugin
;
int
ret
=
-
1
;
switch
(
type
)
{
case
FORMAT_TYPE_VORBIS
:
plugin
=
format_vorbis_get_plugin
();
if
(
plugin
)
plugin
->
mount
=
mount
;
ret
=
format_vorbis_get_plugin
(
source
);
break
;
case
FORMAT_TYPE_MP3
:
plugin
=
format_mp3_get_plugin
(
parser
);
if
(
plugin
)
plugin
->
mount
=
mount
;
ret
=
format_mp3_get_plugin
(
source
);
break
;
default:
plugin
=
NULL
;
break
;
}
return
plugin
;
}
int
format_generic_write_buf_to_client
(
format_plugin_t
*
format
,
client_t
*
client
,
unsigned
char
*
buf
,
int
len
)
{
return
client_send_bytes
(
client
,
buf
,
len
);
return
ret
;
}
void
format_send_general_headers
(
format_plugin_t
*
format
,
...
...
src/format.h
View file @
9c44a7d1
...
...
@@ -45,13 +45,10 @@ typedef struct _format_plugin_tag
*/
int
has_predata
;
int
(
*
get_buffer
)(
struct
_format_plugin_tag
*
self
,
char
*
data
,
unsigned
long
len
,
refbuf_t
**
buffer
);
refbuf_queue_t
*
(
*
get_predata
)(
struct
_format_plugin_tag
*
self
);
int
(
*
write_buf_to_client
)(
struct
_format_plugin_tag
*
format
,
client_t
*
client
,
unsigned
char
*
buf
,
int
len
);
void
*
(
*
create_client_data
)(
struct
_format_plugin_tag
*
format
,
struct
source_tag
*
source
,
client_t
*
client
);
refbuf_t
*
(
*
get_buffer
)(
struct
source_tag
*
);
int
(
*
write_buf_to_client
)(
struct
_format_plugin_tag
*
format
,
client_t
*
client
);
void
(
*
write_buf_to_file
)(
struct
source_tag
*
source
,
refbuf_t
*
refbuf
);
int
(
*
create_client_data
)(
struct
source_tag
*
source
,
client_t
*
client
);
void
(
*
client_send_headers
)(
struct
_format_plugin_tag
*
format
,
struct
source_tag
*
source
,
client_t
*
client
);
void
(
*
free_plugin
)(
struct
_format_plugin_tag
*
self
);
...
...
@@ -62,11 +59,8 @@ typedef struct _format_plugin_tag
format_type_t
format_get_type
(
char
*
contenttype
);
char
*
format_get_mimetype
(
format_type_t
type
);
format_plugin_t
*
format_get_plugin
(
format_type_t
type
,
char
*
mount
,
http_parser_t
*
parser
);
int
format_get_plugin
(
format_type_t
type
,
struct
source_tag
*
source
);
int
format_generic_write_buf_to_client
(
format_plugin_t
*
format
,
client_t
*
client
,
unsigned
char
*
buf
,
int
len
);
void
format_send_general_headers
(
format_plugin_t
*
format
,
struct
source_tag
*
source
,
client_t
*
client
);
...
...
src/format_mp3.c
View file @
9c44a7d1
This diff is collapsed.
Click to expand it.
src/format_mp3.h
View file @
9c44a7d1
...
...
@@ -19,18 +19,23 @@
#define __FORMAT_MP3_H__
typedef
struct
{
char
*
metadata
;
int
metadata_age
;
mutex_t
lock
;
/* These are for inline metadata */
int
inline_metadata_interval
;
int
offset
;
int
metadata_length
;
char
*
metadata_buffer
;
int
metadata_offset
;
unsigned
interval
;
char
*
url_artist
;
char
*
url_title
;
int
update_metadata
;
refbuf_t
*
metadata
;
mutex_t
url_lock
;
unsigned
build_metadata_len
;
unsigned
build_metadata_offset
;
char
build_metadata
[
4081
];
}
mp3_state
;
format_plugin_t
*
format_mp3_get_plugin
(
http_parser_t
*
parser
);
int
format_mp3_get_plugin
(
struct
source_tag
*
src
);
void
mp3_set_tag
(
format_plugin_t
*
plugin
,
char
*
tag
,
char
*
value
);
#endif
/* __FORMAT_MP3_H__ */
src/format_vorbis.c
View file @
9c44a7d1
...
...
@@ -49,20 +49,31 @@ typedef struct _vstate_tag
ogg_page
og
;
unsigned
long
serialno
;
int
header
;
refbuf_t
*
headbuf
[
MAX_HEADER_PAGES
];
refbuf_t
*
file_headers
;
refbuf_t
*
header_pages
;
refbuf_t
*
header_pages_tail
;
int
packets
;
}
vstate_t
;
struct
client_vorbis
{
refbuf_t
*
headers
;
refbuf_t
*
header_page
;
unsigned
int
pos
;
int
processing_headers
;
};
static
void
format_vorbis_free_plugin
(
format_plugin_t
*
self
);
static
int
format_vorbis_get_buffer
(
format_plugin_t
*
self
,
char
*
data
,
unsigned
long
len
,
refbuf_t
**
buffer
);
static
refbuf_queue_t
*
format_vorbis_get_predata
(
format_plugin_t
*
self
);
static
void
*
format_vorbis_create_client_data
(
format_plugin_t
*
self
,
source_t
*
source
,
client_t
*
client
);
static
refbuf_t
*
format_vorbis_get_buffer
(
source_t
*
source
);
static
int
format_vorbis_create_client_data
(
source_t
*
source
,
client_t
*
client
);
static
void
format_vorbis_send_headers
(
format_plugin_t
*
self
,
source_t
*
source
,
client_t
*
client
);
static
int
write_buf_to_client
(
format_plugin_t
*
self
,
client_t
*
client
);
static
void
write_ogg_to_file
(
struct
source_tag
*
source
,
refbuf_t
*
refbuf
);
format_plugin_t
*
format_vorbis_get_plugin
(
void
)
int
format_vorbis_get_plugin
(
source_t
*
source
)
{
format_plugin_t
*
plugin
;
vstate_t
*
state
;
...
...
@@ -70,10 +81,9 @@ format_plugin_t *format_vorbis_get_plugin(void)
plugin
=
(
format_plugin_t
*
)
malloc
(
sizeof
(
format_plugin_t
));
plugin
->
type
=
FORMAT_TYPE_VORBIS
;
plugin
->
has_predata
=
1
;
plugin
->
write_buf_to_file
=
write_ogg_to_file
;
plugin
->
get_buffer
=
format_vorbis_get_buffer
;
plugin
->
get_predata
=
format_vorbis_get_predata
;
plugin
->
write_buf_to_client
=
format_generic_write_buf_to_client
;
plugin
->
write_buf_to_client
=
write_buf_to_client
;
plugin
->
create_client_data
=
format_vorbis_create_client_data
;
plugin
->
client_send_headers
=
format_vorbis_send_headers
;
plugin
->
free_plugin
=
format_vorbis_free_plugin
;
...
...
@@ -83,52 +93,67 @@ format_plugin_t *format_vorbis_get_plugin(void)
ogg_sync_init
(
&
state
->
oy
);
plugin
->
_state
=
(
void
*
)
state
;
source
->
format
=
plugin
;
return
plugin
;
return
0
;
}
void
format_vorbis_free_plugin
(
format_plugin_t
*
self
)
{
int
i
;
vstate_t
*
state
=
(
vstate_t
*
)
self
->
_state
;
refbuf_t
*
header
=
state
->
header_pages
;
/* free memory associated with this plugin instance */
/* free state memory */
while
(
header
)
{
refbuf_t
*
to_release
=
header
;
header
=
header
->
next
;
refbuf_release
(
to_release
);
}
ogg_sync_clear
(
&
state
->
oy
);
ogg_stream_clear
(
&
state
->
os
);
vorbis_comment_clear
(
&
state
->
vc
);
vorbis_info_clear
(
&
state
->
vi
);
for
(
i
=
0
;
i
<
MAX_HEADER_PAGES
;
i
++
)
{
if
(
state
->
headbuf
[
i
])
{
refbuf_release
(
state
->
headbuf
[
i
]);
state
->
headbuf
[
i
]
=
NULL
;
}
}
free
(
state
);
/* free the plugin instance */
free
(
self
);
}
in
t
format_vorbis_get_buffer
(
format_plugin_t
*
self
,
char
*
data
,
unsigned
long
len
,
refbuf_t
**
buffer
)
static
refbuf_
t
*
format_vorbis_get_buffer
(
source_t
*
source
)
{
char
*
buf
;
int
i
,
result
;
int
result
;
ogg_packet
op
;
char
*
tag
;
refbuf_t
*
refbuf
,
*
source_refbuf
;
refbuf_t
*
refbuf
,
*
header
;
char
*
data
;
format_plugin_t
*
self
=
source
->
format
;
int
bytes
;
vstate_t
*
state
=
(
vstate_t
*
)
self
->
_state
;
source_t
*
source
;
if
(
data
)
{
/* write the data to the buffer */
buf
=
ogg_sync_buffer
(
&
state
->
oy
,
len
);
memcpy
(
buf
,
data
,
len
);
ogg_sync_wrote
(
&
state
->
oy
,
len
);
data
=
ogg_sync_buffer
(
&
state
->
oy
,
4096
);
bytes
=
sock_read_bytes
(
source
->
con
->
sock
,
data
,
4096
);
if
(
bytes
<
0
)
{
if
(
sock_recoverable
(
sock_error
()))
return
NULL
;
WARN0
(
"source connection has died"
);
ogg_sync_wrote
(
&
state
->
oy
,
0
);
source
->
running
=
0
;
return
NULL
;
}
if
(
bytes
==
0
)
{
INFO1
(
"End of Stream %s"
,
source
->
mount
);
ogg_sync_wrote
(
&
state
->
oy
,
0
);
source
->
running
=
0
;
return
NULL
;
}
ogg_sync_wrote
(
&
state
->
oy
,
bytes
);
refbuf
=
NULL
;
if
(
ogg_sync_pageout
(
&
state
->
oy
,
&
state
->
og
)
==
1
)
{
...
...
@@ -137,21 +162,25 @@ int format_vorbis_get_buffer(format_plugin_t *self, char *data, unsigned long le
memcpy
(
&
refbuf
->
data
[
state
->
og
.
header_len
],
state
->
og
.
body
,
state
->
og
.
body_len
);
if
(
state
->
serialno
!=
ogg_page_serialno
(
&
state
->
og
))
{
DEBUG0
(
"new stream"
);
/* this is a new logical bitstream */
state
->
header
=
0
;
state
->
packets
=
0
;
/* release old headers, stream state, vorbis data */
for
(
i
=
0
;
i
<
MAX_HEADER_PAGES
;
i
++
)
{
if
(
state
->
headbuf
[
i
])
{
refbuf_release
(
state
->
headbuf
[
i
]);
state
->
headbuf
[
i
]
=
NULL
;
}
}
/* Clear old stuff. Rarely but occasionally needed. */
header
=
state
->
header_pages
;
while
(
header
)
{
refbuf_t
*
to_release
=
header
;
DEBUG0
(
"clearing out header page"
);
header
=
header
->
next
;
refbuf_release
(
to_release
);
}
ogg_stream_clear
(
&
state
->
os
);
vorbis_comment_clear
(
&
state
->
vc
);
vorbis_info_clear
(
&
state
->
vi
);
state
->
header_pages
=
NULL
;
state
->
header_pages_tail
=
NULL
;
state
->
serialno
=
ogg_page_serialno
(
&
state
->
og
);
ogg_stream_init
(
&
state
->
os
,
state
->
serialno
);
...
...
@@ -164,52 +193,40 @@ int format_vorbis_get_buffer(format_plugin_t *self, char *data, unsigned long le
* extras pages beyond the header. We need to collect the pages
* here anyway, but they may have to be discarded later.
*/
DEBUG1
(
"header %d"
,
state
->
header
);
if
(
ogg_page_granulepos
(
&
state
->
og
)
<=
0
)
{
state
->
header
++
;
}
else
{
/* we're done caching headers */
state
->
header
=
-
1
;
DEBUG0
(
"doing stats"
);
/* put known comments in the stats */
tag
=
vorbis_comment_query
(
&
state
->
vc
,
"TITLE"
,
0
);
if
(
tag
)
stats_event
(
s
elf
->
mount
,
"title"
,
tag
);
else
stats_event
(
s
elf
->
mount
,
"title"
,
"unknown"
);
if
(
tag
)
stats_event
(
s
ource
->
mount
,
"title"
,
tag
);
else
stats_event
(
s
ource
->
mount
,
"title"
,
"unknown"
);
tag
=
vorbis_comment_query
(
&
state
->
vc
,
"ARTIST"
,
0
);
if
(
tag
)
stats_event
(
s
elf
->
mount
,
"artist"
,
tag
);
else
stats_event
(
s
elf
->
mount
,
"artist"
,
"unknown"
);
if
(
tag
)
stats_event
(
s
ource
->
mount
,
"artist"
,
tag
);
else
stats_event
(
s
ource
->
mount
,
"artist"
,
"unknown"
);
/* don't need these now */
ogg_stream_clear
(
&
state
->
os
);
vorbis_comment_clear
(
&
state
->
vc
);
vorbis_info_clear
(
&
state
->
vi
);
/* Drain the source queue on metadata update otherwise you
could have a mismatch between what is on the source queue
and what is in the state->headbuf */
avl_tree_rlock
(
global
.
source_tree
);
source
=
source_find_mount_raw
(
self
->
mount
);
avl_tree_unlock
(
global
.
source_tree
);
thread_mutex_lock
(
&
source
->
queue_mutex
);
while
((
source_refbuf
=
refbuf_queue_remove
(
&
source
->
queue
)))
{
refbuf_release
(
source_refbuf
);
}
thread_mutex_unlock
(
&
source
->
queue_mutex
);
yp_touch
(
self
->
mount
);
yp_touch
(
source
->
mount
);
}
}
/* cache header pages */
if
(
state
->
header
>
0
&&
state
->
packets
<
3
)
{
if
(
state
->
header
>
MAX_HEADER_PAGES
)
{
refbuf_release
(
refbuf
);
ERROR1
(
"Bad vorbis input: header is more than %d pages long"
,
MAX_HEADER_PAGES
);
/* build a list of headers pages for attaching */
if
(
state
->
header_pages_tail
)
state
->
header_pages_tail
->
next
=
refbuf
;
state
->
header_pages_tail
=
refbuf
;
return
-
1
;
}
refbuf_addref
(
refbuf
);
state
->
headbuf
[
state
->
header
-
1
]
=
refbuf
;
if
(
state
->
header_pages
==
NULL
)
state
->
header_pages
=
refbuf
;
if
(
state
->
packets
>=
0
&&
state
->
packets
<
3
)
{
ogg_stream_pagein
(
&
state
->
os
,
&
state
->
og
);
...
...
@@ -229,36 +246,40 @@ int format_vorbis_get_buffer(format_plugin_t *self, char *data, unsigned long le
}
}
}
/* we do not place ogg headers on the main queue */
return
NULL
;
}
/* increase ref counts on each header page going out */
header
=
state
->
header_pages
;
while
(
header
)
{
refbuf_addref
(
header
);
header
=
header
->
next
;
}
refbuf
->
associated
=
state
->
header_pages
;
}
*
buffer
=
refbuf
;
return
0
;
return
refbuf
;
}
refbuf_queue_t
*
format_vorbis_get_predata
(
format_plugin_t
*
self
)
static
void
free_ogg_client_data
(
client_t
*
client
)
{
refbuf_queue_t
*
queue
;
int
i
;
vstate_t
*
state
=
(
vstate_t
*
)
self
->
_state
;
queue
=
NULL
;
for
(
i
=
0
;
i
<
MAX_HEADER_PAGES
;
i
++
)
{
if
(
state
->
headbuf
[
i
])
{
refbuf_addref
(
state
->
headbuf
[
i
]);
refbuf_queue_add
(
&
queue
,
state
->
headbuf
[
i
]);
}
else
{
break
;
}
}
return
queue
;
free
(
client
->
format_data
);
client
->
format_data
=
NULL
;
}
static
void
*
format_vorbis_create_client_data
(
format_plugin_t
*
self
,
source_t
*
source
,
client_t
*
client
)
static
int
format_vorbis_create_client_data
(
source_t
*
source
,
client_t
*
client
)
{
return
NULL
;
struct
client_vorbis
*
client_data
=
calloc
(
1
,
sizeof
(
struct
client_vorbis
));
int
ret
=
-
1
;
if
(
client_data
)
{
client
->
format_data
=
client_data
;
client
->
free_client_data
=
free_ogg_client_data
;
ret
=
0
;
}
return
ret
;
}
static
void
format_vorbis_send_headers
(
format_plugin_t
*
self
,
...
...
@@ -277,4 +298,122 @@ static void format_vorbis_send_headers(format_plugin_t *self,
format_send_general_headers
(
self
,
source
,
client
);
}
static
int
send_ogg_headers
(
client_t
*
client
,
refbuf_t
*
headers
)
{
struct
client_vorbis
*
client_data
=
client
->
format_data
;
refbuf_t
*
refbuf
;
int
written
=
0
;
if
(
client_data
->
processing_headers
==
0
)
{
client_data
->
header_page
=
headers
;
client_data
->
pos
=
0
;
client_data
->
processing_headers
=
1
;
}
refbuf
=
client_data
->
header_page
;
while
(
refbuf
)
{
char
*
data
=
refbuf
->
data
+
client_data
->
pos
;
unsigned
int
len
=
refbuf
->
len
-
client_data
->
pos
;
int
ret
;
ret
=
client_send_bytes
(
client
,
data
,
len
);
if
(
ret
>
0
)
{
written
+=