1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
|
/*************************************************************
*
* streaming external for PD
*
* File: streamogg.cpp
*
* Description: Implementation of the streamer class for OGG/vorbis
*
* Author: Thomas Grill (t.grill@gmx.net)
*
*************************************************************/
#include "streamogg.h"
// explicit definition of report functions
extern "C" {
extern void post(char *fmt, ...);
extern void error(char *fmt, ...);
}
StreamOGG::StreamOGG():
ov_inf(NULL),ov_comm(NULL)
{
// set OGG callbacks
callbacks.read_func = read_func;
callbacks.seek_func = seek_func;
callbacks.close_func = close_func;
callbacks.tell_func = tell_func;
}
void StreamOGG::Reset()
{
Stream::Reset();
ov_inf = NULL;
ov_comm = NULL;
}
std::string StreamOGG::getTag(const char *tag) const
{
const char *c = NULL;
if(ov_comm) c = vorbis_comment_query(ov_comm,const_cast<char *>(tag),0);
return c?c:"";
}
#define MAXINITTRIES 5
bool StreamOGG::WorkInit()
{
bool ok = true;
// read in enough data to represent the OGG header
char hdrbuf[8500];
int i,need = sizeof hdrbuf;
for(i = MAXINITTRIES; i > 0 && need > 0; ) {
int n = ReadChunk(hdrbuf,need,true);
if(n)
need -= n;
else {
--i;
if(debug) post("Try to init again (%i)....",i);
}
}
if(!i) ok = false;
// got n bytes into fifo
if(ok && ov_open_callbacks(this,&ov_file,hdrbuf,sizeof hdrbuf,callbacks) < 0 ) {
post("Header format error");
ok = false;
}
else {
ov_inf = ov_info(&ov_file,-1);
ov_comm = ov_comment(&ov_file,-1);
}
return ok;
}
int StreamOGG::DataRead(int frames)
{
int current_section;
return ov_read_float(&ov_file,&bufs,frames,¤t_section);
}
size_t StreamOGG::read_func(void *ptr, size_t size, size_t nmemb, void *datasource)
{
StreamOGG *str = (StreamOGG *)datasource;
if(!str->isInitializing()) pthread_mutex_lock(&str->mutex);
int ret = str->encoded.Read(size*nmemb,(char *)ptr);
if(str->debug) post("read %i of %i bytes from fifo",ret,size*nmemb);
if(!str->isInitializing()) pthread_mutex_unlock(&str->mutex);
return ret;
}
int StreamOGG::close_func(void *datasource)
{
post("Closing stream");
StreamOGG *str = (StreamOGG *)datasource;
pthread_mutex_lock(&str->mutex);
str->Reset();
pthread_mutex_unlock(&str->mutex);
return 0;
}
|