1 /*
2  * Copyright (C) 1997-2002 Kare Sjolander <kare@speech.kth.se>
3  *
4  * This file is part of the Snack Sound Toolkit.
5  * The latest version can be found at http://www.speech.kth.se/snack/
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20  */
21 
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <signal.h>
25 #include <math.h>
26 #include <string.h>
27 #include "tcl.h"
28 #include "jkAudIO.h"
29 #include "jkSound.h"
30 
31 extern int rop, wop;
32 
33 char defaultMixerDevice[MAX_DEVICE_NAME_LENGTH];
34 
35 static int
devicesCmd(Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])36 devicesCmd(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
37 {
38   int i, n;
39   char *arr[MAX_NUM_DEVICES];
40   Tcl_Obj *list = Tcl_NewListObj(0, NULL);
41 
42   n = SnackGetMixerDevices(arr, MAX_NUM_DEVICES);
43   for (i = 0; i < n; i++) {
44     Tcl_ListObjAppendElement(interp, list, Tcl_NewStringObj(arr[i], -1));
45     ckfree(arr[i]);
46   }
47 
48   Tcl_SetObjResult(interp, list);
49 
50   return TCL_OK;
51 }
52 
53 static int
selectCmd(Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])54 selectCmd(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
55 {
56   int i, n, found = 0;
57   char *arr[MAX_NUM_DEVICES];
58   char *devstr;
59 
60   n = SnackGetMixerDevices(arr, MAX_NUM_DEVICES);
61 
62   if (objc == 3) {
63     devstr = Tcl_GetStringFromObj(objv[2], NULL);
64     for (i = 0; i < n; i++) {
65       if (strncmp(devstr, arr[i], strlen(devstr)) == 0 && found == 0) {
66 	strcpy(defaultMixerDevice, arr[i]);
67 	found = 1;
68       }
69       ckfree(arr[i]);
70     }
71     if (found == 0) {
72       Tcl_AppendResult(interp, "No such device: ", devstr, (char *) NULL);
73       return TCL_ERROR;
74     }
75   } else {
76     Tcl_WrongNumArgs(interp, 1, objv, "select device");
77     return TCL_ERROR;
78   }
79 
80   return TCL_OK;
81 }
82 
83 static int
inputCmd(Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])84 inputCmd(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
85 {
86   char *jack, tmpstr[QUERYBUFSIZE];
87 
88   if (objc < 3) {
89     SnackMixerGetInputJack(tmpstr, QUERYBUFSIZE);
90     Tcl_SetObjResult(interp, Tcl_NewStringObj(tmpstr, -1));
91   } else {
92     jack = Tcl_GetStringFromObj(objv[2], NULL);
93     if (objc == 3) {
94       if (SnackMixerSetInputJack(interp, jack, "1")) {
95 	Tcl_AppendResult(interp, "Error setting input jack", NULL);
96 	return TCL_ERROR;
97       };
98     } else {
99       SnackMixerLinkJacks(interp, jack, objv[3]);
100     }
101   }
102 
103   return TCL_OK;
104 }
105 
106 static int
inputsCmd(Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])107 inputsCmd(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
108 {
109   char tmpstr[QUERYBUFSIZE];
110 
111   SnackMixerGetInputJackLabels(tmpstr, QUERYBUFSIZE);
112   Tcl_SetObjResult(interp, Tcl_NewStringObj(tmpstr, -1));
113 
114   return TCL_OK;
115 }
116 
117 static int
outputCmd(Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])118 outputCmd(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
119 {
120   char *jack, tmpstr[QUERYBUFSIZE];
121 
122   if (objc < 3) {
123     SnackMixerGetOutputJack(tmpstr, QUERYBUFSIZE);
124     Tcl_SetObjResult(interp, Tcl_NewStringObj(tmpstr, -1));
125   } else {
126     jack = Tcl_GetStringFromObj(objv[2], NULL);
127     if (objc == 3) {
128       SnackMixerSetOutputJack(jack, "1");
129     } else {
130       SnackMixerLinkJacks(interp, jack, objv[3]);
131     }
132   }
133 
134   return TCL_OK;
135 }
136 
137 static int
outputsCmd(Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])138 outputsCmd(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
139 {
140   char tmpstr[QUERYBUFSIZE];
141 
142   SnackMixerGetOutputJackLabels(tmpstr, QUERYBUFSIZE);
143   Tcl_SetObjResult(interp, Tcl_NewStringObj(tmpstr, -1));
144 
145   return TCL_OK;
146 }
147 
148 static int
channelsCmd(Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])149 channelsCmd(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
150 {
151   char *line, tmpstr[QUERYBUFSIZE];
152 
153   if (objc == 3) {
154     line = Tcl_GetStringFromObj(objv[2], NULL);
155     SnackMixerGetChannelLabels(line, tmpstr, QUERYBUFSIZE);
156     Tcl_SetObjResult(interp, Tcl_NewStringObj(tmpstr, -1));
157   } else {
158     Tcl_WrongNumArgs(interp, 1, objv, "channels line");
159     return TCL_ERROR;
160   }
161 
162   return TCL_OK;
163 }
164 
165 static int
volumeCmd(Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])166 volumeCmd(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
167 {
168   char *line, tmpstr[QUERYBUFSIZE];
169 
170   line = Tcl_GetStringFromObj(objv[2], NULL);
171 #ifdef HPUX
172     if (rop != IDLE || wop != IDLE) return TCL_OK;
173 #endif
174   if (objc == 3) {
175     SnackMixerGetVolume(line, -1, tmpstr, QUERYBUFSIZE);
176     Tcl_SetObjResult(interp, Tcl_NewStringObj(tmpstr, -1));
177   } else if (objc == 4) {
178   } else if (objc == 5) {
179     SnackMixerGetChannelLabels(line, tmpstr, QUERYBUFSIZE);
180     if (strcmp("Mono", tmpstr) == 0) {
181       Tcl_AppendResult(interp, "Line is single channel", NULL);
182       return TCL_ERROR;
183     }
184   } else {
185     Tcl_WrongNumArgs(interp, 1, objv, "audio volume line [leftVar] [rightVar]");
186     return TCL_ERROR;
187   }
188   SnackMixerLinkVolume(interp, line, objc - 3, objv);
189 
190   return TCL_OK;
191 }
192 
193 static int
linesCmd(Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])194 linesCmd(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
195 {
196   char tmpstr[QUERYBUFSIZE];
197 
198   SnackMixerGetLineLabels(tmpstr, QUERYBUFSIZE);
199   Tcl_SetObjResult(interp, Tcl_NewStringObj(tmpstr, -1));
200 
201   return TCL_OK;
202 }
203 
204 static int
updateCmd(Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])205 updateCmd(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
206 {
207   SnackMixerUpdateVars(interp);
208 
209   return TCL_OK;
210 }
211 
212 #define NMIXERCOMMANDS   10
213 #define MAXMIXERCOMMANDS 20
214 
215 int nMixerCommands   = NMIXERCOMMANDS;
216 int maxMixerCommands = MAXMIXERCOMMANDS;
217 
218 CONST84 char *mixerCmdNames[MAXMIXERCOMMANDS] = {
219   "devices",
220   "select",
221   "input",
222   "inputs",
223   "output",
224   "outputs",
225   "channels",
226   "volume",
227   "lines",
228   "update",
229   NULL
230 };
231 
232 /* NOTE: NMIXERCOMMANDS needs updating when new commands are added. */
233 
234 mixerCmd *mixerCmdProcs[MAXMIXERCOMMANDS] = {
235   devicesCmd,
236   selectCmd,
237   inputCmd,
238   inputsCmd,
239   outputCmd,
240   outputsCmd,
241   channelsCmd,
242   volumeCmd,
243   linesCmd,
244   updateCmd,
245 };
246 
247 mixerDelCmd *mixerDelCmdProcs[MAXMIXERCOMMANDS] = {
248   NULL,
249   NULL,
250   NULL,
251   NULL,
252   NULL,
253   NULL,
254   NULL,
255   NULL,
256   NULL,
257   NULL,
258   NULL
259 };
260 
261 int
Snack_MixerCmd(ClientData cdata,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])262 Snack_MixerCmd(ClientData cdata, Tcl_Interp *interp, int objc,
263 	       Tcl_Obj *CONST objv[])
264 {
265   int index;
266 
267   if (objc < 2) {
268     Tcl_WrongNumArgs(interp, 1, objv, "option ?arg?");
269     return TCL_ERROR;
270   }
271 
272   if (Tcl_GetIndexFromObj(interp, objv[1], mixerCmdNames, "option", 0,
273 			  &index) != TCL_OK) {
274     return TCL_ERROR;
275   }
276 
277   return((mixerCmdProcs[index])(interp, objc, objv));
278 }
279 
280 void
Snack_MixerDeleteCmd(ClientData clientData)281 Snack_MixerDeleteCmd(ClientData clientData)
282 {
283   int i;
284 
285   for (i = 0; i < nMixerCommands; i++) {
286     if (mixerDelCmdProcs[i] != NULL) {
287       (mixerDelCmdProcs[i])();
288     }
289   }
290 }
291