/*- * Copyright (c) 1999 Thomas Runge (coto@core.de) * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef __NetBSD__ #include #else #if defined(linux) || defined(__FreeBSD__) #include #else #include #endif #endif #include "sample.h" #include "misc.h" #include "radio.h" #include "analyzer.h" #if (XmVERSION < 2) enum { XmUNSET, XmSET, XmINDETERMINATE }; #endif Widget sample_dialogW, sampleFormW, filename_textW; Widget format_optionW, capture_optionW, stereo_optionW, rate_optionW; Widget overwriteW, recordB, stopB, playbackB, dismissB, searchB; extern Widget analyzerW; static int dsp; static int sampling; static int playing; static int resetmixer; static int old_recsrc; static int is_popped; static char gbuf[BUFSIZ]; extern char *DSP_DEVICE; extern XtAppContext app_con; extern int mixer; extern int debug; #define DEF_FILENAME "capture.audiofile" /* CYCLETIME in seconds */ #define CYCLETIME 0.25 void CheckSampleFormat(); int CheckForProgram(const char *name); void ResetMixer(); int PrepareDSP(int flags); typedef struct { char *name; int id; } option_menu; typedef struct { char *filename; int file_format; int capture_format; int bps; int stereo; int speed; int sign; int ask_overwrite; } sample_format; static sample_format sformat; enum { RAW_FORMAT=1, AU_FORMAT, WAV_FORMAT, VOC_FORMAT, AIFF_FORMAT, MP3_FORMAT }; enum { SAMP8012=8012, SAMP11025=11025, SAMP22050=22050, SAMP44100=44100 }; static option_menu format_options[] = { { "raw_format", RAW_FORMAT }, { "au_format", AU_FORMAT }, { "wav_format", WAV_FORMAT }, { "voc_format", VOC_FORMAT }, { "aiff_format", AIFF_FORMAT }, { "mp3_format", MP3_FORMAT } }; /* if you add new formats, add them in CheckBPS() and CheckSign() as well. */ static option_menu capture_options[] = { { "16-bit signed (LSB) (recommended)", AFMT_S16_LE }, { "16-bit unsigned (LSB)", AFMT_U16_LE }, { "16-bit unsigned (MSB)", AFMT_U16_BE }, { "16-bit signed (MSB)", AFMT_S16_BE }, { "8-bit signed (recommended)", AFMT_S8 }, { "8-bit mu-law", AFMT_MU_LAW }, { "8-bit unsigned", AFMT_U8 } }; static option_menu stereo_options[] = { { "stereo", 1 }, { "mono", 0 } }; static option_menu rate_options[] = { { "44.100 samp/s", SAMP44100 }, { "22.050 samp/s", SAMP22050 }, { "11.025 samp/s", SAMP11025 }, { "8.012 samp/s", SAMP8012 } }; static void closeCB(Widget widget, XtPointer clientData, XtPointer callData) { SampleDialogToggle(); } static void stopCB(Widget widget, XtPointer clientData, XtPointer callData) { if(resetmixer) ResetMixer(); sampling = False; playing = False; } static void searchCB(Widget widget, XtPointer clientData, XtPointer callData) { char *filename = XtomGetFileName(sample_dialogW, "search", NULL, NULL, 0, 0); if(filename && strlen(filename)) XtVaSetValues(filename_textW, XmNvalue, filename, NULL); XtFree(filename); } static void sampleCB(Widget widget, XtPointer clientData, XtPointer callData) { char *buffer; ssize_t len, bufsize; FILE *fp = NULL; XtInputMask mask; int dummy, opened; char command[512]; sampling = True; opened = False; CheckSampleFormat(); if(!sformat.filename || !strlen(sformat.filename)) { XtomShowMessage(sample_dialogW, XmDIALOG_ERROR, "sampling", "no filename set."); return; } if((dummy = access(sformat.filename, W_OK)) == -1) { if(errno != ENOENT) { sprintf(gbuf, "cant access file %s (%s)", sformat.filename, strerror(errno)); XtomShowMessage(sample_dialogW, XmDIALOG_ERROR, "sampling", gbuf); sampling = False; } } else { if(sformat.ask_overwrite) { sprintf(gbuf, "overwrite file %s ?", sformat.filename); dummy = XtomGetChoice(sample_dialogW, "sampling", gbuf); if(!dummy) return; } } dsp = PrepareDSP(O_RDONLY); if(dsp == -1) return; bufsize = sformat.speed * (sformat.stereo+1) * sformat.bps * CYCLETIME; if(debug) printf("bufsize1: %d\n", bufsize); bufsize = (bufsize+3)/4*4; /* hopefully this won't optimized away */ if(debug) printf("bufsize2: %d\n", bufsize); buffer = (char*)malloc(bufsize); switch(sformat.file_format) { case WAV_FORMAT: // TODO -w for 16bit, -b for 8bit sprintf(command, "sox -c %d -t raw -r %d -%c -w - -t wav %s", sformat.stereo + 1, sformat.speed, sformat.sign, sformat.filename); if(!CheckForProgram("sox")) { XtomShowMessage(sample_dialogW, XmDIALOG_ERROR, "sampling", "couldn't find \"sox\" in $PATH."); sampling = False; } else if(debug) printf("using %s\n", command); break; case AU_FORMAT: sprintf(command, "sox -c %d -t raw -r %d -%c -b - -t au %s", sformat.stereo + 1, sformat.speed, sformat.sign, sformat.filename); if(!CheckForProgram("sox")) { XtomShowMessage(sample_dialogW, XmDIALOG_ERROR, "sampling", "couldn't find \"sox\" in $PATH."); sampling = False; } else if(debug) printf("using %s\n", command); break; case VOC_FORMAT: sprintf(command, "sox -c %d -t raw -r %d -%c -b - -t voc %s", sformat.stereo + 1, sformat.speed, sformat.sign, sformat.filename); if(!CheckForProgram("sox")) { XtomShowMessage(sample_dialogW, XmDIALOG_ERROR, "sampling", "couldn't find \"sox\" in $PATH."); sampling = False; } else if(debug) printf("using %s\n", command); break; case AIFF_FORMAT: sprintf(command, "sox -c %d -t raw -r %d -%c -b - -t aiff %s", sformat.stereo + 1, sformat.speed, sformat.sign, sformat.filename); if(!CheckForProgram("sox")) { XtomShowMessage(sample_dialogW, XmDIALOG_ERROR, "sampling", "couldn't find \"sox\" in $PATH."); sampling = False; } else if(debug) printf("using %s\n", command); break; case MP3_FORMAT: sprintf(command, "lame -b 128 -f -r -s %.4f -m %s -S -x --tc %s - > %s", sformat.speed/1000., (sformat.stereo ? "j" : "m"), "\"recorded by xmradio\"", sformat.filename); if(!CheckForProgram("lame")) { XtomShowMessage(sample_dialogW, XmDIALOG_ERROR, "sampling", "couldn't find \"lame\" in $PATH."); sampling = False; } else if(debug) printf("using %s\n", command); break; case RAW_FORMAT: if((fp = fopen(sformat.filename, "w")) == NULL) { sprintf(gbuf, "couldn't open outputfile: %s (%s)", sformat.filename, strerror(errno)); XtomShowMessage(sample_dialogW, XmDIALOG_ERROR, "sampling", gbuf); sampling = False; } else opened = True; break; default: XtomShowMessage(sample_dialogW, XmDIALOG_ERROR, "sampling", "unknown sample format!?!"); sampling = False; break; } if(sampling && sformat.file_format != RAW_FORMAT) { fp = popen(command, "w"); if(fp == NULL) { sprintf(gbuf, "failed to popen() command: %s (%s)", command, strerror(errno)); XtomShowMessage(sample_dialogW, XmDIALOG_ERROR, "sampling", gbuf); sampling = False; } else opened = True; } XtSetSensitive(stopB, True); XtSetSensitive(recordB, False); XtSetSensitive(playbackB, False); /* okay, ready for reading from dsp device */ while(sampling) { if(debug) printf("read dsp\n"); if((len = read(dsp, buffer, bufsize)) == -1) { sprintf(gbuf, "couldn't read all data: %s", strerror(errno)); XtomShowMessage(sample_dialogW, XmDIALOG_ERROR, "sampling", gbuf); sampling = False; } if(debug) printf("read bytes: %d\n", len); /* if writing raw data, just throw it out to file */ if((len > 0) && (fwrite(buffer, len, 1, fp) != 1)) { sprintf(gbuf, "couldn't write to outputfile: %s (%s)", sformat.filename, strerror(errno)); XtomShowMessage(sample_dialogW, XmDIALOG_ERROR, "sampling", gbuf); sampling = False; } while((mask = XtAppPending(app_con)) != 0) { XtAppProcessEvent(app_con, mask); } } free(buffer); if(opened) { if(sformat.file_format != RAW_FORMAT) pclose(fp); else fclose(fp); } XtSetSensitive(stopB, False); XtSetSensitive(recordB, True); XtSetSensitive(playbackB, True); if(close(dsp) == -1) { sprintf(gbuf, "couldn't close dsp: %s", strerror(errno)); XtomShowMessage(sample_dialogW, XmDIALOG_ERROR, "sampling", gbuf); } } static void playbackCB(Widget widget, XtPointer clientData, XtPointer callData) { char *buffer; size_t len, bufsize; FILE *fp = NULL; XtInputMask mask; char command[512]; CheckSampleFormat(); if(!sformat.filename || !strlen(sformat.filename)) { XtomShowMessage(sample_dialogW, XmDIALOG_ERROR, "playback", "no filename set."); return; } dsp = PrepareDSP(O_WRONLY); if(dsp == -1) return; bufsize = sformat.speed * (sformat.stereo+1) * sformat.bps * CYCLETIME; bufsize = (bufsize+3)/4*4; /* hopefully this won't optimized away */ buffer = (char*)malloc(bufsize); playing = True; switch(sformat.file_format) { case WAV_FORMAT: if(!CheckForProgram("sox")) { XtomShowMessage(sample_dialogW, XmDIALOG_ERROR, "playing", "couldn't find \"sox\" in $PATH."); playing = False; } else { // TODO -w for 16bit, -b for 8bit sprintf(command, "sox -t wav %s -c %d -t raw -r %d -%c -w -", sformat.filename, sformat.stereo + 1, sformat.speed, sformat.sign); } break; case AU_FORMAT: if(!CheckForProgram("sox")) { XtomShowMessage(sample_dialogW, XmDIALOG_ERROR, "playing", "couldn't find \"sox\" in $PATH."); playing = False; } else { sprintf(command, "sox -t au %s -c %d -t raw -r %d -%c -b -", sformat.filename, sformat.stereo + 1, sformat.speed, sformat.sign); } break; case VOC_FORMAT: if(!CheckForProgram("sox")) { XtomShowMessage(sample_dialogW, XmDIALOG_ERROR, "playing", "couldn't find \"sox\" in $PATH."); playing = False; } else { sprintf(command, "sox -t voc %s -c %d -t raw -r %d -%c -b -", sformat.filename, sformat.stereo + 1, sformat.speed, sformat.sign); } break; case AIFF_FORMAT: if(!CheckForProgram("sox")) { XtomShowMessage(sample_dialogW, XmDIALOG_ERROR, "playing", "couldn't find \"sox\" in $PATH."); playing = False; } else { sprintf(command, "sox -t aiff %s -c %d -t raw -r %d -%c -b -", sformat.filename, sformat.stereo + 1, sformat.speed, sformat.sign); } break; case MP3_FORMAT: if(!CheckForProgram("mpg123")) { XtomShowMessage(sample_dialogW, XmDIALOG_ERROR, "playing", "couldn't find \"mpg123\" in $PATH."); playing = False; } else { sprintf(command, "mpg123 -q -r %d -s %s", sformat.speed, sformat.filename); } /* XtomShowMessage(sample_dialogW, XmDIALOG_ERROR, "playback", "sample format not implemented, yet."); playing = False; */ break; case RAW_FORMAT: if((fp = fopen(sformat.filename, "r")) == NULL) { sprintf(gbuf, "couldn't open inputfile: %s (%s)", sformat.filename, strerror(errno)); XtomShowMessage(sample_dialogW, XmDIALOG_ERROR, "playback", gbuf); playing = False; } break; default: XtomShowMessage(sample_dialogW, XmDIALOG_ERROR, "playback", "unknown sample format!?!"); playing = False; break; } if(playing && sformat.file_format != RAW_FORMAT) { if(debug) printf("using %s\n", command); fp = popen(command, "r"); if(fp == NULL) { sprintf(gbuf, "failed to popen() command: %s (%s)", command, strerror(errno)); XtomShowMessage(sample_dialogW, XmDIALOG_ERROR, "playback", gbuf); playing = False; } } XtSetSensitive(stopB, True); XtSetSensitive(recordB, False); XtSetSensitive(playbackB, False); while(playing) { len = fread(buffer, 1, bufsize, fp); if(len != bufsize) { if(feof(fp)) { playing = False; if(debug) printf(" done reading audiofile\n"); } else { sprintf(gbuf, "couldn't read from inputfile: %s", sformat.filename); XtomShowMessage(sample_dialogW, XmDIALOG_ERROR, "playback", gbuf); playing = False; break; } } if(playing && write(dsp, buffer, len) == -1) { sprintf(gbuf, "couldn't write all data to dsp: %s", strerror(errno)); XtomShowMessage(sample_dialogW, XmDIALOG_ERROR, "playback", gbuf); playing = False; } while((mask = XtAppPending(app_con)) != 0) { XtAppProcessEvent(app_con, mask); } } if(fp) fclose(fp); free(buffer); if(close(dsp) == -1) { sprintf(gbuf, "couldn't close dsp: %s", strerror(errno)); XtomShowMessage(sample_dialogW, XmDIALOG_ERROR, "sampling", gbuf); } XtSetSensitive(stopB, False); XtSetSensitive(recordB, True); XtSetSensitive(playbackB, True); } int CheckBPS(int format) { switch(format) { case AFMT_MU_LAW: case AFMT_S8: case AFMT_U8: return 1; case AFMT_S16_LE: case AFMT_U16_LE: case AFMT_U16_BE: case AFMT_S16_BE: default: return 2; } } /* return sox flag for format */ char CheckSign(int format) { switch(format) { case AFMT_MU_LAW: return 'U'; break; case AFMT_S8: case AFMT_S16_LE: case AFMT_S16_BE: return 's'; break; case AFMT_U8: case AFMT_U16_LE: case AFMT_U16_BE: default: return 'u'; break; } } void CheckSampleFormat() { Widget dummyW; unsigned char ow; int data; /* filename */ XtVaGetValues(filename_textW, XmNvalue, &(sformat.filename), NULL); if(debug) printf("filename: %s\n", sformat.filename); /* file format */ XtVaGetValues(format_optionW, XmNmenuHistory, &dummyW, NULL); XtVaGetValues(dummyW, XmNuserData, &data, NULL); sformat.file_format = data; if(debug) printf("file format: %d\n", data); /* mono/stereo */ XtVaGetValues(stereo_optionW, XmNmenuHistory, &dummyW, NULL); XtVaGetValues(dummyW, XmNuserData, &data, NULL); sformat.stereo = data; if(debug) printf("stereo: %d\n", data); /* capture format */ XtVaGetValues(capture_optionW, XmNmenuHistory, &dummyW, NULL); XtVaGetValues(dummyW, XmNuserData, &data, NULL); sformat.capture_format = data; if(debug) printf("capture format: %d\n", data); /* bps */ data = CheckBPS(sformat.capture_format); sformat.bps = data; if(debug) printf(" (bps: %d)\n", data); /* sign */ data = CheckSign(sformat.capture_format); sformat.sign = data; if(debug) printf(" (sign: %c)\n", data); /* speed */ XtVaGetValues(rate_optionW, XmNmenuHistory, &dummyW, NULL); XtVaGetValues(dummyW, XmNuserData, &data, NULL); sformat.speed = data; if(debug) printf("speed: %d\n", data); XtVaGetValues(overwriteW, XmNset, &ow, NULL); sformat.ask_overwrite = (ow == XmSET); if(debug) printf("ask for overwrite: %s\n\n", sformat.ask_overwrite ? "yes" : "no"); } int CheckForProgram(const char *name) { char *p, *cur, *path, buf[MAXPATHLEN]; if(!(path = getenv("PATH"))) path = _PATH_DEFPATH; cur = path = strdup(path); while((p = strsep(&cur, ":"))) { sprintf(buf, "%s/%s", p, name); if(!access(buf, X_OK)) { if(debug) printf("using audio tool: %s\n", buf); if(path) free(path); return True; } } if(path) free(path); return False; } void ResetMixer() { if(ioctl(mixer, SOUND_MIXER_WRITE_RECSRC, &old_recsrc) == -1) { sprintf(gbuf, "couldn't reset mixer recsrc: %s", strerror(errno)); XtomShowMessage(sample_dialogW, XmDIALOG_ERROR, "ResetMixer", gbuf); } resetmixer = False; } int PrepareDSP(int flags) { int d, dummy; if(flags == O_RDONLY || flags == O_RDWR) { if(mixer == -1) { XtomShowMessage(sample_dialogW, XmDIALOG_ERROR, "PrepareDSP", "no mixer available."); return -1; } /* getting old rec mask */ if(ioctl(mixer, SOUND_MIXER_READ_RECSRC, &old_recsrc) == -1) { sprintf(gbuf, "couldn't get mixer recsrc: %s", strerror(errno)); XtomShowMessage(sample_dialogW, XmDIALOG_ERROR, "PrepareDSP", gbuf); return -1; } resetmixer = True; /* setting rec mask to line channel */ dummy = SOUND_MASK_LINE; if(ioctl(mixer, SOUND_MIXER_WRITE_RECSRC, &dummy) == -1) { sprintf(gbuf, "couldn't set mixer recsrc: %s", strerror(errno)); XtomShowMessage(sample_dialogW, XmDIALOG_ERROR, "PrepareDSP", gbuf); return -1; } } /* opening dsp device */ if((d = open(DSP_DEVICE, flags, 0)) == -1) { sprintf(gbuf, "couldn't open %s: %s", DSP_DEVICE, strerror(errno)); XtomShowMessage(sample_dialogW, XmDIALOG_ERROR, "PrepareDSP", gbuf); goto error; } /* selecting audio format */ dummy = sformat.capture_format; if(ioctl(d, SNDCTL_DSP_SETFMT, &dummy) == -1) { sprintf(gbuf, "couldn't set dsp format: %s\n", strerror(errno)); XtomShowMessage(sample_dialogW, XmDIALOG_ERROR, "PrepareDSP", gbuf); goto error; } if(sformat.capture_format != dummy) { XtomShowMessage(sample_dialogW, XmDIALOG_ERROR, "PrepareDSP", "device doesn't support the requested audio format."); goto error; } /* selecting stereo/mono mode */ dummy = sformat.stereo; if(ioctl(d, SNDCTL_DSP_STEREO, &dummy) == -1) { sprintf(gbuf, "couldn't set dsp to %s: %s", sformat.stereo ? "stereo" : "mono", strerror(errno)); XtomShowMessage(sample_dialogW, XmDIALOG_ERROR, "PrepareDSP", gbuf); goto error; } if(sformat.stereo != dummy) { sprintf(gbuf, "device doesn't support %s mode.", sformat.stereo ? "stereo" : "mono"); XtomShowMessage(sample_dialogW, XmDIALOG_ERROR, "PrepareDSP", gbuf); goto error; } /* selecting sampling rate */ dummy = sformat.speed; if(ioctl(d, SNDCTL_DSP_SPEED, &dummy) == -1) { sprintf(gbuf, "couldn't set dsp speed: %s", strerror(errno)); XtomShowMessage(sample_dialogW, XmDIALOG_ERROR, "PrepareDSP", gbuf); goto error; } /* we should check if difference is just some percent... */ if(sformat.speed != dummy) { sprintf(gbuf, "device doesn't support requested speed.\nWanted %d, got %d.", sformat.speed, dummy); XtomShowMessage(sample_dialogW, XmDIALOG_ERROR, "PrepareDSP", gbuf); } return d; error: close(d); /* resetting rec mask */ if(resetmixer) ResetMixer(); return -1; } static Widget CreateOptionMenu(Widget parent, option_menu *menu, int n) { unsigned int i; Arg args[10]; Widget menuW, optionW; menuW = XmCreatePulldownMenu(parent, "option_pulldown", (Arg*)NULL, 0); for(i = 0; i < n; i++) { XtVaCreateManagedWidget(menu[i].name, xmPushButtonWidgetClass, menuW, XmNuserData, menu[i].id, NULL); } n = 0; XtSetArg(args[n], XmNsubMenuId, menuW); n++; optionW = XmCreateOptionMenu(parent, "option_menu", args, n); XtManageChild(optionW); #ifdef HAS_XPM if(skin) SkinToWidgets(menuW, skin); #endif return optionW; } static void MakeInterface(Widget topl) { Position x, y; Widget filename_labelW, format_labelW, capture_labelW; Widget sampleMainRowColumnW, formW, frameW, buttonSepW; Widget sampleRC1W, sampleRC2W, sampleRC3W, sampleRC4W, sampleRC5W; extern void _XEditResCheckMessages(Widget, XtPointer, XEvent*, Boolean*); XtVaGetValues(topl, XmNx, &x, XmNy, &y, NULL); sample_dialogW = XtVaCreatePopupShell("sample_dialog", transientShellWidgetClass, topl, XmNx, x, XmNy, y, XmNdeleteResponse, XmDO_NOTHING, XtNiconPixmap, icon_pm, XtNiconMask, icon_pm_mask, NULL); XtAddEventHandler(sample_dialogW, (EventMask)0, True, _XEditResCheckMessages, NULL); formW = XtVaCreateManagedWidget("sample_main", xmFormWidgetClass, sample_dialogW, NULL); frameW = XtVaCreateManagedWidget("sample_frame", xmFrameWidgetClass, formW, XmNleftAttachment, XmATTACH_FORM, XmNleftOffset, 3, XmNrightAttachment, XmATTACH_FORM, XmNrightOffset, 3, XmNtopAttachment, XmATTACH_FORM, XmNtopOffset, 3, XmNbottomAttachment, XmATTACH_FORM, XmNbottomOffset, 3, NULL); sampleMainRowColumnW = XtVaCreateManagedWidget("sample_dialog_main", xmRowColumnWidgetClass, frameW, XmNorientation, XmVERTICAL, NULL); sampleRC1W = XtVaCreateManagedWidget("sample_rc1", xmRowColumnWidgetClass, sampleMainRowColumnW, XmNorientation, XmHORIZONTAL, NULL); filename_labelW = XtVaCreateManagedWidget("filename_label", xmLabelWidgetClass, sampleRC1W, NULL); filename_textW = XtVaCreateManagedWidget("filename_text", xmTextFieldWidgetClass, sampleRC1W, XmNvalue, DEF_FILENAME, NULL); searchB = XtVaCreateManagedWidget("filename_search", xmPushButtonWidgetClass, sampleRC1W, NULL); XtAddCallback(searchB, XmNactivateCallback, searchCB, (XtPointer)NULL); sampleRC2W = XtVaCreateManagedWidget("sample_rc2", xmRowColumnWidgetClass, sampleMainRowColumnW, XmNorientation, XmHORIZONTAL, NULL); format_labelW = XtVaCreateManagedWidget("format_label", xmLabelWidgetClass, sampleRC2W, NULL); format_optionW = CreateOptionMenu(sampleRC2W, format_options, XtNumber(format_options)); sampleRC3W = XtVaCreateManagedWidget("sample_rc3", xmRowColumnWidgetClass, sampleMainRowColumnW, XmNorientation, XmHORIZONTAL, NULL); capture_labelW = XtVaCreateManagedWidget("capture_label", xmLabelWidgetClass, sampleRC3W, NULL); capture_optionW = CreateOptionMenu(sampleRC3W, capture_options, XtNumber(capture_options)); sampleRC4W = XtVaCreateManagedWidget("sample_rc4", xmRowColumnWidgetClass, sampleMainRowColumnW, XmNorientation, XmHORIZONTAL, NULL); stereo_optionW = CreateOptionMenu(sampleRC4W, stereo_options, XtNumber(stereo_options)); rate_optionW = CreateOptionMenu(sampleRC4W, rate_options, XtNumber(rate_options)); overwriteW = XtVaCreateManagedWidget("overwrite_button", xmToggleButtonWidgetClass, sampleMainRowColumnW, XmNset, True, NULL); buttonSepW = XtVaCreateManagedWidget("record_separator", xmSeparatorWidgetClass, sampleMainRowColumnW, NULL); sampleRC5W = XtVaCreateManagedWidget("sample_rc5", xmRowColumnWidgetClass, sampleMainRowColumnW, XmNorientation, XmHORIZONTAL, XmNentryAlignment, XmALIGNMENT_CENTER, NULL); recordB = XtVaCreateManagedWidget("record_button", xmPushButtonWidgetClass, sampleRC5W, NULL); stopB = XtVaCreateManagedWidget("stop_button", xmPushButtonWidgetClass, sampleRC5W, NULL); XtSetSensitive(stopB, False); XtAddCallback(stopB, XmNactivateCallback, stopCB, (XtPointer)recordB); XtAddCallback(recordB, XmNactivateCallback, sampleCB, (XtPointer)stopB); playbackB = XtVaCreateManagedWidget("playback_button", xmPushButtonWidgetClass, sampleRC5W, NULL); XtAddCallback(playbackB, XmNactivateCallback, playbackCB, (XtPointer)NULL); dismissB = XtVaCreateManagedWidget("dismiss_button", xmPushButtonWidgetClass, sampleRC5W, NULL); XtAddCallback(dismissB, XmNactivateCallback, closeCB, (XtPointer)NULL); #ifdef HAS_XPM if(skin) { SkinToWidgets(format_optionW, skin); SkinToWidgets(capture_optionW, skin); SkinToWidgets(stereo_optionW, skin); SkinToWidgets(rate_optionW, skin); } #endif } void SampleDialogToggle() { if(!sample_dialogW) { // init Atom wmDeleteAtom; is_popped = False; MakeInterface(toplevel); AddTooltipsToWidgets(); #ifdef HAS_XPM if(skin) SkinToWidgets(sample_dialogW, skin); #endif wmDeleteAtom = XmInternAtom(dpy, "WM_DELETE_WINDOW", False); XmAddWMProtocolCallback(sample_dialogW, wmDeleteAtom, closeCB, (XtPointer)NULL); } if(is_popped) { is_popped = False; XtSetSensitive(analyzerW, True); XtPopdown(sample_dialogW); } else { is_popped = True; AnalyzerQuit(); XtSetSensitive(analyzerW, False); XtPopup(sample_dialogW, XtGrabNone); } }