FlacIOHandle.cxx 2.59 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
/*
 * Copyright (C) 2003-2012 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"
21
#include "FlacIOHandle.hxx"
22 23 24 25 26 27
#include "io_error.h"
#include "gcc.h"

#include <errno.h>

static size_t
28
FlacIORead(void *ptr, size_t size, size_t nmemb, FLAC__IOHandle handle)
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
{
	input_stream *is = (input_stream *)handle;

	uint8_t *const p0 = (uint8_t *)ptr, *p = p0,
		*const end = p0 + size * nmemb;

	/* libFLAC is very picky about short reads, and expects the IO
	   callback to fill the whole buffer (undocumented!) */

	GError *error = nullptr;
	while (p < end) {
		size_t nbytes = input_stream_lock_read(is, p, end - p, &error);
		if (nbytes == 0) {
			if (error == nullptr)
				/* end of file */
				break;

			if (error->domain == errno_quark())
				errno = error->code;
			else
				/* just some random non-zero
				   errno value */
				errno = EINVAL;
			g_error_free(error);
			return 0;
		}

		p += nbytes;
	}

	/* libFLAC expects a clean errno after returning from the IO
	   callbacks (undocumented!) */
	errno = 0;
	return (p - p0) / size;
}

static int
66
FlacIOSeek(FLAC__IOHandle handle, FLAC__int64 offset, int whence)
67 68 69 70 71 72 73
{
	input_stream *is = (input_stream *)handle;

	return input_stream_lock_seek(is, offset, whence, nullptr) ? 0 : -1;
}

static FLAC__int64
74
FlacIOTell(FLAC__IOHandle handle)
75 76 77 78 79 80 81
{
	input_stream *is = (input_stream *)handle;

	return is->offset;
}

static int
82
FlacIOEof(FLAC__IOHandle handle)
83 84 85 86 87 88 89
{
	input_stream *is = (input_stream *)handle;

	return input_stream_lock_eof(is);
}

static int
90
FlacIOClose(gcc_unused FLAC__IOHandle handle)
91 92 93 94 95 96 97 98
{
	/* no-op because the libFLAC caller is repsonsible for closing
	   the #input_stream */

	return 0;
}

const FLAC__IOCallbacks flac_io_callbacks = {
99
	FlacIORead,
100 101 102
	nullptr,
	nullptr,
	nullptr,
103 104
	FlacIOEof,
	FlacIOClose,
105 106 107
};

const FLAC__IOCallbacks flac_io_callbacks_seekable = {
108
	FlacIORead,
109
	nullptr,
110 111 112 113
	FlacIOSeek,
	FlacIOTell,
	FlacIOEof,
	FlacIOClose,
114
};