native_midi_gpl.c
上传用户:nini_0081
上传日期:2022-07-21
资源大小:2628k
文件大小:11k
源码类别:

多媒体编程

开发平台:

DOS

  1. /***************************************************************************
  2.                            native_midi_lnx.c
  3.    -----------------
  4.    
  5.     copyright            : (C) 2002 by Peter Ku会k
  6.     email                : kutak@stonline.sk
  7.  ***************************************************************************/
  8. /* in this file is used code from PlayMidi    Copyright (C) 1994-1996 Nathan I. Laredo */
  9. /***************************************************************************
  10.  *                                                                         *
  11.  *   This program is free software; you can redistribute it and/or modify  *
  12.  *   it under the terms of the GNU General Public License as published by  *
  13.  *   the Free Software Foundation; either version 2 of the License, or     *
  14.  *   (at your option) any later version.                                   *
  15.  *                                                                         *
  16.  ***************************************************************************/
  17. #if defined(linux) || defined(__FreeBSD__)
  18. #ifndef __FreeBSD__
  19. #include <getopt.h>
  20. #endif
  21. #include <fcntl.h>
  22. #include <ctype.h>
  23. #include <unistd.h>
  24. #include <sys/stat.h>
  25. #include <string.h>
  26. #include "SDL_thread.h"
  27. #include "native_midi.h"
  28. #include "playmidi.h"
  29. SEQ_DEFINEBUF(SEQUENCERBLOCKSIZE);
  30. int play_fm = 0, play_gus = 0, play_ext = 0, play_awe = 0;
  31. int opl3_patch_aviable = 0, fm_patch_aviable = 0;
  32. struct miditrack seq[MAXTRKS];
  33. struct synth_info card_info[MAX_CARDS];
  34. int FORCE_EXT_DEV = -1;
  35. int chanmask = 0xffff, perc = PERCUSSION;
  36. int dochan = 1, force8bit = 0, wantopl3 = FM_DEFAULT_MODE;
  37. int patchloaded[256], fmloaded[256], useprog[16], usevol[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
  38. int reverb = 0, chorus = 0, nrsynths, nrmidis;
  39. int sb_dev = -1, gus_dev = -1, ext_dev = -1, awe_dev = -1, p_remap = 0;
  40. int seqfd,  MT32 = 0;
  41. FILE *mfd;
  42. unsigned long int default_tempo;
  43. float skew = 1.0;
  44. char ImPlaying = 0;
  45. SDL_Thread *playevents_thread=NULL;
  46. extern int ntrks;
  47. extern char *gmvoice[256];
  48. extern int mt32pgm[128];
  49. extern int note_vel[16][128];
  50. extern int playevents();
  51. extern int gus_load(int);
  52. extern int readmidi(unsigned char *, off_t);
  53. extern void loadfm();
  54. void seqbuf_dump();
  55. int synth_setup();
  56. struct _NativeMidiSong
  57. {
  58.     char *filebuf;
  59.     unsigned long int file_size;
  60. };
  61. int native_midi_detect()
  62. {
  63.     int sbfd;
  64.     int ret=0;    
  65.     /* Open sequencer device */
  66.     if ((seqfd = open(SEQUENCER_DEV, O_WRONLY, 0)) < 0) 
  67.     {
  68. perror("open " SEQUENCER_DEV);
  69. return 0;
  70.     }
  71.     gus_dev = -1;
  72.     sb_dev = -1;
  73.     ext_dev = -1;
  74.     awe_dev = -1;
  75.     play_fm = 0;
  76.     play_gus = 0;
  77.     play_ext = 0;
  78.     play_awe = 0;
  79.     
  80.     opl3_patch_aviable = 0;
  81.     fm_patch_aviable = 0;
  82.     sbfd = open(SBMELODIC, O_RDONLY, 0);
  83.     if (sbfd != -1)
  84.     {
  85. close(sbfd);
  86. sbfd = open(SBDRUMS, O_RDONLY, 0);
  87. if (sbfd != -1)
  88. {
  89.             close(sbfd);
  90.     fm_patch_aviable = 1;
  91. }
  92.     }
  93.     sbfd = open(O3MELODIC, O_RDONLY, 0);
  94.     if (sbfd != -1)
  95.     {
  96.         close(sbfd);
  97.         sbfd = open(O3DRUMS, O_RDONLY, 0);
  98. if (sbfd != -1)
  99. {
  100.             close(sbfd);
  101.     opl3_patch_aviable = 1;
  102. }
  103.     }
  104.     ret=synth_setup();
  105.     /* Close sequencer device */
  106.     close(seqfd);
  107.     return ret;
  108. }
  109. NativeMidiSong *native_midi_loadsong(const char *midifile)
  110. {
  111.     NativeMidiSong *song = NULL;
  112.     char  *extra;
  113.     int  piped = 0;
  114.     struct stat  info;
  115.     song = malloc(sizeof(NativeMidiSong));
  116.     if (!song)
  117.     {
  118. return NULL;
  119.     };
  120.     if (stat(midifile, &info) == -1) 
  121.     {
  122.         if ((extra = malloc(strlen(midifile) + 4)) == NULL)
  123.         {
  124.     goto end;
  125. }
  126. sprintf(extra, "%s.mid", midifile);
  127. if (stat(extra, &info) == -1)
  128. {
  129.     free(extra);
  130.     goto end;
  131. }
  132. if ((mfd = fopen(extra, "r")) == NULL)
  133. {
  134.     free(extra);
  135.     goto end;
  136. }
  137. free(extra);
  138.     } else
  139.     {
  140.         char *ext = strrchr(midifile, '.');
  141.         if (ext && strcmp(ext, ".gz") == 0) 
  142. {
  143.     char temp[1024];
  144.     piped = 1;
  145.     sprintf(temp, "gzip -l %s", midifile);
  146.     if ((mfd = popen(temp, "r")) == NULL)
  147.     {
  148.         goto end;
  149.     }
  150.     fgets(temp, sizeof(temp), mfd); /* skip 1st line */
  151.     fgets(temp, sizeof(temp), mfd);
  152.     strtok(temp, " "); /* compressed size */
  153.     info.st_size = atoi(strtok(NULL, " ")); /* original size */
  154.     pclose(mfd);
  155.     sprintf(temp, "gzip -d -c %s",midifile);
  156.     if ((mfd = popen(temp, "r")) == NULL)
  157.     {
  158.         goto end;
  159.     }
  160. }else if ((mfd = fopen(midifile, "r")) == NULL)
  161. {
  162.     goto end;
  163. }
  164.     }
  165.     if ((song->filebuf = malloc(info.st_size)) == NULL)
  166.     {
  167.         if (piped)
  168.         {
  169.     pclose(mfd);
  170. }else
  171. {
  172.     fclose(mfd);
  173. }
  174. goto end;
  175.     }
  176.     song->file_size=info.st_size;
  177.     fread(song->filebuf, 1, info.st_size, mfd);
  178.     if (piped)
  179.     {
  180.         pclose(mfd);
  181.     } else
  182.     {
  183.         fclose(mfd);
  184.     }
  185.     
  186.   return song;
  187. end:
  188.     free(song);
  189.     return NULL;
  190. }
  191. NativeMidiSong *native_midi_loadsong_RW(SDL_RWops *rw)
  192. {
  193. NativeMidiSong *song = NULL;
  194. char  *extra;
  195. song = malloc(sizeof(NativeMidiSong));
  196. if (!song) {
  197. return NULL;
  198. };
  199. SDL_RWseek(rw, 0, RW_SEEK_END);
  200. song->file_size = SDL_RWtell(rw);
  201. SDL_RWseek(rw, 0, RW_SEEK_SET);
  202. song->filebuf = malloc(song->file_size);
  203. if (!song->filebuf) {
  204. free(song);
  205. return NULL;
  206. }
  207. SDL_RWread(rw, song->filebuf, song->file_size, 1);
  208. return song;
  209. }
  210. void native_midi_freesong(NativeMidiSong *song)
  211. {
  212.     free(song->filebuf);
  213.     free(song);
  214. }
  215. void native_midi_start(NativeMidiSong *song)
  216. {
  217.     int i, error = 0, j;
  218.     for (i = 0; i < 16; i++)
  219.     {
  220. useprog[i] = 0; /* reset options */
  221.     }
  222.     
  223.     /* Open sequencer device */
  224.     if ((seqfd = open(SEQUENCER_DEV, O_WRONLY, 0)) < 0) 
  225.     {
  226. perror("open " SEQUENCER_DEV);
  227. goto eend;
  228.     }
  229.     if(!synth_setup()) { goto end;};
  230.     if (play_gus)
  231.     {
  232. gus_load(-1);
  233.     }
  234.     default_tempo = 500000;
  235.     /* error holds number of tracks read */
  236.     error = readmidi(song->filebuf, song->file_size);
  237.     if (play_gus && error > 0) 
  238.     {
  239. int i; /* need to keep other i safe */
  240. #define CMD (seq[i].data[j] & 0xf0)
  241. #define CHN (seq[i].data[j] & 0x0f)
  242. #define PGM (seq[i].data[j + 1])
  243. /* REALLY STUPID way to preload GUS, but it works */
  244. for (i = 0; i < ntrks; i++)
  245.     for (j = 0; j < seq[i].length - 5; j++)
  246. if (ISGUS(CHN) && !(PGM & 0x80) &&
  247.     ((CMD == MIDI_PGM_CHANGE && !ISPERC(CHN))
  248.      || (CMD == MIDI_NOTEON && ISPERC(CHN))))
  249.     gus_load(ISPERC(CHN) ? PGM + 128 :
  250.      useprog[CHN] ? useprog[CHN] - 1 :
  251.      MT32 ? mt32pgm[PGM] : PGM);
  252. /* make sure that some program was loaded to use */
  253. for (j = 0; patchloaded[j] != 1 && j < 128; j++);
  254. if (j > 127)
  255.     gus_load(0);
  256.     }
  257. /* if there's an error skip to next file */
  258.     if (error > 0) /* error holds number of tracks read */
  259.     {
  260. ImPlaying=1;
  261.      playevents_thread=SDL_CreateThread(playevents,NULL);
  262.     }
  263. end:
  264. eend:
  265.     return;
  266. }
  267. void native_midi_stop()
  268. {
  269.     /* Close sequencer device */
  270.     close(seqfd);
  271. }
  272. int native_midi_active()
  273. {
  274.     return ImPlaying;
  275. }
  276. void native_midi_setvolume(int volume)
  277. {
  278. }
  279. const char *native_midi_error(void)
  280. {
  281.   return "stala sa chyba";
  282. }
  283. void seqbuf_dump()
  284. {
  285.     if (_seqbufptr)
  286. if (write(seqfd, _seqbuf, _seqbufptr) == -1) {
  287.     perror("write " SEQUENCER_DEV);
  288.     return;
  289. }
  290.     _seqbufptr = 0;
  291. }
  292. int synth_setup()
  293. {
  294.     int i;
  295.     char *nativemusicenv = getenv("SDL_NATIVE_MUSIC");
  296.     char *extmidi=getenv("SDL_NATIVE_MUSIC_EXT");
  297.     if(extmidi)
  298.     {
  299.      FORCE_EXT_DEV = atoi(extmidi);
  300. printf("EXT midi %s , %d n",extmidi,FORCE_EXT_DEV);
  301.     }
  302.     
  303.     if (ioctl(seqfd, SNDCTL_SEQ_NRSYNTHS, &nrsynths) == -1) 
  304.     {
  305. fprintf(stderr, "there is no soundcardn");
  306. return 0;
  307.     }
  308.     for (i = 0; i < nrsynths; i++) 
  309.     {
  310. card_info[i].device = i;
  311. if (ioctl(seqfd, SNDCTL_SYNTH_INFO, &card_info[i]) == -1) 
  312. {
  313.     fprintf(stderr, "cannot get info on soundcardn");
  314.     perror(SEQUENCER_DEV);
  315.     return 0;
  316. }
  317. card_info[i].device = i;
  318. if (card_info[i].synth_type == SYNTH_TYPE_SAMPLE
  319.     && card_info[i].synth_subtype == SAMPLE_TYPE_GUS)
  320. {
  321.     gus_dev = i;
  322. }else if (card_info[i].synth_type == SYNTH_TYPE_SAMPLE
  323.     && card_info[i].synth_subtype == SAMPLE_TYPE_AWE32)
  324. {
  325.     awe_dev = i;
  326. }else if (card_info[i].synth_type == SYNTH_TYPE_FM) 
  327. {
  328.     sb_dev = i;
  329.     if (play_fm)
  330. loadfm();
  331.     if (wantopl3) 
  332.     {
  333. card_info[i].nr_voices = 12; /* we have 12 with 4-op */
  334.     }
  335. }
  336.     }
  337.     if (gus_dev >= 0) {
  338. if (ioctl(seqfd, SNDCTL_SEQ_RESETSAMPLES, &gus_dev) == -1) 
  339. {
  340.     perror("Sample reset");
  341.     return 0;
  342. }
  343.     }
  344.     if (ioctl(seqfd, SNDCTL_SEQ_NRMIDIS, &nrmidis) == -1) 
  345.     {
  346. fprintf(stderr, "can't get info about midi portsn");
  347. return 0;
  348.     }
  349.     if (nrmidis > 0) {
  350. if (FORCE_EXT_DEV >= 0)
  351.     ext_dev = FORCE_EXT_DEV;
  352. else
  353.     ext_dev = nrmidis - 1;
  354.     }
  355.     if( nativemusicenv ) /* select device by SDL_NATIVE_MUSIC */
  356.     {
  357. if(strcasecmp(nativemusicenv,"GUS") == 0)
  358. {
  359.          if( gus_dev >= 0 )
  360.     {
  361.      play_gus = -1;
  362.         awe_dev = -1;
  363. sb_dev  = -1;
  364.         ext_dev = -1;
  365.         return 1;
  366.             }else
  367.     {
  368.      play_gus = 0;
  369. return 0;
  370.     }
  371. }else if(strcasecmp(nativemusicenv,"AWE") == 0)
  372. {
  373.          if( awe_dev >= 0 )
  374.     {
  375.      play_awe = -1;
  376.         gus_dev = -1;
  377. sb_dev  = -1;
  378.         ext_dev = -1;
  379.         return 1;
  380.             }else
  381.     {
  382.      play_awe = 0;
  383. return 0;
  384.     }
  385. }else if(strcasecmp(nativemusicenv,"FM") == 0)
  386. {
  387.          if( sb_dev >= 0 && fm_patch_aviable )
  388.     {
  389.      play_fm = -1;
  390. gus_dev = -1;
  391.         awe_dev = -1;
  392.         ext_dev = -1;
  393.         wantopl3 = 0;
  394.         return 1;
  395.             }else
  396.     {
  397.      play_fm = 0;
  398. return 0;
  399.     }
  400. }else if(strcasecmp(nativemusicenv,"OPL3") == 0)
  401. {
  402.          if( sb_dev >= 0 && opl3_patch_aviable )
  403.     {
  404.      play_fm = -1;
  405. gus_dev = -1;
  406.         awe_dev = -1;
  407.         ext_dev = -1;
  408.         wantopl3 = 1;
  409.         return 1;
  410.             }else
  411.     {
  412.      play_fm = 0;
  413. return 0;
  414.     }
  415. }else if(strcasecmp(nativemusicenv,"EXT") == 0)
  416. {
  417.          if( ext_dev >= 0 )
  418.     {
  419.      play_ext = -1;
  420.         gus_dev = -1;
  421.         awe_dev = -1;
  422. sb_dev  = -1;
  423.         return 1;
  424.             }else
  425.     {
  426.      play_ext = 0;
  427. return 0;
  428.     }
  429. }
  430.     }
  431.     /* autoselect best device */
  432.     if( gus_dev >= 0 )
  433.     {
  434.         play_gus = -1;
  435.         awe_dev = -1;
  436.         sb_dev  = -1;
  437.         ext_dev = -1;
  438.         return 1;
  439.         }
  440.     if( awe_dev >= 0 )
  441.     {
  442.         play_awe = -1;
  443. gus_dev = -1;
  444.         sb_dev  = -1;
  445.         ext_dev = -1;
  446.         return 1;
  447.     }
  448.     if( sb_dev >= 0 && fm_patch_aviable )
  449.     {
  450.         play_fm = -1;
  451. gus_dev = -1;
  452.         awe_dev = -1;
  453.         ext_dev = -1;
  454.         return 2; /* return 1 if use FM befor Timidity */
  455.     }
  456.     if( ext_dev >= 0 )
  457.     {
  458.         play_ext = -1;
  459. gus_dev = -1;
  460.         awe_dev = -1;
  461.         sb_dev  = -1;
  462.         return 3;
  463.     }
  464.     return 0;
  465. }
  466. #endif /* linux || FreeBSD */