aboutsummaryrefslogtreecommitdiff
path: root/src/plugins/ogg_extractor.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/ogg_extractor.c')
-rw-r--r--src/plugins/ogg_extractor.c178
1 files changed, 129 insertions, 49 deletions
diff --git a/src/plugins/ogg_extractor.c b/src/plugins/ogg_extractor.c
index a9c4f05..971ac8c 100644
--- a/src/plugins/ogg_extractor.c
+++ b/src/plugins/ogg_extractor.c
@@ -1,10 +1,10 @@
1/* 1/*
2 This file is part of libextractor. 2 This file is part of libextractor.
3 (C) 2002, 2003, 2009 Vidyut Samanta and Christian Grothoff 3 (C) 2002, 2003, 2009, 2012 Vidyut Samanta and Christian Grothoff
4 4
5 libextractor is free software; you can redistribute it and/or modify 5 libextractor is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published 6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 2, or (at your 7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version. 8 option) any later version.
9 9
10 libextractor is distributed in the hope that it will be useful, but 10 libextractor is distributed in the hope that it will be useful, but
@@ -17,84 +17,162 @@
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330, 17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA. 18 Boston, MA 02111-1307, USA.
19 */ 19 */
20
21#include "platform.h" 20#include "platform.h"
22#include "extractor.h" 21#include "extractor.h"
23#include "extractor_plugins.h" 22#include "extractor_plugins.h"
23#include <vorbis/vorbisfile.h>
24 24
25#define DEBUG_EXTRACT_OGG 0 25/**
26 * Bytes each ogg file must begin with (not used, but we might
27 * choose to add this back in the future to improve performance
28 * for non-ogg files).
29 */
26#define OGG_HEADER 0x4f676753 30#define OGG_HEADER 0x4f676753
27 31
28#if HAVE_VORBIS_VORBISFILE_H
29#include <vorbis/vorbisfile.h>
30#else
31#error You must install the libvorbis header files!
32#endif
33
34static char *
35get_comment (vorbis_comment * vc, char *label)
36{
37 char *tag;
38 if (vc && (tag = vorbis_comment_query (vc, label, 0)) != NULL)
39 return tag;
40 return NULL;
41}
42 32
33/**
34 * Custom read function for ogg.
35 *
36 * @param ptr where to write the data
37 * @param size number of bytes to read per member
38 * @param nmemb number of members to read
39 * @param datasource the 'struct EXTRACTOR_ExtractContext'
40 * @return 0 on end-of-data, 0 with errno set to indicate read error
41 */
43static size_t 42static size_t
44readOgg (void *ptr, size_t size, size_t nmemb, void *datasource) 43read_ogg (void *ptr, size_t size, size_t nmemb, void *datasource)
45{ 44{
46 struct EXTRACTOR_PluginList *plugin = datasource; 45 struct EXTRACTOR_ExtractContext *ec = datasource;
47 int64_t ret; 46 void *data;
48 unsigned char *read_data; 47 ssize_t ret;
49 48
50 ret = pl_read (plugin, &read_data, size*nmemb); 49 data = NULL;
51 if (ret <= 0) 50 ret = ec->read (ec->cls,
52 { 51 &data,
53 if (ret < 0) 52 size * nmemb);
54 errno = EIO; 53 if (-1 == ret)
55 return 0; 54 return 0;
56 } 55 if (0 == ret)
57 memcpy (ptr, read_data, ret); 56 {
57 errno = 0;
58 return 0;
59 }
60 memcpy (ptr, data, ret);
61 errno = 0;
58 return ret; 62 return ret;
59} 63}
60 64
61#define ADD(t,s) do { if (0 != (ret = proc (proc_cls, "ogg", t, EXTRACTOR_METAFORMAT_UTF8, "text/plain", s, strlen(s)+1))) goto FINISH; } while (0)
62 65
63#define ADDG(t,d) do { m = get_comment (comments, d); if (m != NULL) ADD(t,m); } while (0) 66/**
67 * Seek to a particular position in the file.
68 *
69 * @param datasource the 'struct EXTRACTOR_ExtractContext'
70 * @param offset where to seek
71 * @param whence how to seek
72 * @return -1 on error
73 */
74static int
75seek_ogg (void *datasource,
76 ogg_int64_t offset,
77 int whence)
78{
79 struct EXTRACTOR_ExtractContext *ec = datasource;
80
81 if (-1 == ec->seek (ec->cls,
82 (int64_t) offset,
83 whence))
84 return -1;
85 return 0;
86}
87
88
89/**
90 * Tell ogg where we are in the file
91 *
92 * @param datasource the 'struct EXTRACTOR_ExtractContext'
93 * @return
94 */
95static long
96tell_ogg (void *datasource)
97{
98 struct EXTRACTOR_ExtractContext *ec = datasource;
99
100 return (long) ec->seek (ec->cls,
101 0,
102 SEEK_CUR);
103}
104
105
106
107/**
108 * Extract the associated meta data for a given label from vorbis.
109 *
110 * @param vc vorbis comment data
111 * @param label label marking the desired entry
112 * @return NULL on error, otherwise the meta data
113 */
114static char *
115get_comment (vorbis_comment *vc,
116 const char *label)
117{
118 if (NULL == vc)
119 return NULL;
120 return vorbis_comment_query (vc, label, 0);
121}
122
123
124/**
125 * Extract meta data from vorbis using the given LE type and value.
126 *
127 * @param t LE meta data type
128 * @param s meta data to add
129 */
130#define ADD(t,s) do { if (0 != (ret = ec->proc (ec->cls, "ogg", t, EXTRACTOR_METAFORMAT_UTF8, "text/plain", s, strlen(s)+1))) goto FINISH; } while (0)
131
132
133/**
134 * Extract meta data from vorbis using the given LE type and label.
135 *
136 * @param t LE meta data type
137 * @param d vorbis meta data label
138 */
139#define ADDG(t,d) do { m = get_comment (comments, d); if (NULL != m) ADD(t,m); } while (0)
140
64 141
65/* mimetype = application/ogg */ 142/**
66int 143 * Main entry method for the 'application/ogg' extraction plugin.
67EXTRACTOR_ogg_extract_method (struct EXTRACTOR_PluginList *plugin, 144 *
68 EXTRACTOR_MetaDataProcessor proc, void *proc_cls) 145 * @param ec extraction context provided to the plugin
146 */
147void
148EXTRACTOR_ogg_extract_method (struct EXTRACTOR_ExtractContext *ec)
69{ 149{
150 uint64_t fsize;
151 ov_callbacks callbacks;
70 OggVorbis_File vf; 152 OggVorbis_File vf;
71 vorbis_comment *comments; 153 vorbis_comment *comments;
72 ov_callbacks callbacks;
73 int ret; 154 int ret;
74 int64_t fsize;
75 const char *m; 155 const char *m;
76 156
77 fsize = pl_get_fsize (plugin); 157 fsize = ec->get_size (ec->cls);
78 if (fsize > 0 && fsize < 2 * sizeof (int)) 158 if (fsize < 8)
79 return 1; 159 return;
80 if (fsize == 0)
81 return 1;
82 160
83 /* TODO: rewrite pl_seek() to be STDIO-compatible (SEEK_END) and enable seeking. */ 161 /* TODO: rewrite pl_seek() to be STDIO-compatible (SEEK_END) and enable seeking. */
84 callbacks.read_func = &readOgg; 162 callbacks.read_func = &read_ogg;
85 callbacks.seek_func = NULL; 163 callbacks.seek_func = &seek_ogg;
86 callbacks.close_func = NULL; 164 callbacks.close_func = NULL;
87 callbacks.tell_func = NULL; 165 callbacks.tell_func = &tell_ogg;
88 if (0 != ov_open_callbacks (plugin, &vf, NULL, 0, callbacks)) 166 if (0 != ov_open_callbacks (ec, &vf, NULL, 0, callbacks))
89 { 167 {
90 ov_clear (&vf); 168 ov_clear (&vf);
91 return 1; 169 return;
92 } 170 }
93 comments = ov_comment (&vf, -1); 171 comments = ov_comment (&vf, -1);
94 if (NULL == comments) 172 if (NULL == comments)
95 { 173 {
96 ov_clear (&vf); 174 ov_clear (&vf);
97 return 1; 175 return;
98 } 176 }
99 ret = 0; 177 ret = 0;
100 ADD (EXTRACTOR_METATYPE_MIMETYPE, "application/ogg"); 178 ADD (EXTRACTOR_METATYPE_MIMETYPE, "application/ogg");
@@ -119,5 +197,7 @@ EXTRACTOR_ogg_extract_method (struct EXTRACTOR_PluginList *plugin,
119 ADDG (EXTRACTOR_METATYPE_SONG_VERSION, "version"); 197 ADDG (EXTRACTOR_METATYPE_SONG_VERSION, "version");
120FINISH: 198FINISH:
121 ov_clear (&vf); 199 ov_clear (&vf);
122 return 1;
123} 200}
201
202/* end of ogg_extractor.c */
203