aboutsummaryrefslogtreecommitdiffstats
path: root/src/output/plugins/RecorderOutputPlugin.cxx
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/output/plugins/RecorderOutputPlugin.cxx98
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 &param, Error &error_r) {
return base.Configure(param, error_r);
@@ -66,12 +71,17 @@ struct RecorderOutput {
bool Configure(const config_param &param, 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 &param, 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,