summaryrefslogtreecommitdiff
path: root/community/cmus/cmus-2.5.0-opus-support.patch
diff options
context:
space:
mode:
Diffstat (limited to 'community/cmus/cmus-2.5.0-opus-support.patch')
-rw-r--r--community/cmus/cmus-2.5.0-opus-support.patch417
1 files changed, 417 insertions, 0 deletions
diff --git a/community/cmus/cmus-2.5.0-opus-support.patch b/community/cmus/cmus-2.5.0-opus-support.patch
new file mode 100644
index 000000000..80692e9da
--- /dev/null
+++ b/community/cmus/cmus-2.5.0-opus-support.patch
@@ -0,0 +1,417 @@
+diff -rupN cmus-v2.5.0/Makefile cmus/Makefile
+--- cmus-v2.5.0/Makefile 2012-11-07 09:46:17.000000000 +0100
++++ cmus/Makefile 2013-01-04 07:15:35.293069953 +0100
+@@ -74,6 +74,7 @@ mikmod-objs := mikmod.lo
+ modplug-objs := modplug.lo
+ mpc-objs := mpc.lo
+ vorbis-objs := vorbis.lo
++opus-objs := opus.lo
+ wavpack-objs := wavpack.lo
+ wav-objs := wav.lo
+ mp4-objs := mp4.lo
+@@ -88,6 +89,7 @@ ip-$(CONFIG_MIKMOD) += mikmod.so
+ ip-$(CONFIG_MODPLUG) += modplug.so
+ ip-$(CONFIG_MPC) += mpc.so
+ ip-$(CONFIG_VORBIS) += vorbis.so
++ip-$(CONFIG_OPUS) += opus.so
+ ip-$(CONFIG_WAVPACK) += wavpack.so
+ ip-$(CONFIG_WAV) += wav.so
+ ip-$(CONFIG_MP4) += mp4.so
+@@ -102,6 +104,7 @@ $(mikmod-objs): CFLAGS += $(MIKMOD_CFLA
+ $(modplug-objs): CFLAGS += $(MODPLUG_CFLAGS)
+ $(mpc-objs): CFLAGS += $(MPC_CFLAGS)
+ $(vorbis-objs): CFLAGS += $(VORBIS_CFLAGS)
++$(opus-objs): CFLAGS += $(OPUS_CFLAGS)
+ $(wavpack-objs): CFLAGS += $(WAVPACK_CFLAGS)
+ $(mp4-objs): CFLAGS += $(MP4_CFLAGS)
+ $(aac-objs): CFLAGS += $(AAC_CFLAGS)
+@@ -129,6 +132,9 @@ mpc.so: $(mpc-objs) $(libcmus-y)
+ vorbis.so: $(vorbis-objs) $(libcmus-y)
+ $(call cmd,ld_dl,$(VORBIS_LIBS))
+
++opus.so: $(opus-objs) $(libcmus-y)
++ $(call cmd,ld_dl,$(OPUS_LIBS))
++
+ wavpack.so: $(wavpack-objs) $(libcmus-y)
+ $(call cmd,ld_dl,$(WAVPACK_LIBS))
+
+diff -rupN cmus-v2.5.0/configure cmus/configure
+--- cmus-v2.5.0/configure 2012-11-07 09:46:17.000000000 +0100
++++ cmus/configure 2013-01-04 07:15:35.293069953 +0100
+@@ -228,6 +228,12 @@ check_vorbis()
+ fi
+ }
+
++check_opus()
++{
++ pkg_config OPUS "opusfile"
++ return $?
++}
++
+ check_wavpack()
+ {
+ pkg_config WAVPACK "wavpack" "" "-lwavpack"
+@@ -425,6 +431,7 @@ Optional Features: y/n
+ CONFIG_MPC libmpcdec (Musepack .mpc, .mpp, .mp+) [auto]
+ CONFIG_VORBIS Ogg/Vorbis (.ogg, application/ogg, audio/x-ogg) [auto]
+ CONFIG_TREMOR Use Tremor as Ogg/Vorbis input plugin [n]
++ CONFIG_OPUS Opus (.opus) [auto]
+ CONFIG_WAV WAV [y]
+ CONFIG_WAVPACK WavPack (.wv, audio/x-wavpack) [auto]
+ CONFIG_MP4 MPEG-4 AAC (.mp4, .m4a, .m4b) [auto]
+@@ -485,6 +492,7 @@ check check_mikmod CONFIG_MIKMOD
+ check check_modplug CONFIG_MODPLUG
+ check check_mpc CONFIG_MPC
+ check check_vorbis CONFIG_VORBIS
++check check_opus CONFIG_OPUS
+ check check_wavpack CONFIG_WAVPACK
+ check check_mp4 CONFIG_MP4
+ check check_aac CONFIG_AAC
+@@ -534,7 +542,7 @@ config_header config/cue.h CONFIG_CUE
+ CFLAGS="${CFLAGS} -DHAVE_CONFIG"
+
+ makefile_vars bindir datadir libdir mandir exampledir
+-makefile_vars CONFIG_CDIO CONFIG_FLAC CONFIG_MAD CONFIG_MIKMOD CONFIG_MODPLUG CONFIG_MPC CONFIG_VORBIS CONFIG_WAVPACK CONFIG_WAV CONFIG_MP4 CONFIG_AAC CONFIG_FFMPEG CONFIG_CUE
++makefile_vars CONFIG_CDIO CONFIG_FLAC CONFIG_MAD CONFIG_MIKMOD CONFIG_MODPLUG CONFIG_MPC CONFIG_VORBIS CONFIG_OPUS CONFIG_WAVPACK CONFIG_WAV CONFIG_MP4 CONFIG_AAC CONFIG_FFMPEG CONFIG_CUE
+ makefile_vars CONFIG_ROAR CONFIG_PULSE CONFIG_ALSA CONFIG_AO CONFIG_ARTS CONFIG_OSS CONFIG_SUN CONFIG_WAVEOUT
+
+ generate_config_mk
+diff -rupN cmus-v2.5.0/opus.c cmus/opus.c
+--- cmus-v2.5.0/opus.c 1970-01-01 01:00:00.000000000 +0100
++++ cmus/opus.c 2013-01-04 07:15:35.493069945 +0100
+@@ -0,0 +1,335 @@
++/*
++ * Copyright 2008-2012 Various Authors
++ * Copyright 2004-2005 Timo Hirvonen
++ *
++ * 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, see <http://www.gnu.org/licenses/>.
++ */
++
++#include "ip.h"
++#include "xmalloc.h"
++#include "read_wrapper.h"
++#include "debug.h"
++#include "comment.h"
++
++#include <opusfile.h>
++
++#include <errno.h>
++#include <string.h>
++#include <sys/types.h>
++#include <unistd.h>
++
++#define SAMPLING_RATE 48000
++#define CHANNELS 2
++
++struct opus_private {
++ OggOpusFile *of;
++ int current_link;
++};
++
++static int read_func(void *datasource, unsigned char *ptr, int size)
++{
++ struct input_plugin_data *ip_data = datasource;
++ return read_wrapper(ip_data, ptr, size);
++}
++
++static int seek_func(void *datasource, opus_int64 offset, int whence)
++{
++ struct input_plugin_data *ip_data = datasource;
++ return lseek(ip_data->fd, offset, whence);
++}
++
++static int close_func(void *datasource)
++{
++ struct input_plugin_data *ip_data;
++ int rc;
++
++ ip_data = datasource;
++ rc = close(ip_data->fd);
++ ip_data->fd = -1;
++ return rc;
++}
++
++static opus_int64 tell_func(void *datasource)
++{
++ struct input_plugin_data *ip_data = datasource;
++ return lseek(ip_data->fd, 0, SEEK_CUR);
++}
++
++static OpusFileCallbacks callbacks = {
++ .read = read_func,
++ .seek = seek_func,
++ .tell = tell_func,
++ .close = close_func
++};
++
++static int opus_open(struct input_plugin_data *ip_data)
++{
++ struct opus_private *priv;
++ int rc;
++ void *source;
++
++ priv = xnew(struct opus_private, 1);
++ priv->current_link = -1;
++ priv->of = NULL;
++
++ source = op_fdopen(&callbacks, ip_data->fd, "r");
++ if (source == NULL) {
++ free(priv);
++ return -IP_ERROR_INTERNAL;
++ }
++
++ priv->of = op_open_callbacks(source, &callbacks, NULL, 0, &rc);
++ if (rc != 0) {
++ d_print("op_open_callbacks failed: %d:%s\n", rc, strerror(rc));
++ free(priv);
++ /* ogg is a container format, so it is likely to contain
++ * something else if it isn't opus */
++ return -IP_ERROR_UNSUPPORTED_FILE_TYPE;
++ }
++ ip_data->private = priv;
++
++ ip_data->sf = sf_rate(SAMPLING_RATE)
++ | sf_channels(CHANNELS)
++ | sf_bits(16)
++ | sf_signed(1);
++#ifdef WORDS_BIGENDIAN
++ ip_data->sf |= sf_bigendian(1);
++#endif
++ return 0;
++}
++
++static int opus_close(struct input_plugin_data *ip_data)
++{
++ struct opus_private *priv = ip_data->private;
++ /* this closes ip_data->fd! */
++ op_free(priv->of);
++ ip_data->fd = -1;
++ free(priv);
++ ip_data->private = NULL;
++ return 0;
++}
++
++/*
++ * -n
++ * indicates error
++ * 0
++ * indicates EOF
++ * n
++ * indicates actual number of bytes read
++ */
++static int opus_read(struct input_plugin_data *ip_data, char *buffer, int count)
++{
++ struct opus_private *priv;
++ int samples, current_link, rc;
++
++ priv = ip_data->private;
++
++ /* samples = number of samples read per channel */
++ samples = op_read_stereo(priv->of, (opus_int16*)buffer,
++ count / sizeof(opus_int16));
++ if (samples < 0) {
++ switch (samples) {
++ case OP_HOLE:
++ errno = EAGAIN;
++ rc = -1;
++ break;
++ case OP_EREAD:
++ errno = EINVAL;
++ rc = -1;
++ break;
++ case OP_EFAULT:
++ errno = EINVAL;
++ rc = -1;
++ break;
++ case OP_EIMPL:
++ rc = -IP_ERROR_FUNCTION_NOT_SUPPORTED;
++ break;
++ case OP_EINVAL:
++ errno = EINVAL;
++ rc = -1;
++ break;
++ case OP_ENOTFORMAT:
++ rc = -IP_ERROR_FILE_FORMAT;
++ break;
++ case OP_EBADHEADER:
++ rc = -IP_ERROR_FILE_FORMAT;
++ break;
++ case OP_EVERSION:
++ rc = -IP_ERROR_FILE_FORMAT;
++ break;
++ case OP_EBADPACKET:
++ errno = EINVAL;
++ rc = -1;
++ break;
++ case OP_EBADLINK:
++ errno = EINVAL;
++ rc = -1;
++ break;
++ case OP_EBADTIMESTAMP:
++ rc = -IP_ERROR_FILE_FORMAT;
++ break;
++ default:
++ d_print("error: %d\n", samples);
++ rc = -IP_ERROR_FILE_FORMAT;
++ }
++ } else if (samples == 0) {
++ /* EOF or buffer too small */
++ rc = 0;
++ } else {
++ current_link = op_current_link(priv->of);
++ if (current_link < 0) {
++ d_print("error: %d\n", current_link);
++ rc = -1;
++ } else {
++ if (ip_data->remote && current_link != priv->current_link) {
++ ip_data->metadata_changed = 1;
++ priv->current_link = current_link;
++ }
++
++ /* bytes = samples * channels * sample_size */
++ rc = samples * CHANNELS * sizeof(opus_int16);
++ }
++ }
++
++ return rc;
++}
++
++static int opus_seek(struct input_plugin_data *ip_data, double offset)
++{
++ struct opus_private *priv;
++ int rc;
++
++ priv = ip_data->private;
++
++ rc = op_pcm_seek(priv->of, offset * SAMPLING_RATE);
++ switch (rc) {
++ case OP_ENOSEEK:
++ return -IP_ERROR_FUNCTION_NOT_SUPPORTED;
++ case OP_EINVAL:
++ return -IP_ERROR_INTERNAL;
++ case OP_EREAD:
++ return -IP_ERROR_INTERNAL;
++ case OP_EFAULT:
++ return -IP_ERROR_INTERNAL;
++ case OP_EBADLINK:
++ return -IP_ERROR_INTERNAL;
++ }
++ return 0;
++}
++
++static int opus_read_comments(struct input_plugin_data *ip_data,
++ struct keyval **comments)
++{
++ GROWING_KEYVALS(c);
++ struct opus_private *priv;
++ const OpusTags *ot;
++ int i;
++
++ priv = ip_data->private;
++
++ ot = op_tags(priv->of, -1);
++ if (ot == NULL) {
++ d_print("ot == NULL\n");
++ *comments = keyvals_new(0);
++ return 0;
++ }
++
++ for (i = 0; i < ot->comments; i++) {
++ const char *str = ot->user_comments[i];
++ const char *eq = strchr(str, '=');
++ char *key;
++
++ if (!eq) {
++ d_print("invalid comment: '%s' ('=' expected)\n", str);
++ continue;
++ }
++
++ key = xstrndup(str, eq - str);
++ comments_add_const(&c, key, eq + 1);
++ free(key);
++ }
++ keyvals_terminate(&c);
++ *comments = c.keyvals;
++ return 0;
++}
++
++static int opus_duration(struct input_plugin_data *ip_data)
++{
++ struct opus_private *priv;
++ ogg_int64_t samples;
++
++ priv = ip_data->private;
++
++ samples = op_pcm_total(priv->of, -1);
++ if (samples < 0)
++ return -IP_ERROR_FUNCTION_NOT_SUPPORTED;
++
++ return samples / SAMPLING_RATE;
++}
++
++static long opus_bitrate(struct input_plugin_data *ip_data)
++{
++ struct opus_private *priv;
++ opus_int32 bitrate;
++
++ priv = ip_data->private;
++
++ bitrate = op_bitrate(priv->of, -1);
++ if (bitrate < 0)
++ return -IP_ERROR_FUNCTION_NOT_SUPPORTED;
++ else
++ return bitrate;
++}
++
++static long opus_current_bitrate(struct input_plugin_data *ip_data)
++{
++ struct opus_private *priv;
++ opus_int32 bitrate;
++
++ priv = ip_data->private;
++
++ bitrate = op_bitrate_instant(priv->of);
++ if (bitrate < 0)
++ return -IP_ERROR_FUNCTION_NOT_SUPPORTED;
++ else
++ return bitrate;
++}
++
++static char *opus_codec(struct input_plugin_data *ip_data)
++{
++ return xstrdup("opus");
++}
++
++static char *opus_codec_profile(struct input_plugin_data *ip_data)
++{
++ return NULL;
++}
++
++const struct input_plugin_ops ip_ops = {
++ .open = opus_open,
++ .close = opus_close,
++ .read = opus_read,
++ .seek = opus_seek,
++ .read_comments = opus_read_comments,
++ .duration = opus_duration,
++ .bitrate = opus_bitrate,
++ .bitrate_current = opus_current_bitrate,
++ .codec = opus_codec,
++ .codec_profile = opus_codec_profile
++};
++
++const int ip_priority = 50;
++const char * const ip_extensions[] = { "opus", NULL };
++const char * const ip_mime_types[] = { NULL };
++const char * const ip_options[] = { NULL };