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 f()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 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; 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 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; 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 } 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 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 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 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 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; 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 } 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 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 } 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 } 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 } 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���� 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 } 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; 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 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 ? 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 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 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 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 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 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 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 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