Add Russian translation provided by Валерий Крувялис <valkru@mail.ru>
[xiph-mirror.git] / vorbis-plugins / kmpg / vorbisPlugin.cpp
blob0a2b7b4546013b026147853b4e188a60f88babb1
1 /*
2 vorbis player plugin
3 Copyright (C) 2000 Martin Vogt
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation.
9 For more information look at the file COPYRIGHT in this package
14 #include "vorbisPlugin.h"
16 size_t fread_func(void *ptr, size_t size, size_t nmemb, void *stream) {
17 InputStream* input=(InputStream*) stream;
18 return input->read((char*)ptr,size*nmemb);
22 int fseek_func(void *stream, ogg_int64_t offset, int whence) {
23 int ret;
24 InputStream* input=(InputStream*) stream;
26 if (whence==SEEK_SET) {
27 ret=input->seek(offset);
28 return ret;
30 if (whence==SEEK_CUR) {
31 ret=input->seek(input->getBytePosition()+offset);
32 return ret;
34 if (whence==SEEK_END) {
35 ret=input->seek(input->getByteLength());
36 return ret;
38 cout << "hm, strange call"<<endl;
39 return -1;
43 int fclose_func (void *stream) {
44 InputStream* input=(InputStream*) stream;
46 // its handled different in kmpg
47 // we close the stream if the decoder signals eof.
48 return true;
53 long ftell_func (void *stream) {
54 InputStream* input=(InputStream*) stream;
55 return input->getBytePosition();
59 VorbisPlugin::VorbisPlugin() {
62 timeDummy=new TimeStamp();
63 pcmout=new char[4096];
64 lnoLength=false;
65 lshutdown=true;
70 VorbisPlugin::~VorbisPlugin() {
71 delete timeDummy;
72 delete pcmout;
76 // here we can config our decoder with special flags
77 void VorbisPlugin::config(char* key, char* value,void* user_data) {
79 if (strcmp(key,"-c")==0) {
80 lnoLength=true;
82 DecoderPlugin::config(key,value,user_data);
86 int VorbisPlugin::init() {
87 ov_callbacks callbacks;
89 callbacks.read_func = fread_func;
90 callbacks.seek_func = fseek_func;
91 callbacks.close_func = fclose_func;
92 callbacks.tell_func = ftell_func;
94 // here is the hack to pass the pointer to
95 // our streaming interface.
97 if(ov_open_callbacks(input, &vf, NULL, 0, callbacks) < 0) {
98 return false;
101 return true;
105 // called by decoder thread
106 int VorbisPlugin::processVorbis(vorbis_info* vi,vorbis_comment* comment) {
108 // decode
109 int ret;
110 int current_section=-1; /* A vorbis physical bitstream may
111 consist of many logical sections
112 (information for each of which may be
113 fetched from the vf structure). This
114 value is filled in by ov_read to alert
115 us what section we're currently
116 decoding in case we need to change
117 playback settings at a section
118 boundary */
119 ret=ov_read(&vf,pcmout,4096,0,2,1,&current_section);
120 switch(ret){
121 case 0:
122 /* EOF */
123 lDecoderLoop=false;
124 break;
125 case -1:
126 /* error in the stream. Not a problem, just reporting it in
127 case we (the app) cares. In this case, we don't. */
128 break;
129 default:
130 if(current_section!=last_section){
131 vi=ov_info(&vf,-1); /* The info struct is different in each
132 section. vf holds them all for the
133 given bitstream. This requests the
134 current one */
136 double timeoffset=ov_time_tell(&vf);
138 comment = ov_comment(&vf, -1);
139 if(comment) {
140 cout << "we have a comment"<<endl;
143 last_section=current_section;
144 output->audioPlay(timeDummy,timeDummy,pcmout,ret);
145 break;
147 return true;
151 void VorbisPlugin::decoder_loop() {
152 vorbis_info *vi=NULL;
153 vorbis_comment *comment;
154 last_section=0;
155 current_section=0;
159 if (input == NULL) {
160 cout << "VorbisPlugin::decoder_loop input is NULL"<<endl;
161 exit(0);
163 if (output == NULL) {
164 cout << "VorbisPlugin::decoder_loop output is NULL"<<endl;
165 exit(0);
167 // init audio stream
168 output->audioInit();
170 /********** Decode setup ************/
171 // start decoding
172 lshutdown=false;
173 while(runCheck()) {
175 switch(streamState) {
176 case _STREAM_STATE_FIRST_INIT :
177 if (init()== false) {
178 // total failure. exit decoding
179 lDecoderLoop=false;
180 break;
182 // now init stream
183 vi=ov_info(&vf,-1);
184 if (lnoLength==false) {
185 pluginInfo->setLength(getTotalLength());
186 output->writeInfo(pluginInfo);
188 output->audioSetup(vi->rate,vi->channels-1,1,0,16);
189 lhasLength=true;
190 setStreamState(_STREAM_STATE_PLAY);
191 break;
192 case _STREAM_STATE_INIT :
193 case _STREAM_STATE_PLAY :
194 processVorbis(vi,comment);
195 break;
196 case _STREAM_STATE_WAIT_FOR_END:
197 // exit while loop
198 lDecoderLoop=false;
199 break;
200 default:
201 cout << "unknown stream state vorbis decoder:"<<streamState<<endl;
204 lshutdown=true;
205 ov_clear(&vf); /* ov_clear closes the stream if its open. Safe to
206 call on an uninitialized structure as long as
207 we've zeroed it */
210 output->audioFlush();
213 // vorbis can seek in streams
214 int VorbisPlugin::seek_impl(int second) {
215 ov_time_seek(&vf,(double) second);
216 return true;
221 int VorbisPlugin::getTotalLength() {
222 int back=0;
223 int byteLen=input->getByteLength();
224 if (byteLen == 0) {
225 return 0;
227 /* Retrieve the length in second*/
228 shutdownLock();
229 if (lshutdown==false) {
230 back = (int) ov_time_total(&vf, -1);
232 shutdownUnlock();
234 return back;