/* * xmixer:gui_xaw.c * * Copyright (C) 1997-98 Rasca, Berlin * EMail: thron@gmx.de * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include #include #include #define XK_MISCELLANY #define XK_XKB_KEYS #include #include #include #include /**/ #include #include /**/ #include #include /**/ #include #include #include /**/ #include "gui.h" #include "about.h" #include "mixer.h" #include "input.xbm" #include "norec.xbm" #include "locked.xbm" #include "unlocked.xbm" #include "mute.xbm" #include "icon.xbm" #include "ok.xbm" #include "none.xbm" #include "fallback.h" #include "scf.h" #define LEFT 0 #define RIGHT 1 typedef struct { int dev; int locked; int max; int mute; Widget box; Widget sll; Widget slr; Widget vol; Widget lck; Widget rec; Widget lbl; Widget mut; Pixmap rec_bm; Pixmap norec_bm; Pixmap lck_bm; Pixmap unlck_bm; Pixmap none_bm; Pixmap mute_bm; XColor active; } wMixer; typedef struct { /* resources */ char *dev_name; int update_time; char *help_command; Pixel focus_color; /* private */ char *program; wMixer *devs; XtAppContext context; Widget toplevel; Widget menu_box; Widget label; WidgetList mDev; Pixmap checked; } AppData; #define XtNdeviceName "deviceName" #define XtCDeviceName "DeviceName" #define XtNupdateTime "updateTime" #define XtCUpdateTime "UpdateTime" #define XtNhelpCommand "helpCommand" #define XtCHelpCommand "HelpCommand" #define XtNfocusColor "focusColor" #define XtCFocusColor "FocusColor" /* some globals */ static XtResource resources [] = { { XtNdeviceName, XtCDeviceName, XtRString, sizeof(String), XtOffsetOf(AppData, dev_name), XtRString, DEFAULT_MIXER }, { XtNupdateTime, XtCUpdateTime, XtRInt, sizeof(int), XtOffsetOf(AppData, update_time), XtRImmediate, (XtPointer)60 }, { XtNhelpCommand, XtCHelpCommand, XtRString, sizeof(String), XtOffsetOf(AppData, help_command), XtRImmediate, (XtPointer)NULL }, { XtNfocusColor, XtCFocusColor, XtRPixel, sizeof (Pixel), XtOffsetOf(AppData, focus_color), XtRImmediate, (XtPointer)NULL } }; static AppData App; #define Toplevel() (App.toplevel) /* actions definitions */ static void ExitProgAction (Widget, XEvent*, String*, Cardinal*); static void ReleaseMenuAction (Widget, XEvent*, String*, Cardinal*); static void ActivateMenuAction (Widget, XEvent*, String*, Cardinal*); static void ShowMenuAction (Widget, XEvent*, String*, Cardinal*); static void SetFocusAction (Widget, XEvent*, String*, Cardinal*); static void CloseWinAction (Widget, XEvent*, String*, Cardinal*); static XtActionsRec actionTable[] = { { "exit-program", ExitProgAction }, { "release-menu", ReleaseMenuAction }, { "activate-menu", ActivateMenuAction }, { "show-menu", ShowMenuAction }, { "close-window", CloseWinAction }, { "set-focus", SetFocusAction }, }; /* protos */ void CbChangeLabel (Widget w, XtPointer client_data, XtPointer call_data); static void RegisterWidget (Widget); static Widget NameToWidget (String); /* actions */ /* * exit xmixer */ static void ExitProgAction (Widget w, XEvent *ev, String *parms, Cardinal *num_parms) { printf ("Program canceld!\n"); exit(0); } /* * release the focus from the menu bar */ static void ReleaseMenuAction (Widget w, XEvent *ev, String *parms, Cardinal *num_parms) { #ifdef DEBUG printf ("release-menu()\n"); #endif } /* * set the focus from the menu bar */ static void ActivateMenuAction (Widget w, XEvent *ev, String *parms, Cardinal *num_parms) { #ifdef DEBUG printf ("activate-menu()\n"); #endif if (*num_parms) { Widget first; first = NameToWidget (parms[0]); if (first) { XtSetKeyboardFocus (Toplevel(), first); } } } /* */ static void ShowMenuAction (Widget w, XEvent *ev, String *parms, Cardinal *num_parms) { Dimension height, bheight; #ifdef DEBUG printf ("show-menu()\n"); #endif if (XtIsManaged(App.menu_box)) return; XtVaGetValues (XtParent(App.menu_box), XtNheight, &height, NULL); XtVaGetValues (App.menu_box, XtNheight, &bheight, NULL); XtManageChild (App.menu_box); XtVaSetValues (Toplevel(), XtNheight, height + bheight, NULL); } /* */ static void SetFocusAction (Widget w, XEvent *ev, String *parms, Cardinal *num_parms) { #ifdef DEBUG printf ("set-focus()\n"); #endif if (*num_parms == 2) { Widget widget; Widget tree; tree = NameToWidget (parms[0]); widget = NameToWidget (parms[1]); if (tree && widget) { #ifdef DEBUG printf ("set-focus(%s, %s)\n", XtName(tree), XtName(widget)); #endif XtSetKeyboardFocus (tree, widget); } } } /* */ static void update_label (wMixer *m) { int vol_left, vol_right = 0; static char buff[32]; vol_left = mixer_get_vol_left (1, m->dev); if (mixer_is_stereo (1, m->dev)) { vol_right = mixer_get_vol_right (1, m->dev); sprintf (buff, "%3d:%3d", vol_left, vol_right); } else { sprintf (buff, "%3d ", vol_left); } XtVaSetValues (App.label, XtNlabel, buff, NULL); } /* * close the named window */ static void CloseWinAction (Widget w, XEvent *ev, String *parms, Cardinal *num_parms) { if (*num_parms) { Widget win; win = XtNameToWidget (Toplevel(), parms[0]); if (win) XtDestroyWidget (win); } } /* callbacks */ /* */ static void CbExec (Widget w, XtPointer client_data, XtPointer call_data) { char *exec; exec = (char *) client_data; system (exec); } /* */ static void CbQuit (Widget w, XtPointer client_data, XtPointer call_data) { exit (0); } /* * close the named popup shell */ static void CbClose (Widget w, XtPointer client_data, XtPointer call_data) { XtDestroyWidget ((Widget) client_data); } /* */ static void CbMute (Widget w, XtPointer client_data, XtPointer call_data) { Position y; wMixer *dev = (wMixer *)client_data; XColor color; if (!XwIsSet(w)) { dev->mute = 1; mixer_set_vol_left (1, dev->dev, 0); if (mixer_is_stereo (1, dev->dev)) mixer_set_vol_right (1, dev->dev, 0); XtVaGetValues (w, XtNbackground, &color, NULL); } else { dev->mute = 0; XtVaGetValues (dev->sll, XtNsliderY, &y, NULL); mixer_set_vol_left (1, dev->dev, 100 - y); if (mixer_is_stereo (1, dev->dev)) { XtVaGetValues (dev->slr, XtNsliderY, &y, NULL); mixer_set_vol_right (1, dev->dev, 100 - y); } color = dev->active; } XtVaSetValues (w, XtNforeground, color, NULL); update_label (dev); } /* * map or unmap a slider box and adjust the width of the toplevel */ static void CbMap (Widget menu_entry, XtPointer client_data, XtPointer call_data) { Widget box = (Widget) client_data; Dimension width = 0, dev_width = 0, border_width = 0, space = 0; Dimension height = 0, dev_height; int change_menu_box = 0; char *name = XtName (box); if (strcmp (name, "menu_box") == 0) { change_menu_box = 1; } XtVaGetValues (box, XtNwidth, &dev_width, XtNheight, &dev_height, XtNborderWidth, &border_width, NULL); XtVaGetValues (XtParent(box), XtNhSpace, &space, XtNheight, &height, NULL); XtVaGetValues (Toplevel(), XtNwidth, &width, NULL); if (XtIsManaged (box)) { XtUnmanageChild (box); if (!change_menu_box) { XtVaSetValues (menu_entry, XtNleftBitmap, None, NULL); XtVaSetValues (Toplevel(), XtNwidth, width - dev_width - space - 2 * border_width, NULL); } else { /* disable menu */ XtVaSetValues (Toplevel(), XtNheight, height - dev_height, NULL); } } else { XtManageChild (box); XtVaSetValues (menu_entry, XtNleftBitmap, App.checked, NULL); XtVaSetValues (Toplevel(), XtNwidth, width + dev_width + space + 2 * border_width, NULL); } } /* * event handler to close the application or the window if window manager * sends a WM_DELETE_WINDOW message */ void WmDelEH (Widget shell, XtPointer xtp, XEvent *event, Boolean *boo) { #ifdef DEBUG fprintf (stderr, "WmDelEH() event type=%d format=%d\n", event->type, event->type == ClientMessage ? event->xclient.format : -1); #endif if (event->type != ClientMessage) /* =33 */ return; if (event->xclient.format != 32) return; if (event->xclient.data.l[0] != *((Atom*)xtp)) return; if (!XtParent (shell)) { /* destroy the toplevel widget * and terminate the application */ XtDestroyWidget (shell); exit (0); } else { XtDestroyWidget (shell); } } /* * about popup */ static void CbAbout (Widget w, XtPointer client_data, XtPointer call_data) { Widget toplevel, shell, box, esc, label; Position x, y; static Atom wm_delete; toplevel = Toplevel(); wm_delete = (Atom)client_data; shell= XtVaCreatePopupShell ("about", transientShellWidgetClass, toplevel, NULL); box = XtVaCreateManagedWidget ("about_box", boxWidgetClass, shell, NULL); label= XtVaCreateManagedWidget ("about_label", xwLabelWidgetClass, box, XtNlabel, _ABOUT_, NULL); esc = XtVaCreateManagedWidget ("Ok", xwButtonWidgetClass, box, NULL); XtAddCallback (esc, XtNcallback, CbClose, shell); XtTranslateCoords (toplevel, 0, 0, &x ,&y); XtVaSetValues (shell, XtNx, x+25, XtNy, y+25, NULL); XtPopup (shell, XtGrabNonexclusive); XtSetKeyboardFocus (box, esc); XSetWMProtocols (XtDisplay(shell), XtWindow(shell), &wm_delete, 1); XtAddEventHandler (shell, NoEventMask, True, WmDelEH, &wm_delete); } /* * save current settings in ~/.xmixer.scf */ static void CbSave (Widget w, XtPointer client_data, XtPointer call_data) { AppData *ad = (AppData *) client_data; char *pname = ad->program; const char *fname, *name, *label; FILE *fp; int i, nod; fname = scf_file_name (pname, SCF_PRIVAT); if (fname) { #ifdef DEBUG fprintf (stderr, "CbSave() %s\n", fname); #endif nod = ad->devs[0].max; fp = fopen (fname, "wb"); if (fp) { fprintf (fp, "#SCFF 1.0\n"); fprintf (fp, "# version of the xmixer configuration file\n"); fprintf (fp, "version = 1\n\n"); fprintf (fp, "# mixer device name\n"); fprintf (fp, "[%s]\n\n", ad->dev_name); for (i = 0; i < nod; i++) { name = mixer_get_name(1, i); fprintf (fp, "# Settings for the \"%s\"-device = ", name); if (mixer_is_stereo(1, i)) fprintf (fp, "{ Int[0-100]:leftValue Int[0-100]:rightValue }\n"); else fprintf (fp, "{ Int[0-100]:value }\n"); fprintf (fp, "%s = { ", mixer_get_name(1, i)); if (mixer_is_stereo(1, i)) { fprintf (fp, "%d %d }\n", mixer_get_vol_left(1,i), mixer_get_vol_right(1,i)); } else { fprintf (fp, "%d }\n", mixer_get_vol_left(1,i)); } fprintf (fp, "# show slider for device \"%s\" = Bool[True, False]:Map\n", name); if (XtIsManaged(ad->devs[i].box)) fprintf (fp, "%s_map = True\n", name); else fprintf (fp, "%s_map = False\n", name); label = NULL; XtVaGetValues (ad->devs[i].lbl, XtNlabel, &label, NULL); if (label) { fprintf (fp,"# label of the device \"%s\" = String:Label\n", name); fprintf (fp,"%s_label = \"%s\"\n\n", name, label); } } fclose (fp); } } } /* */ static void CbPanL (Widget w, XtPointer client_data, XtPointer call_data) { wMixer *m; int y, vol; m = (wMixer *) client_data; y = (int) ((XawPannerReport *)call_data)->slider_y; vol= 100 - y; if (!m->mute) vol = mixer_set_vol_left (1, m->dev, vol); #ifdef DEBUG fprintf (stderr, "CbPanL() %d vol=%d\n", m->dev, vol); #endif if (m->locked && mixer_is_stereo (1, m->dev)) { XtVaSetValues (m->slr, XtNsliderY, y, NULL); if (!m->mute) mixer_set_vol_right (1, m->dev, vol); } update_label (m); } /* */ static void CbPanR (Widget w, XtPointer client_data, XtPointer call_data) { wMixer *m; int y, vol; m = (wMixer *) client_data; y = (int) ((XawPannerReport *)call_data)->slider_y; vol=100 - y; #ifdef DEBUG fprintf (stderr, "CbPanR() %d vol=%d\n", m->dev, vol); #endif if (!m->mute) mixer_set_vol_right (1, m->dev, vol); if (m->locked) { XtVaSetValues (m->sll, XtNsliderY, y, NULL); if (!m->mute) mixer_set_vol_left (1, m->dev, vol); } update_label (m); } /* */ static void CbLock (Widget w, XtPointer client_data, XtPointer call_data) { int state; wMixer *m; state = XwIsSet(w); m = (wMixer *) client_data; if (!mixer_is_stereo (1, m->dev)) { XtVaSetValues (w, XtNstate, True, NULL); return; } if (state) { XtVaSetValues (w, XtNbitmap, m->lck_bm, NULL); m->locked = 1; } else { XtVaSetValues (w, XtNbitmap, m->unlck_bm, NULL); m->locked = 0; } } /* */ static void CbRec (Widget w, XtPointer client_data, XtPointer call_data) { int i; wMixer *devs; devs = (wMixer *) client_data; if (XwIsSet(w)) { for (i = 0; i < devs[0].max; i++) { if (mixer_is_rec_dev (1, i)) { if (w == devs[i].rec) { mixer_set_rec (1, i, 1); XtVaSetValues (w, XtNbitmap, devs[i].rec_bm, NULL); } else { if (mixer_exclusive_input (1)) { mixer_set_rec (1, i, 0); XtVaSetValues (devs[i].rec, XtNstate, False, XtNbitmap, devs[i].norec_bm, NULL); } } } } } else { for (i = 0; i < devs[0].max; i++) { if (w == devs[i].rec) { mixer_set_rec (1, i, 0); XtVaSetValues (w, XtNbitmap, devs[i].norec_bm, NULL); break; } } } } /* * update the values, some other programs may have * changed them.. */ static void TCbUpdate (XtPointer client_data, XtIntervalId id) { int no_of_devs, i, vol; wMixer *devs; devs = (wMixer *) client_data; no_of_devs = mixer_num_of_devs (1); for (i = 0; i < no_of_devs; i++) { vol = mixer_get_vol_left (1, i); if (devs[i].mute) { continue; } if (mixer_is_stereo (1, i)) { XtVaSetValues (devs[i].sll, XtNsliderY, 100-vol, NULL); vol = mixer_get_vol_right (1, i); XtVaSetValues (devs[i].slr, XtNsliderY, 100-vol, NULL); #ifdef DEBUG2 fprintf (stderr, "%s %d:%d\n", mixer_get_label(1,i), vol, mixer_get_vol_left(1,i)); #endif } else { XtVaSetValues (devs[i].sll, XtNsliderY, 100-vol, NULL); #ifdef DEBUG2 fprintf (stderr, "%s %d\n", mixer_get_label(1,i), vol); #endif } } XtAppAddTimeOut (App.context, App.update_time * 1000, (XtTimerCallbackProc)TCbUpdate, devs); } /* * reload saved settings */ static void CbReload (Widget w, XtPointer client_data, XtPointer call_data) { AppData *ad = (AppData *) client_data; scf_id id; int nod, i; string name; char key[32]; int map; int left, right; id = scf_init (ad->program, NULL); if (scf_read (id)) { nod = mixer_num_of_devs (1); for ( i = 0; i < nod; i++) { name = (const string) mixer_get_name (1, i); if (scf_get_array_int_val (id, ad->dev_name, name, 0, &left) == SCF_TRUE) mixer_set_vol_left (1, i, left); if (mixer_is_stereo (1, i)) { if (scf_get_array_int_val (id, ad->dev_name, name, 1, &right) == SCF_TRUE) mixer_set_vol_right (1,i, right); } sprintf (key, "%s_map", name); if (scf_get_bool_val (id, ad->dev_name, key, &map)) { if (map == SCF_FALSE) { if (XtIsManaged(ad->devs[i].box)) CbMap (ad->mDev[i], ad->devs[i].box, NULL); } else if (!XtIsManaged(ad->devs[i].box)) CbMap (ad->mDev[i], ad->devs[i].box, NULL); } } TCbUpdate ((XtPointer)ad->devs, 0); } scf_fini (id); } /* */ void focusEH (Widget slider, XtPointer subtree, XEvent *event, Boolean *boo) { static Widget prev = None; static Pixel pp; int i; Widget box; wMixer *m; #ifdef DEBUG printf ("focus() widget=%s\n", XtName(slider)); #endif box = XtParent(slider); if (box != prev) { if (prev) { XtVaSetValues (prev, XtNborderColor, pp, NULL); } XtVaGetValues (box, XtNborderColor, &pp, NULL); prev = box; XtVaSetValues (box, XtNborderColor, App.focus_color, NULL); } XtSetKeyboardFocus (Toplevel(), slider); m = App.devs; for (i = 0; i < m->max; i++) { if (m[i].box == box) { update_label(&(m[i])); } } } /* */ static void CbMenuTab (Widget w, XtPointer client, XtPointer call) { #ifdef DEBUG printf ("CbMenuTab()\n"); #endif XtSetKeyboardFocus (Toplevel(), (Widget)client); } /* * not ready! */ void tabEH (Widget w, XtPointer xtp, XEvent *event, Boolean *boo) { int len, dev_id, nod, i; KeySym ks; XKeyEvent *xkey; XComposeStatus cs; char key[8]; Widget dev; AppData *ad = (AppData *) xtp; xkey = &event->xkey; key[1] = '\0'; len = XLookupString (xkey, key, 8, &ks, &cs); dev = XtParent(w); #ifdef DEBUG fprintf (stderr, "tabEH() widget=%s box=%s keysym=%X\n", XtName(w), XtName(dev), (int)ks); #endif if ((ks == XK_Tab) || (ks == XK_ISO_Left_Tab) || (ks == XK_Left) || (ks == XK_Right)) { /* * find next or the previous widget */ dev_id = atoi (XtName(dev)); nod = mixer_num_of_devs (1); for (i = 0; i < nod; i++) { if (ks == XK_Tab || ks == XK_Right) { dev_id++; if (dev_id > nod-1) dev_id = 0; } else { dev_id--; if (dev_id < 0) dev_id = nod-1; } if (XtIsManaged (ad->devs[dev_id].box)) { focusEH (ad->devs[dev_id].sll, XtParent(ad->devs[dev_id].box), NULL, NULL); return; } } } #ifdef DEBUG else { printf ("tabEH() key sym=%X shift? %d\n", (int)ks, event->xkey.state & ShiftMask); } #endif } /* */ void mouseEH (Widget w, XtPointer xtp, XEvent *event, Boolean *boo) { # define offset 15 KeySym ks; XComposeStatus cs; int x,y; #ifdef DEBUG printf ("mouseEH()\n"); #endif x = y = 0; XLookupString (&(event->xkey), NULL, 0, &ks, &cs); switch (ks) { case XK_Right: x = offset; break; case XK_Left: x = -offset; break; case XK_Up: y = -offset; break; case XK_Down: y = offset; break; default: break; } XWarpPointer (XtDisplay(w), None, None, 0, 0, 0, 0, x, y); } /* */ char * gui_init (int *argc, char ***argv) { App.toplevel = XtVaAppInitialize (&App.context, "XMixer", NULL, 0, argc, *argv, fallback, NULL); RegisterWidget (App.toplevel); XtVaGetApplicationResources (App.toplevel, &App, resources, XtNumber (resources), NULL); XtAppAddActions (App.context, actionTable, sizeof(actionTable)/sizeof(XtActionsRec)); return ((char *)App.dev_name); } /* * gui main() */ int gui_main (char *mixer_dev, char *pname) { Widget toplevel, frame, menu_box, quit, save, load, about, mixer; Widget file_mb, file_menu, help_mb, help_menu, man; Widget map_mb, map_menu, *menu_entries; Pixmap icon_bm; wMixer *devs; int i, vol, no_of_devs, map; scf_id scf; char key[32], wname[8]; const char *name; static Atom wm_delete; no_of_devs = mixer_num_of_devs (1); App.program = pname; App.dev_name = mixer_dev; toplevel = App.toplevel; wm_delete = XInternAtom (XtDisplay(toplevel), "WM_DELETE_WINDOW", False); devs = (wMixer *) malloc (sizeof (wMixer) * no_of_devs); App.devs = devs; icon_bm = XCreateBitmapFromData (XtDisplay(toplevel), RootWindowOfScreen (XtScreen(toplevel)), icon_bits, icon_width, icon_height); XtVaSetValues (toplevel, XtNiconPixmap, icon_bm, NULL); App.checked = XCreateBitmapFromData (XtDisplay(toplevel), RootWindowOfScreen (XtScreen(toplevel)), ok_bits, ok_width, ok_height); /* the main application frame */ frame = XtVaCreateManagedWidget ( "frame", panedWidgetClass, toplevel, NULL); RegisterWidget (frame); App.menu_box = menu_box = XtVaCreateManagedWidget ( "menu_box", boxWidgetClass, frame, XtNorientation, XtorientHorizontal, XtNshowGrip, False, NULL); RegisterWidget (menu_box); /* menus */ file_mb = XtVaCreateManagedWidget ( "file_mb", xwButtonWidgetClass, menu_box, XtNmenuName, "file_menu", NULL); RegisterWidget (file_mb); file_menu = XtVaCreatePopupShell ( "file_menu", simpleMenuWidgetClass, file_mb, NULL); XtAddEventHandler (file_menu, KeyPressMask, False, mouseEH, NULL); map_mb = XtVaCreateManagedWidget ( "map_mb", xwButtonWidgetClass, menu_box, XtNmenuName, "map_menu", NULL); map_menu = XtVaCreatePopupShell ( "map_menu", simpleMenuWidgetClass, map_mb, NULL); XtAddEventHandler (map_menu, KeyPressMask, False, mouseEH, NULL); help_mb = XtVaCreateManagedWidget ( "help_mb", xwButtonWidgetClass, menu_box, XtNmenuName, "help_menu", NULL); help_menu = XtVaCreatePopupShell ( "help_menu", simpleMenuWidgetClass, help_mb, NULL); XtAddEventHandler (help_menu, KeyPressMask, False, mouseEH, NULL); App.label = XtVaCreateManagedWidget ( "label", xwLabelWidgetClass, menu_box, XtNlabel, "???:???", NULL); save = XtVaCreateManagedWidget ( "save", smeBSBObjectClass, file_menu, NULL); XtAddCallback (save, XtNcallback, CbSave, &App); load = XtVaCreateManagedWidget ( "load", smeBSBObjectClass, file_menu, NULL); XtAddCallback (load, XtNcallback, CbReload, &App); quit = XtVaCreateManagedWidget ( "quit", smeBSBObjectClass, file_menu, NULL); XtAddCallback (quit, XtNcallback, CbQuit, NULL); about = XtVaCreateManagedWidget ( "about", smeBSBObjectClass, help_menu, NULL); XtAddCallback (about, XtNcallback, CbAbout, (XtPointer)wm_delete); man = XtVaCreateManagedWidget ( "man", smeBSBObjectClass, help_menu, NULL); XtAddCallback (man, XtNcallback, CbExec, App.help_command); XtAddCallback (file_mb, XtNtabCallback, CbMenuTab, map_mb); XtAddCallback (map_mb, XtNtabCallback, CbMenuTab, help_mb); XtAddCallback (help_mb, XtNtabCallback, CbMenuTab, file_mb); mixer = XtVaCreateManagedWidget ( "mixer_box", boxWidgetClass, frame, XtNorientation, XtorientHorizontal, NULL); App.mDev = menu_entries = (Widget *) malloc (sizeof(Widget) * (no_of_devs + 1)); for (i = 0; i < no_of_devs; i++) { devs[i].dev = i; devs[i].max = no_of_devs; sprintf (wname, "%d", i); devs[i].box = XtVaCreateManagedWidget ( wname, formWidgetClass, mixer, NULL); RegisterWidget (devs[i].box); devs[i].lbl = XtVaCreateManagedWidget ( mixer_get_label (1, i), xwButtonWidgetClass, devs[i].box, XtNborderWidth, 0, XtNresize, True, XtNresizable, True, NULL); XtAddCallback (devs[i].lbl, XtNcallback, CbChangeLabel, (XtPointer)wm_delete); devs[i].sll = XtVaCreateManagedWidget ( "left", pannerWidgetClass, devs[i].box, XtNfromVert, devs[i].lbl, NULL); XtAddCallback(devs[i].sll,XtNreportCallback,CbPanL,(XtPointer)&devs[i]); XtAddEventHandler (devs[i].sll, ButtonPressMask, False, focusEH, mixer); XtAddEventHandler (devs[i].sll, KeyPressMask, False, tabEH, &App); if (mixer_is_stereo (1, i)) { devs[i].slr = XtVaCreateManagedWidget ( "right", pannerWidgetClass, devs[i].box, XtNfromVert, devs[i].lbl, XtNfromHoriz, devs[i].sll, NULL); XtAddCallback (devs[i].slr, XtNreportCallback, CbPanR, (XtPointer)&devs[i]); XtAddEventHandler (devs[i].slr, ButtonPressMask, False, focusEH, mixer); XtAddEventHandler (devs[i].slr, KeyPressMask, False, tabEH, &App); } devs[i].lck = XtVaCreateManagedWidget ( "lck", xwToggleWidgetClass, devs[i].box, XtNstate, True, XtNfromVert, devs[i].sll, NULL); devs[i].locked = 1; XtAddCallback (devs[i].lck, XtNcallback, CbLock, (XtPointer)&devs[i]); if (mixer_is_rec_dev (1, i)) { devs[i].rec = XtVaCreateManagedWidget ( "rec", xwToggleWidgetClass, devs[i].box, XtNfromHoriz, devs[i].lck, XtNfromVert, devs[i].sll, NULL); XtAddCallback (devs[i].rec, XtNcallback, CbRec, (XtPointer) devs); } else { devs[i].rec = XtVaCreateManagedWidget ( "rec", xwToggleWidgetClass, devs[i].box, XtNsensitive, False, /* XtNshadowType, XtShadowNone, */ XtNfromHoriz, devs[i].lck, XtNfromVert, devs[i].sll, NULL); } devs[i].mut = XtVaCreateManagedWidget ("mut", xwToggleWidgetClass, devs[i].box, XtNstate, True, XtNfromHoriz, devs[i].rec, XtNfromVert, devs[i].sll, NULL); XtVaGetValues (devs[i].mut, XtNforeground, &(devs[i].active), NULL); XtAddCallback (devs[i].mut, XtNcallback, CbMute, &(devs[i])); menu_entries[i] = XtVaCreateManagedWidget (mixer_get_label (1,i), smeBSBObjectClass, map_menu, XtNleftMargin, ok_width + 2, XtNleftBitmap, App.checked, NULL); XtAddCallback (menu_entries[i], XtNcallback, CbMap, devs[i].box); } /* */ menu_entries[i] = XtVaCreateManagedWidget ("menu", smeBSBObjectClass, map_menu, XtNleftMargin, ok_width + 2, XtNleftBitmap, App.checked, NULL); XtAddCallback (menu_entries[i], XtNcallback, CbMap, App.menu_box); /* prevent flickering while unmapping some devices */ XtVaSetValues (toplevel, XtNmappedWhenManaged, False, NULL); XtRealizeWidget (toplevel); devs[0].rec_bm = XCreateBitmapFromData (XtDisplay (mixer), XtWindow (mixer), input_bits, input_width, input_height); devs[0].norec_bm=XCreateBitmapFromData (XtDisplay (mixer), XtWindow (mixer), norec_bits, norec_width, norec_height); devs[0].lck_bm = XCreateBitmapFromData (XtDisplay (mixer), XtWindow (mixer), locked_bits, locked_width, locked_height); devs[0].unlck_bm=XCreateBitmapFromData (XtDisplay (mixer), XtWindow (mixer), unlocked_bits, unlocked_width, unlocked_height); devs[0].none_bm=XCreateBitmapFromData (XtDisplay (mixer), XtWindow (mixer), none_bits, none_width, none_height); devs[0].mute_bm=XCreateBitmapFromData (XtDisplay (mixer), XtWindow (mixer), mute_bits, mute_width, mute_height); for ( i = 0; i < no_of_devs; i++) { devs[i].rec_bm = devs[0].rec_bm; devs[i].norec_bm = devs[0].norec_bm; devs[i].lck_bm = devs[0].lck_bm; devs[i].unlck_bm = devs[0].unlck_bm; devs[i].none_bm = devs[0].none_bm; devs[i].mute_bm = devs[0].mute_bm; if (mixer_is_rec_dev (1, i)) { if (mixer_is_rec_on (1, i)) { XtVaSetValues (devs[i].rec, XtNstate, True, XtNbitmap, devs[i].rec_bm, NULL); } else { XtVaSetValues (devs[i].rec, XtNstate, False, XtNbitmap, devs[i].norec_bm, NULL); } } else { XtVaSetValues (devs[i].rec, XtNbitmap, devs[i].none_bm, NULL); } vol = mixer_get_vol_left (1, i); XtVaSetValues (devs[i].mut, XtNbitmap, devs[i].mute_bm, NULL); XtVaSetValues (devs[i].sll, XtNsliderY, 100-vol, NULL); if (mixer_is_stereo (1, i)) { if (vol == mixer_get_vol_right (1, i)) { XtVaSetValues (devs[i].lck, XtNbitmap, devs[i].lck_bm, NULL); XtVaSetValues (devs[i].slr, XtNsliderY, 100-vol, NULL); } else { XtVaSetValues (devs[i].lck, XtNbitmap, devs[i].unlck_bm, XtNstate, False, NULL); vol = mixer_get_vol_right (1, i); XtVaSetValues (devs[i].slr, XtNsliderY, 100-vol, NULL); devs[i].locked = 0; } } else { XtVaSetValues (devs[i].lck, XtNbitmap, devs[i].none_bm, XtNstate, False, XtNsensitive, False, /* XtNshadowType, XtShadowNone, */ NULL); } } /* restore settings for map/unmap */ scf = scf_init (pname, NULL); if (scf_read (scf)) { char *l; for ( i = 0; i < no_of_devs; i++) { name = mixer_get_name (1, i); sprintf (key, "%s_map", name); if (scf_get_bool_val (scf, mixer_dev, key, &map)) { if (map == SCF_FALSE) { CbMap (menu_entries[i], devs[i].box, NULL); } } sprintf (key, "%s_label", name); l = scf_get_val (scf, mixer_dev, key); if (l) { XtVaSetValues (devs[i].lbl, XtNlabel, l, NULL); XtVaSetValues (menu_entries[i], XtNlabel, l, NULL); } } } scf_fini (scf); XtMapWidget (toplevel); XtAppAddTimeOut (App.context, App.update_time * 1000, (XtTimerCallbackProc) TCbUpdate, (XtPointer)devs); XSetWMProtocols (XtDisplay(toplevel), XtWindow(toplevel), &wm_delete, 1); XtAddEventHandler (toplevel, NoEventMask, True, WmDelEH, &wm_delete); XtInstallAccelerators (frame, file_mb); XtInstallAccelerators (frame, map_mb); XtInstallAccelerators (frame, help_mb); XtAppMainLoop (App.context); return (ERROR); } /* * for an internal list .. */ typedef struct widgets { Widget w; struct widgets *next; } Widgets; static Widgets *first = NULL; /* */ static void RegisterWidget (Widget w) { Widgets *t = first; Widgets *new = malloc (sizeof (Widgets)); if (!new) return; new->w = w; new->next = NULL; if (!t) { first = new; } else { while (t->next) t = t->next; t->next = new; } } /* */ static Widget NameToWidget (String name) { Widgets *t = first; while (t && name) { if (strcmp (XtName(t->w), name) == 0) return (t->w); t = t->next; } return (None); }