diff options
| -rw-r--r-- | AudioPlayer.cpp | 43 | ||||
| -rw-r--r-- | AudioPlayer.h | 22 | ||||
| -rw-r--r-- | MIDIPlayer.cpp | 41 | ||||
| -rw-r--r-- | MIDIPlayer.h | 6 | ||||
| -rw-r--r-- | Makefile | 3 | ||||
| -rw-r--r-- | midiplay.cpp | 7 | 
6 files changed, 103 insertions, 19 deletions
| diff --git a/AudioPlayer.cpp b/AudioPlayer.cpp new file mode 100644 index 0000000..e60ae1d --- /dev/null +++ b/AudioPlayer.cpp @@ -0,0 +1,43 @@ +#include "AudioPlayer.h" + +#include <iostream> + +#include <fmt/format.h> + +namespace bp = boost::process; +namespace fs = std::filesystem; + +AudioPlayer::AudioPlayer(const fs::path& dir, const std::string& filename): m_dir(dir), m_file(filename) +{ +} + +void AudioPlayer::start() +{ +  if (m_child_audioplayer.valid() && m_child_audioplayer.running()) { +    stop(); +  } +  if (!m_file.empty()) { +    m_child_audioplayer = bp::child(fmt::format("aplay \"{}\"", (m_dir / m_file).string()).c_str());//, bp::std_out > bp::null); +    if (!m_child_audioplayer.valid() || !m_child_audioplayer.running()) { +      throw std::runtime_error("aplay not started"); +    } +  } +} + +void AudioPlayer::stop() +{ +  // note:: m_child_audioplayer.terminate() would kill via SIGKILL + +  if (m_child_audioplayer.valid()) { +    int result = kill(m_child_audioplayer.native_handle(), SIGTERM); +    if (result < 0) { +      std::cerr << "Error in AudioPlayer::stop(): kill() unsuccessful\n"; +    } +  } +} + +void AudioPlayer::set_file(const std::string& filename) +{ +  m_file = filename; +} + diff --git a/AudioPlayer.h b/AudioPlayer.h new file mode 100644 index 0000000..7f9c180 --- /dev/null +++ b/AudioPlayer.h @@ -0,0 +1,22 @@ +#pragma once + +#include <boost/process.hpp> + +#include <filesystem> + +class AudioPlayer +{ +public: +  AudioPlayer(const std::filesystem::path& dir, const std::string& filename); + +  void start(); + +  void stop(); + +  void set_file(const std::string& filename); + +private: +  std::filesystem::path m_dir; +  std::string m_file; +  boost::process::child m_child_audioplayer; +}; diff --git a/MIDIPlayer.cpp b/MIDIPlayer.cpp index cb6a6bf..6b07105 100644 --- a/MIDIPlayer.cpp +++ b/MIDIPlayer.cpp @@ -20,13 +20,23 @@ using namespace std::chrono_literals;  namespace {    std::unordered_set<std::string> supported_devices{"AudioBox 22 VSL", "CH345", "M2"}; + +  fs::path wav_from_midi(const fs::path& midipath) +  { +    fs::path result{midipath}; + +    result.replace_extension("wav"); + +    return result; +  }  }  MIDIPlayer::MIDIPlayer(Config& config):    m_config(config), -  m_child{}, +  m_child_midiplayer{},    m_dir{m_config.get_file_path()}, -  m_file{} +  m_file{}, +  m_audio_player{m_dir, m_file}  {    std::vector<std::string> list = get_filelist(); @@ -41,34 +51,37 @@ MIDIPlayer::MIDIPlayer(Config& config):  void MIDIPlayer::start()  { -  if (m_child.valid() && m_child.running()) { +  if (m_child_midiplayer.valid() && m_child_midiplayer.running()) {      stop(); -  } else { -    m_child = bp::child(fmt::format("aplaymidi-mp -c -p{} \"{}\"", m_client, (m_dir / m_file).string()).c_str());//, bp::std_out > bp::null); -    if (!m_child.valid() || !m_child.running()) { -      throw std::runtime_error("aplaymidi not started"); -    }    } +  m_child_midiplayer = bp::child(fmt::format("aplaymidi-mp -c -p{} \"{}\"", m_client, (m_dir / m_file).string()).c_str());//, bp::std_out > bp::null); +  if (!m_child_midiplayer.valid() || !m_child_midiplayer.running()) { +    throw std::runtime_error("aplaymidi not started"); +  } + +  m_audio_player.start();  }  void MIDIPlayer::stop()  { -  // note:: m_child.terminate() would kill via SIGKILL, preventing note offs +  // note:: m_child_midiplayer.terminate() would kill via SIGKILL -  if (m_child.valid()) { -    int result = kill(m_child.native_handle(), SIGTERM); +  if (m_child_midiplayer.valid()) { +    int result = kill(m_child_midiplayer.native_handle(), SIGTERM);      if (result < 0) {        std::cerr << "Error in MIDIPlayer::stop(): kill() unsuccessful\n";      }    } + +  m_audio_player.stop();  }  bool MIDIPlayer::is_playing()  { -  if (!m_child.valid()) { +  if (!m_child_midiplayer.valid()) {      return false;    } -  return m_child.running(); +  return m_child_midiplayer.running();  }  void MIDIPlayer::set_file(const std::string& filename) @@ -80,6 +93,8 @@ void MIDIPlayer::set_file(const std::string& filename)      std::this_thread::sleep_for(100ms);      start();    } + +  m_audio_player.set_file(wav_from_midi(filename));  }  std::string MIDIPlayer::get_file() diff --git a/MIDIPlayer.h b/MIDIPlayer.h index 8009029..2b3e994 100644 --- a/MIDIPlayer.h +++ b/MIDIPlayer.h @@ -1,5 +1,7 @@  #pragma once +#include "AudioPlayer.h" +  #include <string>  #include <vector> @@ -35,11 +37,13 @@ private:    void iterate_ports(void);    Config& m_config; -  boost::process::child m_child; +  boost::process::child m_child_midiplayer;    std::filesystem::path m_dir;    std::string m_file;    snd_seq_t* m_seq;    int m_client; + +  AudioPlayer m_audio_player;  }; @@ -3,6 +3,7 @@ TARGET=midiplay-fcgi  SRCS=\       midiplay.cpp \       MIDIPlayer.cpp \ +     AudioPlayer.cpp \       config.cpp \  OBJS=$(SRCS:.cpp=.o) @@ -19,7 +20,7 @@ CFLAGS=-Wall -g -O2 -fPIC  CFLAGS+=-gdwarf-4  CLIBS=-lasound -all: $(TARGET) aplaymidi-mp +all: $(TARGET) #aplaymidi-mp  run-fcgi:  	spawn-fcgi -a 127.0.0.1 -p 9090 -n -- ./midiplay-fcgi diff --git a/midiplay.cpp b/midiplay.cpp index 36b732e..534508f 100644 --- a/midiplay.cpp +++ b/midiplay.cpp @@ -103,10 +103,10 @@ int main(int argc, char* argv[]) {      while (FCGX_Accept_r(&request) == 0) {        std::string method = FCGX_GetParam("REQUEST_METHOD", request.envp); +      FCGX_PutS("Content-Type: text/xml\r\n\r\n", request.out); +        try {          if (method == "POST") { -          FCGX_PutS("Content-Type: text/xml\r\n\r\n", request.out); -            PostData data{request};            std::string command {getCommand(request)};            if (command == "start") { @@ -128,8 +128,7 @@ int main(int argc, char* argv[]) {            throw std::runtime_error(fmt::format("Bad request method: POST expected, got {}", method).c_str());          }        } catch (const std::exception& ex) { -        FCGX_PutS("Content-Type: text/xml\r\n\r\n", request.out); -        FCGX_PutS(("<data><status>error</status><message>"s + ex.what() + "</message></data>").c_str(), request.out); +        FCGX_PutS(("<data><status>error</status><message>Error: "s + ex.what() + "</message></data>").c_str(), request.out);        }      }    } catch (const std::exception& ex) { | 
