source: main/trunk/greenstone2/perllib/plugins/MP3Plugin.pm@ 28489

Last change on this file since 28489 was 24225, checked in by ak19, 13 years ago

Still on ticket 449. Now srclink_file metadata (contains an underscore that makes things difficult for GS3) is renamed to srclinkFile. Related commits are in GS2's runtime-src formattools.cpp and dublincore.cpp and GS3's default/transform/config_format.xsl and Action.java.

  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 10.5 KB
Line 
1###########################################################################
2#
3# MP3Plugin.pm -- Plugin for MP3 files (MPEG audio layer 3).
4#
5# A component of the Greenstone digital library software from the New
6# Zealand Digital Library Project at the University of Waikato, New
7# Zealand.
8#
9# Copyright (C) 2001 New Zealand Digital Library Project
10#
11# This program is free software; you can redistribute it and/or modify
12# it under the terms of the GNU General Public License as published by
13# the Free Software Foundation; either version 2 of the License, or
14# (at your option) any later version.
15#
16# This program is distributed in the hope that it will be useful, but
17# WITHOUT ANY WARRANTY; without even the implied warranty of
18# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19# General Public License for more details.
20#
21# You should have received a copy of the GNU General Public License
22# along with this program; if not, write to the Free Software
23# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24#
25###########################################################################
26
27
28package MP3Plugin;
29
30use BasePlugin;
31
32use strict;
33no strict 'refs'; # allow filehandles to be variables and viceversa
34no strict 'subs';
35
36use MP3::Info;
37
38require giget;
39
40sub BEGIN {
41 @MP3Plugin::ISA = ('BasePlugin');
42}
43
44my $arguments =
45 [ { 'name' => "process_exp",
46 'desc' => "{BasePlugin.process_exp}",
47 'type' => "regexp",
48 'deft' => &get_default_process_exp(),
49 'reqd' => "no" },
50 { 'name' => "assoc_images",
51 'desc' => "{MP3Plugin.assoc_images}",
52 'type' => "flag",
53 'deft' => "",
54 'reqd' => "no" },
55 { 'name' => "applet_metadata",
56 'desc' => "{MP3Plugin.applet_metadata}",
57 'type' => "flag",
58 'deft' => "" },
59 { 'name' => "metadata_fields",
60 'desc' => "{MP3Plugin.metadata_fields}",
61 'type' => "string",
62 'deft' => "Title,Artist,Genre" },
63 { 'name' => "file_rename_method",
64 'desc' => "{BasePlugin.file_rename_method}",
65 'type' => "enum",
66 'deft' => &get_default_file_rename_method(), # by default rename imported files and assoc files using this encoding
67 'list' => $BasePlugin::file_rename_method_list,
68 'reqd' => "no"
69 } ];
70
71my $options = { 'name' => "MP3Plugin",
72 'desc' => "{MP3Plugin.desc}",
73 'abstract' => "no",
74 'inherits' => "yes",
75 'args' => $arguments };
76
77sub new {
78 my ($class) = shift (@_);
79 my ($pluginlist,$inputargs,$hashArgOptLists) = @_;
80 push(@$pluginlist, $class);
81
82 push(@{$hashArgOptLists->{"ArgList"}},@{$arguments});
83 push(@{$hashArgOptLists->{"OptList"}},$options);
84
85 my $self = new BasePlugin($pluginlist, $inputargs, $hashArgOptLists);
86
87 return bless $self, $class;
88}
89
90sub get_default_process_exp {
91 return q^(?i)\.mp3$^;
92}
93
94# rename imported files and assoc files using base64 encoding by default
95# so that the urls generated will always work with media files even when
96# opened in external applications (when wmv file names contain spaces in
97# them and they get url-encoded, wmv player fails to open the doubly url-
98# encoded url reference to the url-encoded filename).
99sub get_default_file_rename_method() {
100 return "base64";
101}
102
103# we don't want to hash on the file
104sub get_oid_hash_type {
105 my $self = shift (@_);
106 return "hash_on_ga_xml";
107}
108
109sub process {
110 my $self = shift (@_);
111 my ($pluginfo, $base_dir, $file, $metadata, $doc_obj, $gli) = @_;
112
113 my ($filename_full_path, $filename_no_path) = &util::get_full_filenames($base_dir, $file);
114
115 # associate the file with the document
116 if ($self->associate_mp3_file($filename_full_path, $filename_no_path, $doc_obj) != 1)
117 {
118 print "MP3Plugin: couldn't process \"$filename_full_path\"\n";
119 return 0;
120 }
121
122 my $text = &gsprintf::lookup_string("{BasePlugin.dummy_text}",1);
123 if ($self->{'assoc_images'}) {
124 $text .= "[img1]<br>";
125 $text .= "[img2]<br>";
126 }
127 $doc_obj->add_utf8_text($doc_obj->get_top_section(), $text);
128 $doc_obj->add_metadata ($doc_obj->get_top_section(), "NoText", "1");
129
130}
131
132sub gen_mp3applet {
133
134 my ($mp3_filename) = @_;
135
136 my $applet_html = '
137<OBJECT classid="clsid:8AD9C840-044E-11D1-B3E9-00805F499D93"
138 WIDTH = "59"
139 HEIGHT = "32"
140 codebase="http://java.sun.com/products/plugin/1.3/jinstall-13-win32.cab#Version=1,3,0,0">
141<PARAM NAME = CODE VALUE = "javazoom.jlGui.TinyPlayer" >
142<PARAM NAME = ARCHIVE VALUE = "_httpcollection_/tinyplayer.jar,_httpcollection_/jl10.jar" >
143<PARAM NAME="type" VALUE="application/x-java-applet;version=1.3">
144<PARAM NAME="scriptable" VALUE="false">
145<PARAM NAME = "skin" VALUE ="_httpcollection_/skins/Digitalized">
146<PARAM NAME = "autoplay" VALUE ="yes">
147<PARAM NAME = "bgcolor" VALUE ="638182">
148<PARAM NAME = "audioURL" VALUE ="MP3FILENAME">
149<COMMENT>
150<EMBED type="application/x-java-applet;version=1.3"
151 CODE = "javazoom.jlGui.TinyPlayer"
152 ARCHIVE = "_httpcollection_/tinyplayer.jar,_httpcollection_/jl10.jar"
153 WIDTH = "59"
154 HEIGHT = "32"
155 skin = "_httpcollection_/skins/Digitalized"
156 autoplay = "yes"
157 bgcolor = "638182"
158 audioURL = "MP3FILENAME"
159 scriptable=false
160 pluginspage="http://java.sun.com/products/plugin/1.3/plugin-install.html">
161<NOEMBED>
162</COMMENT>
163</NOEMBED></EMBED>
164</OBJECT>
165';
166
167 $applet_html =~ s/MP3FILENAME/$mp3_filename/g;
168
169 return $applet_html;
170}
171
172
173
174# Associate the mp3 file with the new document
175
176sub associate_mp3_file {
177 my $self = shift (@_);
178 my $filename = shift (@_); # filename with full path
179 my $file = shift (@_); # filename without path
180 my $doc_obj = shift (@_);
181
182 my $verbosity = $self->{'verbosity'};
183 my $outhandle = $self->{'outhandle'};
184
185 # check the filename is okay
186 return 0 if ($file eq "" || $filename eq "");
187
188 # Add the file metadata.
189 # $assoc_url will be the srcurl. Since it is URL encoded here, it will be
190 # able to cope with special characters--including spaces--in mp3 filenames.
191 # the assocfilename generated will be a URL encoded version of the utf8 filename
192 my $assoc_url = $doc_obj->get_sourcefile();
193 my $dst_file = $doc_obj->get_assocfile_from_sourcefile();
194
195 # Add the file as an associated file ...
196 my $section = $doc_obj->get_top_section();
197 my $mime_type = $self->{'mime_type'} || "audio/mp3";
198 my $assoc_field = $self->{'assoc_field'} || "mp3";
199 my $assoc_name = $file;
200 $assoc_name =~ s/\.mp3$//;
201
202 $doc_obj->associate_file($filename, $dst_file, $mime_type, $section);
203 $doc_obj->add_metadata ($section, $assoc_field, $assoc_name);
204 $doc_obj->add_metadata ($section, "srcurl", $assoc_url);
205
206 my $mp3_info = get_mp3info($filename);
207 my $mp3_tags = get_mp3tag($filename,0,2);
208
209 my $metadata_fields = $self->{'metadata_fields'};
210
211 if ($metadata_fields eq "*") {
212 # Locate all info and tag metadata
213
214 foreach my $ki ( keys %$mp3_info ) {
215 my $mp3_metavalue = $mp3_info->{$ki};
216
217 if ($mp3_metavalue !~ m/^\s*$/s) {
218 my $mp3_metaname = "ex.id3.".lc($ki);
219 $doc_obj->add_metadata ($section, $mp3_metaname, $mp3_metavalue);
220 }
221 }
222
223 foreach my $kt ( keys %$mp3_tags ) {
224 my $mp3_metavalue = $mp3_tags->{$kt};
225
226 if ($mp3_metavalue !~ m/^\s*$/s) {
227 my $kt_len = length($kt);
228 my $kt_initial_cap = uc(substr($kt,0,1)).lc(substr($kt,1,$kt_len-1));
229 my $mp3_metaname = "ex.id3.".$kt_initial_cap;
230
231 $doc_obj->add_metadata ($section, $mp3_metaname, $mp3_metavalue);
232 }
233 }
234 }
235 else {
236
237 # Restrict metadata to that specifically given
238 foreach my $field (split /,/, $metadata_fields) {
239
240 # check info
241 if (defined $mp3_info->{$field}) {
242
243 my $mp3i_metavalue = $mp3_info->{$field};
244
245 if ($mp3i_metavalue !~ m/^\s*$/s) {
246 my $mp3i_metaname = "ex.id3.".lc($field);
247 $doc_obj->add_metadata ($section, $mp3i_metaname, $mp3i_metavalue);
248 }
249 }
250
251 # check tags
252 if (defined $mp3_tags->{uc($field)}) {
253
254 my $mp3t_metavalue = $mp3_tags->{uc($field)};
255
256 if ($mp3t_metavalue !~ m/^\s*$/s) {
257 my $mp3t_metaname = "ex.id3.".$field;
258
259 $doc_obj->add_metadata ($section, $mp3t_metaname, $mp3t_metavalue);
260 }
261 }
262
263 }
264 }
265
266 $doc_obj->add_metadata ($section, "FileFormat", "MP3");
267
268 $doc_obj->add_metadata ($section, "srcicon", "_iconmp3_");
269 # srclink_file is now deprecated because of the "_" in the metadataname. Use srclinkFile
270 $doc_obj->add_metadata ($section, "srclink_file", $assoc_url);
271 $doc_obj->add_metadata ($section, "srclinkFile", $assoc_url);
272 my $applet_metadata = $self->{'applet_metadata'};
273 if (defined $applet_metadata && $applet_metadata ) {
274 my $applet_html
275 = gen_mp3applet("_httpprefix_/collect/[collection]/index/assoc/[assocfilepath]/[srcurl]");
276 $doc_obj->add_metadata ($section, "mp3applet", $applet_html);
277 }
278
279 my $assoc_images = $self->{'assoc_images'};
280 if (defined $assoc_images && $assoc_images) {
281 my @search_terms = ();
282
283 my $title = $mp3_tags->{'TITLE'};
284 my $artist = $mp3_tags->{'ARTIST'};
285
286 if (defined $title && $title ne "") {
287
288 push(@search_terms,$title);
289
290 if (defined $artist && $artist ne "") {
291 push(@search_terms,$artist);
292 }
293 }
294 else {
295 push(@search_terms,$assoc_name);
296 }
297
298 push(@search_terms,"song");
299
300 my $output_dir = $filename;
301 $output_dir =~ s/\.\w+$//;
302
303 my ($imgref_urls) = giget(\@search_terms,$output_dir);
304
305 my $gi_base = gi_url_base();
306 my $gi_query_url = gi_query_url(\@search_terms);
307
308 $doc_obj->add_metadata ($section, "giquery", "<a href=\"$gi_base$gi_query_url\" target=giwindow>");
309 $doc_obj->add_metadata ($section, "/giquery", "</a>");
310
311 for (my $i=1; $i<=2; $i++) {
312 my $img_filename = "$output_dir/img_$i.jpg";
313 my $dst_file = "img_$i.jpg";
314
315 if (-e $img_filename) {
316 $doc_obj->associate_file($img_filename, $dst_file, "image/jpeg", $section);
317
318 my $srcurl = "src=\"_httpprefix_/collect/[collection]/index/assoc/[assocfilepath]/$dst_file\"";
319
320 $doc_obj->add_metadata ($section, "img$i",
321 "<img $srcurl>");
322 $doc_obj->add_metadata ($section, "smallimg$i",
323 "<img $srcurl width=100>");
324
325 my $imgref_url = $imgref_urls->[$i-1];
326
327 $doc_obj->add_metadata ($section, "imgref$i", "<a href=\"$imgref_url\" target=giwindow>");
328 $doc_obj->add_metadata ($section, "/imgref$i", "</a>");
329 }
330
331 }
332
333
334 }
335
336 return 1;
337}
338
339
340# we want to use ex.id3.Title if its there, otherwise we'll use BasePlugin method
341sub title_fallback
342{
343 my $self = shift (@_);
344 my ($doc_obj,$section,$file) = @_;
345
346 if (!defined $doc_obj->get_metadata_element ($section, "Title")) {
347 my $mp3_title = $doc_obj->get_metadata_element ($section, "ex.id3.Title");
348 if (defined $mp3_title) {
349 $doc_obj->add_metadata ($section, "Title", $mp3_title);
350 }
351 else {
352 $self->BasePlugin::title_fallback($doc_obj, $section, $file);
353 }
354 }
355}
356
357
3581;
359
360
361
362
363
364
365
366
367
368
369
Note: See TracBrowser for help on using the repository browser.