URY playd
C++ minimalist audio player
main.cpp File Reference

Main entry point and implementation of the playd class. More...

#include <algorithm>
#include <cstdint>
#include <iostream>
#include <tuple>
#include "io.hpp"
#include "response.hpp"
#include "player.hpp"
#include "messages.h"
+ Include dependency graph for main.cpp:

Go to the source code of this file.

Functions

std::vector< std::string > MakeArgVector (int argc, char *argv[])
 Creates a vector of strings from a C-style argument vector. More...
 
int GetDeviceID (const std::vector< std::string > &args)
 Tries to get the output device ID from program arguments. More...
 
void ExitWithUsage (const std::string &progname)
 Reports usage information and exits. More...
 
std::pair< std::string, std::string > GetHostAndPort (const std::vector< std::string > &args)
 Gets the host and port from the program arguments. More...
 
void ExitWithNetError (const std::string &host, const std::string &port, const std::string &msg)
 Exits with an error message for a network error. More...
 
void ExitWithError (const std::string &msg)
 Exits with an error message for an unhandled exception. More...
 
int main (int argc, char *argv[])
 The main entry point. More...
 

Detailed Description

Main entry point and implementation of the playd class.

See also
main.cpp

Definition in file main.cpp.

Function Documentation

§ ExitWithError()

void ExitWithError ( const std::string &  msg)

Exits with an error message for an unhandled exception.

Parameters
msgThe exception's error message.

Definition at line 138 of file main.cpp.

Referenced by main().

139 {
140  std::cerr << "Unhandled exception in main loop: " << msg << std::endl;
141  exit(EXIT_FAILURE);
142 }

§ ExitWithNetError()

void ExitWithNetError ( const std::string &  host,
const std::string &  port,
const std::string &  msg 
)

Exits with an error message for a network error.

Parameters
hostThe IP host to which playd tried to bind.
portThe TCP port to which playd tried to bind.
msgThe exception's error message.

Definition at line 126 of file main.cpp.

Referenced by main().

128 {
129  std::cerr << "Network error: " << msg << "\n";
130  std::cerr << "Is " << host << ":" << port << " available?\n";
131  exit(EXIT_FAILURE);
132 }

§ ExitWithUsage()

void ExitWithUsage ( const std::string &  progname)

Reports usage information and exits.

Parameters
prognameThe name of the program as executed.

Definition at line 88 of file main.cpp.

References SdlAudioSink::GetDevicesInfo().

Referenced by main().

89 {
90  std::cerr << "usage: " << progname << " ID [HOST] [PORT]\n";
91  std::cerr << "where ID is one of the following numbers:\n";
92 
93  // Show the user the valid device IDs they can use.
94  auto device_list = SdlAudioSink::GetDevicesInfo();
95  for (const auto &device : device_list) {
96  std::cerr << "\t" << device.first << ": " << device.second
97  << "\n";
98  }
99 
100  std::cerr << "default HOST: " << DEFAULT_HOST << "\n";
101  std::cerr << "default PORT: " << DEFAULT_PORT << "\n";
102 
103  exit(EXIT_FAILURE);
104 }
static std::vector< std::pair< int, std::string > > GetDevicesInfo()
Gets the number and name of each output device entry in the AudioSystem.
Definition: audio_sink.cpp:241

§ GetDeviceID()

int GetDeviceID ( const std::vector< std::string > &  args)

Tries to get the output device ID from program arguments.

Parameters
argsThe program argument vector.
Returns
The device ID, -1 if invalid selection (or none).

Definition at line 64 of file main.cpp.

References SdlAudioSink::IsOutputDevice().

Referenced by main().

65 {
66  // Did the user provide an ID at all?
67  if (args.size() < 2) return -1;
68 
69  // Only accept valid numbers (stoi will throw for invalid ones).
70  int id;
71  try {
72  id = std::stoi(args.at(1));
73  } catch (...) {
74  // Only std::{invalid_argument,out_of_range} are thrown here.
75  return -1;
76  }
77 
78  // Only allow valid, outputtable devices; reject input-only devices.
79  if (!SdlAudioSink::IsOutputDevice(id)) return -1;
80 
81  return id;
82 }
static bool IsOutputDevice(int id)
Can a sound device output sound?
Definition: audio_sink.cpp:255

§ GetHostAndPort()

std::pair<std::string, std::string> GetHostAndPort ( const std::vector< std::string > &  args)

Gets the host and port from the program arguments.

The default arguments are used if the host and/or port are not supplied.

Parameters
argsThe program argument vector.
Returns
A pair of strings representing the hostname and port.

Definition at line 112 of file main.cpp.

Referenced by main().

114 {
115  auto size = args.size();
116  return std::make_pair(size > 2 ? args.at(2) : DEFAULT_HOST,
117  size > 3 ? args.at(3) : DEFAULT_PORT);
118 }

§ main()

int main ( int  argc,
char *  argv[] 
)

The main entry point.

Parameters
argcProgram argument count.
argvProgram argument vector.
Returns
The exit code (zero for success; non-zero otherwise).

Definition at line 150 of file main.cpp.

References SdlAudioSink::CleanupLibrary(), ExitWithError(), ExitWithNetError(), ExitWithUsage(), GetDeviceID(), GetHostAndPort(), SdlAudioSink::InitLibrary(), MakeArgVector(), Error::Message(), and IoCore::Run().

151 {
152 #ifndef _MSC_VER
153  // If we don't ignore SIGPIPE, certain classes of connection droppage
154  // will crash our program with it.
155  // TODO(CaptainHayashi): a more rigorous ifndef here.
156  signal(SIGPIPE, SIG_IGN);
157 #endif
158 
159  // SDL requires some cleanup and teardown.
160  // This call needs to happen before GetDeviceID, otherwise no device
161  // IDs will be recognised. (This is why it's here, and not in
162  // SetupAudioSystem.)
165 
166 #ifdef WITH_MP3
167  // mpg123 insists on us running its init and exit functions, too.
168  mpg123_init();
169  atexit(mpg123_exit);
170 #endif // WITH_MP3
171 
172  auto args = MakeArgVector(argc, argv);
173 
174  auto device_id = GetDeviceID(args);
175  if (device_id < 0) ExitWithUsage(args.at(0));
176 
177  Player player(device_id,
178  &std::make_unique<SdlAudioSink, const AudioSource &, int>,
179  SOURCES);
180 
181  // Set up the IO now (to avoid a circular dependency).
182  // Make sure the player broadcasts its responses back to the IoCore.
183  IoCore io(player);
184  player.SetIo(io);
185 
186  // Now, actually run the IO loop.
187  std::string host;
188  std::string port;
189  std::tie(host, port) = GetHostAndPort(args);
190  try {
191  io.Run(host, port);
192  } catch (NetError &e) {
193  ExitWithNetError(host, port, e.Message());
194  } catch (Error &e) {
195  ExitWithError(e.Message());
196  }
197 
198  return EXIT_SUCCESS;
199 }
static void CleanupLibrary()
Cleans up the AudioSink&#39;s libraries, if not cleaned up already.
Definition: audio_sink.cpp:109
A playd exception.
Definition: errors.hpp:19
const std::string & Message() const
The human-readable message for this error.
Definition: errors.cpp:16
void ExitWithNetError(const std::string &host, const std::string &port, const std::string &msg)
Exits with an error message for a network error.
Definition: main.cpp:126
std::pair< std::string, std::string > GetHostAndPort(const std::vector< std::string > &args)
Gets the host and port from the program arguments.
Definition: main.cpp:112
static void InitLibrary()
Initialises the AudioSink&#39;s libraries, if not initialised already.
Definition: audio_sink.cpp:101
int GetDeviceID(const std::vector< std::string > &args)
Tries to get the output device ID from program arguments.
Definition: main.cpp:64
A network error.
Definition: errors.hpp:105
void ExitWithError(const std::string &msg)
Exits with an error message for an unhandled exception.
Definition: main.cpp:138
std::vector< std::string > MakeArgVector(int argc, char *argv[])
Creates a vector of strings from a C-style argument vector.
Definition: main.cpp:52
void ExitWithUsage(const std::string &progname)
Reports usage information and exits.
Definition: main.cpp:88
A Player contains a loaded audio file and a command API for manipulating it.
Definition: player.hpp:31
The IO core, which services input, routes responses, and executes the Player update routine periodica...
Definition: io.hpp:39

§ MakeArgVector()

std::vector<std::string> MakeArgVector ( int  argc,
char *  argv[] 
)

Creates a vector of strings from a C-style argument vector.

Parameters
argcProgram argument count.
argvProgram argument vector.
Returns
The argument vector, as a C++ string vector.

Definition at line 52 of file main.cpp.

Referenced by main().

53 {
54  std::vector<std::string> args;
55  for (int i = 0; i < argc; i++) args.emplace_back(argv[i]);
56  return args;
57 }