/* list MIDI programs */ #ifdef HAVE_CONFIG_H #include "config.h" #endif /* HAVE_CONFIG_H */ #include #ifndef __WIN32__ #include #endif #include #ifndef NO_STRING_H #include #else #include #endif #include "timidity.h" #include "common.h" #include "instrum.h" #include "playmidi.h" #include "readmidi.h" #include "output.h" #include "controls.h" #include "arc.h" #include "wrd.h" ChannelBitMask drumchannel_mask; /*ARGSUSED*/ static int null_cmsg(int type, int verbosity_level, char *fmt, ...){return 0;} static void null_proc(){} static ControlMode null_control_mode = { "", 0, 1,0,0, NULL, null_proc, NULL, NULL, null_cmsg, null_proc }; static PlayMode null_play_mode = { 8000, PE_MONO, 0, -1, {0,0,0,0,0}, "", 0, "", NULL, NULL, null_proc, NULL, NULL, null_proc, NULL, NULL }; /*ARGSUSED*/ static int null_wrdt_open(char *wrdt_opts) { return 0; } /*ARGSUSED*/ static void null_wrdt_apply(int cmd, int argc, int args[]) { } static void null_wrdt_update_events(void) { } static void null_wrdt_end(void) { } static void null_wrdt_close(void) { } static WRDTracer null_wrdt_mode = { "No WRD trace", '-', 0, null_wrdt_open, null_wrdt_apply, null_wrdt_update_events, NULL, null_wrdt_end, null_wrdt_close }; PlayMode *play_mode = &null_play_mode; ControlMode *ctl = &null_control_mode; WRDTracer *wrdt = &null_wrdt_mode; ToneBank *tonebank[128], *drumset[128]; int32 tonebank_start_time[128][128]; int32 drumset_start_time[128][128]; int tonebank_counter[128][128]; int drumset_counter[128][128]; int default_program[MAX_CHANNELS]; ChannelBitMask drumchannels; ChannelBitMask default_drumchannel_mask; ChannelBitMask default_drumchannels; int special_tonebank = -1; int default_tonebank = 0; int progbase = 0; void init_banks(void); int list_midi_file(char *fn); void list_instruments(void); extern struct URL_module URL_module_file; extern struct URL_module URL_module_dir; #ifdef SUPPORT_SOCKET extern struct URL_module URL_module_http; extern struct URL_module URL_module_ftp; extern struct URL_module URL_module_news; extern struct URL_module URL_module_newsgroup; #endif /* SUPPORT_SOCKET */ /*ARGSUSED*/ int midi_drumpart_change(int ch, int isdrum) { return 0; } /*ARGSUSED*/ int get_module_type(char *fn) { return IS_OTHER_FILE; } /*ARGSUSED*/ int load_module_file(struct timidity_file *tf, int mtype) { return 1; } /*ARGSUSED*/ int import_wrd_file(char *fn) { return 0; } /*ARGSUSED*/ int instrument_map(int mapID, int *set_in_out, int *elem_in_out) { return 0; } int main(int argc, char **argv) { int i; int nfiles; char **files; static int drums[] = DEFAULT_DRUMCHANNELS; extern ArchiveFileList *archive_file_list; memset(&drumchannels, 0, sizeof(ChannelBitMask)); for(i = 0; drums[i] > 0; i++) SET_CHANNELMASK(drumchannels, drums[i] - 1); for(i = 0; i < MAX_CHANNELS; i++) default_program[i] = DEFAULT_PROGRAM; url_add_modules( &URL_module_file, &URL_module_dir, #ifdef SUPPORT_SOCKET &URL_module_http, &URL_module_ftp, &URL_module_news, &URL_module_newsgroup, #endif /* SUPPORT_SOCKET */ NULL); if(argc == 1) { static char *v[2]; argc = 2; v[0] = argv[0]; v[1] = "-"; argv = v; } nfiles = argc - 1; files = argv + 1; program_name = argv[0]; for(i = 0; i < 128; i++) { tonebank[i] = (ToneBank *)safe_malloc(sizeof(ToneBank)); drumset[i] = (ToneBank *)safe_malloc(sizeof(ToneBank)); } files = expand_file_archives(files, &nfiles); for(i = 0; i < nfiles; i++) { init_banks(); printf("%s: " NLS, files[i]); list_midi_file(files[i]); } close_archive_files(archive_file_list); return 0; } void init_banks(void) { int i, j; for(i = 0; i < 128; i++) { memset(tonebank[i], 0, sizeof(ToneBank)); memset(drumset[i], 0, sizeof(ToneBank)); for(j = 0; j < 128; j++) { tonebank_start_time[i][j] = -1; drumset_start_time[i][j] = -1; } } memset(tonebank_counter, 0, sizeof(tonebank_counter)); memset(drumset_counter, 0, sizeof(drumset_counter)); } void scan_midievent(MidiEvent *ev) { Channel channel[MAX_CHANNELS]; int ch; memset(channel, 0, sizeof(channel)); while(ev->type != ME_EOT) { ch = ev->channel; switch(ev->type) { case ME_NOTEON: if(ev->b) { /* Note on */ int bank; int inst; bank = channel[ch].bank; if(ISDRUMCHANNEL(ch)) { inst = ev->a; if(drumset_start_time[bank][inst] == -1) drumset_start_time[bank][inst] = ev->time; drumset_counter[bank][inst]++; } else { inst = channel[ch].program; if(tonebank_start_time[bank][inst] == -1) tonebank_start_time[bank][inst] = ev->time; tonebank_counter[bank][inst]++; } } break; case ME_PROGRAM: if(ISDRUMCHANNEL(ch)) channel[ch].bank = ev->a; else { if(current_file_info && current_file_info->mid == 0x43) /* XG */ channel[ch].bank = channel[ch].bank_lsb; else channel[ch].bank = channel[ch].bank_msb; channel[ch].program = ev->a; } break; case ME_TONE_BANK_LSB: channel[ch].bank_lsb = ev->a; break; case ME_TONE_BANK_MSB: channel[ch].bank_msb = ev->a; break; case ME_RESET: memset(channel, 0, sizeof(channel)); break; } ev++; } } int list_midi_file(char *fn) { MidiEvent *event; int32 events, samples; struct timidity_file *tf; ctl->cmsg(CMSG_INFO, VERB_VERBOSE, "MIDI file: %s", fn); if(!(tf=open_midi_file(fn, 1, OF_VERBOSE))) { perror(fn); return RC_ERROR; } event = read_midi_file(tf, &events, &samples, fn); close_file(tf); if (!event) return RC_ERROR; scan_midievent(event); list_instruments(); free(event); return 0; } char *time_str(int t) { static char buff[32]; t = (int)((double)t / (double)play_mode->rate + 0.5); sprintf(buff, "%d:%02d", t / 60, t % 60); return buff; } void list_instruments(void) { int i, j; for(i = 0; i < 128; i++) for(j = 0; j < 128; j++) { if(tonebank[i]->tone[j].instrument == MAGIC_LOAD_INSTRUMENT) { printf("Tonebank %d %d", i, j); if(tonebank_start_time[i][j] != -1) { printf(" (start at %s, %d times note on)", time_str(tonebank_start_time[i][j]), tonebank_counter[i][j]); } fputs(NLS, stdout); } } for(i = 0; i < 128; i++) for(j = 0; j < 128; j++) { if(drumset[i]->tone[j].instrument == MAGIC_LOAD_INSTRUMENT) { printf("Drumset %d %d", i, j); if(drumset_start_time[i][j] != -1) printf(" (start at %s, %d times note on)", time_str(drumset_start_time[i][j]), drumset_counter[i][j]); fputs(NLS, stdout); } } }