/**************************************************************************** * apps/system/nxrecorder/nxrecorder_main.c * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. The * ASF licenses this file to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance with the * License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations * under the License. * ****************************************************************************/ /**************************************************************************** * Included Files ****************************************************************************/ #include #include #include #include #include #include #include #include #include #include "system/readline.h" #include "system/nxrecorder.h" /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ #define NXRECORDER_VER "1.00" #ifdef CONFIG_NXRECORDER_INCLUDE_HELP # define NXRECORDER_HELP_TEXT(x) x #else # define NXRECORDER_HELP_TEXT(x) #endif /**************************************************************************** * Private Type Declarations ****************************************************************************/ struct mp_cmd_s { const char *cmd; /* The command text */ const char *arghelp; /* Text describing the args */ nxrecorder_func pfunc; /* Pointer to command handler */ const char *help; /* The help text */ }; /**************************************************************************** * Private Function Prototypes ****************************************************************************/ static int nxrecorder_cmd_quit(FAR struct nxrecorder_s *precorder, FAR char *parg); static int nxrecorder_cmd_recordraw(FAR struct nxrecorder_s *precorder, FAR char *parg); static int nxrecorder_cmd_record(FAR struct nxrecorder_s *precorder, FAR char *parg); static int nxrecorder_cmd_device(FAR struct nxrecorder_s *precorder, FAR char *parg); #ifndef CONFIG_AUDIO_EXCLUDE_PAUSE_RESUME static int nxrecorder_cmd_pause(FAR struct nxrecorder_s *precorder, FAR char *parg); static int nxrecorder_cmd_resume(FAR struct nxrecorder_s *precorder, FAR char *parg); #endif #ifndef CONFIG_AUDIO_EXCLUDE_STOP static int nxrecorder_cmd_stop(FAR struct nxrecorder_s *precorder, FAR char *parg); #endif #ifdef CONFIG_NXRECORDER_INCLUDE_HELP static int nxrecorder_cmd_help(FAR struct nxrecorder_s *precorder, FAR char *parg); #endif /**************************************************************************** * Private Data ****************************************************************************/ static const struct mp_cmd_s g_nxrecorder_cmds[] = { { "device", "devfile", nxrecorder_cmd_device, NXRECORDER_HELP_TEXT("Specify a preferred audio device") }, #ifdef CONFIG_NXRECORDER_INCLUDE_HELP { "h", "", nxrecorder_cmd_help, NXRECORDER_HELP_TEXT("Display help for commands") }, { "help", "", nxrecorder_cmd_help, NXRECORDER_HELP_TEXT("Display help for commands") }, #endif { "recordraw", "filename", nxrecorder_cmd_recordraw, NXRECORDER_HELP_TEXT("Record a pcm raw file") }, { "record", "filename", nxrecorder_cmd_record, NXRECORDER_HELP_TEXT("Record a media file") }, #ifndef CONFIG_AUDIO_EXCLUDE_PAUSE_RESUME { "pause", "", nxrecorder_cmd_pause, NXRECORDER_HELP_TEXT("Pause record") }, { "resume", "", nxrecorder_cmd_resume, NXRECORDER_HELP_TEXT("Resume record") }, #endif #ifndef CONFIG_AUDIO_EXCLUDE_STOP { "stop", "", nxrecorder_cmd_stop, NXRECORDER_HELP_TEXT("Stop record") }, #endif { "q", "", nxrecorder_cmd_quit, NXRECORDER_HELP_TEXT("Exit NxRecorder") }, { "quit", "", nxrecorder_cmd_quit, NXRECORDER_HELP_TEXT("Exit NxRecorder") }, }; static const int g_nxrecorder_cmd_count = sizeof(g_nxrecorder_cmds) / sizeof(struct mp_cmd_s); /**************************************************************************** * Private Functions ****************************************************************************/ /**************************************************************************** * Name: nxrecorder_cmd_recordraw * * nxrecorder_cmd_recordraw() records the raw data file using the * nxrecorder context. * ****************************************************************************/ static int nxrecorder_cmd_recordraw(FAR struct nxrecorder_s *precorder, FAR char *parg) { int ret; int channels = 0; int bpsamp = 0; int samprate = 0; int chmap = 0; char filename[128]; sscanf(parg, "%s %d %d %d %d", filename, &channels, &bpsamp, &samprate, &chmap); /* Try to record the file specified */ ret = nxrecorder_recordinternal(precorder, filename, AUDIO_FMT_PCM, channels, bpsamp, samprate, chmap); /* nxrecorder_recordfile returned values: * * OK File is being recorded * -EBUSY The media device is busy * -ENOSYS The media file is an unsupported type * -ENODEV No audio device suitable to record the media type * -ENOENT The media file was not found */ switch (-ret) { case OK: break; case ENODEV: printf("No suitable Audio Device found\n"); break; case EBUSY: printf("Audio device busy\n"); break; case ENOENT: printf("File %s not found\n", filename); break; case ENOSYS: printf("Unknown audio format\n"); break; default: printf("Error recording file: %d\n", -ret); break; } return ret; } /**************************************************************************** * Name: nxrecorder_cmd_record * * nxrecorder_cmd_record() record the specified media file using the * nxrecorder context. * ****************************************************************************/ static int nxrecorder_cmd_record(FAR struct nxrecorder_s *precorder, FAR char *parg) { int ret; int channels = 0; int bpsamp = 0; int samprate = 0; int chmap = 0; char filename[128]; sscanf(parg, "%s %d %d %d %d", filename, &channels, &bpsamp, &samprate, &chmap); /* Try to record the file specified */ ret = nxrecorder_recordinternal(precorder, filename, AUDIO_FMT_UNDEF, channels, bpsamp, samprate, chmap); /* nxrecorder_recordfile returned values: * * OK File is being recorded * -EBUSY The media device is busy * -ENOSYS The media file is an unsupported type * -ENODEV No audio device suitable to play the media type * -ENOENT The media file was not found */ switch (-ret) { case OK: break; case ENODEV: printf("No suitable Audio Device found\n"); break; case EBUSY: printf("Audio device busy\n"); break; case ENOENT: printf("File %s not found\n", parg); break; case ENOSYS: printf("Unknown audio format\n"); break; default: printf("Error playing file: %d\n", -ret); break; } return ret; } /**************************************************************************** * Name: nxrecorder_cmd_stop * * nxrecorder_cmd_stop() stops record of currently recording file * context. * ****************************************************************************/ #ifndef CONFIG_AUDIO_EXCLUDE_STOP static int nxrecorder_cmd_stop(FAR struct nxrecorder_s *precorder, FAR char *parg) { /* Stop the record */ nxrecorder_stop(precorder); return OK; } #endif /**************************************************************************** * Name: nxrecorder_cmd_pause * * nxrecorder_cmd_pause() pauses record of currently recording file * context. * ****************************************************************************/ #ifndef CONFIG_AUDIO_EXCLUDE_PAUSE_RESUME static int nxrecorder_cmd_pause(FAR struct nxrecorder_s *precorder, FAR char *parg) { /* Pause the record */ nxrecorder_pause(precorder); return OK; } #endif /**************************************************************************** * Name: nxrecorder_cmd_resume * * nxrecorder_cmd_resume() resumes record of currently recording file * context. * ****************************************************************************/ #ifndef CONFIG_AUDIO_EXCLUDE_PAUSE_RESUME static int nxrecorder_cmd_resume(FAR struct nxrecorder_s *precorder, FAR char *parg) { /* Resume the record */ nxrecorder_resume(precorder); return OK; } #endif /**************************************************************************** * Name: nxrecorder_cmd_device * * nxrecorder_cmd_device() sets the preferred audio device for record * ****************************************************************************/ static int nxrecorder_cmd_device(FAR struct nxrecorder_s *precorder, FAR char *parg) { int ret; char path[PATH_MAX]; /* First try to open the file directly */ ret = nxrecorder_setdevice(precorder, parg); if (ret == -ENOENT) { /* Append the /dev/audio path and try again */ #ifdef CONFIG_AUDIO_CUSTOM_DEV_PATH #ifdef CONFIG_AUDIO_DEV_ROOT snprintf(path, sizeof(path), "/dev/%s", parg); #else snprintf(path, sizeof(path), CONFIG_AUDIO_DEV_PATH "/%s", parg); #endif #else snprintf(path, sizeof(path), "/dev/audio/%s", parg); #endif ret = nxrecorder_setdevice(precorder, path); } /* Test if the device file exists */ if (ret == -ENOENT) { /* Device doesn't exit. Report error */ printf("Device %s not found\n", parg); return ret; } /* Test if is is an audio device */ if (ret == -ENODEV) { printf("Device %s is not an audio device\n", parg); return ret; } if (ret < 0) { return ret; } /* Device set successfully */ return OK; } /**************************************************************************** * Name: nxrecorder_cmd_quit * * nxrecorder_cmd_quit() terminates the application ****************************************************************************/ static int nxrecorder_cmd_quit(FAR struct nxrecorder_s *precorder, FAR char *parg) { /* Stop the record if any */ #ifndef CONFIG_AUDIO_EXCLUDE_STOP nxrecorder_stop(precorder); #endif return OK; } /**************************************************************************** * Name: nxrecorder_cmd_help * * nxrecorder_cmd_help() display the application's help information on * supported commands and command syntax. ****************************************************************************/ #ifdef CONFIG_NXRECORDER_INCLUDE_HELP static int nxrecorder_cmd_help(FAR struct nxrecorder_s *precorder, FAR char *parg) { int len; int maxlen = 0; int x; int c; /* Calculate length of longest cmd + arghelp */ for (x = 0; x < g_nxrecorder_cmd_count; x++) { len = strlen(g_nxrecorder_cmds[x].cmd) + strlen(g_nxrecorder_cmds[x].arghelp); if (len > maxlen) { maxlen = len; } } printf("NxRecorder commands\n================\n"); for (x = 0; x < g_nxrecorder_cmd_count; x++) { /* Print the command and it's arguments */ printf(" %s %s", g_nxrecorder_cmds[x].cmd, g_nxrecorder_cmds[x].arghelp); /* Calculate number of spaces to print before the help text */ len = maxlen - (strlen(g_nxrecorder_cmds[x].cmd) + strlen(g_nxrecorder_cmds[x].arghelp)); for (c = 0; c < len; c++) { printf(" "); } printf(" : %s\n", g_nxrecorder_cmds[x].help); } return OK; } #endif /**************************************************************************** * Public Functions ****************************************************************************/ /**************************************************************************** * Name: nxrecorder * * nxrecorder() reads in commands from the console using the readline * system add-in and implements a command-line based pcm raw data recorder * that uses the NuttX audio system to record pcm raw data files read in * from the audio device. Commands are provided for setting volume, base * and other audio features, as well as for pausing and stopping the * record. * * Input Parameters: * buf - The user allocated buffer to be filled. * buflen - the size of the buffer. * instream - The stream to read characters from * outstream - The stream to each characters to. * * Returned values: * On success, the (positive) number of bytes transferred is returned. * EOF is returned to indicate either an end of file condition or a * failure. * ****************************************************************************/ int main(int argc, FAR char *argv[]) { char buffer[CONFIG_NSH_LINELEN]; int len; int x; int running; char *cmd; char *arg; FAR struct nxrecorder_s *precorder; printf("NxRecorder version " NXRECORDER_VER "\n"); printf("h for commands, q to exit\n"); printf("\n"); /* Initialize our NxRecorder context */ precorder = nxrecorder_create(); if (precorder == NULL) { printf("Error: Out of RAM\n"); return -ENOMEM; } /* Loop until the user exits */ running = TRUE; while (running) { /* Print a prompt */ printf("nxrecorder> "); fflush(stdout); /* Read a line from the terminal */ len = readline(buffer, sizeof(buffer), stdin, stdout); if (len > 0) { buffer[len] = '\0'; if (strncmp(buffer, "!", 1) != 0) { /* nxrecorder command */ if (buffer[len - 1] == '\n') { buffer[len - 1] = '\0'; } /* Parse the command from the argument */ cmd = strtok_r(buffer, " \n", &arg); if (cmd == NULL) { continue; } /* Remove leading spaces from arg */ while (*arg == ' ') { arg++; } /* Find the command in our cmd array */ for (x = 0; x < g_nxrecorder_cmd_count; x++) { if (strcmp(cmd, g_nxrecorder_cmds[x].cmd) == 0) { /* Command found. Call it's handler if not NULL */ if (g_nxrecorder_cmds[x].pfunc != NULL) { g_nxrecorder_cmds[x].pfunc(precorder, arg); } /* Test if it is a quit command */ if (g_nxrecorder_cmds[x].pfunc == nxrecorder_cmd_quit) { running = FALSE; } break; } } } else { #ifdef CONFIG_SYSTEM_SYSTEM /* Transfer nuttx shell */ system(buffer + 1); #else printf("%s: unknown nxplayer command\n", buffer); #endif } } } /* Release the NxRecorder context */ nxrecorder_release(precorder); return OK; }