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 "tcl.h" 23#include "jkAudIO.h" 24#include <stdio.h> 25#include <fcntl.h> 26#include <unistd.h> 27 28extern void Snack_WriteLog(char *s); 29extern void Snack_WriteLogInt(char *s, int n); 30 31#ifndef min 32#define min(a,b) ((a)<(b)?(a):(b)) 33#define max(a,b) ((a)>(b)?(a):(b)) 34#endif 35 36#define SNACK_NUMBER_MIXERS 1 37 38struct MixerLink mixerLinks[SNACK_NUMBER_MIXERS][2]; 39 40int 41SnackAudioOpen(ADesc *A, Tcl_Interp *interp, char *device, int mode, int freq, 42 int nchannels, int encoding) 43{ 44 return TCL_OK; 45} 46 47int 48SnackAudioClose(ADesc *A) 49{ 50 return(0); 51} 52 53long 54SnackAudioPause(ADesc *A) 55{ 56 return(-1); 57} 58 59void 60SnackAudioResume(ADesc *A) 61{ 62} 63 64void 65SnackAudioFlush(ADesc *A) 66{ 67} 68 69void 70SnackAudioPost(ADesc *A) 71{ 72} 73 74int 75SnackAudioRead(ADesc *A, void *buf, int nFrames) 76{ 77} 78 79int 80SnackAudioWrite(ADesc *A, void *buf, int nFrames) 81{ 82} 83 84int 85SnackAudioReadable(ADesc *A) 86{ 87} 88 89int 90SnackAudioWriteable(ADesc *A) 91{ 92 return -1; 93} 94 95long 96SnackAudioPlayed(ADesc *A) 97{ 98} 99 100void 101SnackAudioInit() 102{ 103} 104 105void 106SnackAudioFree() 107{ 108 int i, j; 109 110 for (i = 0; i < SNACK_NUMBER_MIXERS; i++) { 111 for (j = 0; j < 2; j++) { 112 if (mixerLinks[i][j].mixer != NULL) { 113 ckfree(mixerLinks[i][j].mixer); 114 } 115 if (mixerLinks[i][j].mixerVar != NULL) { 116 ckfree(mixerLinks[i][j].mixerVar); 117 } 118 } 119 if (mixerLinks[i][0].jack != NULL) { 120 ckfree(mixerLinks[i][0].jack); 121 } 122 if (mixerLinks[i][0].jackVar != NULL) { 123 ckfree((char *)mixerLinks[i][0].jackVar); 124 } 125 } 126} 127 128void 129ASetRecGain(int gain) 130{ 131 int g = min(max(gain, 0), 100); 132} 133 134void 135ASetPlayGain(int gain) 136{ 137 int g = min(max(gain, 0), 100); 138} 139 140int 141AGetRecGain() 142{ 143 int g = 0; 144 145 return(g); 146} 147 148int 149AGetPlayGain() 150{ 151 int g = 0; 152 153 return(g); 154} 155 156int 157SnackAudioGetEncodings(char *device) 158{ 159 return(LIN16); 160} 161 162void 163SnackAudioGetRates(char *device, char *buf, int n) 164{ 165 strncpy(buf, "8000 11025 16000 22050 32000 44100 48000", n); 166 buf[n-1] = '\0'; 167} 168 169int 170SnackAudioMaxNumberChannels(char *device) 171{ 172 return(2); 173} 174 175int 176SnackAudioMinNumberChannels(char *device) 177{ 178 return(1); 179} 180 181void 182SnackMixerGetInputJackLabels(char *buf, int n) 183{ 184 buf[0] = '\0'; 185} 186 187void 188SnackMixerGetOutputJackLabels(char *buf, int n) 189{ 190 buf[0] = '\0'; 191} 192 193void 194SnackMixerGetInputJack(char *buf, int n) 195{ 196 buf[0] = '\0'; 197} 198 199int 200SnackMixerSetInputJack(Tcl_Interp *interp, char *jack, CONST84 char *status) 201{ 202 return 1; 203} 204 205void 206SnackMixerGetOutputJack(char *buf, int n) 207{ 208 buf[0] = '\0'; 209} 210 211void 212SnackMixerSetOutputJack(char *jack, char *status) 213{ 214} 215 216void 217SnackMixerGetChannelLabels(char *line, char *buf, int n) 218{ 219 strncpy(buf, "Mono", n); 220 buf[n-1] = '\0'; 221} 222 223void 224SnackMixerGetVolume(char *line, int channel, char *buf, int n) 225{ 226 if (strncasecmp(line, "Play", strlen(line)) == 0) { 227 sprintf(buf, "%d", AGetPlayGain()); 228 } 229} 230 231void 232SnackMixerSetVolume(char *line, int channel, int volume) 233{ 234 if (strncasecmp(line, "Play", strlen(line)) == 0) { 235 ASetPlayGain(volume); 236 } 237} 238 239void 240SnackMixerLinkJacks(Tcl_Interp *interp, char *jack, Tcl_Obj *var) 241{ 242} 243 244static char * 245VolumeVarProc(ClientData clientData, Tcl_Interp *interp, CONST84 char *name1, 246 CONST84 char *name2, int flags) 247{ 248 MixerLink *mixLink = (MixerLink *) clientData; 249 CONST84 char *stringValue; 250 251 if (flags & TCL_TRACE_UNSETS) { 252 if ((flags & TCL_TRACE_DESTROYED) && !(flags & TCL_INTERP_DESTROYED)) { 253 Tcl_Obj *obj, *var; 254 char tmp[VOLBUFSIZE]; 255 256 SnackMixerGetVolume(mixLink->mixer, mixLink->channel, tmp, VOLBUFSIZE); 257 obj = Tcl_NewIntObj(atoi(tmp)); 258 var = Tcl_NewStringObj(mixLink->mixerVar, -1); 259 Tcl_ObjSetVar2(interp, var, NULL, obj, TCL_GLOBAL_ONLY | TCL_PARSE_PART1); 260 Tcl_TraceVar(interp, mixLink->mixerVar, 261 TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, 262 VolumeVarProc, (int *)mixLink); 263 } 264 return (char *) NULL; 265 } 266 stringValue = Tcl_GetVar(interp, mixLink->mixerVar, TCL_GLOBAL_ONLY); 267 if (stringValue != NULL) { 268 SnackMixerSetVolume(mixLink->mixer, mixLink->channel, atoi(stringValue)); 269 } 270 271 return (char *) NULL; 272} 273 274void 275SnackMixerLinkVolume(Tcl_Interp *interp, char *line, int n, 276 Tcl_Obj *CONST objv[]) 277{ 278 char *mixLabels[] = { "Play" }; 279 int i, j, channel; 280 CONST84 char *value; 281 char tmp[VOLBUFSIZE]; 282 283 for (i = 0; i < SNACK_NUMBER_MIXERS; i++) { 284 if (strncasecmp(line, mixLabels[i], strlen(line)) == 0) { 285 for (j = 0; j < n; j++) { 286 if (n == 1) { 287 channel = -1; 288 } else { 289 channel = j; 290 } 291 mixerLinks[i][j].mixer = (char *)SnackStrDup(line); 292 mixerLinks[i][j].mixerVar = (char *)SnackStrDup(Tcl_GetStringFromObj(objv[j+3], NULL)); 293 mixerLinks[i][j].channel = j; 294 value = Tcl_GetVar(interp, mixerLinks[i][j].mixerVar, TCL_GLOBAL_ONLY); 295 if (value != NULL) { 296 SnackMixerSetVolume(line, channel, atoi(value)); 297 } else { 298 Tcl_Obj *obj; 299 SnackMixerGetVolume(line, channel, tmp, VOLBUFSIZE); 300 obj = Tcl_NewIntObj(atoi(tmp)); 301 Tcl_ObjSetVar2(interp, objv[j+3], NULL, obj, 302 TCL_GLOBAL_ONLY | TCL_PARSE_PART1); 303 } 304 Tcl_TraceVar(interp, mixerLinks[i][j].mixerVar, 305 TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, 306 VolumeVarProc, (ClientData) &mixerLinks[i][j]); 307 } 308 } 309 } 310} 311 312void 313SnackMixerUpdateVars(Tcl_Interp *interp) 314{ 315 int i, j; 316 char tmp[VOLBUFSIZE]; 317 Tcl_Obj *obj, *var; 318 319 for (i = 0; i < SNACK_NUMBER_MIXERS; i++) { 320 for (j = 0; j < 2; j++) { 321 if (mixerLinks[i][j].mixerVar != NULL) { 322 SnackMixerGetVolume(mixerLinks[i][j].mixer, mixerLinks[i][j].channel, 323 tmp, VOLBUFSIZE); 324 obj = Tcl_NewIntObj(atoi(tmp)); 325 var = Tcl_NewStringObj(mixerLinks[i][j].mixerVar, -1); 326 Tcl_ObjSetVar2(interp, var, NULL, obj, TCL_GLOBAL_ONLY|TCL_PARSE_PART1); 327 } 328 } 329 } 330} 331 332void 333SnackMixerGetLineLabels(char *buf, int n) 334{ 335 strncpy(buf, "Play", n); 336 buf[n-1] = '\0'; 337} 338 339int 340SnackGetOutputDevices(char **arr, int n) 341{ 342 arr[0] = (char *) SnackStrDup("default"); 343 344 return 1; 345} 346 347int 348SnackGetInputDevices(char **arr, int n) 349{ 350 arr[0] = (char *) SnackStrDup("default"); 351 352 return 1; 353} 354 355int 356SnackGetMixerDevices(char **arr, int n) 357{ 358 arr[0] = (char *) SnackStrDup("default"); 359 360 return 1; 361} 362