home *** CD-ROM | disk | FTP | other *** search
/ ftp.4front-tech.com / ftp.4front-tech.com.tar / ftp.4front-tech.com / ossfree / snd-util-3.8.tar.gz / snd-util-3.8.tar / sndkit / xvmixer / xvmixer.c < prev    next >
C/C++ Source or Header  |  1996-01-28  |  9KB  |  399 lines

  1. /*
  2.  * xvmixer.c    xview3 based mixer program for Linux
  3.  * 
  4.  * Copyright by Hannu Savolainen 1993
  5.  * 
  6.  * Redistribution and use in source and binary forms, with or without
  7.  * modification, are permitted provided that the following conditions are
  8.  * met: 1. Redistributions of source code must retain the above copyright
  9.  * notice, this list of conditions and the following disclaimer. 2.
  10.  * Redistributions in binary form must reproduce the above copyright notice,
  11.  * this list of conditions and the following disclaimer in the documentation
  12.  * and/or other materials provided with the distribution.
  13.  * 
  14.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
  15.  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  16.  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  17.  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
  18.  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  19.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  20.  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  21.  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  22.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  23.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  24.  * SUCH DAMAGE.
  25.  * 
  26.  */
  27.  
  28. #include <stdio.h>
  29. #include <stdlib.h>
  30. #include <unistd.h>
  31. #include <fcntl.h>
  32. #include <sys/soundcard.h>
  33. #include <xview/frame.h>
  34. #include <xview/panel.h>
  35. #include <xview/svrimage.h>
  36. #include <xview/icon.h>
  37. #include "locked.bit"
  38. #include "unlocked.bit"
  39. #include "rec.bit"
  40.  
  41. void        slider_moved();
  42. void        toggle_changed();
  43.  
  44. char dev_name[20] = "/dev/mixer";
  45.  
  46. int mixer;            /* The mixer device */
  47. int devmask = 0;        /* Bitmask for supported mixer devices */
  48. int recsrc = 0;            /* Currently selected recording sources */
  49. int recmask = 0;        /* Supported recording sources */
  50. int stereodevs = 0;        /* Channels supporting stereo */
  51. unsigned long locked=0xffffffff;/* Channels with left and right locked */
  52. char *labels[SOUND_MIXER_NRDEVICES] = SOUND_DEVICE_LABELS;
  53.  
  54. int level[SOUND_MIXER_NRDEVICES];
  55. Panel_item    volume_l[SOUND_MIXER_NRDEVICES];
  56. Panel_item    volume_r[SOUND_MIXER_NRDEVICES];
  57. Panel_item    buttons[SOUND_MIXER_NRDEVICES];
  58. int        key;
  59.  
  60. #ifdef USE_XBM_ICON
  61. static    Icon        icon;
  62. static    Pixmap        icon_pm, mask_icon_pm;
  63. static    Server_image    icon_image, icon_image_mask;
  64. static    Display *dpy;
  65. Window    root_win;
  66.  
  67. #include    "xvmixer.xbm"
  68. #include    "xvmixer-mask.xbm"
  69.  
  70. #endif /* USE_XBM_ICON */
  71.  
  72.  
  73. Server_image locked_image, unlocked_image, rec_image, lock;
  74.  
  75. int main(argc, argv)
  76.     int    argc;
  77.     char    *argv[];
  78. {
  79.     Frame        frame;
  80.     Panel        panel;
  81.     int        i, n, left, right, x, rec;
  82.     int        stereo;
  83.  
  84.     xv_init(XV_INIT_ARGC_PTR_ARGV, &argc, argv, NULL);
  85.  
  86.     if (!strcmp(argv[0], "xvmixer2"))
  87.       strcpy(dev_name, "/dev/mixer1");
  88.  
  89.       if ((mixer=open(dev_name, O_RDWR, 0)) == -1)
  90.       {
  91.          perror(dev_name);
  92.          exit(-1);
  93.       }
  94.     
  95.       if (ioctl(mixer, SOUND_MIXER_READ_DEVMASK, &devmask) == -1)
  96.       {
  97.          perror("SOUND_MIXER_READ_DEVMASK");
  98.          exit(-1);
  99.       }
  100.     
  101.       if (ioctl(mixer, SOUND_MIXER_READ_RECMASK, &recmask) == -1)
  102.       {
  103.          perror("SOUND_MIXER_READ_RECMASK");
  104.          exit(-1);
  105.       }
  106.     
  107.       if (ioctl(mixer, SOUND_MIXER_READ_RECSRC, &recsrc) == -1)
  108.       {
  109.          perror("SOUND_MIXER_READ_RECSRC");
  110.          exit(-1);
  111.       }
  112.     
  113.       if (ioctl(mixer, SOUND_MIXER_READ_STEREODEVS, &stereodevs) == -1)
  114.       {
  115.          perror("SOUND_MIXER_READ_STEREODEVS");
  116.          exit(-1);
  117.       }
  118.  
  119.     frame = (Frame) xv_create(XV_NULL, FRAME, 
  120.         FRAME_LABEL, argv[0],
  121.         XV_WIDTH, 800,
  122.         XV_HEIGHT, 400,
  123.         NULL);
  124.  
  125.     panel = (Panel) xv_create(frame, PANEL,
  126.         PANEL_LAYOUT, PANEL_HORIZONTAL,
  127.         PANEL_ITEM_Y_GAP, 0,
  128.         NULL);
  129.  
  130.     locked_image = (Server_image)xv_create((int)NULL, SERVER_IMAGE,
  131.         XV_HEIGHT,        locked_height,
  132.         XV_WIDTH,        locked_width,
  133.         SERVER_IMAGE_X_BITS,    locked_bits,
  134.         NULL);
  135.  
  136.     unlocked_image = (Server_image)xv_create((int)NULL, SERVER_IMAGE,
  137.         XV_HEIGHT,        unlocked_height,
  138.         XV_WIDTH,        unlocked_width,
  139.         SERVER_IMAGE_X_BITS,    unlocked_bits,
  140.         NULL);
  141.  
  142.     rec_image = (Server_image)xv_create((int)NULL, SERVER_IMAGE,
  143.         XV_HEIGHT,        rec_height,
  144.         XV_WIDTH,        rec_width,
  145.         SERVER_IMAGE_X_BITS,    rec_bits,
  146.         NULL);
  147.  
  148. #ifdef USE_XBM_ICON
  149.  
  150.     dpy = (Display *) xv_get(frame, XV_DISPLAY);
  151.     root_win = RootWindow (dpy, DefaultScreen(dpy));
  152.  
  153.     icon_pm = XCreatePixmapFromBitmapData(dpy,
  154.             root_win, icon_bits, icon_width, icon_height,
  155.             1, 0, 1);
  156.  
  157.     mask_icon_pm = XCreatePixmapFromBitmapData(dpy,
  158.             root_win, mask_icon_bits, mask_icon_width,
  159.             mask_icon_height, 1, 0, 1);
  160.  
  161.         icon_image = (Server_image) xv_create(NULL,SERVER_IMAGE,
  162.             SERVER_IMAGE_PIXMAP, icon_pm, NULL);
  163.  
  164.     icon_image_mask = (Server_image) xv_create(NULL,SERVER_IMAGE,
  165.             SERVER_IMAGE_PIXMAP, mask_icon_pm,
  166.             NULL);
  167.  
  168.     icon = (Icon) xv_create(frame, ICON,
  169.             ICON_IMAGE, icon_image,
  170.             ICON_MASK_IMAGE, icon_image_mask,
  171.             ICON_TRANSPARENT, TRUE,
  172.             NULL);
  173.  
  174.     xv_set(frame,
  175.         FRAME_ICON, icon,
  176.         NULL);
  177.  
  178.  
  179. #endif /* USE_XBM_ICON */
  180.  
  181.  
  182.  
  183.     key = xv_unique_key();
  184.     n = 0;
  185.     for(i=0; i<SOUND_MIXER_NRDEVICES; i++) 
  186.     if ((1 << i) & devmask) {
  187.     
  188.         if (ioctl(mixer, MIXER_READ(i), &level[i]) == -1)
  189.         {
  190.             perror("MIXER_READ");
  191.             exit(-1);
  192.         }
  193.     
  194.         left = level[i] & 0x7f;
  195.         right = (level[i] >> 8) & 0x7f;
  196.  
  197.         lock = unlocked_image;
  198.  
  199.         if (left != right)
  200.            locked &=~(1 << i);    /* Unlock */
  201.         else
  202.            lock = locked_image;
  203.  
  204.         if ((1 << i) & locked) left = right = (left+right)/2;
  205.  
  206.         stereo = !!((1 << i) & stereodevs);    /* 0 or 1 */
  207.  
  208.         rec = !!((1 << i) & recsrc);
  209.         rec <<= 1;
  210.  
  211.         x = n++ * 50;
  212.  
  213.         xv_create(panel, PANEL_MESSAGE,
  214.             PANEL_LABEL_STRING, labels[i],
  215.             XV_X, x+4,
  216.             XV_Y, 2,
  217.             NULL);
  218.  
  219.         volume_l[i] = (Panel_item) xv_create(panel, PANEL_SLIDER, 
  220.             XV_KEY_DATA, key, i+1,
  221.             PANEL_NOTIFY_LEVEL, PANEL_ALL,
  222.             PANEL_NOTIFY_PROC, slider_moved,
  223.             PANEL_SHOW_RANGE, FALSE,
  224.             PANEL_SHOW_VALUE, FALSE,
  225.             PANEL_DIRECTION, PANEL_VERTICAL,
  226.             XV_X, x + 4 + !stereo * 7,
  227.             XV_Y, 20,
  228.             PANEL_VALUE, left,
  229.             NULL);
  230.         
  231.         if (stereo) {
  232.             volume_r[i] = (Panel_item) xv_create(panel, PANEL_SLIDER, 
  233.                 XV_KEY_DATA, key, -(i+1),
  234.                 PANEL_NOTIFY_LEVEL, PANEL_ALL,
  235.                 PANEL_NOTIFY_PROC, slider_moved,
  236.                 PANEL_SHOW_RANGE, FALSE,
  237.                 PANEL_SHOW_VALUE, FALSE,
  238.                 PANEL_DIRECTION, PANEL_VERTICAL,
  239.                 XV_X, x+15+4,
  240.                 XV_Y, 20,
  241.                 PANEL_VALUE, right,
  242.                 NULL);
  243.         }
  244.  
  245.  
  246.         if ((1 << i) & recmask)
  247.         {    /* Possible recording source */
  248.             buttons[i] = (Panel_item) xv_create(panel, PANEL_TOGGLE,
  249.                 PANEL_CHOICE_IMAGES, lock, rec_image, NULL,
  250.                 XV_KEY_DATA, key, i,
  251.                 PANEL_NOTIFY_PROC, toggle_changed,
  252.                 PANEL_LAYOUT, PANEL_VERTICAL,
  253.                 XV_Y, 140,
  254.                 XV_X, x,
  255.                 PANEL_VALUE, rec | 0x01,
  256.                 NULL);
  257.         } else {
  258.             buttons[i] = (Panel_item) xv_create(panel, PANEL_TOGGLE,
  259.                 PANEL_CHOICE_IMAGES, lock, NULL,
  260.                 XV_KEY_DATA, key, i,
  261.                 PANEL_NOTIFY_PROC, toggle_changed,
  262.                 PANEL_LAYOUT, PANEL_VERTICAL,
  263.                 XV_Y, 140,
  264.                 XV_X, x,
  265.                 PANEL_VALUE, rec | 0x01,
  266.                 NULL);
  267.         }
  268.     }
  269.  
  270.     window_fit(panel);
  271.  
  272.     window_fit(frame);
  273.     xv_main_loop(frame); 
  274.  
  275.     exit(0);
  276.  
  277.  
  278. void
  279. slider_moved(item, value, event)
  280.     Panel_item    item;
  281.     int        value;
  282.     Event        *event;
  283. {
  284.     int dev, ch, val;
  285.     
  286.     dev = (int) xv_get(item, XV_KEY_DATA, key);
  287.     val = value & 0x7f;
  288.  
  289.     if (dev>0)
  290.        { 
  291.         ch = 0;
  292.         dev--;
  293.        }
  294.     else
  295.        {
  296.         ch = 1;
  297.         dev = -dev - 1;
  298.        }
  299.  
  300.     if ((1 << dev) & locked)
  301.        level[dev] = ((val << 8) & 0x7f00) | (val & 0x007f);
  302.     else
  303.       if (ch)
  304.          level[dev] = (level[dev] & 0x007f) | (val << 8);
  305.       else
  306.          level[dev] = (level[dev] & 0x7f00) | val;
  307.  
  308.     if (ioctl(mixer, MIXER_WRITE(dev), &level[dev]) == -1)
  309.     {
  310.         perror("MIXER_WRITE");
  311.         exit(-1);
  312.     }
  313.  
  314.     if ((1 << dev) & stereodevs)
  315.     if ((1 << dev) & locked)    /* Sync the other channel */
  316.     if (ch) {
  317.         xv_set(volume_l[dev], PANEL_VALUE, val, NULL);
  318.     } else {
  319.         xv_set(volume_r[dev], PANEL_VALUE, val, NULL);
  320.     }
  321. }
  322.  
  323. void
  324. toggle_changed(Panel_item item, int value, Event *event)
  325. {
  326.     int i, dev, rec, lock, val, tmp_src, changed;
  327.     dev = (int) xv_get(item, XV_KEY_DATA, key);
  328.  
  329.     lock = value & 0x01;
  330.     rec  = (value & 0x02) >> 1;
  331.  
  332.     if (locked ^ (lock << dev))    /* Locked or unlocked */
  333.     if (lock) {
  334.         locked |= (1 << dev);
  335.  
  336.         val = ((level[dev] & 0x7f00) >> 8) + (level[dev] & 0x007f);
  337.         val /= 2;
  338.            level[dev] = ((val << 8) & 0x7f00) | (val & 0x007f);
  339.  
  340.         if (ioctl(mixer, MIXER_WRITE(dev), &level[dev]) == -1)
  341.         {
  342.             perror("MIXER_WRITE");
  343.             exit(-1);
  344.         }
  345.  
  346.         xv_set(volume_l[dev], PANEL_VALUE, val, NULL);
  347.  
  348.         if ((1 << dev) & recmask)
  349.         xv_set(buttons[dev], PANEL_CHOICE_IMAGES,
  350.             locked_image, rec_image, NULL, 
  351.             NULL);
  352.         else
  353.         xv_set(buttons[dev], PANEL_CHOICE_IMAGES,
  354.             locked_image, NULL, 
  355.             NULL);
  356.  
  357.         if ((1 << dev) & stereodevs)
  358.            xv_set(volume_r[dev], PANEL_VALUE, val, NULL);
  359.  
  360.     } else {
  361.         locked &= ~(1 << dev);
  362.  
  363.         if ((1 << dev) & recmask)
  364.         xv_set(buttons[dev], PANEL_CHOICE_IMAGES,
  365.             unlocked_image, rec_image, NULL, 
  366.             NULL);
  367.         else
  368.         xv_set(buttons[dev], PANEL_CHOICE_IMAGES,
  369.             unlocked_image, NULL, 
  370.             NULL);
  371.     }
  372.  
  373.     if (recsrc ^ (rec << dev))    /* Rec/play changed */
  374.     {
  375.       recsrc ^= (1 << dev);
  376.       tmp_src = recsrc;
  377.  
  378.       if (ioctl(mixer, SOUND_MIXER_WRITE_RECSRC, &recsrc) == -1)
  379.       {
  380.          perror("SOUND_MIXER_WRITE_RECSRC");
  381.          exit(-1);
  382.       }
  383.  
  384.       if (recsrc ^ tmp_src)    /* The device has changed the mask */
  385.       {
  386.           changed = recsrc ^ tmp_src;
  387.  
  388.           for (i=0;i<SOUND_MIXER_NRDEVICES;i++)
  389.           if (changed & (1 << i))
  390.           {
  391.               xv_set(buttons[i], PANEL_VALUE, 
  392.                   (int)xv_get(buttons[i], PANEL_VALUE) ^ 0x02,
  393.                   NULL);
  394.           }
  395.       }
  396.     }
  397. }
  398.