asctl.cpp 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. /*
  2. * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
  3. * Copyright (c) 2021, kleines Filmröllchen <malu.bertsch@gmail.com>
  4. *
  5. * SPDX-License-Identifier: BSD-2-Clause
  6. */
  7. #include <AK/Variant.h>
  8. #include <AK/Vector.h>
  9. #include <LibAudio/Buffer.h>
  10. #include <LibAudio/ClientConnection.h>
  11. #include <LibCore/ArgsParser.h>
  12. #include <LibCore/EventLoop.h>
  13. #include <LibCore/File.h>
  14. #include <stdio.h>
  15. #include <sys/ioctl.h>
  16. enum AudioVariable : u32 {
  17. Volume,
  18. Mute,
  19. SampleRate
  20. };
  21. // asctl: audio server control utility
  22. int main(int argc, char** argv)
  23. {
  24. Core::EventLoop loop;
  25. auto audio_client = Audio::ClientConnection::construct();
  26. String command = String::empty();
  27. Vector<String> arguments;
  28. bool human_mode = false;
  29. Core::ArgsParser args_parser;
  30. args_parser.set_general_help("Send control signals to the audio server and hardware.");
  31. args_parser.add_option(human_mode, "Print human-readable output", "human-readable", 'h');
  32. args_parser.add_positional_argument(command, "Command, either (g)et or (s)et\n\n\tThe get command accepts a list of variables to print.\n\tThey are printed in the given order.\n\tIf no value is specified, all are printed.\n\n\tThe set command accepts a any number of variables\n\tfollowed by the value they should be set to.\n\n\tPossible variables are (v)olume, (m)ute, sample(r)ate.\n", "command");
  33. args_parser.add_positional_argument(arguments, "Arguments for the command", "args", Core::ArgsParser::Required::No);
  34. args_parser.parse(argc, argv);
  35. if (command.equals_ignoring_case("get") || command == "g") {
  36. // Get variables
  37. Vector<AudioVariable> values_to_print;
  38. if (arguments.is_empty()) {
  39. values_to_print.append(AudioVariable::Volume);
  40. values_to_print.append(AudioVariable::Mute);
  41. values_to_print.append(AudioVariable::SampleRate);
  42. } else {
  43. for (auto& variable : arguments) {
  44. if (variable.is_one_of("v"sv, "volume"sv))
  45. values_to_print.append(AudioVariable::Volume);
  46. else if (variable.is_one_of("m"sv, "mute"sv))
  47. values_to_print.append(AudioVariable::Mute);
  48. else if (variable.is_one_of("r"sv, "samplerate"sv))
  49. values_to_print.append(AudioVariable::SampleRate);
  50. else {
  51. warnln("Error: Unrecognized variable {}", variable);
  52. return 1;
  53. }
  54. }
  55. }
  56. for (auto to_print : values_to_print) {
  57. switch (to_print) {
  58. case AudioVariable::Volume: {
  59. i16 volume = audio_client->get_main_mix_volume();
  60. if (human_mode)
  61. outln("Volume: {:3d}%", volume);
  62. else
  63. out("{} ", volume);
  64. break;
  65. }
  66. case AudioVariable::Mute: {
  67. bool muted = audio_client->get_muted();
  68. if (human_mode)
  69. outln("Muted: {}", muted ? "Yes" : "No");
  70. else
  71. out("{} ", muted ? 1 : 0);
  72. break;
  73. }
  74. case AudioVariable::SampleRate: {
  75. u16 sample_rate = audio_client->get_sample_rate();
  76. if (human_mode)
  77. outln("Sample rate: {:5d} Hz", sample_rate);
  78. else
  79. out("{} ", sample_rate);
  80. break;
  81. }
  82. }
  83. }
  84. if (!human_mode)
  85. outln();
  86. } else if (command.equals_ignoring_case("set") || command == "s") {
  87. // Set variables
  88. HashMap<AudioVariable, Variant<int, bool>> values_to_set;
  89. for (size_t i = 0; i < arguments.size(); ++i) {
  90. if (i == arguments.size() - 1) {
  91. warnln("Error: value missing for last variable");
  92. return 1;
  93. }
  94. auto& variable = arguments[i];
  95. if (variable.is_one_of("v"sv, "volume"sv)) {
  96. auto volume = arguments[++i].to_int();
  97. if (!volume.has_value()) {
  98. warnln("Error: {} is not an integer volume", arguments[i - 1]);
  99. return 1;
  100. }
  101. values_to_set.set(AudioVariable::Volume, volume.value());
  102. } else if (variable.is_one_of("m"sv, "mute"sv)) {
  103. String& mute_text = arguments[++i];
  104. bool mute;
  105. if (mute_text.equals_ignoring_case("true") || mute_text == "1") {
  106. mute = true;
  107. } else if (mute_text.equals_ignoring_case("false") || mute_text == "0") {
  108. mute = false;
  109. } else {
  110. warnln("Error: {} is not one of {{0, 1, true, false}}", mute_text);
  111. return 1;
  112. }
  113. values_to_set.set(AudioVariable::Mute, mute);
  114. } else if (variable.is_one_of("r"sv, "samplerate"sv)) {
  115. auto sample_rate = arguments[++i].to_int();
  116. if (!sample_rate.has_value()) {
  117. warnln("Error: {} is not an integer sample rate", arguments[i - 1]);
  118. return 1;
  119. }
  120. values_to_set.set(AudioVariable::SampleRate, sample_rate.value());
  121. } else {
  122. warnln("Error: Unrecognized variable {}", arguments[i]);
  123. return 1;
  124. }
  125. }
  126. for (auto to_set : values_to_set) {
  127. switch (to_set.key) {
  128. case AudioVariable::Volume: {
  129. int& volume = to_set.value.get<int>();
  130. audio_client->set_main_mix_volume(volume);
  131. break;
  132. }
  133. case AudioVariable::Mute: {
  134. bool& mute = to_set.value.get<bool>();
  135. audio_client->set_muted(mute);
  136. break;
  137. }
  138. case AudioVariable::SampleRate: {
  139. int& sample_rate = to_set.value.get<int>();
  140. audio_client->set_sample_rate(sample_rate);
  141. break;
  142. }
  143. }
  144. }
  145. }
  146. return 0;
  147. }