Input*: move to input/
This commit is contained in:
102
src/input/Init.cxx
Normal file
102
src/input/Init.cxx
Normal file
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* Copyright (C) 2003-2014 The Music Player Daemon Project
|
||||
* http://www.musicpd.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "Init.hxx"
|
||||
#include "Registry.hxx"
|
||||
#include "InputPlugin.hxx"
|
||||
#include "util/Error.hxx"
|
||||
#include "util/Domain.hxx"
|
||||
#include "config/ConfigGlobal.hxx"
|
||||
#include "config/ConfigOption.hxx"
|
||||
#include "config/ConfigData.hxx"
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
extern constexpr Domain input_domain("input");
|
||||
|
||||
/**
|
||||
* Find the "input" configuration block for the specified plugin.
|
||||
*
|
||||
* @param plugin_name the name of the input plugin
|
||||
* @return the configuration block, or nullptr if none was configured
|
||||
*/
|
||||
static const struct config_param *
|
||||
input_plugin_config(const char *plugin_name, Error &error)
|
||||
{
|
||||
const struct config_param *param = nullptr;
|
||||
|
||||
while ((param = config_get_next_param(CONF_INPUT, param)) != nullptr) {
|
||||
const char *name = param->GetBlockValue("plugin");
|
||||
if (name == nullptr) {
|
||||
error.Format(input_domain,
|
||||
"input configuration without 'plugin' name in line %d",
|
||||
param->line);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (strcmp(name, plugin_name) == 0)
|
||||
return param;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool
|
||||
input_stream_global_init(Error &error)
|
||||
{
|
||||
const config_param empty;
|
||||
|
||||
for (unsigned i = 0; input_plugins[i] != nullptr; ++i) {
|
||||
const InputPlugin *plugin = input_plugins[i];
|
||||
|
||||
assert(plugin->name != nullptr);
|
||||
assert(*plugin->name != 0);
|
||||
assert(plugin->open != nullptr);
|
||||
|
||||
const struct config_param *param =
|
||||
input_plugin_config(plugin->name, error);
|
||||
if (param == nullptr) {
|
||||
if (error.IsDefined())
|
||||
return false;
|
||||
|
||||
param = ∅
|
||||
} else if (!param->GetBlockValue("enabled", true))
|
||||
/* the plugin is disabled in mpd.conf */
|
||||
continue;
|
||||
|
||||
if (plugin->init == nullptr || plugin->init(*param, error))
|
||||
input_plugins_enabled[i] = true;
|
||||
else {
|
||||
error.FormatPrefix("Failed to initialize input plugin '%s': ",
|
||||
plugin->name);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void input_stream_global_finish(void)
|
||||
{
|
||||
input_plugins_for_each_enabled(plugin)
|
||||
if (plugin->finish != nullptr)
|
||||
plugin->finish();
|
||||
}
|
36
src/input/Init.hxx
Normal file
36
src/input/Init.hxx
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (C) 2003-2014 The Music Player Daemon Project
|
||||
* http://www.musicpd.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef MPD_INPUT_INIT_HXX
|
||||
#define MPD_INPUT_INIT_HXX
|
||||
|
||||
class Error;
|
||||
|
||||
/**
|
||||
* Initializes this library and all input_stream implementations.
|
||||
*/
|
||||
bool
|
||||
input_stream_global_init(Error &error);
|
||||
|
||||
/**
|
||||
* Deinitializes this library and all input_stream implementations.
|
||||
*/
|
||||
void input_stream_global_finish(void);
|
||||
|
||||
#endif
|
91
src/input/InputPlugin.hxx
Normal file
91
src/input/InputPlugin.hxx
Normal file
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright (C) 2003-2014 The Music Player Daemon Project
|
||||
* http://www.musicpd.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef MPD_INPUT_PLUGIN_HXX
|
||||
#define MPD_INPUT_PLUGIN_HXX
|
||||
|
||||
#include "thread/Mutex.hxx"
|
||||
#include "thread/Cond.hxx"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
struct config_param;
|
||||
struct InputStream;
|
||||
class Error;
|
||||
struct Tag;
|
||||
|
||||
struct InputPlugin {
|
||||
typedef int64_t offset_type;
|
||||
|
||||
const char *name;
|
||||
|
||||
/**
|
||||
* Global initialization. This method is called when MPD starts.
|
||||
*
|
||||
* @return true on success, false if the plugin should be
|
||||
* disabled
|
||||
*/
|
||||
bool (*init)(const config_param ¶m, Error &error);
|
||||
|
||||
/**
|
||||
* Global deinitialization. Called once before MPD shuts
|
||||
* down (only if init() has returned true).
|
||||
*/
|
||||
void (*finish)(void);
|
||||
|
||||
InputStream *(*open)(const char *uri,
|
||||
Mutex &mutex, Cond &cond,
|
||||
Error &error);
|
||||
void (*close)(InputStream *is);
|
||||
|
||||
/**
|
||||
* Check for errors that may have occurred in the I/O thread.
|
||||
* May be unimplemented for synchronous plugins.
|
||||
*
|
||||
* @return false on error
|
||||
*/
|
||||
bool (*check)(InputStream *is, Error &error);
|
||||
|
||||
/**
|
||||
* Update the public attributes. Call before access. Can be
|
||||
* nullptr if the plugin always keeps its attributes up to date.
|
||||
*/
|
||||
void (*update)(InputStream *is);
|
||||
|
||||
Tag *(*tag)(InputStream *is);
|
||||
|
||||
/**
|
||||
* Returns true if the next read operation will not block:
|
||||
* either data is available, or end-of-stream has been
|
||||
* reached, or an error has occurred.
|
||||
*
|
||||
* If this method is unimplemented, then it is assumed that
|
||||
* reading will never block.
|
||||
*/
|
||||
bool (*available)(InputStream *is);
|
||||
|
||||
size_t (*read)(InputStream *is, void *ptr, size_t size,
|
||||
Error &error);
|
||||
bool (*eof)(InputStream *is);
|
||||
bool (*seek)(InputStream *is, offset_type offset, int whence,
|
||||
Error &error);
|
||||
};
|
||||
|
||||
#endif
|
214
src/input/InputStream.cxx
Normal file
214
src/input/InputStream.cxx
Normal file
@@ -0,0 +1,214 @@
|
||||
/*
|
||||
* Copyright (C) 2003-2014 The Music Player Daemon Project
|
||||
* http://www.musicpd.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "InputStream.hxx"
|
||||
#include "Registry.hxx"
|
||||
#include "InputPlugin.hxx"
|
||||
#include "plugins/RewindInputPlugin.hxx"
|
||||
#include "util/UriUtil.hxx"
|
||||
#include "util/Error.hxx"
|
||||
#include "util/Domain.hxx"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h> /* for SEEK_SET */
|
||||
|
||||
static constexpr Domain input_domain("input");
|
||||
|
||||
InputStream *
|
||||
InputStream::Open(const char *url,
|
||||
Mutex &mutex, Cond &cond,
|
||||
Error &error)
|
||||
{
|
||||
input_plugins_for_each_enabled(plugin) {
|
||||
InputStream *is;
|
||||
|
||||
is = plugin->open(url, mutex, cond, error);
|
||||
if (is != nullptr) {
|
||||
assert(is->plugin.close != nullptr);
|
||||
assert(is->plugin.read != nullptr);
|
||||
assert(is->plugin.eof != nullptr);
|
||||
assert(!is->seekable || is->plugin.seek != nullptr);
|
||||
|
||||
is = input_rewind_open(is);
|
||||
|
||||
return is;
|
||||
} else if (error.IsDefined())
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
error.Set(input_domain, "Unrecognized URI");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
InputStream *
|
||||
InputStream::OpenReady(const char *uri,
|
||||
Mutex &mutex, Cond &cond,
|
||||
Error &error)
|
||||
{
|
||||
InputStream *is = Open(uri, mutex, cond, error);
|
||||
if (is == nullptr)
|
||||
return nullptr;
|
||||
|
||||
mutex.lock();
|
||||
is->WaitReady();
|
||||
bool success = is->Check(error);
|
||||
mutex.unlock();
|
||||
|
||||
if (!success) {
|
||||
is->Close();
|
||||
is = nullptr;
|
||||
}
|
||||
|
||||
return is;
|
||||
}
|
||||
|
||||
bool
|
||||
InputStream::Check(Error &error)
|
||||
{
|
||||
return plugin.check == nullptr || plugin.check(this, error);
|
||||
}
|
||||
|
||||
void
|
||||
InputStream::Update()
|
||||
{
|
||||
if (plugin.update != nullptr)
|
||||
plugin.update(this);
|
||||
}
|
||||
|
||||
void
|
||||
InputStream::WaitReady()
|
||||
{
|
||||
while (true) {
|
||||
Update();
|
||||
if (ready)
|
||||
break;
|
||||
|
||||
cond.wait(mutex);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
InputStream::LockWaitReady()
|
||||
{
|
||||
const ScopeLock protect(mutex);
|
||||
WaitReady();
|
||||
}
|
||||
|
||||
bool
|
||||
InputStream::CheapSeeking() const
|
||||
{
|
||||
return IsSeekable() && !uri_has_scheme(uri.c_str());
|
||||
}
|
||||
|
||||
bool
|
||||
InputStream::Seek(offset_type _offset, int whence, Error &error)
|
||||
{
|
||||
if (plugin.seek == nullptr)
|
||||
return false;
|
||||
|
||||
return plugin.seek(this, _offset, whence, error);
|
||||
}
|
||||
|
||||
bool
|
||||
InputStream::LockSeek(offset_type _offset, int whence, Error &error)
|
||||
{
|
||||
if (plugin.seek == nullptr)
|
||||
return false;
|
||||
|
||||
const ScopeLock protect(mutex);
|
||||
return Seek(_offset, whence, error);
|
||||
}
|
||||
|
||||
bool
|
||||
InputStream::Rewind(Error &error)
|
||||
{
|
||||
return Seek(0, SEEK_SET, error);
|
||||
}
|
||||
|
||||
bool
|
||||
InputStream::LockRewind(Error &error)
|
||||
{
|
||||
return LockSeek(0, SEEK_SET, error);
|
||||
}
|
||||
|
||||
Tag *
|
||||
InputStream::ReadTag()
|
||||
{
|
||||
return plugin.tag != nullptr
|
||||
? plugin.tag(this)
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
Tag *
|
||||
InputStream::LockReadTag()
|
||||
{
|
||||
if (plugin.tag == nullptr)
|
||||
return nullptr;
|
||||
|
||||
const ScopeLock protect(mutex);
|
||||
return ReadTag();
|
||||
}
|
||||
|
||||
bool
|
||||
InputStream::IsAvailable()
|
||||
{
|
||||
return plugin.available != nullptr
|
||||
? plugin.available(this)
|
||||
: true;
|
||||
}
|
||||
|
||||
size_t
|
||||
InputStream::Read(void *ptr, size_t _size, Error &error)
|
||||
{
|
||||
assert(ptr != nullptr);
|
||||
assert(_size > 0);
|
||||
|
||||
return plugin.read(this, ptr, _size, error);
|
||||
}
|
||||
|
||||
size_t
|
||||
InputStream::LockRead(void *ptr, size_t _size, Error &error)
|
||||
{
|
||||
assert(ptr != nullptr);
|
||||
assert(_size > 0);
|
||||
|
||||
const ScopeLock protect(mutex);
|
||||
return Read(ptr, _size, error);
|
||||
}
|
||||
|
||||
void
|
||||
InputStream::Close()
|
||||
{
|
||||
plugin.close(this);
|
||||
}
|
||||
|
||||
bool
|
||||
InputStream::IsEOF()
|
||||
{
|
||||
return plugin.eof(this);
|
||||
}
|
||||
|
||||
bool
|
||||
InputStream::LockIsEOF()
|
||||
{
|
||||
const ScopeLock protect(mutex);
|
||||
return IsEOF();
|
||||
}
|
||||
|
301
src/input/InputStream.hxx
Normal file
301
src/input/InputStream.hxx
Normal file
@@ -0,0 +1,301 @@
|
||||
/*
|
||||
* Copyright (C) 2003-2014 The Music Player Daemon Project
|
||||
* http://www.musicpd.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef MPD_INPUT_STREAM_HXX
|
||||
#define MPD_INPUT_STREAM_HXX
|
||||
|
||||
#include "check.h"
|
||||
#include "thread/Mutex.hxx"
|
||||
#include "Compiler.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
|
||||
class Cond;
|
||||
class Error;
|
||||
struct Tag;
|
||||
struct InputPlugin;
|
||||
|
||||
struct InputStream {
|
||||
typedef int64_t offset_type;
|
||||
|
||||
/**
|
||||
* the plugin which implements this input stream
|
||||
*/
|
||||
const InputPlugin &plugin;
|
||||
|
||||
/**
|
||||
* The absolute URI which was used to open this stream.
|
||||
*/
|
||||
std::string uri;
|
||||
|
||||
/**
|
||||
* A mutex that protects the mutable attributes of this object
|
||||
* and its implementation. It must be locked before calling
|
||||
* any of the public methods.
|
||||
*
|
||||
* This object is allocated by the client, and the client is
|
||||
* responsible for freeing it.
|
||||
*/
|
||||
Mutex &mutex;
|
||||
|
||||
/**
|
||||
* A cond that gets signalled when the state of this object
|
||||
* changes from the I/O thread. The client of this object may
|
||||
* wait on it. Optional, may be nullptr.
|
||||
*
|
||||
* This object is allocated by the client, and the client is
|
||||
* responsible for freeing it.
|
||||
*/
|
||||
Cond &cond;
|
||||
|
||||
/**
|
||||
* indicates whether the stream is ready for reading and
|
||||
* whether the other attributes in this struct are valid
|
||||
*/
|
||||
bool ready;
|
||||
|
||||
/**
|
||||
* if true, then the stream is fully seekable
|
||||
*/
|
||||
bool seekable;
|
||||
|
||||
/**
|
||||
* the size of the resource, or -1 if unknown
|
||||
*/
|
||||
offset_type size;
|
||||
|
||||
/**
|
||||
* the current offset within the stream
|
||||
*/
|
||||
offset_type offset;
|
||||
|
||||
/**
|
||||
* the MIME content type of the resource, or empty if unknown.
|
||||
*/
|
||||
std::string mime;
|
||||
|
||||
InputStream(const InputPlugin &_plugin,
|
||||
const char *_uri, Mutex &_mutex, Cond &_cond)
|
||||
:plugin(_plugin), uri(_uri),
|
||||
mutex(_mutex), cond(_cond),
|
||||
ready(false), seekable(false),
|
||||
size(-1), offset(0) {
|
||||
assert(_uri != nullptr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens a new input stream. You may not access it until the "ready"
|
||||
* flag is set.
|
||||
*
|
||||
* @param mutex a mutex that is used to protect this object; must be
|
||||
* locked before calling any of the public methods
|
||||
* @param cond a cond that gets signalled when the state of
|
||||
* this object changes; may be nullptr if the caller doesn't want to get
|
||||
* notifications
|
||||
* @return an #InputStream object on success, nullptr on error
|
||||
*/
|
||||
gcc_nonnull_all
|
||||
gcc_malloc
|
||||
static InputStream *Open(const char *uri, Mutex &mutex, Cond &cond,
|
||||
Error &error);
|
||||
|
||||
/**
|
||||
* Just like Open(), but waits for the stream to become ready.
|
||||
* It is a wrapper for Open(), WaitReady() and Check().
|
||||
*/
|
||||
gcc_malloc gcc_nonnull_all
|
||||
static InputStream *OpenReady(const char *uri,
|
||||
Mutex &mutex, Cond &cond,
|
||||
Error &error);
|
||||
|
||||
/**
|
||||
* Close the input stream and free resources.
|
||||
*
|
||||
* The caller must not lock the mutex.
|
||||
*/
|
||||
void Close();
|
||||
|
||||
void Lock() {
|
||||
mutex.lock();
|
||||
}
|
||||
|
||||
void Unlock() {
|
||||
mutex.unlock();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for errors that may have occurred in the I/O thread.
|
||||
*
|
||||
* @return false on error
|
||||
*/
|
||||
bool Check(Error &error);
|
||||
|
||||
/**
|
||||
* Update the public attributes. Call before accessing attributes
|
||||
* such as "ready" or "offset".
|
||||
*/
|
||||
void Update();
|
||||
|
||||
/**
|
||||
* Wait until the stream becomes ready.
|
||||
*
|
||||
* The caller must lock the mutex.
|
||||
*/
|
||||
void WaitReady();
|
||||
|
||||
/**
|
||||
* Wrapper for WaitReady() which locks and unlocks the mutex;
|
||||
* the caller must not be holding it already.
|
||||
*/
|
||||
void LockWaitReady();
|
||||
|
||||
gcc_pure
|
||||
const char *GetMimeType() const {
|
||||
assert(ready);
|
||||
|
||||
return mime.empty() ? nullptr : mime.c_str();
|
||||
}
|
||||
|
||||
gcc_nonnull_all
|
||||
void OverrideMimeType(const char *_mime) {
|
||||
assert(ready);
|
||||
|
||||
mime = _mime;
|
||||
}
|
||||
|
||||
gcc_pure
|
||||
offset_type GetSize() const {
|
||||
assert(ready);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
gcc_pure
|
||||
offset_type GetOffset() const {
|
||||
assert(ready);
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
gcc_pure
|
||||
bool IsSeekable() const {
|
||||
assert(ready);
|
||||
|
||||
return seekable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether seeking is cheap. This is true for local files.
|
||||
*/
|
||||
gcc_pure
|
||||
bool CheapSeeking() const;
|
||||
|
||||
/**
|
||||
* Seeks to the specified position in the stream. This will most
|
||||
* likely fail if the "seekable" flag is false.
|
||||
*
|
||||
* The caller must lock the mutex.
|
||||
*
|
||||
* @param offset the relative offset
|
||||
* @param whence the base of the seek, one of SEEK_SET, SEEK_CUR, SEEK_END
|
||||
*/
|
||||
bool Seek(offset_type offset, int whence, Error &error);
|
||||
|
||||
/**
|
||||
* Wrapper for Seek() which locks and unlocks the mutex; the
|
||||
* caller must not be holding it already.
|
||||
*/
|
||||
bool LockSeek(offset_type offset, int whence, Error &error);
|
||||
|
||||
/**
|
||||
* Rewind to the beginning of the stream. This is a wrapper
|
||||
* for Seek(0, SEEK_SET, error).
|
||||
*/
|
||||
bool Rewind(Error &error);
|
||||
bool LockRewind(Error &error);
|
||||
|
||||
/**
|
||||
* Returns true if the stream has reached end-of-file.
|
||||
*
|
||||
* The caller must lock the mutex.
|
||||
*/
|
||||
gcc_pure
|
||||
bool IsEOF();
|
||||
|
||||
/**
|
||||
* Wrapper for IsEOF() which locks and unlocks the mutex; the
|
||||
* caller must not be holding it already.
|
||||
*/
|
||||
gcc_pure
|
||||
bool LockIsEOF();
|
||||
|
||||
/**
|
||||
* Reads the tag from the stream.
|
||||
*
|
||||
* The caller must lock the mutex.
|
||||
*
|
||||
* @return a tag object which must be freed by the caller, or
|
||||
* nullptr if the tag has not changed since the last call
|
||||
*/
|
||||
gcc_malloc
|
||||
Tag *ReadTag();
|
||||
|
||||
/**
|
||||
* Wrapper for ReadTag() which locks and unlocks the mutex;
|
||||
* the caller must not be holding it already.
|
||||
*/
|
||||
gcc_malloc
|
||||
Tag *LockReadTag();
|
||||
|
||||
/**
|
||||
* Returns true if the next read operation will not block: either data
|
||||
* is available, or end-of-stream has been reached, or an error has
|
||||
* occurred.
|
||||
*
|
||||
* The caller must lock the mutex.
|
||||
*/
|
||||
gcc_pure
|
||||
bool IsAvailable();
|
||||
|
||||
/**
|
||||
* Reads data from the stream into the caller-supplied buffer.
|
||||
* Returns 0 on error or eof (check with IsEOF()).
|
||||
*
|
||||
* The caller must lock the mutex.
|
||||
*
|
||||
* @param is the InputStream object
|
||||
* @param ptr the buffer to read into
|
||||
* @param size the maximum number of bytes to read
|
||||
* @return the number of bytes read
|
||||
*/
|
||||
gcc_nonnull_all
|
||||
size_t Read(void *ptr, size_t size, Error &error);
|
||||
|
||||
/**
|
||||
* Wrapper for Read() which locks and unlocks the mutex;
|
||||
* the caller must not be holding it already.
|
||||
*/
|
||||
gcc_nonnull_all
|
||||
size_t LockRead(void *ptr, size_t size, Error &error);
|
||||
};
|
||||
|
||||
#endif
|
86
src/input/Registry.cxx
Normal file
86
src/input/Registry.cxx
Normal file
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright (C) 2003-2014 The Music Player Daemon Project
|
||||
* http://www.musicpd.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "Registry.hxx"
|
||||
#include "util/Macros.hxx"
|
||||
#include "plugins/FileInputPlugin.hxx"
|
||||
|
||||
#ifdef HAVE_ALSA
|
||||
#include "plugins/AlsaInputPlugin.hxx"
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_ARCHIVE
|
||||
#include "plugins/ArchiveInputPlugin.hxx"
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_CURL
|
||||
#include "plugins/CurlInputPlugin.hxx"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_FFMPEG
|
||||
#include "plugins/FfmpegInputPlugin.hxx"
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_SMBCLIENT
|
||||
#include "plugins/SmbclientInputPlugin.hxx"
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_MMS
|
||||
#include "plugins/MmsInputPlugin.hxx"
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_CDIO_PARANOIA
|
||||
#include "plugins/CdioParanoiaInputPlugin.hxx"
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_DESPOTIFY
|
||||
#include "plugins/DespotifyInputPlugin.hxx"
|
||||
#endif
|
||||
|
||||
const InputPlugin *const input_plugins[] = {
|
||||
&input_plugin_file,
|
||||
#ifdef HAVE_ALSA
|
||||
&input_plugin_alsa,
|
||||
#endif
|
||||
#ifdef ENABLE_ARCHIVE
|
||||
&input_plugin_archive,
|
||||
#endif
|
||||
#ifdef ENABLE_CURL
|
||||
&input_plugin_curl,
|
||||
#endif
|
||||
#ifdef HAVE_FFMPEG
|
||||
&input_plugin_ffmpeg,
|
||||
#endif
|
||||
#ifdef ENABLE_SMBCLIENT
|
||||
&input_plugin_smbclient,
|
||||
#endif
|
||||
#ifdef ENABLE_MMS
|
||||
&input_plugin_mms,
|
||||
#endif
|
||||
#ifdef ENABLE_CDIO_PARANOIA
|
||||
&input_plugin_cdio_paranoia,
|
||||
#endif
|
||||
#ifdef ENABLE_DESPOTIFY
|
||||
&input_plugin_despotify,
|
||||
#endif
|
||||
nullptr
|
||||
};
|
||||
|
||||
bool input_plugins_enabled[ARRAY_SIZE(input_plugins) - 1];
|
43
src/input/Registry.hxx
Normal file
43
src/input/Registry.hxx
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (C) 2003-2014 The Music Player Daemon Project
|
||||
* http://www.musicpd.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef MPD_INPUT_REGISTRY_HXX
|
||||
#define MPD_INPUT_REGISTRY_HXX
|
||||
|
||||
#include "check.h"
|
||||
|
||||
/**
|
||||
* NULL terminated list of all input plugins which were enabled at
|
||||
* compile time.
|
||||
*/
|
||||
extern const struct InputPlugin *const input_plugins[];
|
||||
|
||||
extern bool input_plugins_enabled[];
|
||||
|
||||
#define input_plugins_for_each(plugin) \
|
||||
for (const InputPlugin *plugin, \
|
||||
*const*input_plugin_iterator = &input_plugins[0]; \
|
||||
(plugin = *input_plugin_iterator) != NULL; \
|
||||
++input_plugin_iterator)
|
||||
|
||||
#define input_plugins_for_each_enabled(plugin) \
|
||||
input_plugins_for_each(plugin) \
|
||||
if (input_plugins_enabled[input_plugin_iterator - input_plugins])
|
||||
|
||||
#endif
|
78
src/input/TextInputStream.cxx
Normal file
78
src/input/TextInputStream.cxx
Normal file
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright (C) 2003-2014 The Music Player Daemon Project
|
||||
* http://www.musicpd.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "TextInputStream.hxx"
|
||||
#include "InputStream.hxx"
|
||||
#include "util/CharUtil.hxx"
|
||||
#include "util/Error.hxx"
|
||||
#include "Log.hxx"
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
bool TextInputStream::ReadLine(std::string &line)
|
||||
{
|
||||
const char *src, *p;
|
||||
|
||||
do {
|
||||
size_t nbytes;
|
||||
auto dest = buffer.Write();
|
||||
if (dest.size >= 2) {
|
||||
/* reserve one byte for the null terminator if
|
||||
the last line is not terminated by a
|
||||
newline character */
|
||||
--dest.size;
|
||||
|
||||
Error error;
|
||||
nbytes = is.LockRead(dest.data, dest.size, error);
|
||||
if (nbytes > 0)
|
||||
buffer.Append(nbytes);
|
||||
else if (error.IsDefined()) {
|
||||
LogError(error);
|
||||
return false;
|
||||
}
|
||||
} else
|
||||
nbytes = 0;
|
||||
|
||||
auto src_p = buffer.Read();
|
||||
if (src_p.IsEmpty())
|
||||
return false;
|
||||
|
||||
src = src_p.data;
|
||||
|
||||
p = reinterpret_cast<const char*>(memchr(src, '\n', src_p.size));
|
||||
if (p == nullptr && nbytes == 0) {
|
||||
/* end of file (or line too long): terminate
|
||||
the current line */
|
||||
dest = buffer.Write();
|
||||
assert(!dest.IsEmpty());
|
||||
dest.data[0] = '\n';
|
||||
buffer.Append(1);
|
||||
}
|
||||
} while (p == nullptr);
|
||||
|
||||
size_t length = p - src + 1;
|
||||
while (p > src && IsWhitespaceOrNull(p[-1]))
|
||||
--p;
|
||||
|
||||
line = std::string(src, p - src);
|
||||
buffer.Consume(length);
|
||||
return true;
|
||||
}
|
56
src/input/TextInputStream.hxx
Normal file
56
src/input/TextInputStream.hxx
Normal file
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (C) 2003-2014 The Music Player Daemon Project
|
||||
* http://www.musicpd.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef MPD_TEXT_INPUT_STREAM_HXX
|
||||
#define MPD_TEXT_INPUT_STREAM_HXX
|
||||
|
||||
#include "util/FifoBuffer.hxx"
|
||||
|
||||
#include <string>
|
||||
|
||||
struct InputStream;
|
||||
|
||||
class TextInputStream {
|
||||
InputStream &is;
|
||||
FifoBuffer<char, 4096> buffer;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Wraps an existing #input_stream object into a #TextInputStream,
|
||||
* to read its contents as text lines.
|
||||
*
|
||||
* @param _is an open #input_stream object
|
||||
*/
|
||||
explicit TextInputStream(InputStream &_is)
|
||||
:is(_is) {}
|
||||
|
||||
TextInputStream(const TextInputStream &) = delete;
|
||||
TextInputStream& operator=(const TextInputStream &) = delete;
|
||||
|
||||
/**
|
||||
* Reads the next line from the stream with newline character stripped.
|
||||
*
|
||||
* @param line a string to put result to
|
||||
* @return true if line is read successfully, false on end of file
|
||||
* or error
|
||||
*/
|
||||
bool ReadLine(std::string &line);
|
||||
};
|
||||
|
||||
#endif
|
@@ -26,8 +26,8 @@
|
||||
|
||||
#include "config.h"
|
||||
#include "AlsaInputPlugin.hxx"
|
||||
#include "InputPlugin.hxx"
|
||||
#include "InputStream.hxx"
|
||||
#include "../InputPlugin.hxx"
|
||||
#include "../InputStream.hxx"
|
||||
#include "util/Domain.hxx"
|
||||
#include "util/Error.hxx"
|
||||
#include "util/StringUtil.hxx"
|
@@ -20,7 +20,7 @@
|
||||
#ifndef MPD_ALSA_INPUT_PLUGIN_HXX
|
||||
#define MPD_ALSA_INPUT_PLUGIN_HXX
|
||||
|
||||
#include "InputPlugin.hxx"
|
||||
#include "../InputPlugin.hxx"
|
||||
|
||||
extern const struct InputPlugin input_plugin_alsa;
|
||||
|
@@ -24,7 +24,7 @@
|
||||
#include "archive/ArchiveList.hxx"
|
||||
#include "archive/ArchivePlugin.hxx"
|
||||
#include "archive/ArchiveFile.hxx"
|
||||
#include "InputPlugin.hxx"
|
||||
#include "../InputPlugin.hxx"
|
||||
#include "fs/Traits.hxx"
|
||||
#include "util/Alloc.hxx"
|
||||
#include "Log.hxx"
|
@@ -23,8 +23,8 @@
|
||||
|
||||
#include "config.h"
|
||||
#include "CdioParanoiaInputPlugin.hxx"
|
||||
#include "InputStream.hxx"
|
||||
#include "InputPlugin.hxx"
|
||||
#include "../InputStream.hxx"
|
||||
#include "../InputPlugin.hxx"
|
||||
#include "util/StringUtil.hxx"
|
||||
#include "util/Error.hxx"
|
||||
#include "util/Domain.hxx"
|
@@ -19,8 +19,8 @@
|
||||
|
||||
#include "config.h"
|
||||
#include "CurlInputPlugin.hxx"
|
||||
#include "InputStream.hxx"
|
||||
#include "InputPlugin.hxx"
|
||||
#include "../InputStream.hxx"
|
||||
#include "../InputPlugin.hxx"
|
||||
#include "config/ConfigGlobal.hxx"
|
||||
#include "config/ConfigData.hxx"
|
||||
#include "tag/Tag.hxx"
|
@@ -20,8 +20,8 @@
|
||||
#include "config.h"
|
||||
#include "DespotifyInputPlugin.hxx"
|
||||
#include "DespotifyUtils.hxx"
|
||||
#include "InputStream.hxx"
|
||||
#include "InputPlugin.hxx"
|
||||
#include "../InputStream.hxx"
|
||||
#include "../InputPlugin.hxx"
|
||||
#include "tag/Tag.hxx"
|
||||
#include "util/StringUtil.hxx"
|
||||
#include "Log.hxx"
|
@@ -22,8 +22,8 @@
|
||||
|
||||
#include "config.h"
|
||||
#include "FfmpegInputPlugin.hxx"
|
||||
#include "InputStream.hxx"
|
||||
#include "InputPlugin.hxx"
|
||||
#include "../InputStream.hxx"
|
||||
#include "../InputPlugin.hxx"
|
||||
#include "util/StringUtil.hxx"
|
||||
#include "util/Error.hxx"
|
||||
#include "util/Domain.hxx"
|
@@ -19,8 +19,8 @@
|
||||
|
||||
#include "config.h" /* must be first for large file support */
|
||||
#include "FileInputPlugin.hxx"
|
||||
#include "InputStream.hxx"
|
||||
#include "InputPlugin.hxx"
|
||||
#include "../InputStream.hxx"
|
||||
#include "../InputPlugin.hxx"
|
||||
#include "util/Error.hxx"
|
||||
#include "util/Domain.hxx"
|
||||
#include "fs/Traits.hxx"
|
@@ -19,8 +19,8 @@
|
||||
|
||||
#include "config.h"
|
||||
#include "MmsInputPlugin.hxx"
|
||||
#include "InputStream.hxx"
|
||||
#include "InputPlugin.hxx"
|
||||
#include "../InputStream.hxx"
|
||||
#include "../InputPlugin.hxx"
|
||||
#include "util/StringUtil.hxx"
|
||||
#include "util/Error.hxx"
|
||||
#include "util/Domain.hxx"
|
@@ -19,8 +19,8 @@
|
||||
|
||||
#include "config.h"
|
||||
#include "RewindInputPlugin.hxx"
|
||||
#include "InputStream.hxx"
|
||||
#include "InputPlugin.hxx"
|
||||
#include "../InputStream.hxx"
|
||||
#include "../InputPlugin.hxx"
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
@@ -19,8 +19,8 @@
|
||||
|
||||
#include "config.h"
|
||||
#include "SmbclientInputPlugin.hxx"
|
||||
#include "InputStream.hxx"
|
||||
#include "InputPlugin.hxx"
|
||||
#include "../InputStream.hxx"
|
||||
#include "../InputPlugin.hxx"
|
||||
#include "util/StringUtil.hxx"
|
||||
#include "util/Error.hxx"
|
||||
|
Reference in New Issue
Block a user