1 /*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include <assert.h>
17 #include <ctype.h>
18 #include <errno.h>
19 #include <getopt.h>
20 #include <math.h>
21 #include <poll.h>
22 #include <stdarg.h>
23 #include <stdint.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27
28 #include "audio_mixer.h"
29 #include "securec.h"
30
31 #define AUDIO_MAX_CARDS 32
32 #define SND_CARD_NAME_LEN 64
33 #define INFO_BUF_LEN 128
34 #define CARD_SRV_NAME_LEN (SND_CARD_NAME_LEN)
35 #define DEFAULT_CARD_NAME "hdf_audio_codec_primary_dev0"
36
37 #define SRV_SND_PRIMARY_MIN 0
38 #define SRV_SND_PRIMARY_MAX 10
39 #define SRV_SND_HDMI_MIN 11
40 #define SRV_SND_HDMI_MAX 20
41 #define SRV_SND_USB_MIN 21
42 #define SRV_SND_USB_MAX 30
43 #define SRV_SND_A2DP_MIN 31
44 #define SRV_SND_A2DP_MAX 40
45
46 #define SSET_WR 0
47 #define SSET_RO 1
48 #define STRTOL_BASE 10
49
50 #define L_INACTIV (1 << 1)
51
52 struct HdfIoService *g_service = NULL;
53 static char g_serviceName[CARD_SRV_NAME_LEN] = DEFAULT_CARD_NAME;
54 static char g_card[SND_CARD_NAME_LEN] = "primary0";
55 static char g_dev[SND_CARD_NAME_LEN] = "default";
56 static AudioPcmType g_pcm = PCM_RENDER;
57 static bool g_debugFlag = false;
58 #ifdef CHANNEL_MAP
59 static bool chnmapFlag = false;
60 #endif
61
ShowUsage(void)62 static int32_t ShowUsage(void)
63 {
64 printf("Usage: audio_mixer <options> [command]\n");
65 printf("\nAvailable options:\n");
66 printf(" -h, --help this help\n");
67 printf(" -l, --list-cards list all soundcards and digital audio devices\n");
68 printf(" -c, --card N select the card\n");
69 printf(" -D, --device N select the device, default '%s'\n", g_dev);
70 printf(" -P, --pcm N select the PCM type(1: reader/2: capture), default 1\n");
71 printf(" -d, --debug debug mode\n");
72 printf(" -v, --version print version of this program\n");
73 printf(" -i, --inactive show also inactive controls. (Reserved)\n");
74 printf(" -S, --service N select the audio card service default '%s'\n", DEFAULT_CARD_NAME);
75 #ifdef CHANNEL_MAP
76 printf(" -m, --chmap=ch1,ch2,.. Give the channel map to override or follow\n");
77 #endif
78
79 printf("\nAvailable commands:\n");
80 printf(" info show all info for mixer\n");
81 printf(" controls show all controls for given card\n");
82 printf(" contents show contents of all controls for given card\n");
83 printf(" set ID P set control contents for one control\n");
84 printf(" get ID get control contents for one control\n");
85
86 return 0;
87 }
88
89 #ifdef LEGECY_STRATEGY
AudioCard2Dev(int32_t card)90 static int32_t AudioCard2Dev(int32_t card)
91 {
92 int32_t ret;
93 SND_TYPE sndType;
94 char ctlDev[CARD_SRV_NAME_LEN] = {0};
95
96 switch (card) {
97 case SRV_SND_PRIMARY_MIN ... SRV_SND_PRIMARY_MAX:
98 sndType = SND_PRIMARY;
99 ret = sprintf_s(ctlDev, CARD_SRV_NAME_LEN - 1, "%s%d", "primary", card);
100 break;
101 case SRV_SND_HDMI_MIN ... SRV_SND_HDMI_MAX:
102 sndType = SND_HDMI;
103 ret = sprintf_s(ctlDev, CARD_SRV_NAME_LEN - 1, "%s%d", "hdmi", card);
104 break;
105 case SRV_SND_USB_MIN ... SRV_SND_USB_MAX:
106 sndType = SND_USB;
107 ret = sprintf_s(ctlDev, CARD_SRV_NAME_LEN - 1, "%s%d", "usb", card);
108 break;
109 case SRV_SND_A2DP_MIN ... SRV_SND_A2DP_MAX:
110 sndType = SND_A2DP;
111 ret = sprintf_s(ctlDev, CARD_SRV_NAME_LEN - 1, "%s%d", "a2dp", card);
112 break;
113 default:
114 DEBUG_LOG("Unknown sound card type!\n");
115 return U_FAILURE;
116 }
117 if (ret < 0) {
118 DEBUG_LOG("Failed to synthesize the card name!\n");
119 return U_FAILURE;
120 }
121 DEBUG_LOG("The card type: %i\n", sndType);
122 DEBUG_LOG("The card name: %s\n", ctlDev);
123 ret = memcpy_s(g_card, SND_CARD_NAME_LEN, ctlDev, strlen(ctlDev));
124 if (ret != 0) {
125 DEBUG_LOG("memcpy_s fail!\n");
126 return U_FAILURE;
127 }
128
129 return U_SUCCESS;
130 }
131
AudioCard2Dev2(const char * string,int32_t * index)132 static int32_t AudioCard2Dev2(const char *string, int32_t *index)
133 {
134 int32_t ret;
135 size_t len, offset;
136 char *name = NULL;
137
138 name = strrchr(string, '/') + 1;
139 len = strlen(name);
140 if (len == 0) {
141 *index = -1;
142 DEBUG_LOG("name is empty!!!\n");
143 return U_FAILURE;
144 }
145 DEBUG_LOG("name is %s, len = %zu\n", name, len);
146
147 offset = len - 1;
148 if (isdigit(name[offset]) == 0) {
149 *index = -1;
150 DEBUG_LOG("name is error!!!\n");
151 return U_FAILURE;
152 }
153 name += isdigit(name[offset - 1]) ? offset - 1 : offset;
154
155 ret = sscanf_s(name, "%i", index);
156 if (ret <= 0) {
157 DEBUG_LOG("%s\n", strerror(errno));
158 printf("%s\n", strerror(errno));
159 return U_FAILURE;
160 }
161
162 return AudioCard2Dev(*index);
163 }
164
AudioCardGetIndex(const char * string,int32_t * index)165 static int32_t AudioCardGetIndex(const char *string, int32_t *index)
166 {
167 int32_t ret;
168 int32_t card = -1;
169
170 if (string == NULL || *string == '\0') {
171 DEBUG_LOG("Invalid parameters!\n");
172 return U_INVALID_PARAM;
173 }
174
175 if ((isdigit(*string) && *(string + 1) == 0) ||
176 (isdigit(*string) && isdigit(*(string + 1)) && *(string + 2) == 0)) { // 2 for offset
177 /* An index was found */
178 ret = sscanf_s(string, "%i", &card);
179 if (ret <= 0) {
180 DEBUG_LOG("%s\n", strerror(errno));
181 printf("%s\n", strerror(errno));
182 return U_FAILURE;
183 }
184 if (card < 0 || card >= AUDIO_MAX_CARDS) {
185 DEBUG_LOG("%s\n", strerror(errno));
186 printf("%s\n", strerror(errno));
187 return U_FAILURE;
188 }
189
190 ret = AudioCard2Dev(card);
191 if (ret != U_SUCCESS) {
192 return ret;
193 }
194 *index = card;
195 } else if (string[0] == '/') {
196 /* Find the device name */
197 return AudioCard2Dev2(string, index);
198 } else {
199 *index = -1;
200 DEBUG_LOG("Sound card name that cannot be converted\n");
201 return U_FAILURE;
202 }
203
204 return U_SUCCESS;
205 }
206 #endif
207
UpdateCardName(const char * card)208 static void UpdateCardName(const char *card)
209 {
210 int32_t id;
211
212 if (card == NULL || *card == '\0') {
213 DEBUG_LOG("Invalid card!\n");
214 return;
215 }
216
217 if ((isdigit(*card) && *(card + 1) == 0) ||
218 (isdigit(*card) && isdigit(*(card + 1)) && *(card + 2) == 0)) { // 2 for offset
219 id = (int32_t)strtol(card, NULL, STRTOL_BASE);
220 DEBUG_LOG("card %i\n", id);
221 UpdateCardSname(id, g_service, g_serviceName, CARD_SRV_NAME_LEN);
222 DEBUG_LOG("cardServiceName:%s, dev:%s\n", g_serviceName, g_dev);
223 }
224 }
225
MixerInfo(void)226 static int32_t MixerInfo(void)
227 {
228 printf("card/dev: '%s'/'%s'\n", g_card, g_dev);
229 printf(" Mixer name : '%s'\n", "MIXER");
230 printf(" Components : '%s'\n", "Audio Components");
231 printf("----------------------------------\n");
232 MctlInfo(g_service, g_serviceName);
233
234 return U_SUCCESS;
235 }
236
237 #ifdef LEGECY_STRATEGY
CheckCardAndDev(int32_t index)238 static bool CheckCardAndDev(int32_t index)
239 {
240 switch (index) {
241 case SRV_SND_PRIMARY_MIN ... SRV_SND_PRIMARY_MAX:
242 DEBUG_LOG("primary%d\n", index);
243 break;
244 case SRV_SND_HDMI_MIN ... SRV_SND_HDMI_MAX:
245 DEBUG_LOG("hdmi%d\n", index);
246 break;
247 case SRV_SND_USB_MIN ... SRV_SND_USB_MAX:
248 DEBUG_LOG("usb%d\n", index);
249 break;
250 case SRV_SND_A2DP_MIN ... SRV_SND_A2DP_MAX:
251 DEBUG_LOG("a2dp%d\n", index);
252 break;
253 default:
254 DEBUG_LOG("Unknown sound card!!!\n");
255 return false;
256 }
257
258 return true;
259 }
260 #endif
261
MixerControls(void)262 static int32_t MixerControls(void)
263 {
264 if (g_service == NULL) {
265 DEBUG_LOG("Invalid service!\n");
266 return U_FAILURE;
267 }
268
269 return MctlList(g_service, g_serviceName);
270 }
271
ShowAllCardList(void)272 static void ShowAllCardList(void)
273 {
274 int32_t ret;
275
276 if (g_service == NULL) {
277 DEBUG_LOG("Invalid service!\n");
278 return;
279 }
280
281 ret = GetAllCards(g_service);
282 if (ret != U_SUCCESS) {
283 DEBUG_LOG("Couldn't find any sound card equipment!\n");
284 }
285 }
286
DupCtlName(char * data,int32_t dataLen,char * buf,int32_t bufSize)287 static int32_t DupCtlName(char *data, int32_t dataLen, char *buf, int32_t bufSize)
288 {
289 int32_t ret;
290
291 if (dataLen <= 0 || bufSize <= 0) {
292 DEBUG_LOG("Unable to copy to control name space!\n");
293 return U_FAILURE;
294 }
295
296 if (bufSize >= dataLen) {
297 bufSize = dataLen - 1;
298 }
299
300 ret = strncpy_s(data, dataLen, buf, bufSize);
301 if (ret != 0) {
302 DEBUG_LOG("strncpy_s fail!\n");
303 return U_FAILURE;
304 }
305 data[dataLen - 1] = '\0';
306
307 return U_SUCCESS;
308 }
309
ParseName(const char * s,struct AudioHwCtlElemId * eId)310 static int32_t ParseName(const char *s, struct AudioHwCtlElemId *eId)
311 {
312 int32_t c, size, len;
313 char *ptr = NULL;
314 char buf[INFO_BUF_LEN] = {0};
315 char *sbuf = buf;
316
317 ptr = strstr(s, "=");
318 if (ptr == NULL) {
319 DEBUG_LOG("Cannot find the given element from control default!\n");
320 return U_FAILURE;
321 }
322 ptr++;
323
324 size = 0;
325 if (*ptr == '\"' || *ptr == '\'') {
326 c = *ptr++;
327 while (*ptr && *ptr != c) {
328 if (size < (int32_t)sizeof(buf)) {
329 *sbuf++ = *ptr;
330 size++;
331 }
332 ptr++;
333 }
334 if (*ptr == c) {
335 ptr++;
336 }
337 } else {
338 while (*ptr && *ptr != ',') {
339 if (size < (int32_t)sizeof(buf)) {
340 *sbuf++ = *ptr;
341 size++;
342 }
343 ptr++;
344 }
345 }
346 *sbuf = (*ptr == '\0') ? *ptr : '\0';
347 DEBUG_LOG("control name=%s, size=%d\n", buf, size);
348 len = (int32_t)sizeof(eId->name);
349
350 return DupCtlName((char *)eId->name, len, buf, size);
351 }
352
ParseNumId(const char * s,uint32_t * idx)353 static int32_t ParseNumId(const char *s, uint32_t *idx)
354 {
355 int32_t numid;
356 char *ptr = NULL;
357
358 ptr = strstr(s, "=");
359 if (ptr == NULL) {
360 DEBUG_LOG("Cannot find the given element from control default!\n");
361 return U_FAILURE;
362 }
363 ptr++;
364
365 if (!isdigit(*ptr)) {
366 DEBUG_LOG("Invalid elem index!\n");
367 printf("Invalid elem index!\n");
368 return U_FAILURE;
369 }
370
371 numid = (int32_t)strtol(ptr, NULL, STRTOL_BASE);
372 if (numid <= 0) {
373 DEBUG_LOG("audio_mixer: Invalid numid %d\n", numid);
374 return U_FAILURE;
375 }
376 *idx = (uint32_t)numid;
377
378 return U_SUCCESS;
379 }
380
ParseElemIndex(const char * str,struct AudioHwCtlElemIndex * sid)381 static int32_t ParseElemIndex(const char *str, struct AudioHwCtlElemIndex *sid)
382 {
383 int32_t ret;
384
385 while (isspace(*str) || *str == '\t') {
386 str++;
387 }
388
389 if (!(*str)) {
390 DEBUG_LOG("Invalid elem index string!\n");
391 return U_FAILURE;
392 }
393
394 sid->eId.iface = AUDIO_CTL_ELEM_IFACE_MIXER;
395 if (strncasecmp(str, "name", strlen("name")) == 0) {
396 ret = ParseName(str + strlen("name"), &sid->eId);
397 if (ret != U_SUCCESS) {
398 DEBUG_LOG("Invalid elem index string!\n");
399 printf("Invalid elem index string!\n");
400 return U_FAILURE;
401 }
402 sid->index = 0;
403 } else if (strncasecmp(str, "numid", strlen("numid")) == 0) {
404 ret = ParseNumId(str + strlen("numid"), &sid->index);
405 if (ret != U_SUCCESS) {
406 DEBUG_LOG("Invalid elem index string!\n");
407 printf("Invalid elem index string!\n");
408 return U_FAILURE;
409 }
410 while (!isdigit(*str)) {
411 str++;
412 }
413 } else {
414 DEBUG_LOG("Cannot be resolved at present %s!\n", str);
415 return U_FAILURE;
416 }
417
418 return U_SUCCESS;
419 }
420
FillSndCardName(struct MixerCardCtlInfo * ctlInfo)421 static int32_t FillSndCardName(struct MixerCardCtlInfo *ctlInfo)
422 {
423 int32_t ret;
424
425 if (strlen(g_serviceName) == 0) {
426 DEBUG_LOG("The sound card service name is error!\n");
427 return U_FAILURE;
428 }
429
430 ret = strncpy_s(ctlInfo->cardSrvName, AUDIO_CARD_SRV_NAME_LEN, g_serviceName, strlen(g_serviceName));
431 if (ret != 0) {
432 DEBUG_LOG("strncpy_s fail!\n");
433 return U_FAILURE;
434 }
435 ctlInfo->cardSrvName[AUDIO_CARD_SRV_NAME_LEN - 1] = '\0';
436
437 return U_SUCCESS;
438 }
439
MixerESet(unsigned int argc,char * argv[],int32_t roflag)440 static int32_t MixerESet(unsigned int argc, char *argv[], int32_t roflag)
441 {
442 int32_t ret, slen;
443 struct MixerCardCtlInfo ctlInfo;
444
445 if (argc < 1) {
446 printf("Specify a full control identifier: "
447 "[[iface=<iface>,][name='name',]"
448 "[index=<index>,]] | [numid=<numid>]\n");
449 return U_FAILURE;
450 }
451
452 slen = (int32_t)sizeof(struct MixerCardCtlInfo);
453 memset_s(&ctlInfo, slen, 0, slen);
454 ret = ParseElemIndex(argv[0], &ctlInfo.edx);
455 if (ret != U_SUCCESS) {
456 DEBUG_LOG("Wrong scontrol identifier: %s\n", argv[0]);
457 printf("Wrong scontrol identifier: %s\n", argv[0]);
458 return U_FAILURE;
459 }
460 if (g_debugFlag) {
461 printf("index=%u, iface=%s, name='%s'\n", ctlInfo.edx.index, STRING(MIXER), ctlInfo.edx.eId.name);
462 }
463
464 if (roflag == SSET_WR && argc < 2) { // 2 for number of argcs
465 DEBUG_LOG("Specify what you want to set...\n");
466 printf("Specify what you want to set...\n");
467 return U_FAILURE;
468 }
469
470 /* Query whether the control to be set exists. */
471 if (!MixerFindSelem(g_service, g_serviceName, &ctlInfo.edx.eId)) {
472 DEBUG_LOG("Can't find scontrol identifier: %s, %i\n", ctlInfo.edx.eId.name, ctlInfo.edx.index);
473 return U_FAILURE;
474 }
475
476 ret = FillSndCardName(&ctlInfo);
477 if (ret != U_SUCCESS) {
478 return ret;
479 }
480
481 if (roflag == SSET_WR) {
482 ret = MctlSetElem(g_service, &ctlInfo, argc, argv);
483 if (ret != U_SUCCESS) {
484 return ret;
485 }
486 }
487
488 return MctlGetElem(g_service, &ctlInfo);
489 }
490
ServiceHandleInit(void)491 static int32_t ServiceHandleInit(void)
492 {
493 int32_t ret;
494
495 ret = GetLibsoHandle(g_pcm);
496 if (ret != U_SUCCESS) {
497 return ret;
498 }
499
500 if (g_service != NULL) {
501 return U_SUCCESS;
502 }
503
504 if (strlen(g_serviceName) >= CARD_SRV_NAME_LEN) {
505 g_service = MixerBindCrlSrvDefault();
506 } else {
507 g_service = MixerBindCrlSrv(g_serviceName);
508 }
509 if (g_service == NULL) {
510 DEBUG_LOG("Failed to obtain the service!\n");
511 CloseLibsoHandle();
512 return U_FAILURE;
513 }
514
515 return U_SUCCESS;
516 }
517
FreeGlobal(void)518 static void FreeGlobal(void)
519 {
520 ReleaseCtlElemList();
521 MixerRecycleCrlSrv(g_service);
522 CloseLibsoHandle();
523 }
524
GetPcm(const char * string)525 static void GetPcm(const char *string)
526 {
527 int type;
528
529 type = (int32_t)strtol(string, NULL, STRTOL_BASE);
530 switch (type) {
531 case PCM_RENDER:
532 g_pcm = PCM_RENDER;
533 break;
534 case PCM_CAPTURE:
535 g_pcm = PCM_CAPTURE;
536 break;
537 default:
538 DEBUG_LOG("Wrong PCM type!\n");
539 break;
540 }
541 }
542
543 #ifdef CHANNEL_MAP
MixerSetChannels(unsigned int argc,char * str)544 static int32_t MixerSetChannels(unsigned int argc, char *str)
545 {
546 if (argc < 1) {
547 DEBUG_LOG("Channels error!\n");
548 return U_FAILURE;
549 }
550
551 return SetChannels(g_service, g_serviceName, argc, str);
552 }
553 #endif
554
main(int argc,char * argv[])555 int main(int argc, char *argv[])
556 {
557 int32_t ret;
558 int32_t c;
559 int32_t optionIndex = -1;
560 #ifdef LEGECY_STRATEGY
561 int index = 0;
562 #else
563 int updateId = 0;
564 char *newCard = NULL;
565 #endif
566 int badOpt = 0;
567 int level = 0;
568 #ifdef CHANNEL_MAP
569 int chnmapId = 0;
570 char *chnmapString = "front,render,2";
571 #endif
572 bool doDeviceList = false;
573 bool doUpdateCardName = false;
574 static const struct option longOpts[] = {
575 {"help", 0, NULL, 'h'},
576 {"list-cards", 0, NULL, 'l'},
577 {"card", 1, NULL, 'c'},
578 {"device", 1, NULL, 'D'},
579 {"pcm", 1, NULL, 'P'},
580 {"inactive", 0, NULL, 'i'},
581 {"debug", 0, NULL, 'd'},
582 {"version", 0, NULL, 'v'},
583 {"service", 1, NULL, 'S'},
584 #ifdef CHANNEL_MAP
585 {"chmap", 1, NULL, 'm'},
586 #endif
587 {NULL, 0, NULL, 0 }
588 };
589
590 static const char shortOptions[] = "hlc:D:P:idvS:"
591 #ifdef CHANNEL_MAP
592 "m:"
593 #endif
594 ;
595
596 while (1) {
597 c = getopt_long(argc, argv, shortOptions, longOpts, &optionIndex);
598 if (c < 0) {
599 DEBUG_LOG("Parameter parsing completed!\n");
600 break;
601 }
602
603 switch (c) {
604 case 'h':
605 ShowUsage();
606 return 0;
607 case 'l':
608 doDeviceList = true;
609 break;
610 case 'c':
611 #ifdef LEGECY_STRATEGY
612 ret = AudioCardGetIndex(optarg, &index);
613 if (ret != U_SUCCESS) {
614 return ret;
615 }
616 if (!CheckCardAndDev(index)) {
617 fprintf(stderr, "Invalid card number '%s'.\n", optarg);
618 badOpt++;
619 }
620 #else
621 /* The new version conversion policy is enabled. */
622 doUpdateCardName = true;
623 updateId = optind;
624 newCard = optarg;
625 #endif
626 break;
627 case 'D':
628 ret = strncpy_s(g_dev, SND_CARD_NAME_LEN - 1, optarg, strlen(optarg));
629 if (ret != 0) {
630 DEBUG_LOG("strncpy_s fail!\n");
631 goto FINISH;
632 }
633 g_dev[sizeof(g_dev) - 1] = '\0';
634
635 break;
636 case 'P':
637 GetPcm(optarg);
638 break;
639 case 'i':
640 level |= L_INACTIV;
641 printf("Reserved Parameters. [level %i]\n", level);
642 return 0;
643 case 'd':
644 g_debugFlag = true;
645 break;
646 case 'v':
647 printf("audio_mixer version %s\n", ShowVersion());
648 return 0;
649 case 'S':
650 ret = strncpy_s(g_serviceName, CARD_SRV_NAME_LEN - 1, optarg, strlen(optarg));
651 if (ret != 0) {
652 DEBUG_LOG("strncpy_s fail!\n");
653 goto FINISH;
654 }
655 g_serviceName[strlen(optarg)] = '\0';
656
657 break;
658 #ifdef CHANNEL_MAP
659 case 'm':
660 chnmapFlag = true;
661 chnmapId = optind;
662 chnmapString = optarg;
663
664 break;
665 #endif
666 default:
667 fprintf(stderr, "Invalid switch or option -%c needs an argument.\n", c);
668 badOpt++;
669 }
670 }
671 if (badOpt) {
672 ERR_LOG("The argument passed in was incorrect!\n");
673 return 1;
674 }
675
676 DebugLog(g_debugFlag);
677 ret = ServiceHandleInit();
678 if (ret != U_SUCCESS) {
679 goto FINISH;
680 }
681 AudioMixerOpsInit();
682
683 if (doDeviceList) {
684 ShowAllCardList();
685 goto FINISH;
686 }
687
688 #ifdef CHANNEL_MAP
689 if (chnmapFlag) {
690 if (chnmapId < 1) {
691 chnmapId = 1;
692 }
693 ret = MixerSetChannels((unsigned int)chnmapId, chnmapString);
694 if (ret != U_SUCCESS) {
695 DEBUG_LOG("Unable to parse channel map string: %s\n", optarg);
696 }
697 goto FINISH;
698 }
699 #endif
700
701 if (doUpdateCardName) {
702 UpdateCardName(newCard);
703 if (argc - optind <= 0) {
704 ret = 0;
705 goto FINISH;
706 }
707 }
708
709 if (argc - optind <= 0) {
710 DEBUG_LOG("The parameter passed in is incorrect, argc = %i, optind = %i\n", argc, optind);
711 printf("Use this parameter together with other parameters!\n");
712 ShowUsage();
713 ret = 0;
714 goto FINISH;
715 }
716
717 if (strcmp(argv[optind], "help") == 0) {
718 ret = ShowUsage() ? 1 : 0;
719 } else if (strcmp(argv[optind], "info") == 0) {
720 ret = MixerInfo() ? 1 : 0;
721 } else if (strcmp(argv[optind], "controls") == 0) {
722 ret = MixerControls() ? 1 : 0;
723 } else if (strcmp(argv[optind], "contents") == 0) {
724 ret = MixerControls() ? 1 : 0;
725 } else if (strcmp(argv[optind], "set") == 0) {
726 ret = MixerESet(argc - optind - 1, (argc - optind > 1) ? (argv + optind + 1) : NULL, SSET_WR) ? 1 : 0;
727 } else if (strcmp(argv[optind], "get") == 0) {
728 ret = MixerESet(argc - optind - 1, (argc - optind > 1) ? (argv + optind + 1) : NULL, SSET_RO) ? 1 : 0;
729 } else {
730 fprintf(stderr, "audio_mixer: Unknown command '%s'...\n", argv[optind]);
731 ret = 0;
732 }
733
734 FINISH:
735 /* Releasing Global Resources. */
736 FreeGlobal();
737
738 return ret;
739 }
740