diff options
Diffstat (limited to 'src/output/plugins/RecorderOutputPlugin.cxx')
-rw-r--r-- | src/output/plugins/RecorderOutputPlugin.cxx | 98 |
1 files changed, 62 insertions, 36 deletions
diff --git a/src/output/plugins/RecorderOutputPlugin.cxx b/src/output/plugins/RecorderOutputPlugin.cxx index 87e23f55a..39fbca6e9 100644 --- a/src/output/plugins/RecorderOutputPlugin.cxx +++ b/src/output/plugins/RecorderOutputPlugin.cxx @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright (C) 2003-2015 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -20,9 +20,13 @@ #include "config.h" #include "RecorderOutputPlugin.hxx" #include "../OutputAPI.hxx" +#include "../Wrapper.hxx" #include "encoder/EncoderPlugin.hxx" #include "encoder/EncoderList.hxx" #include "config/ConfigError.hxx" +#include "Log.hxx" +#include "fs/AllocatedPath.hxx" +#include "fs/FileSystem.hxx" #include "util/Error.hxx" #include "util/Domain.hxx" #include "system/fd_util.h" @@ -45,7 +49,7 @@ struct RecorderOutput { /** * The destination file name. */ - const char *path; + AllocatedPath path; /** * The destination file descriptor. @@ -58,7 +62,8 @@ struct RecorderOutput { char buffer[32768]; RecorderOutput() - :base(recorder_output_plugin) {} + :base(recorder_output_plugin), + path(AllocatedPath::Null()) {} bool Initialize(const config_param ¶m, Error &error_r) { return base.Configure(param, error_r); @@ -66,12 +71,17 @@ struct RecorderOutput { bool Configure(const config_param ¶m, Error &error); + bool Open(AudioFormat &audio_format, Error &error); + void Close(); + bool WriteToFile(const void *data, size_t length, Error &error); /** * Writes pending data from the encoder to the output file. */ bool EncoderToFile(Error &error); + + void SendTag(const Tag &tag); }; static constexpr Domain recorder_output_domain("recorder_output"); @@ -90,9 +100,10 @@ RecorderOutput::Configure(const config_param ¶m, Error &error) return false; } - path = param.GetBlockValue("path"); - if (path == nullptr) { - error.Set(config_domain, "'path' not configured"); + path = param.GetBlockPath("path", error); + if (path.IsNull()) { + if (!error.IsDefined()) + error.Set(config_domain, "'path' not configured"); return false; } @@ -151,7 +162,8 @@ RecorderOutput::WriteToFile(const void *_data, size_t length, Error &error) "write() returned 0"); return false; } else if (errno != EINTR) { - error.FormatErrno("Failed to write to '%s'", path); + error.FormatErrno("Failed to write to '%s'", + path.c_str()); return false; } } @@ -176,56 +188,68 @@ RecorderOutput::EncoderToFile(Error &error) } } -static bool -recorder_output_open(AudioOutput *ao, - AudioFormat &audio_format, - Error &error) +inline bool +RecorderOutput::Open(AudioFormat &audio_format, Error &error) { - RecorderOutput *recorder = (RecorderOutput *)ao; - /* create the output file */ - recorder->fd = open_cloexec(recorder->path, - O_CREAT|O_WRONLY|O_TRUNC|O_BINARY, - 0666); - if (recorder->fd < 0) { - error.FormatErrno("Failed to create '%s'", recorder->path); + fd = OpenFile(path, + O_CREAT|O_WRONLY|O_TRUNC|O_BINARY, + 0666); + if (fd < 0) { + error.FormatErrno("Failed to create '%s'", path.c_str()); return false; } /* open the encoder */ - if (!encoder_open(recorder->encoder, audio_format, error)) { - close(recorder->fd); - unlink(recorder->path); + if (!encoder_open(encoder, audio_format, error)) { + close(fd); + RemoveFile(path); return false; } - if (!recorder->EncoderToFile(error)) { - encoder_close(recorder->encoder); - close(recorder->fd); - unlink(recorder->path); + if (!EncoderToFile(error)) { + encoder_close(encoder); + close(fd); + RemoveFile(path); return false; } return true; } -static void -recorder_output_close(AudioOutput *ao) +inline void +RecorderOutput::Close() { - RecorderOutput *recorder = (RecorderOutput *)ao; - /* flush the encoder and write the rest to the file */ - if (encoder_end(recorder->encoder, IgnoreError())) - recorder->EncoderToFile(IgnoreError()); + if (encoder_end(encoder, IgnoreError())) + EncoderToFile(IgnoreError()); /* now really close everything */ - encoder_close(recorder->encoder); + encoder_close(encoder); - close(recorder->fd); + close(fd); +} + +inline void +RecorderOutput::SendTag(const Tag &tag) +{ + Error error; + if (!encoder_pre_tag(encoder, error) || + !EncoderToFile(error) || + !encoder_tag(encoder, tag, error)) + LogError(error); +} + +static void +recorder_output_send_tag(AudioOutput *ao, const Tag &tag) +{ + RecorderOutput &recorder = *(RecorderOutput *)ao; + + recorder.SendTag(tag); } static size_t @@ -239,6 +263,8 @@ recorder_output_play(AudioOutput *ao, const void *chunk, size_t size, ? size : 0; } +typedef AudioOutputWrapper<RecorderOutput> Wrapper; + const struct AudioOutputPlugin recorder_output_plugin = { "recorder", nullptr, @@ -246,10 +272,10 @@ const struct AudioOutputPlugin recorder_output_plugin = { recorder_output_finish, nullptr, nullptr, - recorder_output_open, - recorder_output_close, - nullptr, + &Wrapper::Open, + &Wrapper::Close, nullptr, + recorder_output_send_tag, recorder_output_play, nullptr, nullptr, |