1 /*
2 TiMidity++ -- MIDI to WAVE converter and player
3 Copyright (C) 1999-2002 Masanao Izumo <mo@goice.co.jp>
4 Copyright (C) 1995 Tuukka Toivonen <tt@cgs.fi>
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
20 gogo_a.c
21
22 Functions to output mp3 by gogo.lib or gogo.dll.
23 */
24
25 #ifdef HAVE_CONFIG_H
26 #include "config.h"
27 #endif /* HAVE_CONFIG_H */
28 #ifdef __POCC__
29 #include <sys/types.h>
30 #endif //for off_t
31 #include "interface.h"
32 #include <stdio.h>
33 #include <stdlib.h>
34
35 #ifdef AU_GOGO
36
37 #ifdef __W32__
38 #include <io.h>
39 #include <windows.h>
40 #include <process.h>
41 #endif
42
43 #ifdef HAVE_UNISTD_H
44 #include <unistd.h>
45 #endif /* HAVE_UNISTD_H */
46
47 #ifndef NO_STRING_H
48 #include <string.h>
49 #else
50 #include <strings.h>
51 #endif
52 #include <fcntl.h>
53
54 /* #include <musenc.h> /* for gogo */
55 #include <gogo/gogo.h> /* for gogo */
56
57 #include "w32_gogo.h"
58 #include "gogo_a.h"
59
60 #include "timidity.h"
61 #include "common.h"
62 #include "output.h"
63 #include "controls.h"
64 #include "instrum.h"
65 #include "playmidi.h"
66 #include "readmidi.h"
67
68 #if defined(__W32__) && !defined ( IA_W32GUI ) && !defined ( IA_W32G_SYN )
69 #include "w32g.h" //for crt_beginthreadex();
70 #endif
71
72 static int open_output(void); /* 0=success, 1=warning, -1=fatal error */
73 static void close_output(void);
74 static int output_data(char *buf, int32 bytes);
75 static int acntl(int request, void *arg);
76
77 /* export the playback mode */
78 #define dpm gogo_play_mode
79
80 PlayMode dpm = {
81 DEFAULT_RATE,
82 #ifdef LITTLE_ENDIAN
83 PE_16BIT|PE_SIGNED,
84 #else
85 PE_16BIT|PE_SIGNED|PE_BYTESWAP,
86 #endif
87 PF_PCM_STREAM|PF_FILE_OUTPUT,
88 -1,
89 {0,0,0,0,0},
90 "MP3 GOGO", 'g',
91 NULL,
92 open_output,
93 close_output,
94 output_data,
95 acntl
96 };
97 static char *tag_title = NULL;
98
99 #if defined ( IA_W32GUI ) || defined ( IA_W32G_SYN )
100 #if defined(_MSC_VER) || defined(__WATCOMC__)
101 //typedef void (__cdecl *MSVC_BEGINTHREAD_START_ADDRESS)(void *);
102 typedef LPTHREAD_START_ROUTINE MSVC_BEGINTHREAD_START_ADDRESS;
103 #elif defined(_BORLANDC_)
104 // typedef _USERENTRY (*BCC_BEGINTHREAD_START_ADDRESS)(void *);
105 typedef LPTHREAD_START_ROUTINE BCC_BEGINTHREAD_START_ADDRESS;
106 #endif
107 // (HANDLE)crt_beginthreadex(LPSECURITY_ATTRIBUTES security, DWORD stack_size, LPTHREAD_START_ROUTINE start_address, LPVOID arglist, DWORD initflag, LPDWORD thrdaddr );
108 #if defined(_MSC_VER) || defined(__WATCOMC__)
109 #define crt_beginthreadex(security,stack_size,start_address,arglist,initflag,thrdaddr ) \
110 (HANDLE)_beginthreadex((void *)security,(unsigned)stack_size,(MSVC_BEGINTHREAD_START_ADDRESS)start_address,(void *)arglist,(unsigned)initflag,(unsigned *)thrdaddr)
111 #elif defined(_BORLANDC_)
112 #define crt_beginthreadex(security,stack_size,start_address,arglist,initflag,thrdaddr ) \
113 (HANDLE)_beginthreadNT((BCC_BEGINTHREAD_START_ADDRESS)start_address,(unsigned)stack_size,(void *)arglist,(void *)security_attrib,(unsigned long)create_flags,(unsigned long *)thread_id)
114 #else
115 #define crt_beginthreadex(security,stack_size,start_address,arglist,initflag,thrdaddr ) \
116 (HANDLE)CreateThread((LPSECURITY_ATTRIBUTES)security,(DWORD)stack_size,(LPTHREAD_START_ROUTINE)start_address,(LPVOID)arglist,(DWORD)initflag,(LPDWORD)thrdaddr)
117 #endif
118
119 volatile extern char *w32g_output_dir;
120 volatile extern int w32g_auto_output_mode;
121
122 extern int gogo_ConfigDialogInfoApply(void);
123 #endif
124
125 #ifdef __W32__
126 volatile static HANDLE hMPGEthread = NULL;
127 volatile static HANDLE hMutexgogo = NULL;
128 volatile static DWORD dwMPGEthreadID = 0;
129 #endif
130
131 volatile gogo_opts_t gogo_opts;
132
133 /*************************************************************************/
134
gogo_error(MERET rval)135 static int gogo_error(MERET rval)
136 {
137 switch(rval){
138 case ME_NOERR:
139 ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "gogo_a : return normally (%d).",rval);
140 break;
141 case ME_EMPTYSTREAM:
142 ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "gogo_a : stream becomes empty (%d).",rval);
143 break;
144 case ME_HALTED:
145 ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "gogo_a : stopped by user (%d).",rval);
146 break;
147 case ME_INTERNALERROR:
148 ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "gogo_a : internal error (%d).",rval);
149 break;
150 case ME_PARAMERROR:
151 ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "gogo_a : parameters error (%d).",rval);
152 break;
153 case ME_NOFPU:
154 ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "gogo_a : no FPU (%d).",rval);
155 break;
156 case ME_INFILE_NOFOUND:
157 ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "gogo_a : can't open input file (%d).",rval);
158 break;
159 case ME_OUTFILE_NOFOUND:
160 ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "gogo_a : can't open output file (%d).",rval);
161 break;
162 case ME_FREQERROR:
163 ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "gogo_a : frequency is not good (%d).",rval);
164 break;
165 case ME_BITRATEERROR :
166 ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "gogo_a : bitrate is not good (%d).",rval);
167 break;
168 case ME_WAVETYPE_ERR:
169 ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "gogo_a : WAV format is not good (%d).",rval);
170 break;
171 case ME_CANNOT_SEEK:
172 ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "gogo_a : can't seek (%d).",rval);
173 break;
174 case ME_BITRATE_ERR:
175 ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "gogo_a : only for compatibility (%d).",rval);
176 break;
177 case ME_BADMODEORLAYER:
178 ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "gogo_a : mode/layer not good (%d).",rval);
179 break;
180 case ME_NOMEMORY:
181 ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "gogo_a : fail to allocate memory (%d).",rval);
182 break;
183 case ME_CANNOT_SET_SCOPE:
184 ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "gogo_a : thread error (%d).",rval);
185 break;
186 case ME_CANNOT_CREATE_THREAD:
187 ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "gogo_a : fail to create thear (%d).",rval);
188 break;
189 case ME_WRITEERROR:
190 ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "gogo_a : lack of capacity of disk (%d).",rval);
191 break;
192 default:
193 ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "gogo_a : unknown error (%d).",rval);
194 break;
195 }
196 return 0;
197 }
198
199 /* mode
200 0,1: Default mode.
201 2: Remove the directory path of input_filename, then add output_dir.
202 3: Replace directory separator characters ('/','\',':') with '_', then add output_dir.
203 */
204 extern char *create_auto_output_name(const char *input_filename, char *ext_str, char *output_dir, int mode);
205
206 volatile static int gogo_lock_flag = 0;
gogo_lock()207 static int gogo_lock()
208 {
209 #ifndef __W32__
210 while(gogo_lock_flag){
211 usleep(100);
212 }
213 gogo_lock_flag++;
214 return 0;
215 #else
216 if(hMutexgogo==NULL){
217 hMutexgogo = CreateMutex(NULL,FALSE,NULL);
218 if(hMutexgogo==NULL)
219 return -1;
220 }
221 if(WaitForSingleObject(hMutexgogo,INFINITE)==WAIT_FAILED){
222 return -1;
223 }
224 return 0;
225 #endif
226 }
227
gogo_unlock()228 static int gogo_unlock()
229 {
230 #ifndef __W32__
231 if(gogo_lock_flag)
232 gogo_lock_flag--;
233 return 0;
234 #else
235 if(hMutexgogo!=NULL){
236 ReleaseMutex(hMutexgogo);
237 Sleep(0);
238 }
239 return 0;
240 #endif
241 }
242
243 //volatile int32 gogo_buffer_size = 1024*1024;
244 volatile int32 gogo_buffer_size = 1024*256;
245 volatile static char *gogo_buffer = NULL; // loop buffer
246 volatile static char *gogo_buffer_from = NULL;
247 volatile static char *gogo_buffer_start = NULL;
248 volatile static char *gogo_buffer_end = NULL;
249 volatile static int32 gogo_buffer_cur_size = 0;
250 volatile static int gogo_buffer_termination = 0;
251
252 volatile int gogo_buffer_initflag = 0;
gogo_buffer_init(void)253 static void gogo_buffer_init(void)
254 {
255 gogo_lock();
256 if(!gogo_buffer_initflag){
257 gogo_buffer = (char *)safe_malloc(sizeof(char)*(gogo_buffer_size+1));
258 gogo_buffer_from = gogo_buffer;
259 gogo_buffer_start = gogo_buffer;
260 gogo_buffer_end = gogo_buffer + gogo_buffer_size - 1;
261 gogo_buffer_cur_size = 0;
262 }
263 gogo_buffer_initflag = 1;
264 gogo_unlock();
265 }
gogo_buffer_reset(void)266 static void gogo_buffer_reset(void)
267 {
268 gogo_lock();
269 if(!gogo_buffer_initflag)
270 gogo_buffer_init();
271 gogo_buffer_from = gogo_buffer;
272 gogo_buffer_cur_size = 0;
273 gogo_unlock();
274 }
275
276 // �����m�[�`�F�b�N
277 // gogo_buffer_cur_size �܂� buf �� gogo_buffer �̓��e�� size ����
278 // �R�s�[����Bmoveflag ������Ƃ��́A�R�s�[����������
279 // gogo_buffer_from �� gogo_buffer_cur_size ��ω�������B
280 // �R�s�[�����T�C�Y��Ԃ��B
__gogo_buffer_copy(char * buf,int32 size,int moveflag)281 static int32 __gogo_buffer_copy(char *buf, int32 size, int moveflag)
282 {
283 int i;
284 int32 size1, ret = 0;
285 gogo_buffer_init();
286 if(size>gogo_buffer_cur_size)
287 size = gogo_buffer_cur_size;
288 for(i=0;i<2;i++){
289 size1 = gogo_buffer_end-gogo_buffer_from+1;
290 if(size<=size1)
291 size1 = size;
292 memcpy(buf,(char *)gogo_buffer_from,size1);
293 ret += size1;
294 size -= size1;
295 buf += size1;
296 if(moveflag){
297 gogo_buffer_from += size1;
298 if(gogo_buffer_from>=gogo_buffer_end+1)
299 gogo_buffer_from = gogo_buffer_start;
300 gogo_buffer_cur_size -= size1;
301 }
302 if(size<=0){
303 return ret;
304 }
305 }
306 return ret;
307 }
308
309 // �����m�[�`�F�b�N
310 // gogo_buffer_cur_size �܂� buf �̓��e�� size ���� gogo_buffer ��
311 // �i�[����B�i�[�����T�C�Y��Ԃ��B
__gogo_buffer_push(char * buf,int32 size)312 static int32 __gogo_buffer_push(char *buf, int32 size)
313 {
314 int i;
315 int32 size1, ret = 0;
316 char *gogo_buffer_pointer;
317 gogo_buffer_init();
318 if(size>gogo_buffer_size-gogo_buffer_cur_size)
319 size = gogo_buffer_size-gogo_buffer_cur_size;
320 if(gogo_buffer+gogo_buffer_size>gogo_buffer_from+gogo_buffer_cur_size){
321 gogo_buffer_pointer = (char *)gogo_buffer_from + gogo_buffer_cur_size;
322 i = 0;
323 } else {
324 gogo_buffer_pointer = (char *)gogo_buffer_from+gogo_buffer_cur_size-gogo_buffer_size;
325 i = 1;
326 }
327 for(;i<2;i++){
328 size1 = gogo_buffer_end-gogo_buffer_pointer+1;
329 if(size<=size1)
330 size1 = size;
331 memcpy(gogo_buffer_pointer,buf,size1);
332 ret += size1;
333 size -= size1;
334 buf += size1;
335 gogo_buffer_cur_size += size1;
336 gogo_buffer_pointer += size1;
337 if(gogo_buffer_pointer>=gogo_buffer_end+1)
338 gogo_buffer_pointer = (char *)gogo_buffer_start;
339 if(size<=0)
340 return ret;
341 }
342 return ret;
343 }
344
gogoUserFunc(char * buf,unsigned long nLength)345 static int __cdecl gogoUserFunc(char *buf, unsigned long nLength )
346 {
347 int flag = 0;
348 gogo_buffer_init();
349 if(buf==NULL || nLength==0){
350 if(!gogo_buffer_termination)
351 gogo_buffer_termination = 1;
352 return ME_NOERR;
353 }
354 for(;;){
355 int32 size;
356 if(gogo_buffer_termination<0){
357 return ME_EMPTYSTREAM;
358 }
359 if(gogo_lock()){
360 gogo_buffer_termination = -1;
361 return ME_EMPTYSTREAM;
362 }
363 size = __gogo_buffer_copy(buf,nLength,1);
364 buf += size;
365 nLength -= size;
366 if(nLength<=0){
367 gogo_unlock();
368 if(size>0)
369 return ME_NOERR;
370 else
371 return ME_EMPTYSTREAM;
372 }
373 if(gogo_buffer_termination>0){
374 gogo_unlock();
375 if(size>0 && nLength>0){
376 if(dpm.encoding & PE_16BIT){
377 memset(buf,0x00,nLength);
378 } else {
379 memset(buf,0x80,nLength);
380 }
381 return ME_NOERR;
382 } else {
383 return ME_EMPTYSTREAM;
384 }
385 }
386 if(gogo_buffer_termination<0){
387 gogo_unlock();
388 return ME_EMPTYSTREAM;
389 }
390 if(gogo_buffer_cur_size<=0){
391 gogo_unlock();
392 #ifndef __W32__
393 usleep(100);
394 #else
395 Sleep(0);
396 Sleep(100);
397 #endif
398 } else {
399 gogo_unlock();
400 }
401 }
402 }
403
gogo_opts_reset(void)404 void gogo_opts_reset(void)
405 {
406 gogo_opts.optENCODEMODE = -1;
407 gogo_opts.optINPFREQ = -1;
408 gogo_opts.optOUTFREQ = -1;
409 gogo_opts.optSTARTOFFSET = -1;
410 gogo_opts.optUSEPSY = -1;
411 gogo_opts.optUSELPF16 = -1;
412 gogo_opts.optUSEMMX = -1;
413 gogo_opts.optUSE3DNOW = -1;
414 gogo_opts.optUSEKNI = -1;
415 gogo_opts.optUSEE3DNOW = -1;
416 gogo_opts.optADDTAGnum = 0; // �lj����邽�тɃC���N�������g����邽�߃f�t�H���g��0
417 gogo_opts.optEMPHASIS = -1;
418 gogo_opts.optVBR = -1;
419 gogo_opts.optCPU = -1;
420 gogo_opts.optBYTE_SWAP = -1;
421 gogo_opts.opt8BIT_PCM = -1;
422 gogo_opts.optMONO_PCM = -1;
423 gogo_opts.optTOWNS_SND = -1;
424 gogo_opts.optTHREAD_PRIORITY = -10000;
425 gogo_opts.optREADTHREAD_PRIORITY = -10000;
426 gogo_opts.optOUTPUT_FORMAT = -1;
427 gogo_opts.optENHANCEDFILTER_A = -1;
428 gogo_opts.optENHANCEDFILTER_B = -1;
429 gogo_opts.optVBRBITRATE_low = -1;
430 gogo_opts.optVBRBITRATE_high = -1;
431 gogo_opts.optMSTHRESHOLD_threshold = -1;
432 gogo_opts.optMSTHRESHOLD_mspower = -1;
433 gogo_opts.optVERIFY = -1;
434 gogo_opts.optOUTPUTDIR[0] = '\0';
435 gogo_opts.optBITRATE1 = -1;
436 gogo_opts.optBITRATE2 = -1;
437 }
438
439 static volatile int gogo_opts_initflag = 0;
gogo_opts_init(void)440 void gogo_opts_init(void)
441 {
442 gogo_lock();
443 if(!gogo_opts_initflag){
444 gogo_opts_initflag = 1;
445 gogo_opts.optADDTAGnum = 0;
446 gogo_opts.output_name[0] = '\0';
447 }
448 gogo_opts_reset();
449 gogo_unlock();
450 }
gogo_opts_reset_tag(void)451 void gogo_opts_reset_tag(void)
452 {
453 if (gogo_opts.optADDTAGnum >= 0) {
454 int i;
455 for (i = 0; i < gogo_opts.optADDTAGnum; i++) {
456 gogo_opts.optADDTAG_len[i] = 0;
457 if (gogo_opts.optADDTAG_buf[i] != NULL) {
458 free(gogo_opts.optADDTAG_buf[i]);
459 gogo_opts.optADDTAG_buf[i] = NULL;
460 }
461 }
462 }
463 }
464
set_gogo_opts(void)465 static void set_gogo_opts(void)
466 {
467 if(gogo_opts.optENCODEMODE>=0)
468 MPGE_setConfigure(MC_ENCODEMODE,(UPARAM)gogo_opts.optENCODEMODE,(UPARAM)0);
469 if(gogo_opts.optINPFREQ>=0)
470 MPGE_setConfigure(MC_INPFREQ,(UPARAM)gogo_opts.optINPFREQ,(UPARAM)0);
471 if(gogo_opts.optOUTFREQ>=0)
472 MPGE_setConfigure(MC_OUTFREQ,(UPARAM)gogo_opts.optOUTFREQ,(UPARAM)0);
473 if(gogo_opts.optSTARTOFFSET>=0)
474 MPGE_setConfigure(MC_STARTOFFSET,(UPARAM)gogo_opts.optSTARTOFFSET,(UPARAM)0);
475 if(gogo_opts.optUSEPSY>=0)
476 MPGE_setConfigure(MC_USEPSY,(UPARAM)gogo_opts.optUSEPSY,(UPARAM)0);
477 if(gogo_opts.optUSELPF16>=0)
478 MPGE_setConfigure(MC_USELPF16,(UPARAM)gogo_opts.optUSELPF16,(UPARAM)0);
479 if(gogo_opts.optUSEMMX>=0)
480 MPGE_setConfigure(MC_USEMMX,(UPARAM)gogo_opts.optUSEMMX,(UPARAM)0);
481 if(gogo_opts.optUSE3DNOW>=0)
482 MPGE_setConfigure(MC_USE3DNOW,(UPARAM)gogo_opts.optUSE3DNOW,(UPARAM)0);
483 if(gogo_opts.optUSEKNI>=0)
484 MPGE_setConfigure(MC_USEKNI,(UPARAM)gogo_opts.optUSEKNI,(UPARAM)0);
485 if(gogo_opts.optUSEE3DNOW>=0)
486 MPGE_setConfigure(MC_USEE3DNOW,(UPARAM)gogo_opts.optUSEE3DNOW,(UPARAM)0);
487 if(gogo_opts.optUSESSE>=0)
488 MPGE_setConfigure(MC_USESSE,(UPARAM)gogo_opts.optUSESSE,(UPARAM)0);
489 if(gogo_opts.optUSECMOV>=0)
490 MPGE_setConfigure(MC_USECMOV,(UPARAM)gogo_opts.optUSECMOV,(UPARAM)0);
491 if(gogo_opts.optUSEEMMX>=0)
492 MPGE_setConfigure(MC_USEEMMX,(UPARAM)gogo_opts.optUSEEMMX,(UPARAM)0);
493 if(gogo_opts.optUSESSE2>=0)
494 MPGE_setConfigure(MC_USESSE2,(UPARAM)gogo_opts.optUSESSE2,(UPARAM)0);
495 if(gogo_opts.optADDTAGnum>=0){
496 int i;
497 for(i=0;i<gogo_opts.optADDTAGnum;i++)
498 MPGE_setConfigure(MC_ADDTAG,(UPARAM)gogo_opts.optADDTAG_len[i],(UPARAM)gogo_opts.optADDTAG_buf[i]);
499 }
500 if(gogo_opts.optEMPHASIS>=0)
501 MPGE_setConfigure(MC_EMPHASIS,(UPARAM)gogo_opts.optEMPHASIS,(UPARAM)0);
502 if(gogo_opts.optVBR>=0)
503 MPGE_setConfigure(MC_VBR,(UPARAM)gogo_opts.optVBR,(UPARAM)0);
504 if(gogo_opts.optCPU>=0)
505 MPGE_setConfigure(MC_CPU,(UPARAM)gogo_opts.optCPU,(UPARAM)0);
506 if(gogo_opts.optBYTE_SWAP>=0)
507 MPGE_setConfigure(MC_BYTE_SWAP,(UPARAM)gogo_opts.optBYTE_SWAP,(UPARAM)0);
508 if(gogo_opts.opt8BIT_PCM>=0)
509 MPGE_setConfigure(MC_8BIT_PCM,(UPARAM)gogo_opts.opt8BIT_PCM,(UPARAM)0);
510 if(gogo_opts.optMONO_PCM>=0)
511 MPGE_setConfigure(MC_MONO_PCM,(UPARAM)gogo_opts.optMONO_PCM,(UPARAM)0);
512 if(gogo_opts.optTOWNS_SND>=0)
513 MPGE_setConfigure(MC_TOWNS_SND,(UPARAM)gogo_opts.optTOWNS_SND,(UPARAM)0);
514 if(gogo_opts.optTHREAD_PRIORITY!=-10000)
515 MPGE_setConfigure(MC_THREAD_PRIORITY,(UPARAM)gogo_opts.optTHREAD_PRIORITY,(UPARAM)0);
516 if(gogo_opts.optREADTHREAD_PRIORITY!=-10000)
517 MPGE_setConfigure(MC_READTHREAD_PRIORITY,(UPARAM)gogo_opts.optREADTHREAD_PRIORITY,(UPARAM)0);
518 if(gogo_opts.optOUTPUT_FORMAT>=0)
519 MPGE_setConfigure(MC_OUTPUT_FORMAT,(UPARAM)gogo_opts.optOUTPUT_FORMAT,(UPARAM)0);
520 if(gogo_opts.optENHANCEDFILTER_A>=0 && gogo_opts.optENHANCEDFILTER_B>=0)
521 MPGE_setConfigure(MC_ENHANCEDFILTER,(UPARAM)gogo_opts.optENHANCEDFILTER_A,(UPARAM)gogo_opts.optENHANCEDFILTER_B);
522 if(gogo_opts.optVBRBITRATE_low>=0 && gogo_opts.optVBRBITRATE_high>=0)
523 MPGE_setConfigure(MC_VBRBITRATE,(UPARAM)gogo_opts.optVBRBITRATE_low,(UPARAM)gogo_opts.optVBRBITRATE_high);
524 if(gogo_opts.optMSTHRESHOLD_threshold>=0 && gogo_opts.optMSTHRESHOLD_mspower>=0)
525 MPGE_setConfigure(MC_MSTHRESHOLD,(UPARAM)gogo_opts.optMSTHRESHOLD_threshold,(UPARAM)gogo_opts.optMSTHRESHOLD_mspower);
526 if(gogo_opts.optVERIFY>=0)
527 MPGE_setConfigure(MC_VERIFY,(UPARAM)gogo_opts.optVERIFY,(UPARAM)0);
528 if(gogo_opts.optOUTPUTDIR[0]!='\0')
529 MPGE_setConfigure(MC_OUTPUTDIR,(UPARAM)gogo_opts.optOUTPUTDIR,(UPARAM)0);
530 if(strcmp((char *)gogo_opts.output_name,"-")==0){
531 MPGE_setConfigure(MC_OUTPUTFILE,(UPARAM)MC_OUTDEV_STDOUT,(UPARAM)0);
532 } else {
533 MPGE_setConfigure(MC_OUTPUTFILE,(UPARAM)MC_OUTDEV_FILE,(UPARAM)gogo_opts.output_name);
534 }
535 if(dpm.rate>=32000){
536 if(gogo_opts.optBITRATE1>=0)
537 MPGE_setConfigure(MC_BITRATE,(UPARAM)gogo_opts.optBITRATE1,(UPARAM)0);
538 } else {
539 if(gogo_opts.optBITRATE2>=0)
540 MPGE_setConfigure(MC_BITRATE,(UPARAM)gogo_opts.optBITRATE2,(UPARAM)0);
541 }
542 }
id3_to_buffer(mp3_id3_tag_t * id3_tag,char * buffer)543 static int id3_to_buffer(mp3_id3_tag_t *id3_tag, char *buffer)
544 {
545 memset(buffer,0x20,128);
546 #if 0
547 memcpy(buffer+0,id3_tag->tag);
548 #else
549 memcpy(buffer+0,"TAG",3); //ID3 Tag v1
550 #endif
551 memcpy(buffer+3,id3_tag->title,30);
552 memcpy(buffer+33,id3_tag->artist,30);
553 memcpy(buffer+63,id3_tag->album,30);
554 memcpy(buffer+93,id3_tag->year,4);
555 memcpy(buffer+97,id3_tag->comment,30);
556 buffer[127] = id3_tag->genre;
557 return 0;
558 }
id3_tag_strncpy(char * dst,const char * src,int num)559 static char *id3_tag_strncpy(char *dst, const char *src, int num)
560 {
561 // NULL�I�[��t�����Ă͂Ȃ�Ȃ�
562 int len = strlen(src);
563 return memcpy (dst, src, (len <= num) ? len : num);
564 }
gogo_opts_id3_tag(const char * title,const char * artist,const char * album,const char * year,const char * comment,int genre)565 int gogo_opts_id3_tag(const char *title, const char *artist, const char *album, const char *year, const char *comment, int genre)
566 {
567 mp3_id3_tag_t id3_tag;
568 char *buffer;
569 buffer = (char *)safe_malloc(128);
570 if(buffer==NULL)
571 return -1;
572 memset(&id3_tag,0x20,128); // TAG�S�̂�������fill
573 if(title){
574 id3_tag_strncpy(id3_tag.title,title,30);
575 }
576 if(artist){
577 id3_tag_strncpy(id3_tag.artist,artist,30);
578 }
579 if(album){
580 id3_tag_strncpy(id3_tag.album,album,30);
581 }
582 if(year){
583 id3_tag_strncpy(id3_tag.year,year,4);
584 }
585 if(comment){
586 id3_tag_strncpy(id3_tag.comment,comment,30);
587 }
588 if(genre>=0)
589 id3_tag.genre = (unsigned char)(genre & 0xff);
590 else // �W���������ݒ�
591 id3_tag.genre = (unsigned char)0xff;
592 id3_to_buffer(&id3_tag,buffer);
593 gogo_opts.optADDTAGnum++;
594 gogo_opts.optADDTAG_len[gogo_opts.optADDTAGnum-1] = 128;
595 gogo_opts.optADDTAG_buf[gogo_opts.optADDTAGnum-1] = buffer;
596 // MPGE_setConfigure(MC_ADDTAG,(UPARAM)128,(UPARAM)buffer);
597 return 0;
598 }
599
600 // �R�}���h���C����W�J����
commandline_to_argc_argv(char * commandline,int * argc,char *** argv)601 int commandline_to_argc_argv(char *commandline, int *argc, char ***argv)
602 {
603 char *p1, *p2, *p3;
604 int argc_max = 0;
605 *argc = 0;
606 *argv = NULL;
607 p1 = commandline;
608 for(;;){
609 int quot = 0;
610 while(isspace(*p1))
611 p1++;
612 if(*p1=='"')
613 quot = 1;
614 else if(*p1=='\'')
615 quot = 2;
616 if(*p1=='\0')
617 return 0;
618 p2 = p1+1;
619 while((quot==1&&*p2=='"') || (quot==2&&*p2=='\'') || *p2=='\0')
620 p2++;
621 while(!isspace(*p2) || *p2=='\0')
622 p2++;
623 if(*p2!='\0'){
624 p3 = p2+1;
625 while(isspace(*p3))
626 p3++;
627 } else{
628 p3 = NULL;
629 }
630 (*argc)++;
631 if(*argc>argc_max)
632 argc_max += 100;
633 *argv = (char **)safe_realloc(*argv,sizeof(char*)*argc_max);
634 if(*argv==NULL)
635 return -1;
636 *argv[*argc-1] = (char *)safe_malloc(sizeof(char)*(p2-p1));
637 if(*argv[*argc-1]==NULL){
638 (*argc)--;
639 return 0;
640 }
641 strncpy(*argv[*argc-1],p1,p2-p1);
642 *argv[*argc-1][p2-p1] = '\0';
643 if(p3==NULL)
644 return 0;
645 p1 = p3;
646 }
647 }
free_argv(char ** argv,int argc)648 void free_argv(char **argv, int argc)
649 {
650 if(argv!=NULL){
651 int i;
652 for(i=0;i<argc;i++)
653 if(argv[i]!=NULL)
654 free(argv[i]);
655 free(argv);
656 }
657 }
658
659 volatile char *gogo_commandline_options = NULL;
660 volatile int use_gogo_commandline_options = 0;
set_gogo_opts_use_commandline_options(char * commandline)661 void set_gogo_opts_use_commandline_options(char *commandline)
662 {
663 int argc;
664 char **argv;
665 int num;
666 if(commandline_to_argc_argv(commandline,&argc,&argv)){
667 return;
668 }
669 for(num = 0;num<argc;){
670 // output bitrate
671 // -b kbps
672 // input PCM is higher than 32kHz [ 32,40,48,56,64,80,96,112,128,160,192,224,256,320 ]
673 // input PCM is lower than 32kHz [ 8,16,24,32,40,48,56,64,80,96,112,128,144,160 ]
674 if(strcasecmp("-b",argv[num])==0){
675 if(num+1>=argc) break;
676 gogo_opts.optBITRATE1 = gogo_opts.optBITRATE2 = atoi(argv[num+1]);
677 num += 2;
678 continue;
679 }
680 // output bitrate for VBR
681 // -br low_kbps high_kbps
682 // [ 32,40,48,56,64,80,96,112,128,160,192,224,256,320 ]
683 if(strcasecmp("-br",argv[num])==0){
684 if(num+2>=argc) break;
685 if(gogo_opts.optVBR==-1)
686 gogo_opts.optVBR = 9;
687 gogo_opts.optVBRBITRATE_low = atoi(argv[num+1]);
688 gogo_opts.optVBRBITRATE_high = atoi(argv[num+2]);
689 num += 3;
690 continue;
691 }
692 // low pass filter
693 // -lpf on : 16kHz low pass filter ON
694 // -lpf off : 16kHz low pass filter OFF
695 // -lpf para1 para2 : enhanced low pass filter
696 // para1 (0-100) para2 (0-100)
697 if(strcasecmp("-lpf",argv[num])==0){
698 if(num+1>=argc) break;
699 if(strcasecmp("on",argv[num+1])==0){
700 gogo_opts.optENHANCEDFILTER_A = -1;
701 gogo_opts.optENHANCEDFILTER_B = -1;
702 gogo_opts.optUSELPF16 = 1;
703 num += 2;
704 continue;
705 } else if(strcasecmp("off",argv[num+1])==0){
706 gogo_opts.optENHANCEDFILTER_A = -1;
707 gogo_opts.optENHANCEDFILTER_B = -1;
708 gogo_opts.optUSELPF16 = 0;
709 num += 2;
710 continue;
711 }
712 if(num+2>=argc) break;
713 gogo_opts.optENHANCEDFILTER_A = atoi(argv[num+1]);
714 gogo_opts.optENHANCEDFILTER_B = atoi(argv[num+2]);
715 num += 3;
716 continue;
717 }
718 // encodemode
719 // -m m : monoral
720 // -m s : stereo
721 // -m j : joint stereo
722 // -m f : mid/side stereo
723 // -m d : dual channel
724 if(strcasecmp("-m",argv[num])==0){
725 if(num+1>=argc) break;
726 if(strcasecmp("m",argv[num+1])==0){
727 gogo_opts.optENCODEMODE = MC_MODE_MONO;
728 } else if(strcasecmp("s",argv[num+1])==0){
729 gogo_opts.optENCODEMODE = MC_MODE_STEREO;
730 } else if(strcasecmp("j",argv[num+1])==0){
731 gogo_opts.optENCODEMODE = MC_MODE_JOINT;
732 } else if(strcasecmp("f",argv[num+1])==0){
733 gogo_opts.optENCODEMODE = MC_MODE_MSSTEREO;
734 } else if(strcasecmp("d",argv[num+1])==0){
735 gogo_opts.optENCODEMODE = MC_MODE_DUALCHANNEL;
736 }
737 num += 2;
738 continue;
739 }
740 // -psy
741 // -nopsy
742 if(strcasecmp("-psy",argv[num])==0){
743 gogo_opts.optUSEPSY = 1;
744 num += 1;
745 continue;
746 }
747 if(strcasecmp("-nopsy",argv[num])==0){
748 gogo_opts.optUSEPSY = 0;
749 num += 1;
750 continue;
751 }
752 // -on 3dn
753 // -on mmx
754 // -on sse
755 // -on kni
756 // -on e3dn
757 // -on sse
758 // -on cmov
759 // -on emmx
760 // -on sse2
761 if(strcasecmp("-on",argv[num])==0){
762 if(num+1>=argc) break;
763 if(strcasecmp("3dn",argv[num+1])==0){
764 gogo_opts.optUSE3DNOW = 1;
765 } else if(strcasecmp("mmx",argv[num+1])==0){
766 gogo_opts.optUSEMMX = 1;
767 } else if(strcasecmp("sse",argv[num+1])==0 || strcasecmp("kni",argv[num+1])==0){
768 gogo_opts.optUSEKNI = 1;
769 } else if(strcasecmp("e3dn",argv[num+1])==0){
770 gogo_opts.optUSEE3DNOW = 1;
771 } else if(strcasecmp("sse",argv[num+1])==0){
772 gogo_opts.optUSESSE = 1;
773 } else if(strcasecmp("cmov",argv[num+1])==0){
774 gogo_opts.optUSECMOV = 1;
775 } else if(strcasecmp("emmx",argv[num+1])==0){
776 gogo_opts.optUSEEMMX = 1;
777 } else if(strcasecmp("sse2",argv[num+1])==0){
778 gogo_opts.optUSESSE2 = 1;
779 }
780 num += 2;
781 continue;
782 }
783 // -off 3dn
784 // -off mmx
785 // -off sse
786 // -off kni
787 // -off e3dn
788 // -off sse
789 // -off cmov
790 // -off emmx
791 // -off sse2
792 if(strcasecmp("-on",argv[num])==0){
793 if(num+1>=argc) break;
794 if(strcasecmp("3dn",argv[num+1])==0){
795 gogo_opts.optUSE3DNOW = 0;
796 } else if(strcasecmp("mmx",argv[num+1])==0){
797 gogo_opts.optUSEMMX = 0;
798 } else if(strcasecmp("sse",argv[num+1])==0 || strcasecmp("kni",argv[num+1])==0){
799 gogo_opts.optUSEKNI = 0;
800 } else if(strcasecmp("e3dn",argv[num+1])==0){
801 gogo_opts.optUSEE3DNOW = 0;
802 } else if(strcasecmp("sse",argv[num+1])==0){
803 gogo_opts.optUSESSE = 0;
804 } else if(strcasecmp("cmov",argv[num+1])==0){
805 gogo_opts.optUSECMOV = 0;
806 } else if(strcasecmp("emmx",argv[num+1])==0){
807 gogo_opts.optUSEEMMX = 0;
808 } else if(strcasecmp("sse2",argv[num+1])==0){
809 gogo_opts.optUSESSE2 = 0;
810 }
811 num += 2;
812 continue;
813 }
814 // emphasis type
815 // -emp n : none
816 // -emp 5 : 50/15ms (normal CD-DA emphasis)
817 // -emp c : CCITT
818 if(strcasecmp("-emp",argv[num])==0){
819 if(num+1>=argc) break;
820 if(strcasecmp("n",argv[num+1])==0){
821 gogo_opts.optEMPHASIS = MC_EMP_NONE;
822 } else if(strcasecmp("5",argv[num+1])==0){
823 gogo_opts.optEMPHASIS = MC_EMP_5015MS;
824 } else if(strcasecmp("c",argv[num+1])==0){
825 gogo_opts.optEMPHASIS = MC_EMP_CCITT;
826 }
827 num += 2;
828 continue;
829 }
830 // -cpu num
831 if(strcasecmp("-cpu",argv[num])==0){
832 if(num+1>=argc) break;
833 gogo_opts.optCPU = atoi(argv[num+1]);
834 num += 2;
835 continue;
836 }
837 // -v 0..9 (low compression - high compression)
838 if(strcasecmp("-v",argv[num])==0){
839 if(num+1>=argc) break;
840 gogo_opts.optVBR = atoi(argv[num+1]);
841 num += 2;
842 continue;
843 }
844 // -d freq : output MP3 frequency(kHz)
845 if(strcasecmp("-d",argv[num])==0){
846 if(num+1>=argc) break;
847 gogo_opts.optOUTFREQ = (int)(atof(argv[num+1])*1000);
848 num += 2;
849 continue;
850 }
851 #if 0 // Do not use it.
852 // -mono
853 // -stereo
854 // -8bit
855 // -16bit
856 // -bswap
857 // -bswap- (not bitswap)
858 // -tos (snd file for TonwsOS)
859 // -tos- (not snd file for TonwsOS
860 if(strcasecmp("-mono",argv[num])==0){
861 gogo_opts.optMONO_PCM = 1;
862 num += 1;
863 continue;
864 }
865 if(strcasecmp("-stereo",argv[num])==0){
866 gogo_opts.optMONO_PCM = 0;
867 num += 1;
868 continue;
869 }
870 if(strcasecmp("-8bit",argv[num])==0){
871 gogo_opts.opt8BIT_PCM = 1;
872 num += 1;
873 continue;
874 }
875 if(strcasecmp("-16bit",argv[num])==0){
876 gogo_opts.opt8BIT_PCM = 0;
877 num += 1;
878 continue;
879 }
880 if(strcasecmp("-bswap",argv[num])==0){
881 gogo_opts.optBYTE_SWAP = 1;
882 num += 1;
883 continue;
884 }
885 if(strcasecmp("-bswap-",argv[num])==0){
886 gogo_opts.optBYTE_SWAP = 0;
887 num += 1;
888 continue;
889 }
890 if(strcasecmp("-ts",argv[num])==0){
891 gogo_opts.optTOWNS_SND = 1;
892 num += 1;
893 continue;
894 }
895 if(strcasecmp("-ts-",argv[num])==0){
896 gogo_opts.optTOWNS_SND = 1;
897 num += 1;
898 continue;
899 }
900 // -s freq : input PCM freqency(kHz)
901 if(strcasecmp("-s",argv[num])==0){
902 if(num+1>=argc) break;
903 gogo_opts.optINPFREQ = (int)(atof(argv[num+1])*1000);
904 num += 2;
905 continue;
906 }
907 // -offset byte : jump byte bytes from head.
908 if(strcasecmp("-offset",argv[num])==0){
909 if(num+1>=argc) break;
910 gogo_opts.optSTARTOFFSET = atol(argv[num+1]);
911 num += 2;
912 continue;
913 }
914 #endif
915 // -th threshold mspower
916 if(strcasecmp("-th",argv[num])==0){
917 if(num+2>=argc) break;
918 gogo_opts.optMSTHRESHOLD_threshold = atoi(argv[num+1]);
919 gogo_opts.optMSTHRESHOLD_mspower = atoi(argv[num+2]);
920 num += 3;
921 continue;
922 }
923 // -riff normal : mp3+TAG
924 // -riff wave : RIFF/WAVE
925 // -riff rmp : RIFF/RMP
926 if(strcasecmp("-riff",argv[num])==0){
927 if(num+1>=argc) break;
928 if(strcasecmp("wave",argv[num+1])==0){
929 gogo_opts.optOUTPUT_FORMAT = MC_OUTPUT_NORMAL;
930 } else if(strcasecmp("wave",argv[num+1])==0){
931 gogo_opts.optOUTPUT_FORMAT = MC_OUTPUT_RIFF_WAVE;
932 } else if(strcasecmp("wave",argv[num+1])==0){
933 gogo_opts.optOUTPUT_FORMAT = MC_OUTPUT_RIFF_RMP;
934 }
935 num += 2;
936 continue;
937 }
938 // -priority normal : normal priority
939 // -priority num
940 if(strcasecmp("-priority",argv[num])==0){
941 if(num+1>=argc) break;
942 if(strcasecmp("normal",argv[num+1])==0){
943 gogo_opts.optTHREAD_PRIORITY = 10;
944 } else {
945 gogo_opts.optTHREAD_PRIORITY = atol(argv[num+1]);
946 }
947 num += 2;
948 continue;
949 }
950 // -readthread num
951 if(strcasecmp("-readthread",argv[num])==0){
952 if(num+1>=argc) break;
953 gogo_opts.optREADTHREAD_PRIORITY = atol(argv[num+1]);
954 num += 2;
955 continue;
956 }
957 // -i
958 // -i-
959 if(strcasecmp("-i",argv[num])==0){
960 gogo_opts.optVERIFY = 1;
961 num += 1;
962 continue;
963 }
964 if(strcasecmp("-i-",argv[num])==0){
965 gogo_opts.optVERIFY = 0;
966 num += 1;
967 continue;
968 }
969 // -o directory_path
970 if(strcasecmp("-o",argv[num])==0){
971 if(num+1>=argc) break;
972 strncpy((char *)gogo_opts.optOUTPUTDIR,argv[num+1],1023);
973 gogo_opts.optOUTPUTDIR[1023] = '\0';
974 num += 2;
975 continue;
976 }
977 num += 1;
978 }
979 return;
980 }
981
982 // gogo.dll or gogo.lib �̊���p���� mp3 �쐬�����͕ʃX���b�h�ɂčs���B�@
983 // �X���b�h�쐬�ɂ� CreateMPGEthread() ��p����B
984 // ���̃X���b�h�́Agogo_buffer_termination ���� 0 �ɂȂ����Ƃ��K���I������B
985 // ���̃X���b�h���I���������Ƃ́AIsTerminatedMPGEthread()�ɂ�茟�m����B
986 // �X���b�h���I���������Ƃ��m�F���Ă��� close_output() �͊�������B
987 // �f�[�^�̓n���� gogo_buffer �ɂčs�����A�o�b�t�@����t�̂Ƃ��́A���X���b�h��
988 // ��~���A�o�b�t�@�̓ǂݍ��ݑҋ@���� gogo �p�X���b�h����~����B
MPGEthread(void)989 static int __stdcall MPGEthread(void)
990 {
991 MERET rval;
992 struct MCP_INPDEV_USERFUNC mcp_inpdev_userfunc;
993 unsigned long gogo_vercode;
994 char gogo_verstring[1024];
995
996 gogo_buffer_reset();
997 rval = MPGE_initializeWork();
998 if(rval != ME_NOERR){
999 gogo_error(rval);
1000 gogo_buffer_termination = -1;
1001 MPGE_endCoder();
1002 return -1;
1003 }
1004 MPGE_getVersion(&gogo_vercode,gogo_verstring);
1005 ctl->cmsg(CMSG_INFO, VERB_NORMAL, "Gogo: %s", gogo_verstring);
1006 memset(&mcp_inpdev_userfunc,0,sizeof(struct MCP_INPDEV_USERFUNC));
1007 mcp_inpdev_userfunc.pUserFunc = (MPGE_USERFUNC)gogoUserFunc;
1008 mcp_inpdev_userfunc.nSize = MC_INPDEV_MEMORY_NOSIZE;
1009 mcp_inpdev_userfunc.nBit = (dpm.encoding & PE_16BIT) ? 16 : 8;
1010 mcp_inpdev_userfunc.nFreq = dpm.rate;
1011 mcp_inpdev_userfunc.nChn = (dpm.encoding & PE_MONO) ? 1 : 2;
1012 #if !defined ( IA_W32GUI ) && !defined ( IA_W32G_SYN )
1013 if(use_gogo_commandline_options && gogo_commandline_options!=NULL){
1014 gogo_opts_reset();
1015 set_gogo_opts_use_commandline_options((char *)gogo_commandline_options);
1016 }
1017 #else
1018 gogo_ConfigDialogInfoApply();
1019 #endif
1020 // title������ꍇ�̓f�t�H���g��TAG�t��
1021 if (tag_title != NULL) {
1022 gogo_opts_id3_tag(tag_title, NULL, NULL, NULL, NULL, -1);
1023 }
1024 set_gogo_opts();
1025 rval = MPGE_setConfigure( MC_INPUTFILE,MC_INPDEV_USERFUNC,(UPARAM)&mcp_inpdev_userfunc);
1026 if(rval != ME_NOERR){
1027 gogo_error(rval);
1028 gogo_buffer_termination = -1;
1029 MPGE_endCoder();
1030 return -1;
1031 }
1032 if(gogo_vercode<300){
1033 rval = MPGE_setConfigure(MC_STARTOFFSET,(UPARAM)0,(UPARAM)0);
1034 if(rval != ME_NOERR){
1035 gogo_error(rval);
1036 gogo_buffer_termination = -1;
1037 MPGE_endCoder();
1038 return -1;
1039 }
1040 }
1041 #if 0
1042 rval = MPGE_setConfigure(MC_INPFREQ,(UPARAM)dpm.rate,(UPARAM)0);
1043 if(rval != ME_NOERR){
1044 gogo_error(rval);
1045 gogo_buffer_termination = -1;
1046 MPGE_endCoder();
1047 return -1;
1048 }
1049 #endif
1050 if(gogo_vercode<300){
1051 rval = MPGE_setConfigure(MC_BYTE_SWAP,(UPARAM)((dpm.encoding & PE_BYTESWAP) ? TRUE : FALSE),(UPARAM)0);
1052 if(rval != ME_NOERR){
1053 gogo_error(rval);
1054 gogo_buffer_termination = -1;
1055 MPGE_endCoder();
1056 return -1;
1057 }
1058 rval = MPGE_setConfigure(MC_8BIT_PCM,(UPARAM)((dpm.encoding & PE_16BIT) ? FALSE : TRUE),(UPARAM)0);
1059 if(rval != ME_NOERR){
1060 gogo_error(rval);
1061 gogo_buffer_termination = -1;
1062 MPGE_endCoder();
1063 return -1;
1064 }
1065 rval = MPGE_setConfigure(MC_MONO_PCM,(UPARAM)((dpm.encoding & PE_MONO) ? TRUE : FALSE),(UPARAM)0);
1066 if(rval != ME_NOERR){
1067 gogo_error(rval);
1068 gogo_buffer_termination = -1;
1069 MPGE_endCoder();
1070 return -1;
1071 }
1072 }
1073 rval = MPGE_detectConfigure();
1074 if( rval != ME_NOERR ){
1075 gogo_error(rval);
1076 gogo_buffer_termination = -1;
1077 MPGE_endCoder();
1078 return -1;
1079 } else {
1080 // UPARAM curFrame;
1081 // curFrame = 0;
1082 do {
1083 // ctl->cmsg(CMSG_INFO, VERB_DEBUG,"gogo_a : frame %d",curFrame);
1084 // curFrame++;
1085 rval = MPGE_processFrame();
1086 } while( rval == ME_NOERR );
1087 if( rval != ME_EMPTYSTREAM ){
1088 gogo_buffer_termination = -1;
1089 gogo_error(rval);
1090 }
1091 }
1092 MPGE_closeCoder();
1093 MPGE_endCoder();
1094 return 0;
1095 }
1096
1097 // Whether the thread of gogo.dll is terminated ?
IsTerminatedMPGEthread(void)1098 static int IsTerminatedMPGEthread(void)
1099 {
1100 #ifndef __W32__
1101 #else
1102 DWORD dwRes;
1103 if(hMPGEthread==NULL)
1104 return 1;
1105 dwRes = WaitForSingleObject(hMPGEthread,0);
1106 if(dwRes==WAIT_TIMEOUT){
1107 return 0;
1108 } else {
1109 return 1;
1110 }
1111 #endif
1112 }
1113
1114 // Create the thread of gogo.dll
CreateMPGEthread(void)1115 static int CreateMPGEthread(void)
1116 {
1117 // gogo �p�̃X���b�h���I�����Ă��邩�m�F����B
1118 gogo_buffer_termination = 1;
1119 while(!IsTerminatedMPGEthread()){
1120 #ifndef __W32__
1121 usleep(100);
1122 #else
1123 Sleep(0);
1124 Sleep(100);
1125 #endif
1126 }
1127 gogo_buffer_termination = 0;
1128
1129 // gogo �p�̃X���b�h���쐬����B
1130 #ifndef __W32__
1131
1132 #else
1133 // �n���h���̓N���[�Y���Ă����B
1134 if(hMPGEthread!=NULL){
1135 CloseHandle(hMPGEthread);
1136 }
1137 hMPGEthread = (HANDLE)crt_beginthreadex(NULL,0,(LPTHREAD_START_ROUTINE)MPGEthread,NULL,0,&dwMPGEthreadID);
1138 if(hMPGEthread==(HANDLE)-1 || hMPGEthread==NULL){
1139 hMPGEthread = NULL;
1140 ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "gogo_a : cannot create thread.");
1141 return -1;
1142 }
1143 #endif
1144 return 0;
1145 }
1146
1147
1148 /**********************************************************************/
1149 #if defined ( IA_W32GUI ) || defined ( IA_W32G_SYN )
1150 extern volatile int w32g_gogo_id3_tag_dialog(void);
1151 extern int w32g_interactive_id3_tag_set;
1152 #endif
gogo_output_open(const char * fname)1153 static int gogo_output_open(const char *fname)
1154 {
1155 if(fname[0]=='\0')
1156 return -1;
1157 if(!gogo_opts_initflag)
1158 gogo_opts_init();
1159 strncpy((char *)gogo_opts.output_name,fname,1023);
1160 gogo_opts.output_name[1023] = '\0';
1161 #if defined ( IA_W32GUI ) || defined ( IA_W32G_SYN )
1162 gogo_opts_reset_tag();
1163 if(w32g_interactive_id3_tag_set){ // ���t����ID3�^�O�����̓_�C�A���O���J���B
1164 w32g_gogo_id3_tag_dialog();
1165 }
1166 #endif
1167
1168 if(CreateMPGEthread()){
1169 gogo_buffer_termination = -1;
1170 return -1;
1171 }
1172
1173 return 0;
1174 }
1175
auto_gogo_output_open(const char * input_filename,const char * title)1176 static int auto_gogo_output_open(const char *input_filename, const char *title)
1177 {
1178 char *output_filename;
1179
1180 #if !defined ( IA_W32GUI ) && !defined ( IA_W32G_SYN )
1181 output_filename = create_auto_output_name(input_filename,"mp3",NULL,0);
1182 #else
1183 gogo_ConfigDialogInfoApply();
1184 switch(gogo_opts.optOUTPUT_FORMAT){
1185 case MC_OUTPUT_NORMAL:
1186 output_filename = create_auto_output_name(input_filename,"mp3",(char *)w32g_output_dir,w32g_auto_output_mode);
1187 break;
1188 case MC_OUTPUT_RIFF_WAVE:
1189 output_filename = create_auto_output_name(input_filename,"wav",(char *)w32g_output_dir,w32g_auto_output_mode);
1190 break;
1191 case MC_OUTPUT_RIFF_RMP:
1192 output_filename = create_auto_output_name(input_filename,"rmp",(char *)w32g_output_dir,w32g_auto_output_mode);
1193 break;
1194 default:
1195 output_filename = create_auto_output_name(input_filename,"mp3",(char *)w32g_output_dir,w32g_auto_output_mode);
1196 break;
1197 }
1198 #endif
1199 if(output_filename==NULL){
1200 return -1;
1201 }
1202 if (tag_title != NULL) {
1203 free(tag_title);
1204 tag_title = NULL;
1205 }
1206 if (title != NULL) {
1207 tag_title = (char *)safe_malloc(sizeof(char)*(strlen(title)+1));
1208 strcpy(tag_title, title);
1209 }
1210 if((dpm.fd = gogo_output_open(output_filename)) == -1) {
1211 free(output_filename);
1212 return -1;
1213 }
1214 if(dpm.name != NULL){
1215 free(dpm.name);
1216 dpm.name = NULL;
1217 }
1218 dpm.name = output_filename;
1219 ctl->cmsg(CMSG_INFO, VERB_NORMAL, "Output %s", dpm.name);
1220 return 0;
1221 }
1222
1223 #ifdef AU_GOGO_DLL
1224 extern int gogo_dll_check(void);
1225 #endif
open_output(void)1226 static int open_output(void)
1227 {
1228 int include_enc, exclude_enc;
1229
1230 #ifdef AU_VORBIS_DLL
1231 if(!gogo_dll_check()){
1232 ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "can not find gogo.dll.");
1233 return -1;
1234 }
1235 #endif
1236
1237 include_enc = exclude_enc = 0;
1238 if(dpm.encoding & PE_24BIT) { /* 24 bit is not supported */
1239 exclude_enc |= PE_24BIT;
1240 include_enc |= PE_16BIT;
1241 }
1242 if(dpm.encoding & PE_16BIT || dpm.encoding & PE_24BIT) {
1243 #ifdef LITTLE_ENDIAN
1244 exclude_enc |= PE_BYTESWAP;
1245 #else
1246 include_enc |= PE_BYTESWAP;
1247 #endif /* LITTLE_ENDIAN */
1248 include_enc |= PE_SIGNED;
1249 } else {
1250 exclude_enc |= PE_SIGNED;
1251 #if 0
1252 } else if(!(dpm.encoding & (PE_ULAW|PE_ALAW))){
1253 exclude_enc = PE_SIGNED;
1254 #endif
1255 }
1256
1257 dpm.encoding = validate_encoding(dpm.encoding, include_enc, exclude_enc);
1258
1259 #if !defined ( IA_W32GUI ) && !defined ( IA_W32G_SYN )
1260 if(dpm.name == NULL) {
1261 dpm.flag |= PF_AUTO_SPLIT_FILE;
1262 } else {
1263 dpm.flag &= ~PF_AUTO_SPLIT_FILE;
1264 if((dpm.fd = gogo_output_open(dpm.name)) == -1)
1265 return -1;
1266 }
1267 #else
1268 if(w32g_auto_output_mode>0){
1269 dpm.flag |= PF_AUTO_SPLIT_FILE;
1270 dpm.name = NULL;
1271 } else {
1272 dpm.flag &= ~PF_AUTO_SPLIT_FILE;
1273 if((dpm.fd = gogo_output_open(dpm.name)) == -1)
1274 return -1;
1275 }
1276 #endif
1277
1278 return 0;
1279 }
1280
output_data(char * readbuffer,int32 bytes)1281 static int output_data(char *readbuffer, int32 bytes)
1282 {
1283 int32 rest_bytes = bytes;
1284 int32 out_bytes = 0;
1285
1286 if(dpm.fd<0)
1287 return 0;
1288
1289 gogo_buffer_init();
1290 if(bytes>gogo_buffer_size){
1291 gogo_buffer_termination = -1;
1292 ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "gogo_a : buffer size is small.");
1293 return -1;
1294 }
1295 for(;;){
1296 int32 size;
1297 if(bytes<=0)
1298 break;
1299 if(gogo_buffer_termination<0){
1300 ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "gogo_a : output_data error.");
1301 return -1;
1302 }
1303 if(gogo_buffer_termination)
1304 return out_bytes;
1305 if(gogo_lock()){
1306 ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "gogo_a : lock error.");
1307 gogo_buffer_termination = -1;
1308 return -1;
1309 }
1310 size = __gogo_buffer_push(readbuffer,bytes);
1311 readbuffer += size;
1312 bytes -= size;
1313 out_bytes += size;
1314 gogo_unlock();
1315 if(bytes>0){
1316 #ifndef __W32__
1317 usleep(100);
1318 #else
1319 Sleep(0);
1320 Sleep(100);
1321 #endif
1322 }
1323 }
1324 return out_bytes;
1325 }
1326
close_output(void)1327 static void close_output(void)
1328 {
1329 if (dpm.fd < 0)
1330 return;
1331
1332 gogo_buffer_termination = 1;
1333 for (;;) {
1334 if (IsTerminatedMPGEthread()) {
1335 break;
1336 }
1337 #ifndef __W32__
1338 usleep(100000);
1339 #else
1340 Sleep(100);
1341 #endif
1342 }
1343 dpm.fd = -1;
1344 }
1345
acntl(int request,void * arg)1346 static int acntl(int request, void *arg)
1347 {
1348 switch(request) {
1349 case PM_REQ_PLAY_START:
1350 if(dpm.flag & PF_AUTO_SPLIT_FILE){
1351 if( ( NULL == current_file_info ) || (NULL == current_file_info->filename ) )
1352 return auto_gogo_output_open("Output.mid",NULL);
1353 return auto_gogo_output_open(current_file_info->filename, current_file_info->seq_name);
1354 }
1355 return 0;
1356 case PM_REQ_PLAY_END:
1357 if(dpm.flag & PF_AUTO_SPLIT_FILE)
1358 close_output();
1359 return 0;
1360 case PM_REQ_DISCARD:
1361 #if 1
1362 gogo_buffer_reset();
1363 #endif
1364 return 0;
1365 case PM_REQ_FLUSH:
1366 case PM_REQ_OUTPUT_FINISH:
1367 break;
1368 default:
1369 break;
1370 }
1371 return -1;
1372 }
1373
1374 #endif
1375