home *** CD-ROM | disk | FTP | other *** search
/ Inside Multimedia 1995 August / IMM0895.ISO01.iso / share / os2 / track061 / main.c < prev    next >
Text File  |  1992-12-08  |  21KB  |  735 lines

  1. /* main.c (formerly str32.c) */
  2.  
  3. /* modified (rewritten) by David Nichols for PM MOD player */
  4.  
  5. /* original authors:
  6.  * Authors  : Liam Corner - zenith@dcs.warwick.ac.uk
  7.  *            Marc Espie - espie@dmi.ens.fr
  8.  *            Steve Haehnichen - shaehnic@ucsd.edu
  9. */
  10.  
  11. #include <stdio.h>
  12.  
  13. #define INCL_DOS
  14. #define INCL_WIN
  15. #define INCL_GPI
  16.  
  17. #include <os2.h>
  18. #include <stdlib.h>
  19. #include <string.h>
  20. #include <ctype.h>
  21. #include "sblast_user.h"
  22. #include "defs.h"
  23. #include "os2defs.h"
  24. #include "tracker.h"
  25. #include "easyfont.h"
  26.  
  27. #define LCID_MYFONT 1
  28.  
  29. HWND hwndControl;
  30. HWND hwndSong;
  31. HWND hwndTime;
  32. HWND hwndName;
  33. HWND hwndQueue;
  34. HWND hwndChan1, hwndChan2, hwndChan3, hwndChan4;
  35.  
  36. HPS hpsSong;
  37. HPS hpsTime;
  38. HPS hpsName;
  39. HPS hpsQueue;
  40. HPS hpsChan1, hpsChan2, hpsChan3, hpsChan4;
  41.  
  42. RECTL rclTime, rclSong, rclName, rclQueue,
  43.     rclChan1, rclChan2, rclChan3, rclChan4;
  44.  
  45. HAB hab;
  46. HMQ hmq;
  47.  
  48. HSWITCH hSwitch;                /* Switch entry handle        */
  49.  
  50. int quiet = 0;                  /* Global flag for no text output */
  51. int suspended = 0;              /* flag for pause mode */
  52. int abortsong = 0;                  /* abort flag */
  53. int blink;
  54. int pauseack = 0;
  55. int terminate = 0;
  56. int iconic = 0;
  57.  
  58. struct pref pref;               /* Global user preferences */
  59.  
  60. int error_flag = 0;
  61.  
  62. int priority = 0;
  63.  
  64. /* global variable to catch various types of errors
  65.  * and achieve the desired flow of control
  66.  */
  67. int error;
  68. /* small hack for transposing songs on the fly */
  69. static int transpose;
  70.  
  71. char *msong[MAXSONGS];
  72.  
  73. int numsongs = 0,
  74.    songnum = 0,
  75.    frequency, 
  76.    oversample;
  77.  
  78. int fwidth, fheight;
  79.  
  80. USHORT DMAbuffersize = 63;
  81.  
  82. char playermode[32] = " ";
  83.  
  84. char title[] = "Tracker/PM";
  85. char paused[] = " (paused)";
  86.  
  87. char progname[128] = "Tracker";
  88.  
  89. char programpath[256];
  90. char currentdisk[3] = "c:";
  91. char currentdir[256];
  92.  
  93. char usage[] = \
  94.   "usage: %s [-][options] filename [filename [...]]\n"
  95.   "-h: Help; display usage information\n"
  96.   "-i: Iconic; start as an icon\n"
  97.   "-m: Mono; select single audio channel output\n"
  98.   "-s: Stereo; select dual audio channel output\n"
  99.   "-n: New; select new MOD type for mod playing\n"
  100.   "-o: Old; select old MOD type for mod playing\n"
  101.   "-b: Both; select both MOD types to try (default is -both)\n"
  102.   "-T: Terminate; terminate after playing all MODs\n"
  103.   "-L: Low priority; sets tracker to normal low priority (default)\n"
  104.   "-M: Middle priority; sets tracker to \"foregroundserver\" priority\n" 
  105.   "-H: Highest priority; sets tracker to \"timecritical\" priority\n"
  106.   "-dnum: DMA buffer size; set DMA buffer size in K.\n"
  107.   "-fnum: Frequency; sets playback frequency to <num> Hz.\n"
  108.   "-tnum: Transpose all notes up <num> half-steps\n"
  109.   "-rnum: Repeat; repeats <num> number of repeats (0 is forever) (default 1)\n"
  110.   "-Bnum: Blend; sets percent of channel mixing to <num>. (0=spatial, 100=mono)\n"
  111.   "-Onum: Oversample; set oversampling to <num> times.\n"
  112.   "-Snum: Speed; set song speed to <speed>.  Some songs want 60 (default 50)\n"
  113.   "%s: OS/2 2.0 32bit MOD player\n";
  114.  
  115. FILE *debug;
  116. int logerrors = 1;
  117.  
  118. void quit(int rv)
  119. {
  120.    restoreparams();
  121.    close_audio();
  122.    WinDestroyWindow(hwndControl);
  123.    WinDestroyMsgQueue(hmq);
  124.    WinTerminate(hab);
  125.    exit(rv);
  126. }
  127.  
  128. void trackerror(int err, char *txt, int errtype)
  129. {
  130.    if (logerrors) fprintf(debug, "ERROR %d: %s\n", err, txt);
  131.    if (errtype == FATAL_ERROR) quit(err);
  132. }
  133.  
  134. struct song *do_read_song(char *s, int type)
  135. {
  136.   struct song *song;
  137.   FILE *fp;
  138.  
  139.   fp = fopen (s, "rb");
  140.   if (fp == NULL)
  141.     {
  142.       trackerror(1, "Unable to open tune file", NONFATAL_ERROR);
  143.       return NULL;
  144.     }
  145.   song = read_song (fp, type, transpose);
  146.   fclose (fp);
  147.   
  148.   return song;
  149. }
  150.  
  151. char *strtolower(wordv)
  152. char *wordv;
  153. {
  154.    int loop = 0;
  155.  
  156.    while(wordv[loop])
  157.    {
  158.       if (isupper(wordv[loop])) wordv[loop] = tolower(wordv[loop]);
  159.       loop++;
  160.    }
  161.    return wordv;
  162. }
  163.  
  164. void checkext(char *fn)
  165. {
  166.    int l;
  167.  
  168.    strtolower(fn);
  169.    l = strlen(fn);
  170.    if ((l < 5)||(strcmp(&fn[l-4],".mod"))) 
  171.       if (fn[l] != '.') strcat(fn, ".mod");
  172. }
  173.  
  174. void getpname(char *argv[])
  175. {
  176.    int cp;
  177.    char t[2] = { '\0', '\0' };
  178.  
  179.    programpath[0] = '\0';
  180.    cp = strlen(argv[0]);
  181.    if (cp)
  182.    {
  183.       while (cp && (argv[0][cp] != '\\') && (argv[0][cp] != ':')) cp--;
  184.       if (cp)
  185.       {
  186.          t[0] = argv[0][cp];
  187.      argv[0][cp] = '\0';
  188.          cp++;
  189.       }
  190.       strcpy(progname, &argv[0][cp]);
  191.       strtolower(progname);
  192.       cp = strlen(progname);
  193.       while (cp && (progname[cp] != '.')) cp--;
  194.       if (progname[cp] == '.') progname[cp] = '\0';
  195.       strcpy(programpath, argv[0]);
  196.       strcat(programpath, t);
  197.    }
  198. }
  199.  
  200.  
  201. void fixfn(char *fn)
  202. {
  203.    int cp;
  204.    char buf[strlen(fn)];
  205.  
  206.    cp = strlen(fn);
  207.    if (cp)
  208.    {
  209.       while (cp && (fn[cp] != '\\') && (fn[cp] != ':')) cp--;
  210.       strcpy(buf, &fn[cp+1]);
  211.       strcpy(fn, buf);
  212.    }
  213. }
  214.  
  215. void gotodir(char *path)
  216. {
  217.    int cp;
  218.    char buf[strlen(path)+1];
  219.    char *p;
  220.  
  221.    strcpy(buf, path);
  222.    p = buf;
  223.    if (p[1] == ':')
  224.    {
  225.       if (islower(p[0])) p[0] = toupper(p[0]);
  226.       if (isupper(p[0])) 
  227.       {
  228. /*     DosSetDefaultDisk(p[0]-'A'); */
  229.      currentdisk[0] = p[0];
  230.       }
  231.       p += 2;
  232.    }
  233.    cp = strlen(p);
  234.    if (cp)
  235.    {
  236.       while (cp && (p[cp] != '\\') && (p[cp] != ':')) cp--;
  237.       p[cp+1] = '\0';
  238.       strcpy(currentdir, p);
  239. /*      DosSetCurrentDir(p); */
  240.    }   
  241. }
  242.  
  243. int OpenDlg(HWND hwndOwner)
  244. {
  245.    FILEDLG fild;         /* File dialog structure. */
  246.  
  247.    memset(&fild, 0, sizeof(FILEDLG));
  248.    fild.cbSize     = sizeof(FILEDLG);
  249.    fild.fl         = FDS_OPEN_DIALOG|FDS_CENTER;
  250.    fild.pszIDrive  = currentdisk;
  251.    strcpy(fild.szFullFile, currentdir);
  252.    strcat(fild.szFullFile, "*.mod");
  253.    fild.pszTitle = "Queue Song";
  254.    fild.pszOKButton = "Queue";
  255.    WinFileDlg(HWND_DESKTOP, hwndOwner, &fild);
  256.    if (fild.lReturn == DID_OK)
  257.    {
  258.       DosAllocMem((PVOID) &msong[numsongs], strlen(fild.szFullFile)+1,
  259.           PAG_READ|PAG_WRITE|PAG_COMMIT);
  260. /*    msong[numsongs] = (char *)malloc(strlen(fild.szFullFile)+1); */
  261.       strcpy(msong[numsongs], fild.szFullFile);
  262.       gotodir(msong[numsongs]);
  263.       numsongs++;
  264.       PrintSong(NULL);
  265.       return 1;
  266.    }
  267.    return 0;
  268. }
  269.  
  270.  
  271. MRESULT AboutDlgProc(HWND hwnd, USHORT msg, MPARAM mp1, MPARAM mp2)
  272. {
  273.    switch(msg)
  274.    {
  275.       case WM_INITDLG:
  276.      break;
  277.  
  278.       case WM_COMMAND:
  279.       switch(SHORT1FROMMP(mp1))
  280.        {
  281.         case MBID_OK:
  282.                break;
  283.      }
  284.      break;
  285.    }
  286.    return WinDefDlgProc(hwnd, msg, mp1, mp2);
  287. }
  288.  
  289. MRESULT ControlDlgProc(HWND hwnd, USHORT msg, MPARAM mp1, MPARAM mp2)
  290. {
  291.    static TID tid;
  292.    static THREADPARAMS tp;
  293.    static struct song *song = NULL;
  294.    static char buf[256];
  295.    static HRGN hrgnSong;
  296.    static HRGN hrgnTime;
  297.    static HRGN hrgnName;
  298.    static HRGN hrgnQueue;
  299.    static HRGN hrgnChan1;
  300.    static HRGN hrgnChan2;
  301.    static HRGN hrgnChan3;
  302.    static HRGN hrgnChan4;
  303.    static HRGN hrgnTemp;
  304.    static int x;
  305.    static FONTMETRICS fm;
  306.    static REAL_SWCNTRL SwitchData;        /* Switch control data block  */
  307.  
  308.    switch (msg)
  309.    {
  310.       case WM_INITDLG:
  311.          DosCreateEventSem("\\sem32\\done", &tp.hevDone, 0, (BOOL32) FALSE);
  312.      DosCreateEventSem("\\sem32\\pause", &tp.hevPause, 0, (BOOL32) FALSE);
  313.      tp.fPlaying = FALSE;
  314.      hwndSong = WinWindowFromID(hwnd, ID_SONGRECT);
  315.      hwndTime = WinWindowFromID(hwnd, ID_TIMERECT);
  316.      hwndName = WinWindowFromID(hwnd, ID_NAMERECT);
  317.      hwndQueue = WinWindowFromID(hwnd, ID_QUEUERECT);
  318.      hwndChan1 = WinWindowFromID(hwnd, ID_CHAN1RECT);
  319.      hwndChan2 = WinWindowFromID(hwnd, ID_CHAN2RECT);
  320.      hwndChan3 = WinWindowFromID(hwnd, ID_CHAN3RECT);
  321.      hwndChan4 = WinWindowFromID(hwnd, ID_CHAN4RECT);
  322.      hpsSong = WinGetPS(hwndSong);
  323.      hpsTime = WinGetPS(hwndTime);
  324.      hpsName = WinGetPS(hwndName);
  325.      hpsQueue = WinGetPS(hwndQueue);
  326.      hpsChan1 = WinGetPS(hwndChan1);
  327.      hpsChan2 = WinGetPS(hwndChan2);
  328.      hpsChan3 = WinGetPS(hwndChan3);
  329.      hpsChan4 = WinGetPS(hwndChan4);
  330.      WinQueryWindowRect(hwndSong, &rclSong);
  331.      WinQueryWindowRect(hwndTime, &rclTime);
  332.      WinQueryWindowRect(hwndName, &rclName);
  333.      WinQueryWindowRect(hwndQueue, &rclQueue);
  334.      WinQueryWindowRect(hwndChan1, &rclChan1);
  335.      WinQueryWindowRect(hwndChan2, &rclChan2);
  336.      WinQueryWindowRect(hwndChan3, &rclChan3);
  337.      WinQueryWindowRect(hwndChan4, &rclChan4);
  338.      hrgnSong = GpiCreateRegion(hpsSong, 1, &rclSong);
  339.      hrgnTime = GpiCreateRegion(hpsTime, 1, &rclTime);
  340.      hrgnName = GpiCreateRegion(hpsName, 1, &rclName);
  341.      hrgnQueue = GpiCreateRegion(hpsQueue, 1, &rclQueue);
  342.      hrgnChan1 = GpiCreateRegion(hpsChan1, 1, &rclChan1);
  343.      hrgnChan2 = GpiCreateRegion(hpsChan2, 1, &rclChan2);
  344.      hrgnChan3 = GpiCreateRegion(hpsChan3, 1, &rclChan3);
  345.      hrgnChan4 = GpiCreateRegion(hpsChan4, 1, &rclChan4);
  346.      GpiSetClipRegion(hpsSong, hrgnSong, hrgnTemp);
  347.      GpiSetClipRegion(hpsTime, hrgnTime, hrgnTemp);
  348.      GpiSetClipRegion(hpsName, hrgnName, hrgnTemp);
  349.      GpiSetClipRegion(hpsQueue, hrgnQueue, hrgnTemp);
  350.      GpiSetClipRegion(hpsChan1, hrgnChan1, hrgnTemp);
  351.      GpiSetClipRegion(hpsChan2, hrgnChan2, hrgnTemp);
  352.      GpiSetClipRegion(hpsChan3, hrgnChan3, hrgnTemp);
  353.      GpiSetClipRegion(hpsChan4, hrgnChan4, hrgnTemp);
  354.          GpiCreateLogColorTable(hpsSong, LCOL_PURECOLOR, LCOLF_RGB,
  355.                 0L, 0L, NULL);
  356.          GpiCreateLogColorTable(hpsTime, LCOL_PURECOLOR, LCOLF_RGB,
  357.                 0L, 0L, NULL);
  358.          GpiCreateLogColorTable(hpsName, LCOL_PURECOLOR, LCOLF_RGB,
  359.                 0L, 0L, NULL);
  360.          GpiCreateLogColorTable(hpsQueue, LCOL_PURECOLOR, LCOLF_RGB,
  361.                 0L, 0L, NULL);
  362.          GpiCreateLogColorTable(hpsChan1, LCOL_PURECOLOR, LCOLF_RGB,
  363.                 0L, 0L, NULL);
  364.          GpiCreateLogColorTable(hpsChan2, LCOL_PURECOLOR, LCOLF_RGB,
  365.                 0L, 0L, NULL);
  366.          GpiCreateLogColorTable(hpsChan3, LCOL_PURECOLOR, LCOLF_RGB,
  367.                 0L, 0L, NULL);
  368.          GpiCreateLogColorTable(hpsChan4, LCOL_PURECOLOR, LCOLF_RGB,
  369.                 0L, 0L, NULL);
  370.      EzfQueryFonts(hpsSong);
  371.      EzfQueryFonts(hpsName);
  372.          EzfCreateLogFont(hpsSong, LCID_MYFONT, FONTFACE_TIMES, 
  373.                                  FONTSIZE_10, 0) ;         
  374.          EzfCreateLogFont(hpsName, LCID_MYFONT, FONTFACE_TIMES, 
  375.                                  FONTSIZE_10, 0) ;         
  376.      GpiSetCharSet(hpsSong, LCID_MYFONT);
  377.      GpiSetCharSet(hpsName, LCID_MYFONT);
  378.      strcpy(buf, programpath);
  379.      strcat(buf, "lcd.fon");
  380.      if (!GpiLoadFonts(hab, buf)) trackerror(1, "can't load font", FATAL_ERROR);
  381.      EzfQueryFonts(hpsTime);
  382.      EzfQueryFonts(hpsQueue);
  383.          EzfCreateLogFont(hpsTime, LCID_MYFONT, FONTFACE_SYSTEM,
  384.                                  FONTSIZE_10, 0) ;         
  385.          EzfCreateLogFont(hpsQueue, LCID_MYFONT, FONTFACE_SYSTEM,
  386.                                  FONTSIZE_10, 0) ;         
  387.      GpiSetCharSet(hpsTime, LCID_MYFONT);
  388.      GpiSetCharSet(hpsQueue, LCID_MYFONT);
  389.      GpiQueryFontMetrics(hpsSong, sizeof(FONTMETRICS), &fm);
  390.      fwidth = (USHORT)(1.2*fm.lAveCharWidth);
  391.          fheight= (USHORT)(fm.lExternalLeading+fm.lMaxBaselineExt);
  392.      playermode[0] = PLAYER_STOP;
  393.  
  394.      if (numsongs) WinPostMsg(hwnd,WM_COMMAND,MPFROM2SHORT(IDM_PLAY,0),0);
  395.      break;
  396.  
  397.       case WM_SHOW:
  398.       case WM_ENABLE:
  399.       case WM_ACTIVATE:
  400.          DosEnterCritSec();
  401.  
  402. /*     WinQueryWindowRect(hwndSong, &rclSong);
  403.      WinFillRect(hpsSong, &rclSong, CLR_BLACK);
  404.      WinQueryWindowRect(hwndName, &rclName);
  405.      WinFillRect(hpsName, &rclName, CLR_BLACK);
  406.      WinQueryWindowRect(hwndTime, &rclTime);
  407.      WinFillRect(hpsTime, &rclTime, CLR_BLACK); 
  408. */
  409.      if (tp.fPlaying) PrintSong(tp.fn);
  410.      else PrintSong(NULL);
  411.      
  412.      DosExitCritSec();
  413.      break;
  414.        
  415.       case WM_CLOSE:
  416.             if (tp.fPlaying) WinSendMsg(hwnd, WM_COMMAND, MPFROM2SHORT(IDM_STOP,0), 0);
  417.      return WinDefWindowProc(hwnd, msg, mp1, mp2);
  418.  
  419.       case WM_DESTROY:
  420.          WinReleasePS(hpsSong);
  421.      WinReleasePS(hpsTime);
  422.      WinReleasePS(hpsName);
  423.      WinReleasePS(hpsQueue);
  424.      WinReleasePS(hpsChan1);
  425.      WinReleasePS(hpsChan2);
  426.      WinReleasePS(hpsChan3);
  427.      WinReleasePS(hpsChan4);
  428.      return 0;
  429.  
  430.       case WM_COMMAND:
  431.      switch (SHORT1FROMMP (mp1))
  432.      {
  433.         case IDM_OPEN:
  434.            if (OpenDlg(hwnd)&&!suspended) WinSendMsg(hwnd,WM_COMMAND,MPFROM2SHORT(IDM_PLAY,0),0);
  435.            return 0;
  436.  
  437.         case IDM_PAUSE:
  438.            if (suspended) WinSendMsg(hwnd,WM_COMMAND,MPFROM2SHORT(IDM_PLAY,0),0);
  439.            else if (tp.fPlaying)
  440.            {
  441.           blink = 1;
  442.           DosResetEventSem(tp.hevPause, &x);
  443.           pauseack = 1;
  444.           WinQuerySwitchEntry(hSwitch, (PSWCNTRL) &SwitchData);
  445.           strcpy(buf, title);
  446.           strcat(buf, " - ");
  447.           strcat(buf, tp.fn);
  448.           strcat(buf, paused);
  449.           strcpy(SwitchData.szSwtitle, buf);
  450.           WinChangeSwitchEntry(hSwitch, (PSWCNTRL) &SwitchData);
  451.           WinSetWindowText(hwndControl, buf);
  452.            }
  453.            return 0;
  454.  
  455.         case IDM_FF:
  456.         case IDM_FR:
  457.  
  458.         case IDM_PREV:
  459.         case IDM_NEXT:
  460.            if (SHORT1FROMMP(mp1)==IDM_PREV)
  461.            {
  462.           songnum -= 2;
  463.           if (songnum < 0) songnum = 0;
  464.           if (tp.fPlaying)
  465.           {
  466.              playermode[0] = PLAYER_REWIND;
  467.              PrintSong(NULL);
  468.            }
  469.            }
  470.            else if (tp.fPlaying)
  471.            {
  472.               playermode[0] = PLAYER_FASTFORWARD;
  473.           PrintSong(NULL);
  474.            }
  475.            if (tp.fPlaying) WinSendMsg(hwnd, WM_COMMAND, MPFROM2SHORT(IDM_STOP,0), 0);
  476.            WinSendMsg(hwnd, WM_COMMAND, MPFROM2SHORT(IDM_PLAY,0), 0);
  477.            return 0;
  478.  
  479.             case IDM_RESTART:
  480.            if (tp.fPlaying)
  481.            {
  482.               WinSendMsg(hwnd, WM_COMMAND, MPFROM2SHORT(IDM_STOP,0), 0);
  483.           songnum--;
  484.               WinSendMsg(hwnd, WM_COMMAND, MPFROM2SHORT(IDM_PLAY,0), 0);
  485.            }
  486.            return 0;
  487.  
  488.         case IDM_STOP:
  489.            if (tp.fPlaying)
  490.            {
  491.           blink = TRUE;
  492.           abortsong = TRUE;
  493.           tp.fTerminate = TRUE;
  494.           if (suspended) 
  495.           {
  496.              DosPostEventSem(tp.hevPause);
  497. /*             DosResumeThread(tid); */
  498.              WinQuerySwitchEntry(hSwitch, (PSWCNTRL) &SwitchData); 
  499.              strcpy(SwitchData.szSwtitle, title);
  500.              WinChangeSwitchEntry(hSwitch, (PSWCNTRL) &SwitchData);
  501.              WinSetWindowText(hwndControl,title);
  502.              suspended = 0;
  503.           }
  504.           DosWaitEventSem(tp.hevDone, SEM_INDEFINITE_WAIT);
  505.            }
  506.            return 0;
  507.  
  508.         case IDM_PLAY:
  509.            if (tp.fPlaying)
  510.           if (suspended)
  511.           {
  512.              DosPostEventSem(tp.hevPause);
  513. /*             DosResumeThread(tid); */
  514.              WinQuerySwitchEntry(hSwitch, (PSWCNTRL) &SwitchData); 
  515.              strcpy(buf,title);
  516.              strcat(buf, " - ");
  517.              strcat(buf, tp.fn);
  518.              strcpy(SwitchData.szSwtitle, buf);
  519.              WinChangeSwitchEntry(hSwitch, (PSWCNTRL) &SwitchData);
  520.              WinSetWindowText(hwnd,buf);
  521.              suspended = 0;
  522.              playermode[0] = PLAYER_PLAY;
  523.              PrintSong(NULL);
  524.              return 0;
  525.           }
  526.               else return 0;
  527.            if (songnum < numsongs)
  528.            {
  529.           switch (pref.type)
  530.           {
  531.              case BOTH:
  532.                 song = do_read_song(msong[songnum], NEW);
  533.                 if (!song) song = do_read_song (msong[songnum], OLD);
  534.                 break;
  535.              case OLD:
  536.                 song = do_read_song (msong[songnum], pref.type);
  537.                 break;
  538.              case NEW:
  539.                 song = do_read_song (msong[songnum], NEW_NO_CHECK);
  540.                 break;
  541.           }
  542.           if (song != NULL)
  543.           {
  544.              DosResetEventSem(tp.hevDone, &x);
  545.              tp.fTerminate = FALSE;
  546.              tp.song = song;
  547.              tp.pref = &pref;
  548.              tp.fPlaying = TRUE;
  549.              tp.hwndControl = hwnd;
  550.              DosAllocMem((PVOID) &tp.fn, strlen(msong[songnum])+1,
  551.                  PAG_READ|PAG_WRITE|PAG_COMMIT);
  552.              strcpy(tp.fn, msong[songnum]);
  553.              fixfn(tp.fn);
  554.              playermode[0] = PLAYER_PLAY;
  555.              PrintSong(NULL);
  556.              DosCreateThread(&tid, PlaySong, (ULONG)&tp, 0, 0x4000);
  557.              if (priority) DosSetPriority(PRTYS_THREAD,priority,0,tid);
  558.              WinQuerySwitchEntry(hSwitch, (PSWCNTRL) &SwitchData); 
  559.              strcpy(buf,title);
  560.              strcat(buf, " - ");
  561.              strcat(buf, tp.fn);
  562.              strcpy(SwitchData.szSwtitle, buf);
  563.              WinChangeSwitchEntry(hSwitch, (PSWCNTRL) &SwitchData);
  564.              WinSetWindowText(hwnd,buf);
  565.           }
  566.           songnum++;
  567.            }
  568.            else
  569.            {
  570.           playermode[0] = PLAYER_STOP;
  571.           PrintSong(NULL);
  572.              if (terminate) WinSendMsg(hwnd, WM_CLOSE, 0, 0);
  573.            }
  574.            return 0;
  575.  
  576.         case IDM_EXIT:
  577.            WinSendMsg (hwnd, WM_CLOSE, 0L, 0L);
  578.            return 0;
  579.  
  580.             case IDM_ABOUT:
  581.            DosEnterCritSec();
  582.  
  583.                WinLoadDlg(HWND_DESKTOP, hwnd, AboutDlgProc, NULL, IDM_ABOUT, NULL);
  584.  
  585.            DosExitCritSec();
  586.                return 0;
  587.      }
  588.      break;
  589.    }
  590.    return WinDefDlgProc(hwnd, msg, mp1, mp2);
  591. }
  592.  
  593. void getcd(char *cdfile)
  594. {
  595.    FILE *cdf;
  596.    char buf[256];
  597.  
  598.    if ((cdf = fopen(cdfile, "rt")) == NULL) return;
  599.    while (!feof(cdf))
  600.    {
  601.       fscanf(cdf, "%s", buf);
  602.       msong[numsongs] = (char *)malloc(strlen(buf)+5);
  603.       strcpy(msong[numsongs], buf);
  604.       checkext(msong[numsongs]);
  605.       numsongs++;
  606.    }
  607.    fclose(cdf);
  608. }
  609.  
  610. int checkcd(char *fn)
  611. {
  612.    int x;
  613.    char buf[4];
  614.  
  615.    if ((x = strlen(fn)) < 4) return 0;
  616.    strcpy(buf, &fn[x-3]);
  617.    strtolower(buf);
  618.    return !strcmp(buf, ".cd");
  619. }
  620.  
  621. void parsecommandline(int argc, char *argv[])
  622. {
  623.    int i, j, count;
  624.  
  625.    if (argc) for (i=1; i<argc; i++)
  626.       {
  627.      if (argv[i][0] == '@') getcd(&argv[i][1]);
  628.      else if (checkcd(argv[i])) getcd(argv[i]);
  629.      else if (argv[i][0] != '-') 
  630.      {
  631.         msong[numsongs] = (char *)malloc(strlen(argv[i])+5);
  632.         strcpy(msong[numsongs], argv[i]);
  633.         checkext(msong[numsongs]);
  634.         numsongs++;
  635.      }
  636.      else
  637.      {
  638.         count = strlen(argv[i]);
  639.         for(j=1;j<count;j++)
  640.         {
  641.            switch (argv[i][j])
  642.            {
  643. /*          case 'h': help(); break; */
  644.           case 'i': iconic = TRUE; break;
  645.           case 'p': pref.tolerate = 0; break; /* tolerate faults */
  646.           case 'n': pref.type = NEW; break; /* new mod type */
  647.                case 'o': pref.type = OLD; break; /* old mod type */
  648.           case 'b': pref.type = BOTH; break; /* try both types */
  649.           case 'm': pref.stereo = 0; break; /* mono */
  650.           case 's': pref.stereo = 1; break; /* stereo */
  651.           case 'd': DMAbuffersize = atoi(&argv[i][j+1]); break;
  652.           case 'T': terminate = 1; break;
  653.           case 'f': frequency = atoi(&argv[i][j+1]); break; /* frequency */
  654.           case 't': transpose = atoi(&argv[i][j+1]); break;
  655.           case 'r': pref.repeats = atoi(&argv[i][j+1]); break;
  656.           case 'O': oversample = atoi(&argv[i][j+1]); break;
  657.           case 'S': pref.speed = atoi(&argv[i][j+1]); break;
  658.           case 'B': set_mix(atoi(&argv[i][j+1])); break;
  659.           case 'L': priority = 0; break;
  660.           case 'M': priority = PRTYC_FOREGROUNDSERVER; break;
  661.           case 'H': priority = PRTYC_TIMECRITICAL; break;
  662.           default: error_flag++; break;
  663.            }
  664.         }
  665.      }
  666.       }
  667. }
  668.  
  669. void main(int argc, char *argv[])
  670. {
  671.    static char szClientClass[] = "form.child";
  672.    QMSG qmsg;
  673.    REAL_SWCNTRL SwitchData;
  674.    HPOINTER hptr;
  675.    HACCEL haccel;
  676.   
  677.    if (logerrors)
  678.    {
  679.       debug = fopen("debug", "w");
  680.       fprintf(debug, "error log file opened\n");
  681.    }
  682.    getpname(argv);
  683.    pref.stereo = DEFAULT_CHANNELS - 1;
  684.    pref.type = BOTH;
  685.    pref.repeats = 1;
  686.    pref.speed = 50;
  687.    pref.tolerate = 2;
  688.    pref.verbose = 0;
  689.    pref.stereo = 1;
  690.    frequency = 20000;
  691.    oversample = 1;
  692.    transpose = 0;
  693.  
  694.    set_mix (DEFAULT_MIX);        /* 0 = full stereo, 100 = mono */
  695.    parsecommandline(argc, argv);
  696.  
  697.    if (numsongs) gotodir(msong[numsongs-1]);
  698.    error_flag = 0;
  699.    frequency = open_audio(frequency, DMAbuffersize);
  700.    init_player(oversample, frequency);
  701.  
  702.    hab = WinInitialize (0) ;
  703.    hmq = WinCreateMsgQueue (hab, 0) ;
  704.  
  705.    WinRegisterClass (hab, szClientClass, ControlDlgProc,
  706.                  CS_SIZEREDRAW, 0);
  707.  
  708.    hwndControl = WinLoadDlg(HWND_DESKTOP, NULL, ControlDlgProc, NULL, IDM_CONTROL, NULL);
  709.  
  710.    SwitchData.hwnd = hwndControl;
  711.    SwitchData.hwndIcon = NULL;
  712.    SwitchData.hprog = NULL;
  713.    SwitchData.idProcess = 0;
  714.    SwitchData.idSession = 0;
  715.    SwitchData.uchVisibility = SWL_VISIBLE;
  716.    SwitchData.fbJump = SWL_JUMPABLE;
  717.    SwitchData.bProgType = PROG_PM;
  718.  
  719.    strcpy(SwitchData.szSwtitle,title);
  720.  
  721.    hSwitch = WinCreateSwitchEntry(hab, (PSWCNTRL)&SwitchData);
  722.  
  723.    hptr = WinLoadPointer(HWND_DESKTOP, NULL, ID_TRACKER);
  724.    WinPostMsg(hwndControl, WM_SETICON, hptr, NULL);
  725.    haccel = WinLoadAccelTable(hab, NULL, ID_TRACKER);
  726.    WinSetAccelTable(hab, haccel, hwndControl);
  727.  
  728.    PrintSong(NULL);
  729.  
  730.    while (WinGetMsg (hab, &qmsg, NULL, 0, 0))
  731.        WinDispatchMsg (hab, &qmsg);
  732.  
  733.    quit(0);
  734. }
  735.