To play the music in the background, we add the subprocess function to call the music playback while the main function is still running to check the distance data from sensor in order to switch the music. when the distance reach the given range, the main function would create the subprocess to initial the music play thread.
class Popen
{
public:
friend struct detail::ArgumentDeducer;
friend class detail::Child;
template <typename... Args>
Popen(const std::string& cmd_args, Args&& ...args):
args_(cmd_args)
{
vargs_ = util::split(cmd_args);
init_args(std::forward<Args>(args)...);
// Setup the communication channels of the Popen class
stream_.setup_comm_channels();
if (!defer_process_start_) execute_process();
}
template <typename... Args>
Popen(std::initializer_list<const char*> cmd_args, Args&& ...args)
{
vargs_.insert(vargs_.end(), cmd_args.begin(), cmd_args.end());
init_args(std::forward<Args>(args)...);
// Setup the communication channels of the Popen class
stream_.setup_comm_channels();
if (!defer_process_start_) execute_process();
}
void start_process() noexcept(false);
int pid() const noexcept { return child_pid_; }
int retcode() const noexcept { return retcode_; }
int wait() noexcept(false);
int poll() noexcept(false);
// Does not fail, Caller is expected to recheck the
// status with a call to poll()
void kill(int sig_num = 9);
void set_out_buf_cap(size_t cap) { stream_.set_out_buf_cap(cap); }
void set_err_buf_cap(size_t cap) { stream_.set_err_buf_cap(cap); }
int send(const char* msg, size_t length)
{ return stream_.send(msg, length); }
int send(const std::vector<char>& msg)
{ return stream_.send(msg); }
std::pair<OutBuffer, ErrBuffer> communicate(const char* msg, size_t length)
{
auto res = stream_.communicate(msg, length);
retcode_ = wait();
return res;
}
std::pair<OutBuffer, ErrBuffer> communicate(const std::vector<char>& msg)
{
auto res = stream_.communicate(msg);
retcode_ = wait();
return res;
}
std::pair<OutBuffer, ErrBuffer> communicate()
{
return communicate(nullptr, 0);
}
FILE* input() { return stream_.input(); }
FILE* output() { return stream_.output();}
FILE* error() { return stream_.error(); }
/// Stream close APIs
void close_input() { stream_.input_.reset(); }
void close_output() { stream_.output_.reset(); }
void close_error() { stream_.error_.reset(); }
private:
template <typename F, typename... Args>
void init_args(F&& farg, Args&&... args);
void init_args();
void populate_c_argv();
void execute_process() noexcept(false);
private:
detail::Streams stream_;
bool defer_process_start_ = false;
bool close_fds_ = false;
bool has_preexec_fn_ = false;
bool shell_ = false;
bool session_leader_ = false;
std::string exe_name_;
std::string cwd_;
std::map<std::string, std::string> env_;
preexec_func preexec_fn_;
// Command in string format
std::string args_;
// Comamnd provided as sequence
std::vector<std::string> vargs_;
std::vector<char*> cargv_;
bool child_created_ = false;
// Pid of the child process
int child_pid_ = -1;
int retcode_ = -1;
};
inline void Popen::init_args() {
populate_c_argv();
}
template <typename F, typename... Args>
inline void Popen::init_args(F&& farg, Args&&... args)
{
detail::ArgumentDeducer argd(this);
argd.set_option(std::forward<F>(farg));
init_args(std::forward<Args>(args)...);
}
inline void Popen::populate_c_argv()
{
cargv_.clear();
cargv_.reserve(vargs_.size() + 1);
for (auto& arg : vargs_) cargv_.push_back(&arg[0]);
cargv_.push_back(nullptr);
}
Discussions
Become a Hackaday.io Member
Create an account to leave a comment. Already have an account? Log In.