home *** CD-ROM | disk | FTP | other *** search
/ PC Online 1999 February / PCO_0299.ISO / filesbbs / linux / mikmod-3.000 / mikmod-3 / mikmod-3.1.2 / mikmod / display.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-12-07  |  12.5 KB  |  546 lines

  1. /*  MikMod example player
  2.     (c) 1998 Miodrag Vallat and others - see file AUTHORS for complete list
  3.  
  4.     This program is free software; you can redistribute it and/or modify
  5.     it under the terms of the GNU General Public License as published by
  6.     the Free Software Foundation; either version 2 of the License, or
  7.     (at your option) any later version.
  8.  
  9.     This program is distributed in the hope that it will be useful,
  10.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.     GNU General Public License for more details.
  13.  
  14.     You should have received a copy of the GNU General Public License
  15.     along with this program; if not, write to the Free Software
  16.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17. */
  18.  
  19. /*==============================================================================
  20.  
  21.   $Id: display.c,v 1.31 1998/12/07 06:01:23 miod Exp $
  22.  
  23.   Ncurses display section of mikmod - bare unix version.
  24.  
  25.   Should deal with all the quiet options and refresh() after ncurses calls,
  26.   so just call these functions direct wherever needed. 
  27.  
  28. ==============================================================================*/
  29.  
  30. #ifdef HAVE_CONFIG_H
  31. #include "config.h"
  32. #endif
  33.  
  34. #ifdef HAVE_UNISTD_H
  35. #include <unistd.h>
  36. #endif
  37. #include <signal.h>
  38. #include <stdio.h>
  39. #include <stdlib.h>
  40. #include <string.h>
  41.  
  42. #if defined(__OS2__)||defined(__EMX__)
  43. #define INCL_VIO
  44. #include <os2.h>
  45. #else
  46. #ifdef HAVE_SYS_IOCTL_H
  47. #include <sys/ioctl.h>
  48. #endif
  49. #ifdef HAVE_NCURSES_H
  50. #include <ncurses.h>
  51. #else
  52. #include <curses.h>
  53. #endif
  54. #endif
  55.  
  56. #include <mikmod.h>
  57. #include "player.h"
  58.  
  59. /*========== Display layout constants */
  60.  
  61. /* maximum screen width we handle */
  62. #define MAXWIDTH (80)
  63. /* half width */
  64. #define HALFWIDTH (MAXWIDTH>>1)
  65. /* format used for message/banner lines */
  66. #define FMT_FULLWIDTH "%-80.80s"
  67. /* format used for sample/instrument lines - the number should be HALFWIDTH-4 */
  68. #define FMT_HALFWIDTH "%-36.36s"
  69.  
  70. /*========== Variables */
  71.  
  72. extern int quiet,semiquiet;
  73. extern MODULE *mf;
  74.  
  75. int curses_on=0;
  76. int firstinst,dispsamp=1;
  77.  
  78. /* help panels */
  79. static    char keyhelp1[]=keyhelptext1;
  80. static    char keyhelp2[]=keyhelptext2;
  81.  
  82. /* screen size */
  83.         int winy=0; /* not static since used by mikmod.c */
  84. static    int winx=0;
  85. #if !defined(__OS2__)&&!defined(__EMX__)
  86. static    int resize=0;
  87. #endif
  88.  
  89. /* text creation buffer */
  90. static    char storage[MAXWIDTH+1];
  91.  
  92. #if defined(__OS2__)||defined(__EMX__)
  93. static    HVIO hvio=0;
  94. static    VIOCURSORINFO viocursorinfo;
  95. static    BYTE clearscreen[2]={0xff,0x0f};
  96. #endif
  97.  
  98. /*========== Display routines */
  99.  
  100. /* old AIX curses are very limited */
  101. #if defined(AIX) && !defined(mvaddnstr)
  102. #define mvaddnstr(y,x,str,cnt) mvaddstr(y,x,str)
  103. #endif
  104.  
  105. /* HP-UX curses macros don't work with every cpp */
  106. #if defined __hpux
  107. void getmaxyx_hpux(WINDOW* win,int* y,int *x)
  108. {
  109.     *y=__getmaxy(win);
  110.     *x=__getmaxx(win);
  111. }
  112. #define getmaxyx(win,y,x) getmaxyx_hpux((win),&(y),&(x))
  113. #endif
  114.  
  115. void display_all(void);
  116.  
  117. #if !defined(__OS2__)&&!defined(__EMX__)
  118. /* handler for terminal resize events */
  119. RETSIGTYPE sigwinch_handler(int signum)
  120. {
  121.     /* schedule a resizeterm() */
  122.     resize=1;
  123.  
  124.     signal(SIGWINCH,sigwinch_handler);
  125. }
  126. #endif
  127.  
  128. #if defined(__OS2__)||defined(__EMX__)
  129.  
  130. void clear(void)
  131. {
  132.     /* overwrite entire screen with 0s */
  133.     VioWrtNCell(clearscreen,winy*winx,0,0,hvio);
  134. }
  135. #define mvaddnstr(y,x,text,width) VioWrtCharStr(text,strlen(text),y,x,hvio)
  136. #define refresh()
  137.  
  138. /* initialize screen */
  139. void init_display(void)
  140. {
  141.     VIOCURSORINFO tmpviocursorinfo;
  142.     VIOMODEINFO tmpviomodeinfo;
  143.  
  144.     if(quiet) return;
  145.  
  146.     /* get old cursor */
  147.     VioGetCurType(&viocursorinfo,hvio);
  148.     /* set new cursor */
  149.     tmpviocursorinfo.yStart=0;
  150.     tmpviocursorinfo.cEnd=0;
  151.     tmpviocursorinfo.cx=viocursorinfo.cx;
  152.     tmpviocursorinfo.attr=-1; /* hide cursor */
  153.     VioSetCurType(&viocursorinfo,hvio);
  154.     /* get video mode info */
  155.     tmpviomodeinfo.cb=sizeof(tmpviomodeinfo);
  156.     VioGetMode(&tmpviomodeinfo,hvio);
  157.     winy=tmpviomodeinfo.row;winx=tmpviomodeinfo.col;
  158.  
  159.     clear();
  160.     VioSetCurPos(winy-1,0,hvio);
  161.  
  162.     curses_on=1;
  163. }
  164.  
  165. void mikmod_clrtoeol(int y,int x)
  166. {
  167.     VioWrtNCell(clearscreen,winx-x,y,x,hvio);
  168. }
  169.  
  170. void mikmod_clrtobot(int y,int x)
  171. {
  172.     VioWrtNCell(clearscreen,winx*(winy-y)+winx-x,y,x,hvio);
  173. }
  174.  
  175. #else
  176.  
  177. /* initialize curses */
  178. void init_curses(void)
  179. {
  180.     initscr(); 
  181.     cbreak(); 
  182.     noecho(); 
  183.     nonl(); 
  184.     nodelay(stdscr,TRUE);
  185. #if !defined(AIX) || defined(NCURSES_VERSION)
  186.     timeout(0);
  187. #endif
  188.     keypad(stdscr,TRUE); 
  189.     curses_on=1;
  190. }
  191.  
  192. /* initialize screen */
  193. void init_display(void)
  194. {
  195.     if(quiet) return;
  196.  
  197.     init_curses();
  198. #if defined(AIX) && !defined(NCURSES_VERSION)
  199.     winy=LINES;winx=COLS;
  200. #else
  201.     getmaxyx(stdscr,winy,winx);
  202. #endif
  203.     signal(SIGWINCH,sigwinch_handler);
  204. }
  205.  
  206. void mikmod_clrtoeol(int y,int x)
  207. {
  208.     move(y,x);clrtoeol();
  209. }
  210.  
  211. void mikmod_clrtobot(int y,int x)
  212. {
  213.     move(y,x);clrtobot();
  214. }
  215.  
  216. #endif
  217.  
  218. /* first line : MikMod version */
  219. void display_version(void)
  220. {
  221.     if(quiet) return;
  222.  
  223.     /* we always use display_version first, so clear call is OK here... */
  224.     clear(); 
  225.  
  226.     mvaddnstr(0,0,mikversion,winx);
  227.     refresh();
  228. }    
  229.  
  230. /* display a banner/message from line skip, at position origin
  231.    returns updated skip value if it is out of bounds and would prevent the
  232.    message from being seen. */
  233. int display_banner(char* banner,int origin,int skip)
  234. {
  235.     char *foo=banner,str[MAXWIDTH+1];
  236.     int i,n,t;
  237.  
  238.     /* count message lines */
  239.     for(t=1;*foo;t++) {
  240.         while((*foo!='\r')&&(*foo!='\n')&&(*foo))
  241.             foo++;
  242.         if (*foo) foo++;
  243.     }
  244.     /* update skip value */
  245.     if (skip+winy-origin+1>=t) skip=t-winy+origin-1;
  246.     if (skip<0) skip=0;
  247.     /* display lines */
  248.     foo=banner;
  249.     for(i=0;i<t;i++) {
  250.         for(n=0;(*foo!='\r')&&(*foo!='\n')&&(*foo);foo++) {
  251.             str[n]=*foo;
  252.             if(n<MAXWIDTH) n++;
  253.         }
  254.         foo++;
  255.         if (i>=skip) {
  256.             if (n) {
  257.                 str[n]=0;
  258.                 sprintf(storage,FMT_FULLWIDTH,str);
  259.                 mvaddnstr(i-skip+origin,0,storage,winx);
  260.             } else
  261.                 mikmod_clrtoeol(i-skip+origin,0);
  262.         }
  263.     }
  264.     /* clear remaining part of the screen */
  265.     mikmod_clrtobot(t-skip+origin,0);
  266.  
  267.     return skip;
  268. }
  269.  
  270. /* displays the "paused" banner */
  271. void display_pausebanner(void)
  272. {
  273.     if(quiet) return;
  274.     clear();
  275.     mvaddnstr(0,0,mikversion,winx);
  276.     display_banner(pausebanner,1,0);
  277.     refresh();
  278. }    
  279.  
  280. /* display the "extracting" banner */
  281. void display_extractbanner(void)
  282. {
  283.     if(quiet) return;
  284.     clear();
  285.     mvaddnstr(0,0,mikversion,winx);
  286.     display_banner(extractbanner,1,0);
  287.     refresh();
  288. }    
  289.  
  290. /* display the "loading" banner */
  291. void display_loadbanner(void)
  292. {
  293.     if(quiet) return;
  294.     clear();
  295.     mvaddnstr(0,0,mikversion,winx);
  296.     display_banner(loadbanner,1,0);
  297.     refresh();
  298.     firstinst=0;
  299. }    
  300.  
  301. /* second line : driver settings */
  302. void display_driver(void)
  303. {
  304.     if((quiet)||(winy<=1)) return;
  305.     if (md_reverb)
  306. #if defined(__OS2__)||defined(__EMX__)
  307.         sprintf(storage,"%s: %d bit %s %s, %u Hz, reverb: %u",
  308. #else
  309.         sprintf(storage,"%s: %d bit %s %s, %u Hz, reverb: %u\n",
  310. #endif
  311.             md_driver->Name,
  312.             (md_mode&DMODE_16BITS) ? 16:8,
  313.  
  314.             (md_mode&DMODE_INTERP) ?
  315.                 (md_mode&DMODE_SURROUND?"interp. surround":"interpolated"):
  316.                 (md_mode&DMODE_SURROUND?"surround":"normal"),
  317.  
  318.             (md_mode&DMODE_STEREO) ? "stereo":"mono",
  319.             md_mixfreq, md_reverb);
  320.     else
  321. #if defined(__OS2__)||defined(__EMX__)
  322.         sprintf(storage,"%s: %d bit %s %s, %u Hz, no reverb",
  323. #else
  324.         sprintf(storage,"%s: %d bit %s %s, %u Hz, no reverb\n",
  325. #endif
  326.             md_driver->Name,
  327.             (md_mode&DMODE_16BITS) ? 16:8,
  328.  
  329.             (md_mode&DMODE_INTERP) ?
  330.                 (md_mode&DMODE_SURROUND?"interp. surround":"interpolated"):
  331.                 (md_mode&DMODE_SURROUND?"surround":"normal"),
  332.  
  333.             (md_mode&DMODE_STEREO) ? "stereo":"mono",
  334.             md_mixfreq);
  335.     mvaddnstr(1,0,storage,winx);
  336. #if defined(__OS2__)||defined(__EMX__)
  337.     mikmod_clrtoeol(1,strlen(storage));
  338. #endif
  339.     refresh();
  340. }
  341.  
  342. /* third line : filename */
  343. void display_file(void)
  344. {
  345.     char filename[255];
  346.     char arc[255];
  347.  
  348.     if((quiet)||(winy<=2)) return;
  349.     PL_GetCurrent(&playlist,filename,arc);
  350. #if defined(__OS2__)||defined(__EMX__)
  351.     sprintf(storage,"File: %.70s",filename); 
  352. #else
  353.     sprintf(storage,"File: %.70s\n",filename); 
  354. #endif
  355.     mvaddnstr(2,0,storage,winx);
  356.     refresh();
  357. }
  358.  
  359. /* fourth and fifth lines : module name and format */
  360. void display_name(void)
  361. {
  362.     if((quiet)||(winy<=3)) return;
  363. #if defined(__OS2__)||defined(__EMX__)
  364.     sprintf(storage,"Name: %.70s",mf->songname);
  365. #else
  366.     sprintf(storage,"Name: %.70s\n",mf->songname);
  367. #endif
  368.     mvaddnstr(3,0,storage,winx);
  369. #if defined(__OS2__)||defined(__EMX__)
  370.     sprintf(storage,"Type: %s, Periods: %s, %s",
  371. #else
  372.     sprintf(storage,"Type: %s, Periods: %s, %s\n",
  373. #endif
  374.         mf->modtype,
  375.         (mf->flags&UF_XMPERIODS) ? "XM type" : "mod type",
  376.         (mf->flags&UF_LINEAR) ? "linear" : "log");
  377.     mvaddnstr(4,0,storage,winx);
  378.     refresh();
  379. }
  380.  
  381. /* sixth line : player status */
  382. void display_status(void)
  383. {
  384.     if(quiet) return;
  385.  
  386. #if !defined(__OS2__)&&!defined(__EMX__)
  387.     /* if a resize was scheduled, do it now */
  388.     if(resize) {
  389. #if (NCURSES_VERSION_MAJOR >= 4) && defined(TIOCGWINSZ)
  390.         struct winsize ws;
  391.  
  392.         ws.ws_col=ws.ws_row=0;
  393.         ioctl(0,TIOCGWINSZ,&ws);
  394.         if(ws.ws_col && ws.ws_row) 
  395.             resizeterm(ws.ws_row,ws.ws_col);
  396. #else
  397. #ifndef NCURSES_VERSION
  398.         endwin();
  399.         init_curses();
  400. #endif
  401. #endif
  402. #if defined(AIX) && !defined(NCURSES_VERSION)
  403.         winy=LINES;winx=COLS;
  404. #else
  405.         getmaxyx(stdscr,winy,winx);
  406. #endif
  407.         resize=0;
  408.         display_all();
  409.     }
  410. #endif
  411.  
  412.     if (winy<=5) return;
  413.     if (mf->sngpos<mf->numpos) {
  414. #if defined(sun) && !defined(HAVE_NCURSES)
  415.         /* Solaris curses has a nasty bug and will try to interpret the hexa
  416.            digits generated by %02.2X, so we'll add these manually after... */
  417.         sprintf(storage,"pat:%03d/%03d pos:   spd:%2d bpm:%3d "
  418.                         "vol:%3d%% time:%2d:%02d",
  419.             mf->sngpos,mf->numpos-1,mf->sngspd,mf->bpm,
  420.             (mf->volume*100+64)>>7,(int)(((mf->sngtime>>10)/60)%60),
  421.             (int)((mf->sngtime>>10)%60));
  422. #else
  423.         sprintf(storage,"pat:%03d/%03d pos:%02.2X spd:%2d bpm:%3d "
  424.                         "vol:%3d%% time:%2d:%02d",
  425.             mf->sngpos,mf->numpos-1,mf->patpos,mf->sngspd,mf->bpm,
  426.             (mf->volume*100+64)>>7,(int)(((mf->sngtime>>10)/60)%60),
  427.             (int)((mf->sngtime>>10)%60));
  428. #endif
  429.         if (!semiquiet)
  430.             strcat(storage," - press H for help");
  431.         mvaddnstr(5,0,storage,winx);
  432. #if defined(sun) && !defined(HAVE_NCURSES)
  433.         if (winx>17)
  434.             mvaddch(5,17,((mf->patpos&0x0f)<=9)?'0'+(mf->patpos&0x0f):'A'+((mf->patpos&0x0f)-10));
  435.         if (winx>16)
  436.             mvaddch(5,16,((mf->patpos>>4)<=9)?'0'+(mf->patpos>>4):'A'+((mf->patpos>>4)-10));
  437.         move(5,strlen(storage));
  438. #endif
  439.     }
  440.     refresh();
  441. }
  442.  
  443. #if defined(__OS2__)||defined(__EMX__)
  444.  
  445. /* exits curses */
  446. void exit_display(void)
  447. {
  448.     if(quiet) return;
  449.  
  450.     clear();
  451.     mvaddnstr(winy-2,0,mikversion,winx);
  452.     /* restore old cursor */
  453.     VioSetCurType(&viocursorinfo,hvio);
  454.     VioSetCurPos(winy-1,0,hvio);
  455.  
  456.     curses_on=0;
  457. }
  458.  
  459. #else
  460.  
  461. /* exits curses */
  462. void exit_display(void)
  463. {
  464.     if(quiet) return;
  465.  
  466.     signal(SIGWINCH,SIG_DFL);
  467.     clear();
  468.     mvaddnstr(winy-2,0,mikversion,winx);
  469.     refresh();
  470.     endwin();
  471.     curses_on=0;
  472. }
  473.  
  474. #endif
  475.  
  476. /* seventh line to bottom of screen : information panel */
  477. void display_information(void)
  478. {
  479.     int t,x;
  480.     int count,semicount;
  481.  
  482.     if(quiet || semiquiet || (winy<=6)) return;
  483.     if((dispsamp&2)&&(!mf->comment)) dispsamp^=2;
  484.     if((dispsamp&1)&&(!mf->instruments)) dispsamp^=1;
  485.     if((!(dispsamp&1))&&(!mf->samples)) dispsamp^=1;
  486.     semicount=winy-6,count=semicount<<1;
  487.  
  488.     if (dispsamp&8) {
  489.         /* bit 3 set : help panel 2 */
  490.         display_banner(keyhelp2,6,0);
  491.     } else
  492.       if (dispsamp&4) {
  493.         /* bit 2 set : help panel 1 */
  494.         display_banner(keyhelp1,6,0);
  495.     } else
  496.       if (dispsamp&2) {
  497.         /* bit 1 set : module comments */
  498.         firstinst=display_banner(mf->comment,6,firstinst);
  499.     } else
  500.       if (dispsamp&1) {
  501.         /* bit 0 set : samples */
  502.         mikmod_clrtobot(6,0);
  503.         if(firstinst>=mf->numins-count) firstinst=mf->numins-count;
  504.         if(firstinst<0) firstinst=0;
  505.         if ((mf->numins>semicount)&&(mf->numins<count)) {
  506.             semicount=(mf->numins+1)>>1;count=semicount<<1;
  507.         }
  508.         for(t=firstinst;t<mf->numins && t<(count+firstinst);t++) {
  509.             sprintf(storage,"%3i " FMT_HALFWIDTH,t,
  510.                     mf->instruments[t].insname?mf->instruments[t].insname:"");
  511.             x=((t-firstinst)<semicount)?0:HALFWIDTH;
  512.             if(x<winx)
  513.                 mvaddnstr((t-firstinst)%semicount+6,x,storage,winx-x);
  514.         }
  515.     } else {
  516.         /* bit 0 unset : instruments */
  517.         mikmod_clrtobot(6,0);
  518.         if(firstinst>=mf->numsmp-count) firstinst=mf->numsmp-count;
  519.         if(firstinst<0) firstinst=0;
  520.         if ((mf->numsmp>semicount)&&(mf->numsmp<count)) {
  521.             semicount=(mf->numsmp+1)>>1;count=semicount<<1;
  522.         }
  523.         for(t=firstinst;t<mf->numsmp && t<(count+firstinst);t++) {
  524.             sprintf(storage,"%3i " FMT_HALFWIDTH,t,
  525.                     mf->samples[t].samplename?mf->samples[t].samplename:"");
  526.             x=((t-firstinst)<semicount)?0:HALFWIDTH;
  527.             if(x<winx)
  528.                 mvaddnstr((t-firstinst)%semicount+6,x,storage,winx-x);
  529.         }
  530.     }
  531.     refresh();
  532. }
  533.  
  534. /* redisplays the whole screen */
  535. void display_all(void)
  536. {
  537.     if(quiet) return;
  538.  
  539.     display_version();
  540.     display_driver();
  541.     display_file();
  542.     display_name();
  543.     display_status();
  544.     display_information();
  545. }
  546.