* Copyright (c) 2026 Huawei Device Co., Ltd.
* Licensed 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.
*/
#include <iostream>
#include <string>
#include <unordered_map>
#include <functional>
#include <cstring>
#include <memory>
#include <vector>
#include "audio_system_manager.h"
#include "audio_device_descriptor.h"
#include "common.h"
using namespace OHOS::AudioStandard;
typedef std::function<int(int, char**)> CommandHandler;
struct CommandDetails {
const char* description;
const char* usage;
const char* parameters;
const char* examples;
};
struct Command {
const char* name;
CommandDetails details;
CommandHandler handler;
};
static std::unordered_map<std::string, Command> gCommands;
static const char* G_PROGRAM_NAME = "";
static bool g_hasSubCommand = false;
static const char* G_TOOL_DESCRIPTION = "Audio management tool for controlling volume, devices, and audio settings. "
"Used for audio device management and volume control scenarios. "
"Does not support advanced audio processing or routing configuration.";
static constexpr int32_t SUCCESS = 0;
static constexpr int32_t FAILURE = 1;
static constexpr int32_t MAX_VOLUME = 15;
static constexpr int32_t MIN_VOLUME = 0;
static constexpr int32_t INT_NUM1 = 1;
static constexpr int32_t INT_NUM2 = 2;
void RegisterCommand(const char* name, const CommandDetails& details, CommandHandler handler)
{
gCommands[name] = {name, details, handler};
}
static const std::unordered_map<std::string, AudioVolumeType> gVolumeTypeMap = {
{"STREAM_MUSIC", AudioVolumeType::STREAM_MUSIC},
{"STREAM_RING", AudioVolumeType::STREAM_RING},
{"STREAM_VOICE_CALL", AudioVolumeType::STREAM_VOICE_CALL},
{"STREAM_VOICE_COMMUNICATION", AudioVolumeType::STREAM_VOICE_COMMUNICATION},
{"STREAM_VOICE_ASSISTANT", AudioVolumeType::STREAM_VOICE_ASSISTANT},
{"STREAM_ALARM", AudioVolumeType::STREAM_ALARM},
{"STREAM_SYSTEM", AudioVolumeType::STREAM_SYSTEM},
{"STREAM_VOICE_RING", AudioVolumeType::STREAM_VOICE_RING},
{"STREAM_NAVIGATION", AudioVolumeType::STREAM_NAVIGATION},
{"STREAM_NOTIFICATION", AudioVolumeType::STREAM_NOTIFICATION},
{"STREAM_ULTRASONIC", AudioVolumeType::STREAM_ULTRASONIC},
{"STREAM_ANNOUNCEMENT", AudioVolumeType::STREAM_ANNOUNCEMENT},
{"STREAM_EMERGENCY", AudioVolumeType::STREAM_EMERGENCY},
{"STREAM_ALL", AudioVolumeType::STREAM_ALL}
};
static const std::unordered_map<AudioVolumeType, std::string> gVolumeTypeToStringMap = {
{AudioVolumeType::STREAM_MUSIC, "STREAM_MUSIC"},
{AudioVolumeType::STREAM_RING, "STREAM_RING"},
{AudioVolumeType::STREAM_VOICE_CALL, "STREAM_VOICE_CALL"},
{AudioVolumeType::STREAM_VOICE_COMMUNICATION, "STREAM_VOICE_COMMUNICATION"},
{AudioVolumeType::STREAM_VOICE_ASSISTANT, "STREAM_VOICE_ASSISTANT"},
{AudioVolumeType::STREAM_ALARM, "STREAM_ALARM"},
{AudioVolumeType::STREAM_SYSTEM, "STREAM_SYSTEM"},
{AudioVolumeType::STREAM_VOICE_RING, "STREAM_VOICE_RING"},
{AudioVolumeType::STREAM_NAVIGATION, "STREAM_NAVIGATION"},
{AudioVolumeType::STREAM_NOTIFICATION, "STREAM_NOTIFICATION"},
{AudioVolumeType::STREAM_ULTRASONIC, "STREAM_ULTRASONIC"},
{AudioVolumeType::STREAM_ANNOUNCEMENT, "STREAM_ANNOUNCEMENT"},
{AudioVolumeType::STREAM_EMERGENCY, "STREAM_EMERGENCY"},
{AudioVolumeType::STREAM_ALL, "STREAM_ALL"}
};
static const std::unordered_map<std::string, DeviceType> gDeviceTypeMap = {
{"DEVICE_TYPE_INVALID", DeviceType::DEVICE_TYPE_INVALID},
{"DEVICE_TYPE_EARPIECE", DeviceType::DEVICE_TYPE_EARPIECE},
{"DEVICE_TYPE_SPEAKER", DeviceType::DEVICE_TYPE_SPEAKER},
{"DEVICE_TYPE_WIRED_HEADSET", DeviceType::DEVICE_TYPE_WIRED_HEADSET},
{"DEVICE_TYPE_WIRED_HEADPHONES", DeviceType::DEVICE_TYPE_WIRED_HEADPHONES},
{"DEVICE_TYPE_BLUETOOTH_SCO", DeviceType::DEVICE_TYPE_BLUETOOTH_SCO},
{"DEVICE_TYPE_BLUETOOTH_A2DP", DeviceType::DEVICE_TYPE_BLUETOOTH_A2DP},
{"DEVICE_TYPE_MIC", DeviceType::DEVICE_TYPE_MIC},
{"DEVICE_TYPE_USB_HEADSET", DeviceType::DEVICE_TYPE_USB_HEADSET},
{"DEVICE_TYPE_DP", DeviceType::DEVICE_TYPE_DP},
{"DEVICE_TYPE_REMOTE_CAST", DeviceType::DEVICE_TYPE_REMOTE_CAST},
{"DEVICE_TYPE_USB_DEVICE", DeviceType::DEVICE_TYPE_USB_DEVICE},
{"DEVICE_TYPE_HDMI", DeviceType::DEVICE_TYPE_HDMI},
{"DEVICE_TYPE_LINE_DIGITAL", DeviceType::DEVICE_TYPE_LINE_DIGITAL},
{"DEVICE_TYPE_REMOTE_DAUDIO", DeviceType::DEVICE_TYPE_REMOTE_DAUDIO},
{"DEVICE_TYPE_HEARING_AID", DeviceType::DEVICE_TYPE_HEARING_AID},
{"DEVICE_TYPE_NEARLINK", DeviceType::DEVICE_TYPE_NEARLINK},
{"DEVICE_TYPE_SYSTEM_PRIVATE", DeviceType::DEVICE_TYPE_SYSTEM_PRIVATE},
{"DEVICE_TYPE_DEFAULT", DeviceType::DEVICE_TYPE_DEFAULT},
{"DEVICE_TYPE_NONE", DeviceType::DEVICE_TYPE_NONE}
};
static const std::unordered_map<DeviceType, std::string> gDeviceTypeToStringMap = {
{DeviceType::DEVICE_TYPE_INVALID, "DEVICE_TYPE_INVALID"},
{DeviceType::DEVICE_TYPE_EARPIECE, "DEVICE_TYPE_EARPIECE"},
{DeviceType::DEVICE_TYPE_SPEAKER, "DEVICE_TYPE_SPEAKER"},
{DeviceType::DEVICE_TYPE_WIRED_HEADSET, "DEVICE_TYPE_WIRED_HEADSET"},
{DeviceType::DEVICE_TYPE_WIRED_HEADPHONES, "DEVICE_TYPE_WIRED_HEADPHONES"},
{DeviceType::DEVICE_TYPE_BLUETOOTH_SCO, "DEVICE_TYPE_BLUETOOTH_SCO"},
{DeviceType::DEVICE_TYPE_BLUETOOTH_A2DP, "DEVICE_TYPE_BLUETOOTH_A2DP"},
{DeviceType::DEVICE_TYPE_MIC, "DEVICE_TYPE_MIC"},
{DeviceType::DEVICE_TYPE_USB_HEADSET, "DEVICE_TYPE_USB_HEADSET"},
{DeviceType::DEVICE_TYPE_DP, "DEVICE_TYPE_DP"},
{DeviceType::DEVICE_TYPE_REMOTE_CAST, "DEVICE_TYPE_REMOTE_CAST"},
{DeviceType::DEVICE_TYPE_USB_DEVICE, "DEVICE_TYPE_USB_DEVICE"},
{DeviceType::DEVICE_TYPE_HDMI, "DEVICE_TYPE_HDMI"},
{DeviceType::DEVICE_TYPE_LINE_DIGITAL, "DEVICE_TYPE_LINE_DIGITAL"},
{DeviceType::DEVICE_TYPE_REMOTE_DAUDIO, "DEVICE_TYPE_REMOTE_DAUDIO"},
{DeviceType::DEVICE_TYPE_HEARING_AID, "DEVICE_TYPE_HEARING_AID"},
{DeviceType::DEVICE_TYPE_NEARLINK, "DEVICE_TYPE_NEARLINK"},
{DeviceType::DEVICE_TYPE_SYSTEM_PRIVATE, "DEVICE_TYPE_SYSTEM_PRIVATE"},
{DeviceType::DEVICE_TYPE_DEFAULT, "DEVICE_TYPE_DEFAULT"},
{DeviceType::DEVICE_TYPE_NONE, "DEVICE_TYPE_NONE"}
};
static const std::unordered_map<std::string, DeviceFlag> gDeviceFlagMap = {
{"OUTPUT_DEVICES_FLAG", DeviceFlag::OUTPUT_DEVICES_FLAG},
{"INPUT_DEVICES_FLAG", DeviceFlag::INPUT_DEVICES_FLAG},
{"ALL_DEVICES_FLAG", DeviceFlag::ALL_DEVICES_FLAG}
};
AudioVolumeType ParseVolumeType(const std::string& typeStr)
{
auto it = gVolumeTypeMap.find(typeStr);
if (it != gVolumeTypeMap.end()) {
return it->second;
}
return AudioVolumeType::STREAM_MUSIC;
}
DeviceType ParseDeviceType(const std::string& typeStr)
{
auto it = gDeviceTypeMap.find(typeStr);
if (it != gDeviceTypeMap.end()) {
return it->second;
}
return DeviceType::DEVICE_TYPE_NONE;
}
DeviceFlag ParseDeviceFlag(const std::string& flagStr)
{
auto it = gDeviceFlagMap.find(flagStr);
if (it != gDeviceFlagMap.end()) {
return it->second;
}
return DeviceFlag::OUTPUT_DEVICES_FLAG;
}
std::string VolumeTypeToString(AudioVolumeType type)
{
auto it = gVolumeTypeToStringMap.find(type);
if (it != gVolumeTypeToStringMap.end()) {
return it->second;
}
return "STREAM_MUSIC";
}
std::string DeviceTypeToString(DeviceType type)
{
auto it = gDeviceTypeToStringMap.find(type);
if (it != gDeviceTypeToStringMap.end()) {
return it->second;
}
return "DEVICE_TYPE_NONE";
}
int CmdGetVolume(int argc, char** argv)
{
AudioVolumeType volumeType = AudioVolumeType::STREAM_MUSIC;
std::string typeStr = "STREAM_MUSIC";
bool hasTypeParam = false;
const char* validTypes = "Check if volume type is valid";
for (int i = 0; i < argc; i++) {
if (strcmp(argv[i], "--type") == 0 && i + 1 < argc) {
typeStr = argv[i + 1];
hasTypeParam = true;
}
}
if (hasTypeParam) {
auto it = gVolumeTypeMap.find(typeStr);
if (it == gVolumeTypeMap.end()) {
return OutputError("ERR_INVALID_ARG", "Invalid volume type: " + typeStr, validTypes);
}
volumeType = it->second;
}
AudioSystemManager* manager = AudioSystemManager::GetInstance();
if (manager == nullptr) {
return OutputError("ERR_INTERNAL_ERROR", "Failed to get AudioSystemManager instance",
"Check if audio service is running");
}
int32_t volume = manager->GetVolume(volumeType);
if (volume < MIN_VOLUME) {
return OutputError("ERR_INTERNAL_ERROR", "Failed to get volume",
"Check if audio service is running and volume type is valid");
}
json result;
result["volumeType"] = VolumeTypeToString(volumeType);
result["volume"] = volume;
return OutputSuccess(result);
}
bool IsAlarmOrCallVolumeType(AudioVolumeType volumeType)
{
return volumeType == AudioVolumeType::STREAM_ALARM ||
volumeType == AudioVolumeType::STREAM_VOICE_CALL ||
volumeType == AudioVolumeType::STREAM_VOICE_COMMUNICATION ||
volumeType == AudioVolumeType::STREAM_ALL;
}
int ParseVolumeArgs(int argc, char** argv, AudioVolumeType& volumeType, int32_t& volume)
{
std::string typeStr = "STREAM_MUSIC";
bool hasTypeParam = false;
bool hasVolumeParam = false;
const char* validTypes = "Check if volume type is valid";
for (int i = 0; i < argc; i++) {
if (strcmp(argv[i], "--type") == 0 && i + 1 < argc) {
typeStr = argv[i + 1];
hasTypeParam = true;
} else if (strcmp(argv[i], "--volume") == 0 && i + 1 < argc) {
volume = atoi(argv[i + 1]);
hasVolumeParam = true;
}
}
if (!hasVolumeParam) {
return OutputError("ERR_ARG_MISSING", "Missing required parameter: --volume",
"Please provide volume value. Example: --volume 50");
}
if (volume < MIN_VOLUME || volume > MAX_VOLUME) {
return OutputError("ERR_INVALID_ARG", "Volume must be between 0 and 15",
"Please provide a volume value in the range 0-15");
}
if (hasTypeParam) {
auto it = gVolumeTypeMap.find(typeStr);
if (it == gVolumeTypeMap.end()) {
return OutputError("ERR_INVALID_ARG", "Invalid volume type: " + typeStr, validTypes);
}
volumeType = it->second;
}
if (volume == MIN_VOLUME && IsAlarmOrCallVolumeType(volumeType)) {
return OutputError("ERR_INVALID_ARG", "Cannot set alarm or call volume to 0",
"Alarm and call volumes must be at least 1");
}
return SUCCESS;
}
int CmdSetVolume(int argc, char** argv)
{
AudioVolumeType volumeType = AudioVolumeType::STREAM_MUSIC;
int32_t volume = -1;
int parseResult = ParseVolumeArgs(argc, argv, volumeType, volume);
if (parseResult != SUCCESS) {
return parseResult;
}
AudioSystemManager* manager = AudioSystemManager::GetInstance();
if (manager == nullptr) {
return OutputError("ERR_INTERNAL_ERROR", "Failed to get AudioSystemManager instance",
"Check if audio service is running");
}
int32_t result = manager->SetVolume(volumeType, volume);
if (result != SUCCESS) {
return OutputError("ERR_PERMISSION_DENIED",
"Failed to set volume. System permission may be required",
"Check if the process has system permission or volume value is valid");
}
json resultJson;
resultJson["volumeType"] = VolumeTypeToString(volumeType);
resultJson["volume"] = volume;
return OutputSuccess(resultJson);
}
int CmdGetMaxVolume(int argc, char** argv)
{
AudioVolumeType volumeType = AudioVolumeType::STREAM_MUSIC;
std::string typeStr = "STREAM_MUSIC";
bool hasTypeParam = false;
const char* validTypes = "Check if volume type is valid";
for (int i = 0; i < argc; i++) {
if (strcmp(argv[i], "--type") == 0 && i + 1 < argc) {
typeStr = argv[i + 1];
hasTypeParam = true;
}
}
if (hasTypeParam) {
auto it = gVolumeTypeMap.find(typeStr);
if (it == gVolumeTypeMap.end()) {
return OutputError("ERR_INVALID_ARG", "Invalid volume type: " + typeStr, validTypes);
}
volumeType = it->second;
}
AudioSystemManager* manager = AudioSystemManager::GetInstance();
if (manager == nullptr) {
return OutputError("ERR_INTERNAL_ERROR", "Failed to get AudioSystemManager instance",
"Check if audio service is running");
}
int32_t maxVolume = manager->GetMaxVolume(volumeType);
if (maxVolume < MIN_VOLUME) {
return OutputError("ERR_INTERNAL_ERROR", "Failed to get max volume",
"Check if audio service is running and volume type is valid");
}
json result;
result["volumeType"] = VolumeTypeToString(volumeType);
result["maxVolume"] = maxVolume;
return OutputSuccess(result);
}
int CmdIsMute(int argc, char** argv)
{
AudioVolumeType volumeType = AudioVolumeType::STREAM_MUSIC;
std::string typeStr = "STREAM_MUSIC";
bool hasTypeParam = false;
const char* validTypes = "Check if volume type is valid";
for (int i = 0; i < argc; i++) {
if (strcmp(argv[i], "--type") == 0 && i + 1 < argc) {
typeStr = argv[i + 1];
hasTypeParam = true;
}
}
if (hasTypeParam) {
auto it = gVolumeTypeMap.find(typeStr);
if (it == gVolumeTypeMap.end()) {
return OutputError("ERR_INVALID_ARG", "Invalid volume type: " + typeStr, validTypes);
}
volumeType = it->second;
}
AudioSystemManager* manager = AudioSystemManager::GetInstance();
if (manager == nullptr) {
return OutputError("ERR_INTERNAL_ERROR", "Failed to get AudioSystemManager instance",
"Check if audio service is running");
}
bool isMute = manager->IsStreamMute(volumeType);
json result;
result["volumeType"] = VolumeTypeToString(volumeType);
result["isMute"] = isMute;
return OutputSuccess(result);
}
int ParseMuteArgs(int argc, char** argv, AudioVolumeType& volumeType, bool& mute)
{
std::string typeStr = "STREAM_MUSIC";
bool hasTypeParam = false;
const char* validTypes = "Check if volume type is valid";
for (int i = 0; i < argc; i++) {
if (strcmp(argv[i], "--type") == 0 && i + 1 < argc) {
typeStr = argv[i + 1];
hasTypeParam = true;
} else if (strcmp(argv[i], "--mute") == 0) {
if (i + 1 < argc && argv[i + 1][0] != '-') {
mute = (strcmp(argv[i + 1], "true") == 0 || strcmp(argv[i + 1], "1") == 0);
} else {
mute = true;
}
}
}
if (hasTypeParam) {
auto it = gVolumeTypeMap.find(typeStr);
if (it == gVolumeTypeMap.end()) {
return OutputError("ERR_INVALID_ARG", "Invalid volume type: " + typeStr, validTypes);
}
volumeType = it->second;
}
if (mute && IsAlarmOrCallVolumeType(volumeType)) {
return OutputError("ERR_INVALID_ARG", "Cannot mute alarm or call volume",
"Alarm and call volumes cannot be muted");
}
return SUCCESS;
}
int CmdSetMute(int argc, char** argv)
{
AudioVolumeType volumeType = AudioVolumeType::STREAM_MUSIC;
bool mute = false;
int parseResult = ParseMuteArgs(argc, argv, volumeType, mute);
if (parseResult != SUCCESS) {
return parseResult;
}
AudioSystemManager* manager = AudioSystemManager::GetInstance();
if (manager == nullptr) {
return OutputError("ERR_INTERNAL_ERROR", "Failed to get AudioSystemManager instance",
"Check if audio service is running");
}
int32_t result = manager->SetMute(volumeType, mute);
if (result != SUCCESS) {
return OutputError("ERR_PERMISSION_DENIED",
"Failed to set mute. Permission may be required for STREAM_RING or STREAM_VOICE_RING type",
"Check if the process has required permissions. STREAM_RING and STREAM_VOICE_RING types "
"require ACCESS_NOTIFICATION_POLICY_PERMISSION");
}
json resultJson;
resultJson["volumeType"] = VolumeTypeToString(volumeType);
resultJson["mute"] = mute;
return OutputSuccess(resultJson);
}
int CmdGetDevices(int argc, char** argv)
{
DeviceFlag deviceFlag = DeviceFlag::OUTPUT_DEVICES_FLAG;
std::string flagStr = "OUTPUT_DEVICES_FLAG";
bool hasFlagParam = false;
for (int i = 0; i < argc; i++) {
if (strcmp(argv[i], "--flag") == 0 && i + 1 < argc) {
flagStr = argv[i + 1];
hasFlagParam = true;
}
}
if (hasFlagParam) {
auto it = gDeviceFlagMap.find(flagStr);
if (it == gDeviceFlagMap.end()) {
return OutputError("ERR_INVALID_ARG", "Invalid device flag: " + flagStr,
"Valid: OUTPUT_DEVICES_FLAG, INPUT_DEVICES_FLAG, ALL_DEVICES_FLAG");
}
deviceFlag = it->second;
}
AudioSystemManager* manager = AudioSystemManager::GetInstance();
if (manager == nullptr) {
return OutputError("ERR_INTERNAL_ERROR", "Failed to get AudioSystemManager instance",
"Check if audio service is running");
}
std::vector<std::shared_ptr<AudioDeviceDescriptor>> devices = manager->GetDevices(deviceFlag);
json result;
result["deviceFlag"] = static_cast<int>(deviceFlag);
result["devices"] = json::array();
for (const auto& device : devices) {
json deviceJson;
deviceJson["deviceType"] = static_cast<int>(device->deviceType_);
result["devices"].push_back(deviceJson);
}
return OutputSuccess(result);
}
int CmdSelectOutputDevice(int argc, char** argv)
{
std::vector<std::shared_ptr<AudioDeviceDescriptor>> audioDeviceDescriptors;
for (int i = 0; i < argc; i++) {
if (strcmp(argv[i], "--type") == 0 && i + 1 < argc) {
DeviceType deviceType = ParseDeviceType(argv[i + 1]);
auto descriptor = std::make_shared<AudioDeviceDescriptor>();
descriptor->deviceType_ = deviceType;
audioDeviceDescriptors.push_back(descriptor);
}
}
if (audioDeviceDescriptors.empty()) {
return OutputError("ERR_ARG_MISSING", "Missing required parameter: --type",
"Please provide at least one device type. Example: --type DEVICE_TYPE_SPEAKER");
}
AudioSystemManager* manager = AudioSystemManager::GetInstance();
if (manager == nullptr) {
return OutputError("ERR_INTERNAL_ERROR", "Failed to get AudioSystemManager instance",
"Check if audio service is running");
}
int32_t result = manager->SelectOutputDevice(audioDeviceDescriptors);
if (result != SUCCESS) {
return OutputError("ERR_PERMISSION_DENIED", "Failed to select output device. "
"System permission is required",
"Check if the process has system permission and device type is valid");
}
json resultJson;
resultJson["devices"] = json::array();
for (const auto& device : audioDeviceDescriptors) {
resultJson["devices"].push_back(static_cast<int>(device->deviceType_));
}
return OutputSuccess(resultJson);
}
void ShowGeneralHelp()
{
CLI_LOG("%s - %s", G_PROGRAM_NAME, G_TOOL_DESCRIPTION);
CLI_LOG("");
CLI_LOG("Usage:");
CLI_LOG(" %s [command] [options]", G_PROGRAM_NAME);
CLI_LOG("");
CLI_LOG("Parameters:");
CLI_LOG(" --help Display this help message");
CLI_LOG("");
CLI_LOG("SubCommands:");
for (const auto& pair : gCommands) {
CLI_LOG(" %-22s %s", pair.first.c_str(),
pair.second.details.description ? pair.second.details.description : "");
}
CLI_LOG("");
CLI_LOG("Examples:");
CLI_LOG(" %s --help", G_PROGRAM_NAME);
for (const auto& pair : gCommands) {
if (strcmp(pair.first.c_str(), "help") != 0) {
CLI_LOG(" %s %s --help", G_PROGRAM_NAME, pair.first.c_str());
break;
}
}
}
void ShowCommandHelp(const Command& cmd)
{
CLI_LOG("%s %s - %s", G_PROGRAM_NAME, cmd.name,
cmd.details.description ? cmd.details.description : "N/A");
if (cmd.details.usage) {
CLI_LOG("");
CLI_LOG("Usage:");
CLI_LOG(" %s", cmd.details.usage);
}
if (cmd.details.parameters) {
CLI_LOG("");
CLI_LOG("Parameters:");
CLI_LOG("%s", cmd.details.parameters);
}
CLI_LOG(" --help Display this help message");
if (cmd.details.examples) {
CLI_LOG("");
CLI_LOG("Examples:");
CLI_LOG("%s", cmd.details.examples);
}
}
int CmdHelp(int argc, char** argv)
{
std::string targetCmd;
for (int i = INT_NUM1; i < argc; i++) {
if (argv[i][0] != '-') {
targetCmd = argv[i];
break;
}
}
if (targetCmd.empty()) {
ShowGeneralHelp();
return SUCCESS;
}
auto it = gCommands.find(targetCmd);
if (it == gCommands.end()) {
json response;
response["status"] = "failed";
response["errCode"] = "ERR_INVALID_COMMAND";
response["errMsg"] = "Unknown command: " + targetCmd;
std::cout << response.dump() << std::endl;
return FAILURE;
}
ShowCommandHelp(it->second);
return SUCCESS;
}
void RegisterHelpCommand()
{
CommandDetails details = {
"Show help information",
"ohos-audioManager help [command]",
" command Optional. Show detailed help for a specific command.",
" ohos-audioManager help\n"
" ohos-audioManager help get-volume"
};
RegisterCommand("help", details, CmdHelp);
}
void RegisterGetVolumeCommand()
{
CommandDetails details = {
"Get the current volume for a specific volume type",
"ohos-audioManager get-volume [--type <type>]",
" --type <type> Optional. Volume type. Values: [STREAM_MUSIC, STREAM_RING, "
"STREAM_VOICE_CALL, STREAM_VOICE_COMMUNICATION, STREAM_VOICE_ASSISTANT, STREAM_ALARM, "
"STREAM_SYSTEM, STREAM_VOICE_RING, STREAM_NAVIGATION, "
"STREAM_NOTIFICATION, STREAM_ULTRASONIC, STREAM_ANNOUNCEMENT, STREAM_EMERGENCY, "
"STREAM_ALL]. Default: STREAM_MUSIC",
" ohos-audioManager get-volume\n"
" ohos-audioManager get-volume --type STREAM_RING\n"
" ohos-audioManager get-volume --type STREAM_MUSIC"
};
RegisterCommand("get-volume", details, CmdGetVolume);
}
void RegisterSetVolumeCommand()
{
CommandDetails details = {
"Set the volume for a specific volume type",
"ohos-audioManager set-volume --volume <value> [--type <type>]",
" --volume <value> Required. Volume value to set (typically 0-100 or 0-15)\n"
" --type <type> Optional. Volume type. Values: [STREAM_MUSIC, STREAM_RING, "
"STREAM_VOICE_CALL, STREAM_VOICE_COMMUNICATION, STREAM_VOICE_ASSISTANT, STREAM_ALARM, "
"STREAM_SYSTEM, STREAM_VOICE_RING, STREAM_NAVIGATION, "
"STREAM_NOTIFICATION, STREAM_ULTRASONIC, STREAM_ANNOUNCEMENT, STREAM_EMERGENCY, "
"STREAM_ALL]. Default: STREAM_MUSIC",
" ohos-audioManager set-volume --volume 50\n"
" ohos-audioManager set-volume --volume 10 --type STREAM_RING\n"
" ohos-audioManager set-volume --volume 80 --type STREAM_MUSIC"
};
RegisterCommand("set-volume", details, CmdSetVolume);
}
void RegisterGetMaxVolumeCommand()
{
CommandDetails details = {
"Get the maximum volume for a specific volume type",
"ohos-audioManager get-max-volume [--type <type>]",
" --type <type> Optional. Volume type. Values: [STREAM_MUSIC, STREAM_RING, "
"STREAM_VOICE_CALL, STREAM_VOICE_COMMUNICATION, STREAM_VOICE_ASSISTANT, STREAM_ALARM, "
"STREAM_SYSTEM, STREAM_VOICE_RING, STREAM_NAVIGATION, "
"STREAM_NOTIFICATION, STREAM_ULTRASONIC, STREAM_ANNOUNCEMENT, STREAM_EMERGENCY, "
"STREAM_ALL]. Default: STREAM_MUSIC",
" ohos-audioManager get-max-volume\n"
" ohos-audioManager get-max-volume --type STREAM_RING\n"
" ohos-audioManager get-max-volume --type STREAM_MUSIC"
};
RegisterCommand("get-max-volume", details, CmdGetMaxVolume);
}
void RegisterIsMuteCommand()
{
CommandDetails details = {
"Check if a specific volume type is muted",
"ohos-audioManager is-mute [--type <type>]",
" --type <type> Optional. Volume type. Values: [STREAM_MUSIC, STREAM_RING, "
"STREAM_VOICE_CALL, STREAM_VOICE_COMMUNICATION, STREAM_VOICE_ASSISTANT, STREAM_ALARM, "
"STREAM_SYSTEM, STREAM_VOICE_RING, STREAM_NAVIGATION, "
"STREAM_NOTIFICATION, STREAM_ULTRASONIC, STREAM_ANNOUNCEMENT, STREAM_EMERGENCY, "
"STREAM_ALL]. Default: STREAM_MUSIC",
" ohos-audioManager is-mute\n"
" ohos-audioManager is-mute --type STREAM_RING\n"
" ohos-audioManager is-mute --type STREAM_MUSIC"
};
RegisterCommand("is-mute", details, CmdIsMute);
}
void RegisterSetMuteCommand()
{
CommandDetails details = {
"Set the mute state for a specific volume type",
"ohos-audioManager set-mute --mute <true|false> [--type <type>]",
" --mute <true|false> Required. Mute state: true to mute, false to unmute\n"
" --type <type> Optional. Volume type. Values: [STREAM_MUSIC, STREAM_RING, "
"STREAM_VOICE_CALL, STREAM_VOICE_COMMUNICATION, STREAM_VOICE_ASSISTANT, STREAM_ALARM, "
"STREAM_SYSTEM, STREAM_VOICE_RING, STREAM_NAVIGATION, "
"STREAM_NOTIFICATION, STREAM_ULTRASONIC, STREAM_ANNOUNCEMENT, STREAM_EMERGENCY, "
"STREAM_ALL]. Default: STREAM_MUSIC",
" ohos-audioManager set-mute --mute true\n"
" ohos-audioManager set-mute --mute false --type STREAM_RING\n"
" ohos-audioManager set-mute --mute true --type STREAM_MUSIC"
};
RegisterCommand("set-mute", details, CmdSetMute);
}
void RegisterGetDevicesCommand()
{
CommandDetails details = {
"Get the list of audio devices",
"ohos-audioManager get-devices [--flag <flag>]",
" --flag <flag> Optional. Device flag. Values: [OUTPUT_DEVICES_FLAG, "
"INPUT_DEVICES_FLAG, ALL_DEVICES_FLAG]. Default: OUTPUT_DEVICES_FLAG",
" ohos-audioManager get-devices\n"
" ohos-audioManager get-devices --flag OUTPUT_DEVICES_FLAG\n"
" ohos-audioManager get-devices --flag INPUT_DEVICES_FLAG"
};
RegisterCommand("get-devices", details, CmdGetDevices);
}
void RegisterSelectOutputDeviceCommand()
{
CommandDetails details = {
"Select the output audio device",
"ohos-audioManager select-output-device --type <deviceType>",
" --type <deviceType> Required. Device type. Values: [DEVICE_TYPE_INVALID, "
"DEVICE_TYPE_EARPIECE, DEVICE_TYPE_SPEAKER, DEVICE_TYPE_WIRED_HEADSET, "
"DEVICE_TYPE_WIRED_HEADPHONES, DEVICE_TYPE_BLUETOOTH_SCO, DEVICE_TYPE_BLUETOOTH_A2DP, "
"DEVICE_TYPE_MIC, DEVICE_TYPE_USB_HEADSET, DEVICE_TYPE_DP, DEVICE_TYPE_REMOTE_CAST, "
"DEVICE_TYPE_USB_DEVICE, DEVICE_TYPE_HDMI, DEVICE_TYPE_LINE_DIGITAL, "
"DEVICE_TYPE_REMOTE_DAUDIO, DEVICE_TYPE_HEARING_AID, DEVICE_TYPE_NEARLINK, "
"DEVICE_TYPE_SYSTEM_PRIVATE, DEFAULT]. Can be specified multiple times",
" ohos-audioManager select-output-device --type DEVICE_TYPE_SPEAKER\n"
" ohos-audioManager select-output-device --type DEVICE_TYPE_BLUETOOTH_A2DP\n"
" ohos-audioManager select-output-device --type DEFAULT"
};
RegisterCommand("select-output-device", details, CmdSelectOutputDevice);
}
void InitCommands()
{
RegisterHelpCommand();
RegisterGetVolumeCommand();
RegisterSetVolumeCommand();
RegisterGetMaxVolumeCommand();
RegisterIsMuteCommand();
RegisterSetMuteCommand();
RegisterGetDevicesCommand();
RegisterSelectOutputDeviceCommand();
g_hasSubCommand = (gCommands.size() > INT_NUM1);
}
void PrintUsage(const char* prog)
{
CLI_ERROR("Usage: %s <command> [options...]", prog);
CLI_ERROR("Run '%s help' for more information", prog);
}
int main(int argc, char** argv)
{
G_PROGRAM_NAME = argv[0];
if (argc >= INT_NUM2 && strcmp(argv[1], "--help") == 0) {
InitCommands();
char* helpArgv[2] = {argv[0], nullptr};
CmdHelp(INT_NUM1, helpArgv);
return SUCCESS;
}
if (argc < INT_NUM2) {
PrintUsage(argv[0]);
return FAILURE;
}
InitCommands();
std::string cmdName = argv[1];
for (int i = INT_NUM2; i < argc; i++) {
if (strcmp(argv[i], "--help") == 0) {
char* helpArgv[2] = {argv[0], const_cast<char*>(cmdName.c_str())};
CmdHelp(INT_NUM2, helpArgv);
return SUCCESS;
}
}
auto it = gCommands.find(cmdName);
if (it == gCommands.end()) {
OutputError("ERR_INVALID_COMMAND", "Unknown command: " + cmdName,
"Use --help to see available commands");
return FAILURE;
}
return it->second.handler(argc - INT_NUM2, argv + INT_NUM2);
}