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