aboutsummaryrefslogtreecommitdiff
path: root/src/input
diff options
context:
space:
mode:
Diffstat (limited to 'src/input')
-rw-r--r--src/input/ArchiveInputPlugin.cxx (renamed from src/input/archive_input_plugin.c)40
-rw-r--r--src/input/ArchiveInputPlugin.hxx (renamed from src/input/archive_input_plugin.h)6
-rw-r--r--src/input/CdioParanoiaInputPlugin.cxx (renamed from src/input/cdio_paranoia_input_plugin.c)114
-rw-r--r--src/input/CdioParanoiaInputPlugin.hxx (renamed from src/input/cdio_paranoia_input_plugin.h)6
-rw-r--r--src/input/CurlInputPlugin.cxx (renamed from src/input/curl_input_plugin.c)596
-rw-r--r--src/input/CurlInputPlugin.hxx (renamed from src/input/curl_input_plugin.h)6
-rw-r--r--src/input/DespotifyInputPlugin.cxx (renamed from src/input/despotify_input_plugin.c)107
-rw-r--r--src/input/DespotifyInputPlugin.hxx (renamed from src/input/despotify_input_plugin.h)6
-rw-r--r--src/input/FfmpegInputPlugin.cxx (renamed from src/input/ffmpeg_input_plugin.c)136
-rw-r--r--src/input/FfmpegInputPlugin.hxx (renamed from src/input/ffmpeg_input_plugin.h)6
-rw-r--r--src/input/FileInputPlugin.cxx (renamed from src/input/file_input_plugin.c)92
-rw-r--r--src/input/FileInputPlugin.hxx (renamed from src/input/file_input_plugin.h)6
-rw-r--r--src/input/MmsInputPlugin.cxx (renamed from src/input/mms_input_plugin.c)81
-rw-r--r--src/input/MmsInputPlugin.hxx (renamed from src/input/mms_input_plugin.h)0
-rw-r--r--src/input/RewindInputPlugin.cxx (renamed from src/input/rewind_input_plugin.c)148
-rw-r--r--src/input/RewindInputPlugin.hxx (renamed from src/input/rewind_input_plugin.h)6
-rw-r--r--src/input/SoupInputPlugin.cxx (renamed from src/input/soup_input_plugin.c)287
-rw-r--r--src/input/SoupInputPlugin.hxx (renamed from src/input/soup_input_plugin.h)6
18 files changed, 789 insertions, 860 deletions
diff --git a/src/input/archive_input_plugin.c b/src/input/ArchiveInputPlugin.cxx
index 4a038b9e..0d856527 100644
--- a/src/input/archive_input_plugin.c
+++ b/src/input/ArchiveInputPlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2011 The Music Player Daemon Project
+ * Copyright (C) 2003-2013 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -18,10 +18,12 @@
*/
#include "config.h"
-#include "input/archive_input_plugin.h"
-#include "archive_api.h"
-#include "archive_list.h"
-#include "input_plugin.h"
+#include "ArchiveInputPlugin.hxx"
+#include "ArchiveLookup.hxx"
+#include "ArchiveList.hxx"
+#include "ArchivePlugin.hxx"
+#include "ArchiveFile.hxx"
+#include "InputPlugin.hxx"
#include <glib.h>
@@ -35,11 +37,10 @@
*/
static struct input_stream *
input_archive_open(const char *pathname,
- GMutex *mutex, GCond *cond,
+ Mutex &mutex, Cond &cond,
GError **error_r)
{
const struct archive_plugin *arplug;
- struct archive_file *file;
char *archive, *filename, *suffix, *pname;
struct input_stream *is;
@@ -62,20 +63,31 @@ input_archive_open(const char *pathname,
return NULL;
}
- file = archive_file_open(arplug, archive, error_r);
- if (file == NULL)
+ auto file = archive_file_open(arplug, archive, error_r);
+ if (file == NULL) {
+ g_free(pname);
return NULL;
+ }
//setup fileops
- is = archive_file_open_stream(file, filename, mutex, cond,
- error_r);
- archive_file_close(file);
+ is = file->OpenStream(filename, mutex, cond, error_r);
g_free(pname);
+ file->Close();
return is;
}
const struct input_plugin input_plugin_archive = {
- .name = "archive",
- .open = input_archive_open,
+ "archive",
+ nullptr,
+ nullptr,
+ input_archive_open,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
};
diff --git a/src/input/archive_input_plugin.h b/src/input/ArchiveInputPlugin.hxx
index 51095f37..96fcd0dd 100644
--- a/src/input/archive_input_plugin.h
+++ b/src/input/ArchiveInputPlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2011 The Music Player Daemon Project
+ * Copyright (C) 2003-2013 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -17,8 +17,8 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-#ifndef MPD_INPUT_ARCHIVE_H
-#define MPD_INPUT_ARCHIVE_H
+#ifndef MPD_INPUT_ARCHIVE_HXX
+#define MPD_INPUT_ARCHIVE_HXX
extern const struct input_plugin input_plugin_archive;
diff --git a/src/input/cdio_paranoia_input_plugin.c b/src/input/CdioParanoiaInputPlugin.cxx
index 1de7623a..f0fa835b 100644
--- a/src/input/cdio_paranoia_input_plugin.c
+++ b/src/input/CdioParanoiaInputPlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2011 The Music Player Daemon Project
+ * Copyright (C) 2003-2013 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -22,10 +22,10 @@
*/
#include "config.h"
-#include "input/cdio_paranoia_input_plugin.h"
-#include "input_internal.h"
-#include "input_plugin.h"
-#include "refcount.h"
+#include "CdioParanoiaInputPlugin.hxx"
+#include "InputInternal.hxx"
+#include "InputStream.hxx"
+#include "InputPlugin.hxx"
#include <stdio.h>
#include <stdint.h>
@@ -38,7 +38,7 @@
#include <cdio/paranoia.h>
#include <cdio/cd_types.h>
-struct input_cdio_paranoia {
+struct CdioParanoiaInputStream {
struct input_stream base;
cdrom_drive_t *drv;
@@ -52,6 +52,23 @@ struct input_cdio_paranoia {
char buffer[CDIO_CD_FRAMESIZE_RAW];
int buffer_lsn;
+
+ CdioParanoiaInputStream(const char *uri, Mutex &mutex, Cond &cond,
+ int _trackno)
+ :base(input_plugin_cdio_paranoia, uri, mutex, cond),
+ drv(nullptr), cdio(nullptr), para(nullptr),
+ trackno(_trackno)
+ {
+ }
+
+ ~CdioParanoiaInputStream() {
+ if (para != nullptr)
+ cdio_paranoia_free(para);
+ if (drv != nullptr)
+ cdio_cddap_close_no_free_cdio(drv);
+ if (cdio != nullptr)
+ cdio_destroy(cdio);
+ }
};
static inline GQuark
@@ -63,17 +80,9 @@ cdio_quark(void)
static void
input_cdio_close(struct input_stream *is)
{
- struct input_cdio_paranoia *i = (struct input_cdio_paranoia *)is;
+ CdioParanoiaInputStream *i = (CdioParanoiaInputStream *)is;
- if (i->para)
- cdio_paranoia_free(i->para);
- if (i->drv)
- cdio_cddap_close_no_free_cdio( i->drv);
- if (i->cdio)
- cdio_destroy( i->cdio );
-
- input_stream_deinit(&i->base);
- g_free(i);
+ delete i;
}
struct cdio_uri {
@@ -97,7 +106,7 @@ parse_cdio_uri(struct cdio_uri *dest, const char *src, GError **error_r)
}
const char *slash = strrchr(src, '/');
- if (slash == NULL) {
+ if (slash == nullptr) {
/* play the whole CD in the specified drive */
g_strlcpy(dest->device, src, sizeof(dest->device));
dest->track = -1;
@@ -131,9 +140,10 @@ parse_cdio_uri(struct cdio_uri *dest, const char *src, GError **error_r)
static char *
cdio_detect_device(void)
{
- char **devices = cdio_get_devices_with_cap(NULL, CDIO_FS_AUDIO, false);
- if (devices == NULL)
- return NULL;
+ char **devices = cdio_get_devices_with_cap(nullptr, CDIO_FS_AUDIO,
+ false);
+ if (devices == nullptr)
+ return nullptr;
char *device = g_strdup(devices[0]);
cdio_free_device_list(devices);
@@ -143,55 +153,47 @@ cdio_detect_device(void)
static struct input_stream *
input_cdio_open(const char *uri,
- GMutex *mutex, GCond *cond,
+ Mutex &mutex, Cond &cond,
GError **error_r)
{
- struct input_cdio_paranoia *i;
-
struct cdio_uri parsed_uri;
if (!parse_cdio_uri(&parsed_uri, uri, error_r))
- return NULL;
-
- i = g_new(struct input_cdio_paranoia, 1);
- input_stream_init(&i->base, &input_plugin_cdio_paranoia, uri,
- mutex, cond);
+ return nullptr;
- /* initialize everything (should be already) */
- i->drv = NULL;
- i->cdio = NULL;
- i->para = NULL;
- i->trackno = parsed_uri.track;
+ CdioParanoiaInputStream *i =
+ new CdioParanoiaInputStream(uri, mutex, cond,
+ parsed_uri.track);
/* get list of CD's supporting CD-DA */
char *device = parsed_uri.device[0] != 0
? g_strdup(parsed_uri.device)
: cdio_detect_device();
- if (device == NULL) {
+ if (device == nullptr) {
g_set_error(error_r, cdio_quark(), 0,
"Unable find or access a CD-ROM drive with an audio CD in it.");
- input_cdio_close(&i->base);
- return NULL;
+ delete i;
+ return nullptr;
}
/* Found such a CD-ROM with a CD-DA loaded. Use the first drive in the list. */
i->cdio = cdio_open(device, DRIVER_UNKNOWN);
g_free(device);
- i->drv = cdio_cddap_identify_cdio(i->cdio, 1, NULL);
+ i->drv = cdio_cddap_identify_cdio(i->cdio, 1, nullptr);
if ( !i->drv ) {
g_set_error(error_r, cdio_quark(), 0,
"Unable to identify audio CD disc.");
- input_cdio_close(&i->base);
- return NULL;
+ delete i;
+ return nullptr;
}
cdda_verbose_set(i->drv, CDDA_MESSAGE_FORGETIT, CDDA_MESSAGE_FORGETIT);
if ( 0 != cdio_cddap_open(i->drv) ) {
g_set_error(error_r, cdio_quark(), 0, "Unable to open disc.");
- input_cdio_close(&i->base);
- return NULL;
+ delete i;
+ return nullptr;
}
bool reverse_endian;
@@ -212,8 +214,8 @@ input_cdio_open(const char *uri,
g_set_error(error_r, cdio_quark(), 0,
"Drive returns unknown data type %d",
data_bigendianp(i->drv));
- input_cdio_close(&i->base);
- return NULL;
+ delete i;
+ return nullptr;
}
i->lsn_relofs = 0;
@@ -250,7 +252,7 @@ static bool
input_cdio_seek(struct input_stream *is,
goffset offset, int whence, GError **error_r)
{
- struct input_cdio_paranoia *cis = (struct input_cdio_paranoia *)is;
+ CdioParanoiaInputStream *cis = (CdioParanoiaInputStream *)is;
/* calculate absolute offset */
switch (whence) {
@@ -288,7 +290,7 @@ static size_t
input_cdio_read(struct input_stream *is, void *ptr, size_t length,
GError **error_r)
{
- struct input_cdio_paranoia *cis = (struct input_cdio_paranoia *)is;
+ CdioParanoiaInputStream *cis = (CdioParanoiaInputStream *)is;
size_t nbytes = 0;
int diff;
size_t len, maxwrite;
@@ -305,7 +307,7 @@ input_cdio_read(struct input_stream *is, void *ptr, size_t length,
//current sector was changed ?
if (cis->lsn_relofs != cis->buffer_lsn) {
- rbuf = cdio_paranoia_read(cis->para, NULL);
+ rbuf = cdio_paranoia_read(cis->para, nullptr);
s_err = cdda_errors(cis->drv);
if (s_err) {
@@ -356,16 +358,22 @@ input_cdio_read(struct input_stream *is, void *ptr, size_t length,
static bool
input_cdio_eof(struct input_stream *is)
{
- struct input_cdio_paranoia *cis = (struct input_cdio_paranoia *)is;
+ CdioParanoiaInputStream *cis = (CdioParanoiaInputStream *)is;
return (cis->lsn_from + cis->lsn_relofs > cis->lsn_to);
}
const struct input_plugin input_plugin_cdio_paranoia = {
- .name = "cdio_paranoia",
- .open = input_cdio_open,
- .close = input_cdio_close,
- .seek = input_cdio_seek,
- .read = input_cdio_read,
- .eof = input_cdio_eof
+ "cdio_paranoia",
+ nullptr,
+ nullptr,
+ input_cdio_open,
+ input_cdio_close,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ input_cdio_read,
+ input_cdio_eof,
+ input_cdio_seek,
};
diff --git a/src/input/cdio_paranoia_input_plugin.h b/src/input/CdioParanoiaInputPlugin.hxx
index 71c5cbe8..80d98b4b 100644
--- a/src/input/cdio_paranoia_input_plugin.h
+++ b/src/input/CdioParanoiaInputPlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2011 The Music Player Daemon Project
+ * Copyright (C) 2003-2013 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -17,8 +17,8 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-#ifndef MPD_CDIO_PARANOIA_INPUT_PLUGIN_H
-#define MPD_CDIO_PARANOIA_INPUT_PLUGIN_H
+#ifndef MPD_CDIO_PARANOIA_INPUT_PLUGIN_HXX
+#define MPD_CDIO_PARANOIA_INPUT_PLUGIN_HXX
/**
* An input plugin based on libcdio_paranoia library.
diff --git a/src/input/curl_input_plugin.c b/src/input/CurlInputPlugin.cxx
index 3f191141..fe944b75 100644
--- a/src/input/curl_input_plugin.c
+++ b/src/input/CurlInputPlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2011 The Music Player Daemon Project
+ * Copyright (C) 2003-2013 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -18,14 +18,16 @@
*/
#include "config.h"
-#include "input/curl_input_plugin.h"
-#include "input_internal.h"
-#include "input_plugin.h"
+#include "CurlInputPlugin.hxx"
+#include "InputInternal.hxx"
+#include "InputStream.hxx"
+#include "InputPlugin.hxx"
#include "conf.h"
#include "tag.h"
-#include "icy_metadata.h"
-#include "io_thread.h"
-#include "glib_compat.h"
+#include "IcyMetaDataParser.hxx"
+#include "event/MultiSocketMonitor.hxx"
+#include "event/Loop.hxx"
+#include "IOThread.hxx"
#include <assert.h>
@@ -38,9 +40,16 @@
#include <string.h>
#include <errno.h>
+#include <list>
+#include <forward_list>
+
#include <curl/curl.h>
#include <glib.h>
+#if LIBCURL_VERSION_NUM < 0x071200
+#error libcurl is too old
+#endif
+
#undef G_LOG_DOMAIN
#define G_LOG_DOMAIN "input_curl"
@@ -59,7 +68,7 @@ static const size_t CURL_RESUME_AT = 384 * 1024;
/**
* Buffers created by input_curl_writefunction().
*/
-struct buffer {
+class CurlInputBuffer {
/** size of the payload */
size_t size;
@@ -67,7 +76,55 @@ struct buffer {
size_t consumed;
/** the payload */
- unsigned char data[sizeof(long)];
+ uint8_t *data;
+
+public:
+ CurlInputBuffer(const void *_data, size_t _size)
+ :size(_size), consumed(0), data(new uint8_t[size]) {
+ memcpy(data, _data, size);
+ }
+
+ ~CurlInputBuffer() {
+ delete[] data;
+ }
+
+ CurlInputBuffer(const CurlInputBuffer &) = delete;
+ CurlInputBuffer &operator=(const CurlInputBuffer &) = delete;
+
+ const void *Begin() const {
+ return data + consumed;
+ }
+
+ size_t TotalSize() const {
+ return size;
+ }
+
+ size_t Available() const {
+ return size - consumed;
+ }
+
+ /**
+ * Mark a part of the buffer as consumed.
+ *
+ * @return false if the buffer is now empty
+ */
+ bool Consume(size_t length) {
+ assert(consumed < size);
+
+ consumed += length;
+ if (consumed < size)
+ return true;
+
+ assert(consumed == size);
+ return false;
+ }
+
+ bool Read(void *dest, size_t length) {
+ assert(consumed + length <= size);
+
+ memcpy(dest, data + consumed, length);
+ return Consume(length);
+ }
};
struct input_curl {
@@ -75,40 +132,28 @@ struct input_curl {
/* some buffers which were passed to libcurl, which we have
too free */
- char *url, *range;
+ char *range;
struct curl_slist *request_headers;
/** the curl handles */
CURL *easy;
- /** the GMainLoop source used to poll all CURL file
- descriptors */
- GSource *source;
-
- /** the source id of #source */
- guint source_id;
-
- /** a linked list of all registered GPollFD objects */
- GSList *fds;
-
/** list of buffers, where input_curl_writefunction() appends
to, and input_curl_read() reads from them */
- GQueue *buffers;
+ std::list<CurlInputBuffer> buffers;
-#if LIBCURL_VERSION_NUM >= 0x071200
/**
* Is the connection currently paused? That happens when the
* buffer was getting too large. It will be unpaused when the
* buffer is below the threshold again.
*/
bool paused;
-#endif
/** error message provided by libcurl */
char error[CURL_ERROR_SIZE];
/** parser for icy-metadata */
- struct icy_metadata icy_metadata;
+ IcyMetaDataParser icy;
/** the stream name from the icy-name response header */
char *meta_name;
@@ -118,6 +163,50 @@ struct input_curl {
struct tag *tag;
GError *postponed_error;
+
+ input_curl(const char *url, Mutex &mutex, Cond &cond)
+ :base(input_plugin_curl, url, mutex, cond),
+ range(nullptr), request_headers(nullptr),
+ paused(false),
+ meta_name(nullptr),
+ tag(nullptr),
+ postponed_error(nullptr) {
+ }
+
+ ~input_curl();
+
+ input_curl(const input_curl &) = delete;
+ input_curl &operator=(const input_curl &) = delete;
+};
+
+/**
+ * This class monitors all CURL file descriptors.
+ */
+class CurlSockets final : private MultiSocketMonitor {
+ /**
+ * Did CURL give us a timeout? If yes, then we need to call
+ * curl_multi_perform(), even if there was no event on any
+ * file descriptor.
+ */
+ bool have_timeout;
+
+ /**
+ * The absolute time stamp when the timeout expires.
+ */
+ gint64 absolute_timeout;
+
+public:
+ CurlSockets(EventLoop &_loop)
+ :MultiSocketMonitor(_loop) {}
+
+ using MultiSocketMonitor::InvalidateSockets;
+
+private:
+ void UpdateSockets();
+
+ virtual void PrepareSockets(gcc_unused gint *timeout_r) override;
+ virtual bool CheckSockets() const override;
+ virtual void DispatchSockets() override;
};
/** libcurl should accept "ICY 200 OK" */
@@ -134,35 +223,9 @@ static struct {
* A linked list of all active HTTP requests. An active
* request is one that doesn't have the "eof" flag set.
*/
- GSList *requests;
-
- /**
- * The GMainLoop source used to poll all CURL file
- * descriptors.
- */
- GSource *source;
+ std::forward_list<input_curl *> requests;
- /**
- * The source id of #source.
- */
- guint source_id;
-
- GSList *fds;
-
-#if LIBCURL_VERSION_NUM >= 0x070f04
- /**
- * Did CURL give us a timeout? If yes, then we need to call
- * curl_multi_perform(), even if there was no event on any
- * file descriptor.
- */
- bool timeout;
-
- /**
- * The absolute time stamp when the timeout expires. This is
- * used in the GSource method check().
- */
- gint64 absolute_timeout;
-#endif
+ CurlSockets *sockets;
} curl;
static inline GQuark
@@ -181,23 +244,19 @@ input_curl_find_request(CURL *easy)
{
assert(io_thread_inside());
- for (GSList *i = curl.requests; i != NULL; i = g_slist_next(i)) {
- struct input_curl *c = i->data;
+ for (auto c : curl.requests)
if (c->easy == easy)
return c;
- }
return NULL;
}
-#if LIBCURL_VERSION_NUM >= 0x071200
-
static gpointer
input_curl_resume(gpointer data)
{
assert(io_thread_inside());
- struct input_curl *c = data;
+ struct input_curl *c = (struct input_curl *)data;
if (c->paused) {
c->paused = false;
@@ -207,13 +266,11 @@ input_curl_resume(gpointer data)
return NULL;
}
-#endif
-
/**
* Calculates the GLib event bit mask for one file descriptor,
* obtained from three #fd_set objects filled by curl_multi_fdset().
*/
-static gushort
+static unsigned
input_curl_fd_events(int fd, fd_set *rfds, fd_set *wfds, fd_set *efds)
{
gushort events = 0;
@@ -242,8 +299,8 @@ input_curl_fd_events(int fd, fd_set *rfds, fd_set *wfds, fd_set *efds)
*
* Runs in the I/O thread. No lock needed.
*/
-static void
-curl_update_fds(void)
+void
+CurlSockets::UpdateSockets()
{
assert(io_thread_inside());
@@ -262,42 +319,15 @@ curl_update_fds(void)
return;
}
- GSList *fds = curl.fds;
- curl.fds = NULL;
-
- while (fds != NULL) {
- GPollFD *poll_fd = fds->data;
- gushort events = input_curl_fd_events(poll_fd->fd, &rfds,
- &wfds, &efds);
-
- assert(poll_fd->events != 0);
-
- fds = g_slist_remove(fds, poll_fd);
-
- if (events != poll_fd->events)
- g_source_remove_poll(curl.source, poll_fd);
-
- if (events != 0) {
- if (events != poll_fd->events) {
- poll_fd->events = events;
- g_source_add_poll(curl.source, poll_fd);
- }
-
- curl.fds = g_slist_prepend(curl.fds, poll_fd);
- } else {
- g_free(poll_fd);
- }
- }
+ UpdateSocketList([&rfds, &wfds, &efds](int fd){
+ return input_curl_fd_events(fd, &rfds,
+ &wfds, &efds);
+ });
for (int fd = 0; fd <= max_fd; ++fd) {
- gushort events = input_curl_fd_events(fd, &rfds, &wfds, &efds);
- if (events != 0) {
- GPollFD *poll_fd = g_new(GPollFD, 1);
- poll_fd->fd = fd;
- poll_fd->events = events;
- g_source_add_poll(curl.source, poll_fd);
- curl.fds = g_slist_prepend(curl.fds, poll_fd);
- }
+ unsigned events = input_curl_fd_events(fd, &rfds, &wfds, &efds);
+ if (events != 0)
+ AddSocket(fd, events);
}
}
@@ -312,7 +342,7 @@ input_curl_easy_add(struct input_curl *c, GError **error_r)
assert(c->easy != NULL);
assert(input_curl_find_request(c->easy) == NULL);
- curl.requests = g_slist_prepend(curl.requests, c);
+ curl.requests.push_front(c);
CURLMcode mcode = curl_multi_add_handle(curl.multi, c->easy);
if (mcode != CURLM_OK) {
@@ -322,7 +352,7 @@ input_curl_easy_add(struct input_curl *c, GError **error_r)
return false;
}
- curl_update_fds();
+ curl.sockets->InvalidateSockets();
return true;
}
@@ -335,7 +365,8 @@ struct easy_add_params {
static gpointer
input_curl_easy_add_callback(gpointer data)
{
- const struct easy_add_params *params = data;
+ const struct easy_add_params *params =
+ (const struct easy_add_params *)data;
bool success = input_curl_easy_add(params->c, params->error_r);
return GUINT_TO_POINTER(success);
@@ -352,8 +383,8 @@ input_curl_easy_add_indirect(struct input_curl *c, GError **error_r)
assert(c->easy != NULL);
struct easy_add_params params = {
- .c = c,
- .error_r = error_r,
+ c,
+ error_r,
};
gpointer result =
@@ -376,7 +407,7 @@ input_curl_easy_free(struct input_curl *c)
if (c->easy == NULL)
return;
- curl.requests = g_slist_remove(curl.requests, c);
+ curl.requests.remove(c);
curl_multi_remove_handle(curl.multi, c->easy);
curl_easy_cleanup(c->easy);
@@ -392,10 +423,10 @@ input_curl_easy_free(struct input_curl *c)
static gpointer
input_curl_easy_free_callback(gpointer data)
{
- struct input_curl *c = data;
+ struct input_curl *c = (struct input_curl *)data;
input_curl_easy_free(c);
- curl_update_fds();
+ curl.sockets->InvalidateSockets();
return NULL;
}
@@ -424,17 +455,18 @@ input_curl_abort_all_requests(GError *error)
assert(io_thread_inside());
assert(error != NULL);
- while (curl.requests != NULL) {
- struct input_curl *c = curl.requests->data;
+ while (!curl.requests.empty()) {
+ struct input_curl *c = curl.requests.front();
assert(c->postponed_error == NULL);
input_curl_easy_free(c);
- g_mutex_lock(c->base.mutex);
+ const ScopeLock protect(c->base.mutex);
+
c->postponed_error = g_error_copy(error);
c->base.ready = true;
- g_cond_broadcast(c->base.cond);
- g_mutex_unlock(c->base.mutex);
+
+ c->base.cond.broadcast();
}
g_error_free(error);
@@ -454,7 +486,7 @@ input_curl_request_done(struct input_curl *c, CURLcode result, long status)
assert(c->easy == NULL);
assert(c->postponed_error == NULL);
- g_mutex_lock(c->base.mutex);
+ const ScopeLock protect(c->base.mutex);
if (result != CURLE_OK) {
c->postponed_error = g_error_new(curl_quark(), result,
@@ -467,8 +499,8 @@ input_curl_request_done(struct input_curl *c, CURLcode result, long status)
}
c->base.ready = true;
- g_cond_broadcast(c->base.cond);
- g_mutex_unlock(c->base.mutex);
+
+ c->base.cond.broadcast();
}
static void
@@ -532,28 +564,18 @@ input_curl_perform(void)
return true;
}
-/*
- * GSource methods
- *
- */
-
-/**
- * The GSource prepare() method implementation.
- */
-static gboolean
-input_curl_source_prepare(G_GNUC_UNUSED GSource *source, gint *timeout_r)
+void
+CurlSockets::PrepareSockets(gint *timeout_r)
{
- curl_update_fds();
+ UpdateSockets();
-#if LIBCURL_VERSION_NUM >= 0x070f04
- curl.timeout = false;
+ have_timeout = false;
long timeout2;
CURLMcode mcode = curl_multi_timeout(curl.multi, &timeout2);
if (mcode == CURLM_OK) {
if (timeout2 >= 0)
- curl.absolute_timeout = g_source_get_time(source)
- + timeout2 * 1000;
+ absolute_timeout = GetTime() + timeout2 * 1000;
if (timeout2 >= 0 && timeout2 < 10)
/* CURL 7.21.1 likes to report "timeout=0",
@@ -564,69 +586,28 @@ input_curl_source_prepare(G_GNUC_UNUSED GSource *source, gint *timeout_r)
*timeout_r = timeout2;
- curl.timeout = timeout2 >= 0;
+ have_timeout = timeout2 >= 0;
} else
g_warning("curl_multi_timeout() failed: %s\n",
curl_multi_strerror(mcode));
-#else
- (void)timeout_r;
-#endif
-
- return false;
}
-/**
- * The GSource check() method implementation.
- */
-static gboolean
-input_curl_source_check(G_GNUC_UNUSED GSource *source)
+bool
+CurlSockets::CheckSockets() const
{
-#if LIBCURL_VERSION_NUM >= 0x070f04
- if (curl.timeout) {
- /* when a timeout has expired, we need to call
- curl_multi_perform(), even if there was no file
- descriptor event */
-
- if (g_source_get_time(source) >= curl.absolute_timeout)
- return true;
- }
-#endif
-
- for (GSList *i = curl.fds; i != NULL; i = i->next) {
- GPollFD *poll_fd = i->data;
- if (poll_fd->revents != 0)
- return true;
- }
-
- return false;
+ /* when a timeout has expired, we need to call
+ curl_multi_perform(), even if there was no file descriptor
+ event */
+ return have_timeout && GetTime() >= absolute_timeout;
}
-/**
- * The GSource dispatch() method implementation. The callback isn't
- * used, because we're handling all events directly.
- */
-static gboolean
-input_curl_source_dispatch(G_GNUC_UNUSED GSource *source,
- G_GNUC_UNUSED GSourceFunc callback,
- G_GNUC_UNUSED gpointer user_data)
+void
+CurlSockets::DispatchSockets()
{
if (input_curl_perform())
input_curl_info_read();
-
- return true;
}
-/**
- * The vtable for our GSource implementation. Unfortunately, we
- * cannot declare it "const", because g_source_new() takes a non-const
- * pointer, for whatever reason.
- */
-static GSourceFuncs curl_source_funcs = {
- .prepare = input_curl_source_prepare,
- .check = input_curl_source_check,
- .dispatch = input_curl_source_dispatch,
-};
-
/*
* input_plugin methods
*
@@ -668,8 +649,7 @@ input_curl_init(const struct config_param *param,
return false;
}
- curl.source = g_source_new(&curl_source_funcs, sizeof(*curl.source));
- curl.source_id = g_source_attach(curl.source, io_thread_context());
+ curl.sockets = new CurlSockets(io_thread_get());
return true;
}
@@ -677,7 +657,7 @@ input_curl_init(const struct config_param *param,
static gpointer
curl_destroy_sources(G_GNUC_UNUSED gpointer data)
{
- g_source_destroy(curl.source);
+ delete curl.sockets;
return NULL;
}
@@ -685,7 +665,7 @@ curl_destroy_sources(G_GNUC_UNUSED gpointer data)
static void
input_curl_finish(void)
{
- assert(curl.requests == NULL);
+ assert(curl.requests.empty());
io_thread_call(curl_destroy_sources, NULL);
@@ -696,8 +676,6 @@ input_curl_finish(void)
curl_global_cleanup();
}
-#if LIBCURL_VERSION_NUM >= 0x071200
-
/**
* Determine the total sizes of all buffers, including portions that
* have already been consumed.
@@ -710,55 +688,22 @@ curl_total_buffer_size(const struct input_curl *c)
{
size_t total = 0;
- for (GList *i = g_queue_peek_head_link(c->buffers);
- i != NULL; i = g_list_next(i)) {
- struct buffer *buffer = i->data;
- total += buffer->size;
- }
+ for (const auto &i : c->buffers)
+ total += i.TotalSize();
return total;
}
-#endif
-
-static void
-buffer_free_callback(gpointer data, G_GNUC_UNUSED gpointer user_data)
+input_curl::~input_curl()
{
- struct buffer *buffer = data;
+ if (tag != NULL)
+ tag_free(tag);
+ g_free(meta_name);
- assert(buffer->consumed <= buffer->size);
+ input_curl_easy_free_indirect(this);
- g_free(buffer);
-}
-
-static void
-input_curl_flush_buffers(struct input_curl *c)
-{
- g_queue_foreach(c->buffers, buffer_free_callback, NULL);
- g_queue_clear(c->buffers);
-}
-
-/**
- * Frees this stream, including the input_stream struct.
- */
-static void
-input_curl_free(struct input_curl *c)
-{
- if (c->tag != NULL)
- tag_free(c->tag);
- g_free(c->meta_name);
-
- input_curl_easy_free_indirect(c);
- input_curl_flush_buffers(c);
-
- g_queue_free(c->buffers);
-
- if (c->postponed_error != NULL)
- g_error_free(c->postponed_error);
-
- g_free(c->url);
- input_stream_deinit(&c->base);
- g_free(c);
+ if (postponed_error != NULL)
+ g_error_free(postponed_error);
}
static bool
@@ -788,8 +733,8 @@ input_curl_tag(struct input_stream *is)
static bool
fill_buffer(struct input_curl *c, GError **error_r)
{
- while (c->easy != NULL && g_queue_is_empty(c->buffers))
- g_cond_wait(c->base.cond, c->base.mutex);
+ while (c->easy != NULL && c->buffers.empty())
+ c->base.cond.wait(c->base.mutex);
if (c->postponed_error != NULL) {
g_propagate_error(error_r, c->postponed_error);
@@ -797,86 +742,63 @@ fill_buffer(struct input_curl *c, GError **error_r)
return false;
}
- return !g_queue_is_empty(c->buffers);
-}
-
-/**
- * Mark a part of the buffer object as consumed.
- */
-static struct buffer *
-consume_buffer(struct buffer *buffer, size_t length)
-{
- assert(buffer != NULL);
- assert(buffer->consumed < buffer->size);
-
- buffer->consumed += length;
- if (buffer->consumed < buffer->size)
- return buffer;
-
- assert(buffer->consumed == buffer->size);
-
- g_free(buffer);
-
- return NULL;
+ return !c->buffers.empty();
}
static size_t
-read_from_buffer(struct icy_metadata *icy_metadata, GQueue *buffers,
+read_from_buffer(IcyMetaDataParser &icy, std::list<CurlInputBuffer> &buffers,
void *dest0, size_t length)
{
- struct buffer *buffer = g_queue_pop_head(buffers);
- uint8_t *dest = dest0;
+ auto &buffer = buffers.front();
+ uint8_t *dest = (uint8_t *)dest0;
size_t nbytes = 0;
- assert(buffer->size > 0);
- assert(buffer->consumed < buffer->size);
-
- if (length > buffer->size - buffer->consumed)
- length = buffer->size - buffer->consumed;
+ if (length > buffer.Available())
+ length = buffer.Available();
while (true) {
size_t chunk;
- chunk = icy_data(icy_metadata, length);
+ chunk = icy.Data(length);
if (chunk > 0) {
- memcpy(dest, buffer->data + buffer->consumed,
- chunk);
- buffer = consume_buffer(buffer, chunk);
+ const bool empty = !buffer.Read(dest, chunk);
nbytes += chunk;
dest += chunk;
length -= chunk;
- if (length == 0)
+ if (empty) {
+ buffers.pop_front();
break;
+ }
- assert(buffer != NULL);
+ if (length == 0)
+ break;
}
- chunk = icy_meta(icy_metadata, buffer->data + buffer->consumed,
- length);
+ chunk = icy.Meta(buffer.Begin(), length);
if (chunk > 0) {
- buffer = consume_buffer(buffer, chunk);
+ const bool empty = !buffer.Consume(chunk);
length -= chunk;
- if (length == 0)
+ if (empty) {
+ buffers.pop_front();
break;
+ }
- assert(buffer != NULL);
+ if (length == 0)
+ break;
}
}
- if (buffer != NULL)
- g_queue_push_head(buffers, buffer);
-
return nbytes;
}
static void
copy_icy_tag(struct input_curl *c)
{
- struct tag *tag = icy_tag(&c->icy_metadata);
+ struct tag *tag = c->icy.ReadTag();
if (tag == NULL)
return;
@@ -896,7 +818,7 @@ input_curl_available(struct input_stream *is)
struct input_curl *c = (struct input_curl *)is;
return c->postponed_error != NULL || c->easy == NULL ||
- !g_queue_is_empty(c->buffers);
+ !c->buffers.empty();
}
static size_t
@@ -906,7 +828,7 @@ input_curl_read(struct input_stream *is, void *ptr, size_t size,
struct input_curl *c = (struct input_curl *)is;
bool success;
size_t nbytes = 0;
- char *dest = ptr;
+ char *dest = (char *)ptr;
do {
/* fill the buffer */
@@ -917,8 +839,8 @@ input_curl_read(struct input_stream *is, void *ptr, size_t size,
/* send buffer contents */
- while (size > 0 && !g_queue_is_empty(c->buffers)) {
- size_t copy = read_from_buffer(&c->icy_metadata, c->buffers,
+ while (size > 0 && !c->buffers.empty()) {
+ size_t copy = read_from_buffer(c->icy, c->buffers,
dest + nbytes, size);
nbytes += copy;
@@ -926,18 +848,16 @@ input_curl_read(struct input_stream *is, void *ptr, size_t size,
}
} while (nbytes == 0);
- if (icy_defined(&c->icy_metadata))
+ if (c->icy.IsDefined())
copy_icy_tag(c);
is->offset += (goffset)nbytes;
-#if LIBCURL_VERSION_NUM >= 0x071200
if (c->paused && curl_total_buffer_size(c) < CURL_RESUME_AT) {
- g_mutex_unlock(c->base.mutex);
+ c->base.mutex.unlock();
io_thread_call(input_curl_resume, c);
- g_mutex_lock(c->base.mutex);
+ c->base.mutex.lock();
}
-#endif
return nbytes;
}
@@ -947,7 +867,7 @@ input_curl_close(struct input_stream *is)
{
struct input_curl *c = (struct input_curl *)is;
- input_curl_free(c);
+ delete c;
}
static bool
@@ -955,7 +875,7 @@ input_curl_eof(G_GNUC_UNUSED struct input_stream *is)
{
struct input_curl *c = (struct input_curl *)is;
- return c->easy == NULL && g_queue_is_empty(c->buffers);
+ return c->easy == NULL && c->buffers.empty();
}
/** called by curl when new data is available */
@@ -963,13 +883,14 @@ static size_t
input_curl_headerfunction(void *ptr, size_t size, size_t nmemb, void *stream)
{
struct input_curl *c = (struct input_curl *)stream;
- const char *header = ptr, *end, *value;
char name[64];
size *= nmemb;
- end = header + size;
- value = memchr(header, ':', size);
+ const char *header = (const char *)ptr;
+ const char *end = header + size;
+
+ const char *value = (const char *)memchr(header, ':', size);
if (value == NULL || (size_t)(value - header) >= sizeof(name))
return size;
@@ -990,7 +911,7 @@ input_curl_headerfunction(void *ptr, size_t size, size_t nmemb, void *stream)
if (g_ascii_strcasecmp(name, "accept-ranges") == 0) {
/* a stream with icy-metadata is not seekable */
- if (!icy_defined(&c->icy_metadata))
+ if (!c->icy.IsDefined())
c->base.seekable = true;
} else if (g_ascii_strcasecmp(name, "content-length") == 0) {
char buffer[64];
@@ -1003,8 +924,7 @@ input_curl_headerfunction(void *ptr, size_t size, size_t nmemb, void *stream)
c->base.size = c->base.offset + g_ascii_strtoull(buffer, NULL, 10);
} else if (g_ascii_strcasecmp(name, "content-type") == 0) {
- g_free(c->base.mime);
- c->base.mime = g_strndup(value, end - value);
+ c->base.mime.assign(value, end);
} else if (g_ascii_strcasecmp(name, "icy-name") == 0 ||
g_ascii_strcasecmp(name, "ice-name") == 0 ||
g_ascii_strcasecmp(name, "x-audiocast-name") == 0) {
@@ -1021,7 +941,7 @@ input_curl_headerfunction(void *ptr, size_t size, size_t nmemb, void *stream)
size_t icy_metaint;
if ((size_t)(end - header) >= sizeof(buffer) ||
- icy_defined(&c->icy_metadata))
+ c->icy.IsDefined())
return size;
memcpy(buffer, value, end - value);
@@ -1031,7 +951,7 @@ input_curl_headerfunction(void *ptr, size_t size, size_t nmemb, void *stream)
g_debug("icy-metaint=%zu", icy_metaint);
if (icy_metaint > 0) {
- icy_start(&c->icy_metadata, icy_metaint);
+ c->icy.Start(icy_metaint);
/* a stream with icy-metadata is not
seekable */
@@ -1047,33 +967,22 @@ static size_t
input_curl_writefunction(void *ptr, size_t size, size_t nmemb, void *stream)
{
struct input_curl *c = (struct input_curl *)stream;
- struct buffer *buffer;
size *= nmemb;
if (size == 0)
return 0;
- g_mutex_lock(c->base.mutex);
+ const ScopeLock protect(c->base.mutex);
-#if LIBCURL_VERSION_NUM >= 0x071200
if (curl_total_buffer_size(c) + size >= CURL_MAX_BUFFERED) {
c->paused = true;
- g_mutex_unlock(c->base.mutex);
return CURL_WRITEFUNC_PAUSE;
}
-#endif
-
- buffer = g_malloc(sizeof(*buffer) - sizeof(buffer->data) + size);
- buffer->size = size;
- buffer->consumed = 0;
- memcpy(buffer->data, ptr, size);
- g_queue_push_tail(c->buffers, buffer);
+ c->buffers.emplace_back(ptr, size);
c->base.ready = true;
- g_cond_broadcast(c->base.cond);
- g_mutex_unlock(c->base.mutex);
-
+ c->base.cond.broadcast();
return size;
}
@@ -1120,7 +1029,7 @@ input_curl_easy_init(struct input_curl *c, GError **error_r)
g_free(proxy_auth_str);
}
- code = curl_easy_setopt(c->easy, CURLOPT_URL, c->url);
+ code = curl_easy_setopt(c->easy, CURLOPT_URL, c->base.uri.c_str());
if (code != CURLE_OK) {
g_set_error(error_r, curl_quark(), code,
"curl_easy_setopt() failed: %s",
@@ -1179,19 +1088,15 @@ input_curl_seek(struct input_stream *is, goffset offset, int whence,
/* check if we can fast-forward the buffer */
- while (offset > is->offset && !g_queue_is_empty(c->buffers)) {
- struct buffer *buffer;
- size_t length;
-
- buffer = (struct buffer *)g_queue_pop_head(c->buffers);
-
- length = buffer->size - buffer->consumed;
+ while (offset > is->offset && !c->buffers.empty()) {
+ auto &buffer = c->buffers.front();
+ size_t length = buffer.Available();
if (offset - is->offset < (goffset)length)
length = offset - is->offset;
- buffer = consume_buffer(buffer, length);
- if (buffer != NULL)
- g_queue_push_head(c->buffers, buffer);
+ const bool empty = !buffer.Consume(length);
+ if (empty)
+ c->buffers.pop_front();
is->offset += length;
}
@@ -1201,10 +1106,10 @@ input_curl_seek(struct input_stream *is, goffset offset, int whence,
/* close the old connection and open a new one */
- g_mutex_unlock(c->base.mutex);
+ c->base.mutex.unlock();
input_curl_easy_free_indirect(c);
- input_curl_flush_buffers(c);
+ c->buffers.clear();
is->offset = offset;
if (is->offset == is->size) {
@@ -1230,10 +1135,10 @@ input_curl_seek(struct input_stream *is, goffset offset, int whence,
if (!input_curl_easy_add_indirect(c, error_r))
return false;
- g_mutex_lock(c->base.mutex);
+ c->base.mutex.lock();
while (!c->base.ready)
- g_cond_wait(c->base.cond, c->base.mutex);
+ c->base.cond.wait(c->base.mutex);
if (c->postponed_error != NULL) {
g_propagate_error(error_r, c->postponed_error);
@@ -1245,40 +1150,21 @@ input_curl_seek(struct input_stream *is, goffset offset, int whence,
}
static struct input_stream *
-input_curl_open(const char *url, GMutex *mutex, GCond *cond,
+input_curl_open(const char *url, Mutex &mutex, Cond &cond,
GError **error_r)
{
- assert(mutex != NULL);
- assert(cond != NULL);
-
- struct input_curl *c;
-
if (strncmp(url, "http://", 7) != 0)
return NULL;
- c = g_new0(struct input_curl, 1);
- input_stream_init(&c->base, &input_plugin_curl, url,
- mutex, cond);
-
- c->url = g_strdup(url);
- c->buffers = g_queue_new();
-
- icy_clear(&c->icy_metadata);
- c->tag = NULL;
-
- c->postponed_error = NULL;
-
-#if LIBCURL_VERSION_NUM >= 0x071200
- c->paused = false;
-#endif
+ struct input_curl *c = new input_curl(url, mutex, cond);
if (!input_curl_easy_init(c, error_r)) {
- input_curl_free(c);
+ delete c;
return NULL;
}
if (!input_curl_easy_add_indirect(c, error_r)) {
- input_curl_free(c);
+ delete c;
return NULL;
}
@@ -1286,16 +1172,16 @@ input_curl_open(const char *url, GMutex *mutex, GCond *cond,
}
const struct input_plugin input_plugin_curl = {
- .name = "curl",
- .init = input_curl_init,
- .finish = input_curl_finish,
-
- .open = input_curl_open,
- .close = input_curl_close,
- .check = input_curl_check,
- .tag = input_curl_tag,
- .available = input_curl_available,
- .read = input_curl_read,
- .eof = input_curl_eof,
- .seek = input_curl_seek,
+ "curl",
+ input_curl_init,
+ input_curl_finish,
+ input_curl_open,
+ input_curl_close,
+ input_curl_check,
+ nullptr,
+ input_curl_tag,
+ input_curl_available,
+ input_curl_read,
+ input_curl_eof,
+ input_curl_seek,
};
diff --git a/src/input/curl_input_plugin.h b/src/input/CurlInputPlugin.hxx
index c6e71bf4..20d1309d 100644
--- a/src/input/curl_input_plugin.h
+++ b/src/input/CurlInputPlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2011 The Music Player Daemon Project
+ * Copyright (C) 2003-2013 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -17,8 +17,8 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-#ifndef MPD_INPUT_CURL_H
-#define MPD_INPUT_CURL_H
+#ifndef MPD_INPUT_CURL_HXX
+#define MPD_INPUT_CURL_HXX
struct input_stream;
diff --git a/src/input/despotify_input_plugin.c b/src/input/DespotifyInputPlugin.cxx
index 200a0afd..1e5a8c60 100644
--- a/src/input/despotify_input_plugin.c
+++ b/src/input/DespotifyInputPlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 The Music Player Daemon Project
+ * Copyright (C) 2011-2013 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -18,22 +18,26 @@
*/
#include "config.h"
-#include "input/despotify_input_plugin.h"
-#include "input_internal.h"
-#include "input_plugin.h"
+#include "DespotifyInputPlugin.hxx"
+#include "DespotifyUtils.hxx"
+#include "InputInternal.hxx"
+#include "InputStream.hxx"
+#include "InputPlugin.hxx"
#include "tag.h"
-#include "despotify_utils.h"
+
+extern "C" {
+#include <despotify.h>
+}
#include <glib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
-#include <despotify.h>
#include <stdio.h>
-struct input_despotify {
+struct DespotifyInputStream {
struct input_stream base;
struct despotify_session *session;
@@ -42,11 +46,33 @@ struct input_despotify {
struct ds_pcm_data pcm;
size_t len_available;
bool eof;
-};
+ DespotifyInputStream(const char *uri,
+ Mutex &mutex, Cond &cond,
+ despotify_session *_session,
+ ds_track *_track)
+ :base(input_plugin_despotify, uri, mutex, cond),
+ session(_session), track(_track),
+ tag(mpd_despotify_tag_from_track(track)),
+ len_available(0), eof(false) {
+
+ memset(&pcm, 0, sizeof(pcm));
+
+ /* Despotify outputs pcm data */
+ base.mime = g_strdup("audio/x-mpd-cdda-pcm");
+ base.ready = true;
+ }
+
+ ~DespotifyInputStream() {
+ if (tag != NULL)
+ tag_free(tag);
+
+ despotify_free_track(track);
+ }
+};
static void
-refill_buffer(struct input_despotify *ctx)
+refill_buffer(DespotifyInputStream *ctx)
{
/* Wait until there is data */
while (1) {
@@ -73,7 +99,7 @@ refill_buffer(struct input_despotify *ctx)
static void callback(G_GNUC_UNUSED struct despotify_session* ds,
int sig, G_GNUC_UNUSED void* data, void* callback_data)
{
- struct input_despotify *ctx = (struct input_despotify *)callback_data;
+ DespotifyInputStream *ctx = (DespotifyInputStream *)callback_data;
switch (sig) {
case DESPOTIFY_NEW_TRACK:
@@ -98,10 +124,9 @@ static void callback(G_GNUC_UNUSED struct despotify_session* ds,
static struct input_stream *
input_despotify_open(const char *url,
- GMutex *mutex, GCond *cond,
+ Mutex &mutex, Cond &cond,
G_GNUC_UNUSED GError **error_r)
{
- struct input_despotify *ctx;
struct despotify_session *session;
struct ds_link *ds_link;
struct ds_track *track;
@@ -123,35 +148,23 @@ input_despotify_open(const char *url,
return NULL;
}
- ctx = g_new(struct input_despotify, 1);
- memset(ctx, 0, sizeof(*ctx));
-
track = despotify_link_get_track(session, ds_link);
despotify_free_link(ds_link);
- if (!track) {
- g_free(ctx);
+ if (!track)
return NULL;
- }
- input_stream_init(&ctx->base, &input_plugin_despotify, url,
- mutex, cond);
- ctx->session = session;
- ctx->track = track;
- ctx->tag = mpd_despotify_tag_from_track(track);
- ctx->eof = false;
- /* Despotify outputs pcm data */
- ctx->base.mime = g_strdup("audio/x-mpd-cdda-pcm");
- ctx->base.ready = true;
+ DespotifyInputStream *ctx =
+ new DespotifyInputStream(url, mutex, cond,
+ session, track);
if (!mpd_despotify_register_callback(callback, ctx)) {
- despotify_free_link(ds_link);
-
+ delete ctx;
return NULL;
}
if (despotify_play(ctx->session, ctx->track, false) == false) {
- despotify_free_track(ctx->track);
- g_free(ctx);
+ mpd_despotify_unregister_callback(callback);
+ delete ctx;
return NULL;
}
@@ -162,7 +175,7 @@ static size_t
input_despotify_read(struct input_stream *is, void *ptr, size_t size,
G_GNUC_UNUSED GError **error_r)
{
- struct input_despotify *ctx = (struct input_despotify *)is;
+ DespotifyInputStream *ctx = (DespotifyInputStream *)is;
size_t to_cpy = size;
if (ctx->len_available == 0)
@@ -181,21 +194,16 @@ input_despotify_read(struct input_stream *is, void *ptr, size_t size,
static void
input_despotify_close(struct input_stream *is)
{
- struct input_despotify *ctx = (struct input_despotify *)is;
-
- if (ctx->tag != NULL)
- tag_free(ctx->tag);
+ DespotifyInputStream *ctx = (DespotifyInputStream *)is;
mpd_despotify_unregister_callback(callback);
- despotify_free_track(ctx->track);
- input_stream_deinit(&ctx->base);
- g_free(ctx);
+ delete ctx;
}
static bool
input_despotify_eof(struct input_stream *is)
{
- struct input_despotify *ctx = (struct input_despotify *)is;
+ DespotifyInputStream *ctx = (DespotifyInputStream *)is;
return ctx->eof;
}
@@ -211,7 +219,7 @@ input_despotify_seek(G_GNUC_UNUSED struct input_stream *is,
static struct tag *
input_despotify_tag(struct input_stream *is)
{
- struct input_despotify *ctx = (struct input_despotify *)is;
+ DespotifyInputStream *ctx = (DespotifyInputStream *)is;
struct tag *tag = ctx->tag;
ctx->tag = NULL;
@@ -220,11 +228,16 @@ input_despotify_tag(struct input_stream *is)
}
const struct input_plugin input_plugin_despotify = {
- .name = "spt",
- .open = input_despotify_open,
- .close = input_despotify_close,
- .read = input_despotify_read,
- .eof = input_despotify_eof,
- .seek = input_despotify_seek,
+ "spt",
+ nullptr,
+ nullptr,
+ input_despotify_open,
+ input_despotify_close,
+ nullptr,
+ nullptr,
.tag = input_despotify_tag,
+ nullptr,
+ input_despotify_read,
+ input_despotify_eof,
+ input_despotify_seek,
};
diff --git a/src/input/despotify_input_plugin.h b/src/input/DespotifyInputPlugin.hxx
index 4c070d88..00d69940 100644
--- a/src/input/despotify_input_plugin.h
+++ b/src/input/DespotifyInputPlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 The Music Player Daemon Project
+ * Copyright (C) 2011-2013 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -17,8 +17,8 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-#ifndef INPUT_DESPOTIFY_H
-#define INPUT_DESPOTIFY_H
+#ifndef INPUT_DESPOTIFY_HXX
+#define INPUT_DESPOTIFY_HXX
extern const struct input_plugin input_plugin_despotify;
diff --git a/src/input/ffmpeg_input_plugin.c b/src/input/FfmpegInputPlugin.cxx
index 6d339a06..1660f177 100644
--- a/src/input/ffmpeg_input_plugin.c
+++ b/src/input/FfmpegInputPlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2011 The Music Player Daemon Project
+ * Copyright (C) 2003-2013 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -17,28 +17,49 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
+/* necessary because libavutil/common.h uses UINT64_C */
+#define __STDC_CONSTANT_MACROS
+
#include "config.h"
-#include "input/ffmpeg_input_plugin.h"
-#include "input_internal.h"
-#include "input_plugin.h"
+#include "FfmpegInputPlugin.hxx"
+#include "InputInternal.hxx"
+#include "InputStream.hxx"
+#include "InputPlugin.hxx"
+extern "C" {
#include <libavutil/avutil.h>
#include <libavformat/avio.h>
#include <libavformat/avformat.h>
+}
#undef G_LOG_DOMAIN
#define G_LOG_DOMAIN "input_ffmpeg"
-struct input_ffmpeg {
+struct FfmpegInputStream {
struct input_stream base;
-#if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(53,0,0)
AVIOContext *h;
-#else
- URLContext *h;
-#endif
bool eof;
+
+ FfmpegInputStream(const char *uri, Mutex &mutex, Cond &cond,
+ AVIOContext *_h)
+ :base(input_plugin_ffmpeg, uri, mutex, cond),
+ h(_h), eof(false) {
+ base.ready = true;
+ base.seekable = (h->seekable & AVIO_SEEKABLE_NORMAL) != 0;
+ base.size = avio_size(h);
+
+ /* hack to make MPD select the "ffmpeg" decoder plugin
+ - since avio.h doesn't tell us the MIME type of the
+ resource, we can't select a decoder plugin, but the
+ "ffmpeg" plugin is quite good at auto-detection */
+ base.mime = g_strdup("audio/x-mpd-ffmpeg");
+ }
+
+ ~FfmpegInputStream() {
+ avio_close(h);
+ }
};
static inline GQuark
@@ -50,12 +71,8 @@ ffmpeg_quark(void)
static inline bool
input_ffmpeg_supported(void)
{
-#if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(53,0,0)
- void *opaque = NULL;
- return avio_enum_protocols(&opaque, 0) != NULL;
-#else
- return av_protocol_next(NULL) != NULL;
-#endif
+ void *opaque = nullptr;
+ return avio_enum_protocols(&opaque, 0) != nullptr;
}
static bool
@@ -76,54 +93,26 @@ input_ffmpeg_init(G_GNUC_UNUSED const struct config_param *param,
static struct input_stream *
input_ffmpeg_open(const char *uri,
- GMutex *mutex, GCond *cond,
+ Mutex &mutex, Cond &cond,
GError **error_r)
{
- struct input_ffmpeg *i;
-
if (!g_str_has_prefix(uri, "gopher://") &&
!g_str_has_prefix(uri, "rtp://") &&
!g_str_has_prefix(uri, "rtsp://") &&
!g_str_has_prefix(uri, "rtmp://") &&
!g_str_has_prefix(uri, "rtmpt://") &&
!g_str_has_prefix(uri, "rtmps://"))
- return NULL;
-
- i = g_new(struct input_ffmpeg, 1);
- input_stream_init(&i->base, &input_plugin_ffmpeg, uri,
- mutex, cond);
-
-#if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(53,1,0)
- int ret = avio_open(&i->h, uri, AVIO_FLAG_READ);
-#elif LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(53,0,0)
- int ret = avio_open(&i->h, uri, AVIO_RDONLY);
-#else
- int ret = url_open(&i->h, uri, URL_RDONLY);
-#endif
+ return nullptr;
+
+ AVIOContext *h;
+ int ret = avio_open(&h, uri, AVIO_FLAG_READ);
if (ret != 0) {
- g_free(i);
g_set_error(error_r, ffmpeg_quark(), ret,
"libavformat failed to open the URI");
- return NULL;
+ return nullptr;
}
- i->eof = false;
-
- i->base.ready = true;
-#if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(53,0,0)
- i->base.seekable = (i->h->seekable & AVIO_SEEKABLE_NORMAL) != 0;
- i->base.size = avio_size(i->h);
-#else
- i->base.seekable = !i->h->is_streamed;
- i->base.size = url_filesize(i->h);
-#endif
-
- /* hack to make MPD select the "ffmpeg" decoder plugin - since
- avio.h doesn't tell us the MIME type of the resource, we
- can't select a decoder plugin, but the "ffmpeg" plugin is
- quite good at auto-detection */
- i->base.mime = g_strdup("audio/x-mpd-ffmpeg");
-
+ auto *i = new FfmpegInputStream(uri, mutex, cond, h);
return &i->base;
}
@@ -131,13 +120,9 @@ static size_t
input_ffmpeg_read(struct input_stream *is, void *ptr, size_t size,
GError **error_r)
{
- struct input_ffmpeg *i = (struct input_ffmpeg *)is;
+ FfmpegInputStream *i = (FfmpegInputStream *)is;
-#if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(53,0,0)
- int ret = avio_read(i->h, ptr, size);
-#else
- int ret = url_read(i->h, ptr, size);
-#endif
+ int ret = avio_read(i->h, (unsigned char *)ptr, size);
if (ret <= 0) {
if (ret < 0)
g_set_error(error_r, ffmpeg_quark(), 0,
@@ -154,21 +139,15 @@ input_ffmpeg_read(struct input_stream *is, void *ptr, size_t size,
static void
input_ffmpeg_close(struct input_stream *is)
{
- struct input_ffmpeg *i = (struct input_ffmpeg *)is;
-
-#if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(53,0,0)
- avio_close(i->h);
-#else
- url_close(i->h);
-#endif
- input_stream_deinit(&i->base);
- g_free(i);
+ FfmpegInputStream *i = (FfmpegInputStream *)is;
+
+ delete i;
}
static bool
input_ffmpeg_eof(struct input_stream *is)
{
- struct input_ffmpeg *i = (struct input_ffmpeg *)is;
+ FfmpegInputStream *i = (FfmpegInputStream *)is;
return i->eof;
}
@@ -177,12 +156,8 @@ static bool
input_ffmpeg_seek(struct input_stream *is, goffset offset, int whence,
G_GNUC_UNUSED GError **error_r)
{
- struct input_ffmpeg *i = (struct input_ffmpeg *)is;
-#if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(53,0,0)
+ FfmpegInputStream *i = (FfmpegInputStream *)is;
int64_t ret = avio_seek(i->h, offset, whence);
-#else
- int64_t ret = url_seek(i->h, offset, whence);
-#endif
if (ret >= 0) {
i->eof = false;
@@ -194,11 +169,16 @@ input_ffmpeg_seek(struct input_stream *is, goffset offset, int whence,
}
const struct input_plugin input_plugin_ffmpeg = {
- .name = "ffmpeg",
- .init = input_ffmpeg_init,
- .open = input_ffmpeg_open,
- .close = input_ffmpeg_close,
- .read = input_ffmpeg_read,
- .eof = input_ffmpeg_eof,
- .seek = input_ffmpeg_seek,
+ "ffmpeg",
+ input_ffmpeg_init,
+ nullptr,
+ input_ffmpeg_open,
+ input_ffmpeg_close,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ input_ffmpeg_read,
+ input_ffmpeg_eof,
+ input_ffmpeg_seek,
};
diff --git a/src/input/ffmpeg_input_plugin.h b/src/input/FfmpegInputPlugin.hxx
index 393836ca..d5e3a8d9 100644
--- a/src/input/ffmpeg_input_plugin.h
+++ b/src/input/FfmpegInputPlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2011 The Music Player Daemon Project
+ * Copyright (C) 2003-2013 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -17,8 +17,8 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-#ifndef MPD_FFMPEG_INPUT_PLUGIN_H
-#define MPD_FFMPEG_INPUT_PLUGIN_H
+#ifndef MPD_FFMPEG_INPUT_PLUGIN_HXX
+#define MPD_FFMPEG_INPUT_PLUGIN_HXX
/**
* An input plugin based on libavformat's "avio" library.
diff --git a/src/input/file_input_plugin.c b/src/input/FileInputPlugin.cxx
index 5ee3f200..2eecf32b 100644
--- a/src/input/file_input_plugin.c
+++ b/src/input/FileInputPlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2011 The Music Player Daemon Project
+ * Copyright (C) 2003-2013 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -18,11 +18,13 @@
*/
#include "config.h" /* must be first for large file support */
-#include "input/file_input_plugin.h"
-#include "input_internal.h"
-#include "input_plugin.h"
+#include "FileInputPlugin.hxx"
+#include "InputInternal.hxx"
+#include "InputStream.hxx"
+#include "InputPlugin.hxx"
#include "fd_util.h"
#include "open.h"
+#include "io_error.h"
#include <sys/stat.h>
#include <unistd.h>
@@ -33,69 +35,67 @@
#undef G_LOG_DOMAIN
#define G_LOG_DOMAIN "input_file"
-struct file_input_stream {
+struct FileInputStream {
struct input_stream base;
int fd;
-};
-static inline GQuark
-file_quark(void)
-{
- return g_quark_from_static_string("file");
-}
+ FileInputStream(const char *path, int _fd, off_t size,
+ Mutex &mutex, Cond &cond)
+ :base(input_plugin_file, path, mutex, cond),
+ fd(_fd) {
+ base.size = size;
+ base.seekable = true;
+ base.ready = true;
+ }
+
+ ~FileInputStream() {
+ close(fd);
+ }
+};
static struct input_stream *
input_file_open(const char *filename,
- GMutex *mutex, GCond *cond,
+ Mutex &mutex, Cond &cond,
GError **error_r)
{
int fd, ret;
struct stat st;
- struct file_input_stream *fis;
if (!g_path_is_absolute(filename))
- return NULL;
+ return nullptr;
fd = open_cloexec(filename, O_RDONLY|O_BINARY, 0);
if (fd < 0) {
if (errno != ENOENT && errno != ENOTDIR)
- g_set_error(error_r, file_quark(), errno,
+ g_set_error(error_r, errno_quark(), errno,
"Failed to open \"%s\": %s",
filename, g_strerror(errno));
- return NULL;
+ return nullptr;
}
ret = fstat(fd, &st);
if (ret < 0) {
- g_set_error(error_r, file_quark(), errno,
+ g_set_error(error_r, errno_quark(), errno,
"Failed to stat \"%s\": %s",
filename, g_strerror(errno));
close(fd);
- return NULL;
+ return nullptr;
}
if (!S_ISREG(st.st_mode)) {
- g_set_error(error_r, file_quark(), 0,
+ g_set_error(error_r, errno_quark(), 0,
"Not a regular file: %s", filename);
close(fd);
- return NULL;
+ return nullptr;
}
#ifdef POSIX_FADV_SEQUENTIAL
posix_fadvise(fd, (off_t)0, st.st_size, POSIX_FADV_SEQUENTIAL);
#endif
- fis = g_new(struct file_input_stream, 1);
- input_stream_init(&fis->base, &input_plugin_file, filename,
- mutex, cond);
-
- fis->base.size = st.st_size;
- fis->base.seekable = true;
- fis->base.ready = true;
-
- fis->fd = fd;
-
+ FileInputStream *fis = new FileInputStream(filename, fd, st.st_size,
+ mutex, cond);
return &fis->base;
}
@@ -103,11 +103,11 @@ static bool
input_file_seek(struct input_stream *is, goffset offset, int whence,
GError **error_r)
{
- struct file_input_stream *fis = (struct file_input_stream *)is;
+ FileInputStream *fis = (FileInputStream *)is;
offset = (goffset)lseek(fis->fd, (off_t)offset, whence);
if (offset < 0) {
- g_set_error(error_r, file_quark(), errno,
+ g_set_error(error_r, errno_quark(), errno,
"Failed to seek: %s", g_strerror(errno));
return false;
}
@@ -120,12 +120,12 @@ static size_t
input_file_read(struct input_stream *is, void *ptr, size_t size,
GError **error_r)
{
- struct file_input_stream *fis = (struct file_input_stream *)is;
+ FileInputStream *fis = (FileInputStream *)is;
ssize_t nbytes;
nbytes = read(fis->fd, ptr, size);
if (nbytes < 0) {
- g_set_error(error_r, file_quark(), errno,
+ g_set_error(error_r, errno_quark(), errno,
"Failed to read: %s", g_strerror(errno));
return 0;
}
@@ -137,11 +137,9 @@ input_file_read(struct input_stream *is, void *ptr, size_t size,
static void
input_file_close(struct input_stream *is)
{
- struct file_input_stream *fis = (struct file_input_stream *)is;
+ FileInputStream *fis = (FileInputStream *)is;
- close(fis->fd);
- input_stream_deinit(&fis->base);
- g_free(fis);
+ delete fis;
}
static bool
@@ -151,10 +149,16 @@ input_file_eof(struct input_stream *is)
}
const struct input_plugin input_plugin_file = {
- .name = "file",
- .open = input_file_open,
- .close = input_file_close,
- .read = input_file_read,
- .eof = input_file_eof,
- .seek = input_file_seek,
+ "file",
+ nullptr,
+ nullptr,
+ input_file_open,
+ input_file_close,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ input_file_read,
+ input_file_eof,
+ input_file_seek,
};
diff --git a/src/input/file_input_plugin.h b/src/input/FileInputPlugin.hxx
index f24769d5..aacfd0b5 100644
--- a/src/input/file_input_plugin.h
+++ b/src/input/FileInputPlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2011 The Music Player Daemon Project
+ * Copyright (C) 2003-2013 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -17,8 +17,8 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-#ifndef MPD_INPUT_FILE_H
-#define MPD_INPUT_FILE_H
+#ifndef MPD_INPUT_FILE_HXX
+#define MPD_INPUT_FILE_HXX
extern const struct input_plugin input_plugin_file;
diff --git a/src/input/mms_input_plugin.c b/src/input/MmsInputPlugin.cxx
index cff15125..b347eb92 100644
--- a/src/input/mms_input_plugin.c
+++ b/src/input/MmsInputPlugin.cxx
@@ -18,9 +18,10 @@
*/
#include "config.h"
-#include "input/mms_input_plugin.h"
-#include "input_internal.h"
-#include "input_plugin.h"
+#include "MmsInputPlugin.hxx"
+#include "InputInternal.hxx"
+#include "InputStream.hxx"
+#include "InputPlugin.hxx"
#include <glib.h>
#include <libmms/mmsx.h>
@@ -31,12 +32,28 @@
#undef G_LOG_DOMAIN
#define G_LOG_DOMAIN "input_mms"
-struct input_mms {
+struct MmsInputStream {
struct input_stream base;
mmsx_t *mms;
bool eof;
+
+ MmsInputStream(const char *uri,
+ Mutex &mutex, Cond &cond,
+ mmsx_t *_mms)
+ :base(input_plugin_mms, uri, mutex, cond),
+ mms(_mms), eof(false) {
+ /* XX is this correct? at least this selects the ffmpeg
+ decoder, which seems to work fine*/
+ base.mime = g_strdup("audio/x-ms-wma");
+
+ base.ready = true;
+ }
+
+ ~MmsInputStream() {
+ mmsx_close(mms);
+ }
};
static inline GQuark
@@ -47,36 +64,22 @@ mms_quark(void)
static struct input_stream *
input_mms_open(const char *url,
- GMutex *mutex, GCond *cond,
+ Mutex &mutex, Cond &cond,
GError **error_r)
{
- struct input_mms *m;
-
if (!g_str_has_prefix(url, "mms://") &&
!g_str_has_prefix(url, "mmsh://") &&
!g_str_has_prefix(url, "mmst://") &&
!g_str_has_prefix(url, "mmsu://"))
- return NULL;
-
- m = g_new(struct input_mms, 1);
- input_stream_init(&m->base, &input_plugin_mms, url,
- mutex, cond);
+ return nullptr;
- m->mms = mmsx_connect(NULL, NULL, url, 128 * 1024);
- if (m->mms == NULL) {
- g_free(m);
+ const auto mms = mmsx_connect(nullptr, nullptr, url, 128 * 1024);
+ if (mms == nullptr) {
g_set_error(error_r, mms_quark(), 0, "mmsx_connect() failed");
- return NULL;
+ return nullptr;
}
- m->eof = false;
-
- /* XX is this correct? at least this selects the ffmpeg
- decoder, which seems to work fine*/
- m->base.mime = g_strdup("audio/x-ms-wma");
-
- m->base.ready = true;
-
+ auto m = new MmsInputStream(url, mutex, cond, mms);
return &m->base;
}
@@ -84,10 +87,10 @@ static size_t
input_mms_read(struct input_stream *is, void *ptr, size_t size,
GError **error_r)
{
- struct input_mms *m = (struct input_mms *)is;
+ MmsInputStream *m = (MmsInputStream *)is;
int ret;
- ret = mmsx_read(NULL, m->mms, ptr, size);
+ ret = mmsx_read(nullptr, m->mms, (char *)ptr, size);
if (ret <= 0) {
if (ret < 0) {
g_set_error(error_r, mms_quark(), errno,
@@ -107,17 +110,15 @@ input_mms_read(struct input_stream *is, void *ptr, size_t size,
static void
input_mms_close(struct input_stream *is)
{
- struct input_mms *m = (struct input_mms *)is;
+ MmsInputStream *m = (MmsInputStream *)is;
- mmsx_close(m->mms);
- input_stream_deinit(&m->base);
- g_free(m);
+ delete m;
}
static bool
input_mms_eof(struct input_stream *is)
{
- struct input_mms *m = (struct input_mms *)is;
+ MmsInputStream *m = (MmsInputStream *)is;
return m->eof;
}
@@ -131,10 +132,16 @@ input_mms_seek(G_GNUC_UNUSED struct input_stream *is,
}
const struct input_plugin input_plugin_mms = {
- .name = "mms",
- .open = input_mms_open,
- .close = input_mms_close,
- .read = input_mms_read,
- .eof = input_mms_eof,
- .seek = input_mms_seek,
+ "mms",
+ nullptr,
+ nullptr,
+ input_mms_open,
+ input_mms_close,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ input_mms_read,
+ input_mms_eof,
+ input_mms_seek,
};
diff --git a/src/input/mms_input_plugin.h b/src/input/MmsInputPlugin.hxx
index d6aa593f..d6aa593f 100644
--- a/src/input/mms_input_plugin.h
+++ b/src/input/MmsInputPlugin.hxx
diff --git a/src/input/rewind_input_plugin.c b/src/input/RewindInputPlugin.cxx
index cf06fc57..d93d7d1c 100644
--- a/src/input/rewind_input_plugin.c
+++ b/src/input/RewindInputPlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2011 The Music Player Daemon Project
+ * Copyright (C) 2003-2013 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -18,9 +18,10 @@
*/
#include "config.h"
-#include "input/rewind_input_plugin.h"
-#include "input_internal.h"
-#include "input_plugin.h"
+#include "RewindInputPlugin.hxx"
+#include "InputInternal.hxx"
+#include "InputStream.hxx"
+#include "InputPlugin.hxx"
#include "tag.h"
#include <glib.h>
@@ -31,14 +32,16 @@
#undef G_LOG_DOMAIN
#define G_LOG_DOMAIN "input_rewind"
-struct input_rewind {
+extern const struct input_plugin rewind_input_plugin;
+
+struct RewindInputStream {
struct input_stream base;
struct input_stream *input;
/**
* The read position within the buffer. Undefined as long as
- * reading_from_buffer() returns false.
+ * ReadingFromBuffer() returns false.
*/
size_t head;
@@ -56,61 +59,61 @@ struct input_rewind {
* stream (offset 0).
*/
char buffer[64 * 1024];
-};
-/**
- * Are we currently reading from the buffer, and does the buffer
- * contain more data for the next read operation?
- */
-static bool
-reading_from_buffer(const struct input_rewind *r)
-{
- return r->tail > 0 && r->base.offset < r->input->offset;
-}
+ RewindInputStream(input_stream *_input)
+ :base(rewind_input_plugin, _input->uri.c_str(),
+ _input->mutex, _input->cond),
+ input(_input), tail(0) {
+ }
-/**
- * Copy public attributes from the underlying input stream to the
- * "rewind" input stream. This function is called when a method of
- * the underlying stream has returned, which may have modified these
- * attributes.
- */
-static void
-copy_attributes(struct input_rewind *r)
-{
- struct input_stream *dest = &r->base;
- const struct input_stream *src = r->input;
+ ~RewindInputStream() {
+ input_stream_close(input);
+ }
- assert(dest != src);
- assert(src->mime == NULL || dest->mime != src->mime);
+ /**
+ * Are we currently reading from the buffer, and does the
+ * buffer contain more data for the next read operation?
+ */
+ bool ReadingFromBuffer() const {
+ return tail > 0 && base.offset < input->offset;
+ }
+
+ /**
+ * Copy public attributes from the underlying input stream to the
+ * "rewind" input stream. This function is called when a method of
+ * the underlying stream has returned, which may have modified these
+ * attributes.
+ */
+ void CopyAttributes() {
+ struct input_stream *dest = &base;
+ const struct input_stream *src = input;
+
+ assert(dest != src);
- bool dest_ready = dest->ready;
+ bool dest_ready = dest->ready;
- dest->ready = src->ready;
- dest->seekable = src->seekable;
- dest->size = src->size;
- dest->offset = src->offset;
+ dest->ready = src->ready;
+ dest->seekable = src->seekable;
+ dest->size = src->size;
+ dest->offset = src->offset;
- if (!dest_ready && src->ready) {
- g_free(dest->mime);
- dest->mime = g_strdup(src->mime);
+ if (!dest_ready && src->ready)
+ dest->mime = src->mime;
}
-}
+};
static void
input_rewind_close(struct input_stream *is)
{
- struct input_rewind *r = (struct input_rewind *)is;
-
- input_stream_close(r->input);
+ RewindInputStream *r = (RewindInputStream *)is;
- input_stream_deinit(&r->base);
- g_free(r);
+ delete r;
}
static bool
input_rewind_check(struct input_stream *is, GError **error_r)
{
- struct input_rewind *r = (struct input_rewind *)is;
+ RewindInputStream *r = (RewindInputStream *)is;
return input_stream_check(r->input, error_r);
}
@@ -118,16 +121,16 @@ input_rewind_check(struct input_stream *is, GError **error_r)
static void
input_rewind_update(struct input_stream *is)
{
- struct input_rewind *r = (struct input_rewind *)is;
+ RewindInputStream *r = (RewindInputStream *)is;
- if (!reading_from_buffer(r))
- copy_attributes(r);
+ if (!r->ReadingFromBuffer())
+ r->CopyAttributes();
}
static struct tag *
input_rewind_tag(struct input_stream *is)
{
- struct input_rewind *r = (struct input_rewind *)is;
+ RewindInputStream *r = (RewindInputStream *)is;
return input_stream_tag(r->input);
}
@@ -135,7 +138,7 @@ input_rewind_tag(struct input_stream *is)
static bool
input_rewind_available(struct input_stream *is)
{
- struct input_rewind *r = (struct input_rewind *)is;
+ RewindInputStream *r = (RewindInputStream *)is;
return input_stream_available(r->input);
}
@@ -144,9 +147,9 @@ static size_t
input_rewind_read(struct input_stream *is, void *ptr, size_t size,
GError **error_r)
{
- struct input_rewind *r = (struct input_rewind *)is;
+ RewindInputStream *r = (RewindInputStream *)is;
- if (reading_from_buffer(r)) {
+ if (r->ReadingFromBuffer()) {
/* buffered read */
assert(r->head == (size_t)is->offset);
@@ -177,7 +180,7 @@ input_rewind_read(struct input_stream *is, void *ptr, size_t size,
assert(r->tail == (size_t)r->input->offset);
}
- copy_attributes(r);
+ r->CopyAttributes();
return nbytes;
}
@@ -186,23 +189,23 @@ input_rewind_read(struct input_stream *is, void *ptr, size_t size,
static bool
input_rewind_eof(struct input_stream *is)
{
- struct input_rewind *r = (struct input_rewind *)is;
+ RewindInputStream *r = (RewindInputStream *)is;
- return !reading_from_buffer(r) && input_stream_eof(r->input);
+ return !r->ReadingFromBuffer() && input_stream_eof(r->input);
}
static bool
input_rewind_seek(struct input_stream *is, goffset offset, int whence,
GError **error_r)
{
- struct input_rewind *r = (struct input_rewind *)is;
+ RewindInputStream *r = (RewindInputStream *)is;
assert(is->ready);
if (whence == SEEK_SET && r->tail > 0 && offset <= (goffset)r->tail) {
/* buffered seek */
- assert(!reading_from_buffer(r) ||
+ assert(!r->ReadingFromBuffer() ||
r->head == (size_t)is->offset);
assert(r->tail == (size_t)r->input->offset);
@@ -213,7 +216,7 @@ input_rewind_seek(struct input_stream *is, goffset offset, int whence,
} else {
bool success = input_stream_seek(r->input, offset, whence,
error_r);
- copy_attributes(r);
+ r->CopyAttributes();
/* disable the buffer, because r->input has left the
buffered range now */
@@ -223,22 +226,24 @@ input_rewind_seek(struct input_stream *is, goffset offset, int whence,
}
}
-static const struct input_plugin rewind_input_plugin = {
- .close = input_rewind_close,
- .check = input_rewind_check,
- .update = input_rewind_update,
- .tag = input_rewind_tag,
- .available = input_rewind_available,
- .read = input_rewind_read,
- .eof = input_rewind_eof,
- .seek = input_rewind_seek,
+const struct input_plugin rewind_input_plugin = {
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ input_rewind_close,
+ input_rewind_check,
+ input_rewind_update,
+ input_rewind_tag,
+ input_rewind_available,
+ input_rewind_read,
+ input_rewind_eof,
+ input_rewind_seek,
};
struct input_stream *
input_rewind_open(struct input_stream *is)
{
- struct input_rewind *c;
-
assert(is != NULL);
assert(is->offset == 0);
@@ -246,11 +251,6 @@ input_rewind_open(struct input_stream *is)
/* seekable resources don't need this plugin */
return is;
- c = g_new(struct input_rewind, 1);
- input_stream_init(&c->base, &rewind_input_plugin, is->uri,
- is->mutex, is->cond);
- c->tail = 0;
- c->input = is;
-
+ RewindInputStream *c = new RewindInputStream(is);
return &c->base;
}
diff --git a/src/input/rewind_input_plugin.h b/src/input/RewindInputPlugin.hxx
index 83abe257..cf21e92f 100644
--- a/src/input/rewind_input_plugin.h
+++ b/src/input/RewindInputPlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2011 The Music Player Daemon Project
+ * Copyright (C) 2003-2013 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -24,8 +24,8 @@
* each decoder plugin peek a portion from the stream).
*/
-#ifndef MPD_INPUT_REWIND_H
-#define MPD_INPUT_REWIND_H
+#ifndef MPD_INPUT_REWIND_HXX
+#define MPD_INPUT_REWIND_HXX
#include "check.h"
diff --git a/src/input/soup_input_plugin.c b/src/input/SoupInputPlugin.cxx
index fc903b48..e9767c20 100644
--- a/src/input/soup_input_plugin.c
+++ b/src/input/SoupInputPlugin.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2011 The Music Player Daemon Project
+ * Copyright (C) 2003-2013 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -18,14 +18,18 @@
*/
#include "config.h"
-#include "input/soup_input_plugin.h"
-#include "input_internal.h"
-#include "input_plugin.h"
-#include "io_thread.h"
+#include "SoupInputPlugin.hxx"
+#include "InputPlugin.hxx"
+#include "InputStream.hxx"
+#include "InputInternal.hxx"
+#include "IOThread.hxx"
+#include "event/Loop.hxx"
#include "conf.h"
+extern "C" {
#include <libsoup/soup-uri.h>
#include <libsoup/soup-session-async.h>
+}
#include <assert.h>
#include <string.h>
@@ -48,7 +52,7 @@ static const size_t SOUP_RESUME_AT = 384 * 1024;
static SoupURI *soup_proxy;
static SoupSession *soup_session;
-struct input_soup {
+struct SoupInputStream {
struct input_stream base;
SoupMessage *msg;
@@ -68,6 +72,15 @@ struct input_soup {
bool completed;
GError *postponed_error;
+
+ SoupInputStream(const char *uri, Mutex &mutex, Cond &cond);
+ ~SoupInputStream();
+
+ bool CopyError(const SoupMessage *msg);
+
+ bool WaitData();
+
+ size_t Read(void *ptr, size_t size, GError **error_r);
};
static inline GQuark
@@ -99,7 +112,7 @@ input_soup_init(const struct config_param *param, GError **error_r)
soup_session_async_new_with_options(SOUP_SESSION_PROXY_URI,
soup_proxy,
SOUP_SESSION_ASYNC_CONTEXT,
- io_thread_context(),
+ io_thread_get().GetContext(),
NULL);
return true;
@@ -123,31 +136,31 @@ input_soup_finish(void)
*
* @return true if there was no error
*/
-static bool
-input_soup_copy_error(struct input_soup *s, const SoupMessage *msg)
+bool
+SoupInputStream::CopyError(const SoupMessage *src)
{
- if (SOUP_STATUS_IS_SUCCESSFUL(msg->status_code))
+ if (SOUP_STATUS_IS_SUCCESSFUL(src->status_code))
return true;
- if (msg->status_code == SOUP_STATUS_CANCELLED)
+ if (src->status_code == SOUP_STATUS_CANCELLED)
/* failure, but don't generate a GError, because this
status was caused by _close() */
return false;
- if (s->postponed_error != NULL)
+ if (postponed_error != nullptr)
/* there's already a GError, don't overwrite it */
return false;
- if (SOUP_STATUS_IS_TRANSPORT_ERROR(msg->status_code))
- s->postponed_error =
- g_error_new(soup_quark(), msg->status_code,
+ if (SOUP_STATUS_IS_TRANSPORT_ERROR(src->status_code))
+ postponed_error =
+ g_error_new(soup_quark(), src->status_code,
"HTTP client error: %s",
- msg->reason_phrase);
+ src->reason_phrase);
else
- s->postponed_error =
- g_error_new(soup_quark(), msg->status_code,
+ postponed_error =
+ g_error_new(soup_quark(), src->status_code,
"got HTTP status: %d %s",
- msg->status_code, msg->reason_phrase);
+ src->status_code, src->reason_phrase);
return false;
}
@@ -156,33 +169,32 @@ static void
input_soup_session_callback(G_GNUC_UNUSED SoupSession *session,
SoupMessage *msg, gpointer user_data)
{
- struct input_soup *s = user_data;
+ SoupInputStream *s = (SoupInputStream *)user_data;
assert(msg == s->msg);
assert(!s->completed);
- g_mutex_lock(s->base.mutex);
+ const ScopeLock protect(s->base.mutex);
if (!s->base.ready)
- input_soup_copy_error(s, msg);
+ s->CopyError(msg);
s->base.ready = true;
s->alive = false;
s->completed = true;
- g_cond_broadcast(s->base.cond);
- g_mutex_unlock(s->base.mutex);
+ s->base.cond.broadcast();
}
static void
input_soup_got_headers(SoupMessage *msg, gpointer user_data)
{
- struct input_soup *s = user_data;
+ SoupInputStream *s = (SoupInputStream *)user_data;
- g_mutex_lock(s->base.mutex);
+ s->base.mutex.lock();
- if (!input_soup_copy_error(s, msg)) {
- g_mutex_unlock(s->base.mutex);
+ if (!s->CopyError(msg)) {
+ s->base.mutex.unlock();
soup_session_cancel_message(soup_session, msg,
SOUP_STATUS_CANCELLED);
@@ -190,8 +202,8 @@ input_soup_got_headers(SoupMessage *msg, gpointer user_data)
}
s->base.ready = true;
- g_cond_broadcast(s->base.cond);
- g_mutex_unlock(s->base.mutex);
+ s->base.cond.broadcast();
+ s->base.mutex.unlock();
soup_message_body_set_accumulate(msg->response_body, false);
}
@@ -199,11 +211,11 @@ input_soup_got_headers(SoupMessage *msg, gpointer user_data)
static void
input_soup_got_chunk(SoupMessage *msg, SoupBuffer *chunk, gpointer user_data)
{
- struct input_soup *s = user_data;
+ SoupInputStream *s = (SoupInputStream *)user_data;
assert(msg == s->msg);
- g_mutex_lock(s->base.mutex);
+ const ScopeLock protect(s->base.mutex);
g_queue_push_tail(s->buffers, soup_buffer_copy(chunk));
s->total_buffered += chunk->length;
@@ -213,50 +225,50 @@ input_soup_got_chunk(SoupMessage *msg, SoupBuffer *chunk, gpointer user_data)
soup_session_pause_message(soup_session, msg);
}
- g_cond_broadcast(s->base.cond);
- g_mutex_unlock(s->base.mutex);
+ s->base.cond.broadcast();
+ s->base.mutex.unlock();
}
static void
input_soup_got_body(G_GNUC_UNUSED SoupMessage *msg, gpointer user_data)
{
- struct input_soup *s = user_data;
+ SoupInputStream *s = (SoupInputStream *)user_data;
assert(msg == s->msg);
- g_mutex_lock(s->base.mutex);
+ const ScopeLock protect(s->base.mutex);
s->base.ready = true;
s->eof = true;
s->alive = false;
- g_cond_broadcast(s->base.cond);
- g_mutex_unlock(s->base.mutex);
+ s->base.cond.broadcast();
+ s->base.mutex.unlock();
}
-static bool
-input_soup_wait_data(struct input_soup *s)
+inline bool
+SoupInputStream::WaitData()
{
while (true) {
- if (s->eof)
+ if (eof)
return true;
- if (!s->alive)
+ if (!alive)
return false;
- if (!g_queue_is_empty(s->buffers))
+ if (!g_queue_is_empty(buffers))
return true;
- assert(s->current_consumed == 0);
+ assert(current_consumed == 0);
- g_cond_wait(s->base.cond, s->base.mutex);
+ base.cond.wait(base.mutex);
}
}
static gpointer
input_soup_queue(gpointer data)
{
- struct input_soup *s = data;
+ SoupInputStream *s = (SoupInputStream *)data;
soup_session_queue_message(soup_session, s->msg,
input_soup_session_callback, s);
@@ -264,22 +276,14 @@ input_soup_queue(gpointer data)
return NULL;
}
-static struct input_stream *
-input_soup_open(const char *uri,
- GMutex *mutex, GCond *cond,
- G_GNUC_UNUSED GError **error_r)
+SoupInputStream::SoupInputStream(const char *uri,
+ Mutex &mutex, Cond &cond)
+ :base(input_plugin_soup, uri, mutex, cond),
+ buffers(g_queue_new()),
+ current_consumed(0), total_buffered(0),
+ alive(false), pause(false), eof(false), completed(false),
+ postponed_error(nullptr)
{
- if (strncmp(uri, "http://", 7) != 0)
- return NULL;
-
- struct input_soup *s = g_new(struct input_soup, 1);
- input_stream_init(&s->base, &input_plugin_soup, uri,
- mutex, cond);
-
- s->buffers = g_queue_new();
- s->current_consumed = 0;
- s->total_buffered = 0;
-
#if GCC_CHECK_VERSION(4,6)
#pragma GCC diagnostic push
/* the libsoup macro SOUP_METHOD_GET discards the "const"
@@ -288,39 +292,43 @@ input_soup_open(const char *uri,
#pragma GCC diagnostic ignored "-Wcast-qual"
#endif
- s->msg = soup_message_new(SOUP_METHOD_GET, uri);
+ msg = soup_message_new(SOUP_METHOD_GET, uri);
#if GCC_CHECK_VERSION(4,6)
#pragma GCC diagnostic pop
#endif
- soup_message_set_flags(s->msg, SOUP_MESSAGE_NO_REDIRECT);
+ soup_message_set_flags(msg, SOUP_MESSAGE_NO_REDIRECT);
- soup_message_headers_append(s->msg->request_headers, "User-Agent",
+ soup_message_headers_append(msg->request_headers, "User-Agent",
"Music Player Daemon " VERSION);
- g_signal_connect(s->msg, "got-headers",
- G_CALLBACK(input_soup_got_headers), s);
- g_signal_connect(s->msg, "got-chunk",
- G_CALLBACK(input_soup_got_chunk), s);
- g_signal_connect(s->msg, "got-body",
- G_CALLBACK(input_soup_got_body), s);
+ g_signal_connect(msg, "got-headers",
+ G_CALLBACK(input_soup_got_headers), this);
+ g_signal_connect(msg, "got-chunk",
+ G_CALLBACK(input_soup_got_chunk), this);
+ g_signal_connect(msg, "got-body",
+ G_CALLBACK(input_soup_got_body), this);
- s->alive = true;
- s->pause = false;
- s->eof = false;
- s->completed = false;
- s->postponed_error = NULL;
+ io_thread_call(input_soup_queue, this);
+}
- io_thread_call(input_soup_queue, s);
+static struct input_stream *
+input_soup_open(const char *uri,
+ Mutex &mutex, Cond &cond,
+ G_GNUC_UNUSED GError **error_r)
+{
+ if (strncmp(uri, "http://", 7) != 0)
+ return NULL;
+ SoupInputStream *s = new SoupInputStream(uri, mutex, cond);
return &s->base;
}
static gpointer
input_soup_cancel(gpointer data)
{
- struct input_soup *s = data;
+ SoupInputStream *s = (SoupInputStream *)data;
if (!s->completed)
soup_session_cancel_message(soup_session, s->msg,
@@ -329,44 +337,46 @@ input_soup_cancel(gpointer data)
return NULL;
}
-static void
-input_soup_close(struct input_stream *is)
+SoupInputStream::~SoupInputStream()
{
- struct input_soup *s = (struct input_soup *)is;
-
- g_mutex_lock(s->base.mutex);
+ base.mutex.lock();
- if (!s->completed) {
+ if (!completed) {
/* the messages's session callback hasn't been invoked
yet; cancel it and wait for completion */
- g_mutex_unlock(s->base.mutex);
+ base.mutex.unlock();
- io_thread_call(input_soup_cancel, s);
+ io_thread_call(input_soup_cancel, this);
- g_mutex_lock(s->base.mutex);
- while (!s->completed)
- g_cond_wait(s->base.cond, s->base.mutex);
+ base.mutex.lock();
+ while (!completed)
+ base.cond.wait(base.mutex);
}
- g_mutex_unlock(s->base.mutex);
+ base.mutex.unlock();
SoupBuffer *buffer;
- while ((buffer = g_queue_pop_head(s->buffers)) != NULL)
+ while ((buffer = (SoupBuffer *)g_queue_pop_head(buffers)) != NULL)
soup_buffer_free(buffer);
- g_queue_free(s->buffers);
+ g_queue_free(buffers);
- if (s->postponed_error != NULL)
- g_error_free(s->postponed_error);
+ if (postponed_error != NULL)
+ g_error_free(postponed_error);
+}
+
+static void
+input_soup_close(struct input_stream *is)
+{
+ SoupInputStream *s = (SoupInputStream *)is;
- input_stream_deinit(&s->base);
- g_free(s);
+ delete s;
}
static bool
input_soup_check(struct input_stream *is, GError **error_r)
{
- struct input_soup *s = (struct input_soup *)is;
+ SoupInputStream *s = (SoupInputStream *)is;
bool success = s->postponed_error == NULL;
if (!success) {
@@ -380,45 +390,43 @@ input_soup_check(struct input_stream *is, GError **error_r)
static bool
input_soup_available(struct input_stream *is)
{
- struct input_soup *s = (struct input_soup *)is;
+ SoupInputStream *s = (SoupInputStream *)is;
return s->eof || !s->alive || !g_queue_is_empty(s->buffers);
}
-static size_t
-input_soup_read(struct input_stream *is, void *ptr, size_t size,
- G_GNUC_UNUSED GError **error_r)
+inline size_t
+SoupInputStream::Read(void *ptr, size_t size, GError **error_r)
{
- struct input_soup *s = (struct input_soup *)is;
+ if (!WaitData()) {
+ assert(!alive);
- if (!input_soup_wait_data(s)) {
- assert(!s->alive);
-
- if (s->postponed_error != NULL) {
- g_propagate_error(error_r, s->postponed_error);
- s->postponed_error = NULL;
+ if (postponed_error != nullptr) {
+ g_propagate_error(error_r, postponed_error);
+ postponed_error = nullptr;
} else
g_set_error_literal(error_r, soup_quark(), 0,
"HTTP failure");
return 0;
}
- char *p0 = ptr, *p = p0, *p_end = p0 + size;
+ char *p0 = (char *)ptr, *p = p0, *p_end = p0 + size;
while (p < p_end) {
- SoupBuffer *buffer = g_queue_pop_head(s->buffers);
+ SoupBuffer *buffer = (SoupBuffer *)
+ g_queue_pop_head(buffers);
if (buffer == NULL) {
- assert(s->current_consumed == 0);
+ assert(current_consumed == 0);
break;
}
- assert(s->current_consumed < buffer->length);
- assert(s->total_buffered >= buffer->length);
+ assert(current_consumed < buffer->length);
+ assert(total_buffered >= buffer->length);
const char *q = buffer->data;
- q += s->current_consumed;
+ q += current_consumed;
- size_t remaining = buffer->length - s->current_consumed;
+ size_t remaining = buffer->length - current_consumed;
size_t nbytes = p_end - p;
if (nbytes > remaining)
nbytes = remaining;
@@ -426,48 +434,59 @@ input_soup_read(struct input_stream *is, void *ptr, size_t size,
memcpy(p, q, nbytes);
p += nbytes;
- s->current_consumed += remaining;
- if (s->current_consumed >= buffer->length) {
+ current_consumed += remaining;
+ if (current_consumed >= buffer->length) {
/* done with this buffer */
- s->total_buffered -= buffer->length;
+ total_buffered -= buffer->length;
soup_buffer_free(buffer);
- s->current_consumed = 0;
+ current_consumed = 0;
} else {
/* partial read */
assert(p == p_end);
- g_queue_push_head(s->buffers, buffer);
+ g_queue_push_head(buffers, buffer);
}
}
- if (s->pause && s->total_buffered < SOUP_RESUME_AT) {
- s->pause = false;
- soup_session_unpause_message(soup_session, s->msg);
+ if (pause && total_buffered < SOUP_RESUME_AT) {
+ pause = false;
+ soup_session_unpause_message(soup_session, msg);
}
size_t nbytes = p - p0;
- s->base.offset += nbytes;
+ base.offset += nbytes;
return nbytes;
}
+static size_t
+input_soup_read(struct input_stream *is, void *ptr, size_t size,
+ GError **error_r)
+{
+ SoupInputStream *s = (SoupInputStream *)is;
+
+ return s->Read(ptr, size, error_r);
+}
+
static bool
input_soup_eof(G_GNUC_UNUSED struct input_stream *is)
{
- struct input_soup *s = (struct input_soup *)is;
+ SoupInputStream *s = (SoupInputStream *)is;
return !s->alive && g_queue_is_empty(s->buffers);
}
const struct input_plugin input_plugin_soup = {
- .name = "soup",
- .init = input_soup_init,
- .finish = input_soup_finish,
-
- .open = input_soup_open,
- .close = input_soup_close,
- .check = input_soup_check,
- .available = input_soup_available,
- .read = input_soup_read,
- .eof = input_soup_eof,
+ "soup",
+ input_soup_init,
+ input_soup_finish,
+ input_soup_open,
+ input_soup_close,
+ input_soup_check,
+ nullptr,
+ nullptr,
+ input_soup_available,
+ input_soup_read,
+ input_soup_eof,
+ nullptr,
};
diff --git a/src/input/soup_input_plugin.h b/src/input/SoupInputPlugin.hxx
index 689b2d97..4c089b39 100644
--- a/src/input/soup_input_plugin.h
+++ b/src/input/SoupInputPlugin.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2011 The Music Player Daemon Project
+ * Copyright (C) 2003-2013 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -17,8 +17,8 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-#ifndef MPD_INPUT_SOUP_H
-#define MPD_INPUT_SOUP_H
+#ifndef MPD_INPUT_SOUP_HXX
+#define MPD_INPUT_SOUP_HXX
extern const struct input_plugin input_plugin_soup;