Handle streams separately in tree_add_track()
[cmus.git] / modplug.c
blobb4a5d05fa17eec1298bdf7e28102ec62741e7464
1 /*
2 * Copyright 2005 Timo Hirvonen
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
17 * 02111-1307, USA.
20 #include "ip.h"
21 #include "file.h"
22 #include "xmalloc.h"
24 #include <modplug.h>
25 #include <sys/types.h>
26 #include <unistd.h>
27 #include <stdlib.h>
28 #include <errno.h>
30 struct mod_private {
31 ModPlugFile *file;
34 static int mod_open(struct input_plugin_data *ip_data)
36 struct mod_private *priv;
37 char *contents;
38 int size, rc;
39 ModPlugFile *file;
40 ModPlug_Settings settings;
42 size = lseek(ip_data->fd, 0, SEEK_END);
43 if (size == -1)
44 return -IP_ERROR_ERRNO;
45 if (lseek(ip_data->fd, 0, SEEK_SET) == -1)
46 return -IP_ERROR_ERRNO;
48 contents = xnew(char, size);
49 rc = read_all(ip_data->fd, contents, size);
50 if (rc == -1) {
51 int save = errno;
53 free(contents);
54 errno = save;
55 return -IP_ERROR_ERRNO;
57 if (rc != size) {
58 free(contents);
59 return -IP_ERROR_FILE_FORMAT;
61 errno = 0;
62 file = ModPlug_Load(contents, size);
63 if (file == NULL) {
64 int save = errno;
66 free(contents);
67 errno = save;
68 if (errno == 0) {
69 /* libmodplug never sets errno? */
70 return -IP_ERROR_FILE_FORMAT;
72 return -IP_ERROR_ERRNO;
74 free(contents);
76 priv = xnew(struct mod_private, 1);
77 priv->file = file;
79 ModPlug_GetSettings(&settings);
80 settings.mFlags = MODPLUG_ENABLE_OVERSAMPLING | MODPLUG_ENABLE_NOISE_REDUCTION;
81 /* settings.mFlags |= MODPLUG_ENABLE_REVERB; */
82 /* settings.mFlags |= MODPLUG_ENABLE_MEGABASS; */
83 /* settings.mFlags |= MODPLUG_ENABLE_SURROUND; */
84 settings.mChannels = 2;
85 settings.mBits = 16;
86 settings.mFrequency = 44100;
87 settings.mResamplingMode = MODPLUG_RESAMPLE_FIR;
88 ModPlug_SetSettings(&settings);
90 ip_data->private = priv;
91 ip_data->sf = sf_bits(16) | sf_rate(44100) | sf_channels(2) | sf_signed(1);
92 return 0;
95 static int mod_close(struct input_plugin_data *ip_data)
97 struct mod_private *priv = ip_data->private;
99 ModPlug_Unload(priv->file);
100 free(priv);
101 ip_data->private = NULL;
102 return 0;
105 static int mod_read(struct input_plugin_data *ip_data, char *buffer, int count)
107 struct mod_private *priv = ip_data->private;
108 int rc;
110 errno = 0;
111 rc = ModPlug_Read(priv->file, buffer, count);
112 if (rc < 0) {
113 if (errno == 0)
114 return -IP_ERROR_INTERNAL;
115 return -IP_ERROR_ERRNO;
117 return rc;
120 static int mod_seek(struct input_plugin_data *ip_data, double offset)
122 struct mod_private *priv = ip_data->private;
123 int ms = (int)(offset * 1000.0 + 0.5);
125 /* void */
126 ModPlug_Seek(priv->file, ms);
127 return 0;
130 static int mod_read_comments(struct input_plugin_data *ip_data, struct keyval **comments)
132 struct mod_private *priv = ip_data->private;
133 struct keyval *c;
134 const char *name;
136 c = xnew0(struct keyval, 2);
137 name = ModPlug_GetName(priv->file);
138 if (name != NULL && *name != 0) {
139 c[0].key = xstrdup("title");
140 c[0].val = xstrdup(name);
142 *comments = c;
143 return 0;
146 static int mod_duration(struct input_plugin_data *ip_data)
148 struct mod_private *priv = ip_data->private;
150 return (ModPlug_GetLength(priv->file) + 500) / 1000;
153 const struct input_plugin_ops ip_ops = {
154 .open = mod_open,
155 .close = mod_close,
156 .read = mod_read,
157 .seek = mod_seek,
158 .read_comments = mod_read_comments,
159 .duration = mod_duration
162 const char * const ip_extensions[] = {
163 "mod", "s3m", "xm", "it", "669", "amf", "ams", "dbm", "dmf", "dsm",
164 "far", "mdl", "med", "mtm", "okt", "ptm", "stm", "ult", "umx", "mt2",
165 "psm", "mdz", "s3z", "xmz", "itz", "mdr", "s3r", "xmr", "itr", "mdgz",
166 "s3gz", "xmgz", "itgz", NULL
168 const char * const ip_mime_types[] = { NULL };