Browse Source

Bug 8377 [ENH] Show HTML5 video/ audio for media files in OPAC and staff client

This enhancement uses information from MARC field 856 to generate the appropriate HTML5 code to embed am media player for the file(s) in a tab in the OPAC and staff client detail view. This patch supports the HTML5 <audio> and <video> element. Additionally it gives basic support for the <track> element. This element is not supported very well by recent browsers. Please consider the patch working when you get working video or audio.

Rebased to Master 22.11.2012

Signed-off-by: Chris Cormack <chrisc@catalyst.net.nz>
Signed-off-by: Jonathan Druart <jonathan.druart@biblibre.com>
Signed-off-by: Jared Camins-Esakov <jcamins@cpbibliography.com>
3.12.x
Mirko Tietgen 12 years ago
committed by Jared Camins-Esakov
parent
commit
33aa6ec2fd
  1. 226
      C4/HTML5Media.pm
  2. 7
      catalogue/detail.pl
  3. 2
      installer/data/mysql/sysprefs.sql
  4. 8
      installer/data/mysql/updatedatabase.pl
  5. 14
      koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/enhanced_content.pref
  6. 17
      koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/detail.tt
  7. 19
      koha-tmpl/opac-tmpl/prog/en/modules/opac-detail.tt
  8. 6
      opac/opac-detail.pl

226
C4/HTML5Media.pm

@ -0,0 +1,226 @@
package C4::HTML5Media;
# Copyright 2012 Mirko Tietgen
#
# This file is part of Koha.
#
# Koha 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.
#
# Koha 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 Koha; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
use strict;
use warnings;
use C4::Context;
use MARC::Field;
=head1 HTML5Media
C4::HTML5Media
=head1 Description
This module gets the relevant data from field 856 (MARC21/UNIMARC) to create a HTML5 audio or video element containing the file(s) catalogued in 856.
=cut
=head2 gethtml5media
Get all relevant data from field 856. Takes $template and $record in the subroutine call, sets appropriate params.
=cut
sub gethtml5media {
my $self = shift;
my $template = shift;
my $record = shift;
my @HTML5Media_sets = ();
my @HTML5Media_fields = $record->field(856);
my $HTML5MediaParent;
my $HTML5MediaWidth;
my @HTML5MediaExtensions = split( /\|/, C4::Context->preference("HTML5MediaExtensions") );
my $marcflavour = C4::Context->preference("marcflavour");
foreach my $HTML5Media_field (@HTML5Media_fields) {
my %HTML5Media;
# protocol
if ( $HTML5Media_field->indicator(1) eq '1' ) {
$HTML5Media{protocol} = 'ftp';
}
elsif ( $HTML5Media_field->indicator(1) eq '4' ) {
$HTML5Media{protocol} = 'http';
}
elsif ( $HTML5Media_field->indicator(1) eq '7' ) {
if ($marcflavour eq 'MARC21' || $marcflavour eq 'NORMARC') {
$HTML5Media{protocol} = $HTML5Media_field->subfield('2');
}
elsif ($marcflavour eq 'UNIMARC') {
$HTML5Media{protocol} = $HTML5Media_field->subfield('y');
}
}
else {
$HTML5Media{protocol} = 'http';
}
# user
if ( $HTML5Media_field->subfield('l') ) {
$HTML5Media{username} = $HTML5Media_field->subfield('l'); # yes, that is arbitrary if h and l are not the same. originally i flipped a coin in that case.
}
elsif ( $HTML5Media_field->subfield('h') ) {
$HTML5Media{username} = $HTML5Media_field->subfield('h');
}
# user/pass
if ( $HTML5Media{username} && $HTML5Media_field->subfield('k') ) {
$HTML5Media{loginblock} = $HTML5Media{username} . ':' . $HTML5Media_field->subfield('k') . '@';
}
elsif ( $HTML5Media{username} ) {
$HTML5Media{loginblock} = $HTML5Media{username} . '@';
}
else {
$HTML5Media{loginblock} = '';
}
# port
if ( $HTML5Media_field->subfield('p') ) {
$HTML5Media{portblock} = ':' . $HTML5Media_field->subfield('k');
}
else {
$HTML5Media{portblock} = '';
}
# src
if ( $HTML5Media_field->subfield('u') ) {
$HTML5Media{srcblock} = $HTML5Media_field->subfield('u');
}
elsif ( $HTML5Media_field->subfield('a') && $HTML5Media_field->subfield('d') && $HTML5Media_field->subfield('f') ) {
$HTML5Media{host} = $HTML5Media_field->subfield('a');
$HTML5Media{host} =~ s/(^\/|\/$)//g;
$HTML5Media{path} = $HTML5Media_field->subfield('d');
$HTML5Media{path} =~ s/(^\/|\/$)//g;
$HTML5Media{file} = $HTML5Media_field->subfield('f');
$HTML5Media{srcblock} = $HTML5Media{protocol} . '://' . $HTML5Media{loginblock} . $HTML5Media{host} . $HTML5Media{portblock} . '/' . $HTML5Media{path} . '/' . $HTML5Media{file};
}
else {
next; # no file to play
}
# extension
$HTML5Media{extension} = ($HTML5Media{srcblock} =~ m/([^.]+)$/)[0];
if ( !grep /$HTML5Media{extension}/, @HTML5MediaExtensions ) {
next; # not a specified media file
}
# mime
if ( $HTML5Media_field->subfield('c') ) {
$HTML5Media{codecs} = $HTML5Media_field->subfield('c');
}
### from subfield q…
if ( $HTML5Media_field->subfield('q') ) {
$HTML5Media{mime} = $HTML5Media_field->subfield('q');
}
### …or from file extension and codecs…
elsif ( $HTML5Media{codecs} ) {
if ( $HTML5Media{codecs} =~ /theora.*vorbis/ ) {
$HTML5Media{mime} = 'video/ogg';
}
elsif ( $HTML5Media{codecs} =~ /vp8.*vorbis/ ) {
$HTML5Media{mime} = 'video/webm';
}
elsif ( ($HTML5Media{codecs} =~ /^vorbis$/) && ($HTML5Media{extension} eq 'ogg') ) {
$HTML5Media{mime} = 'audio/ogg';
}
elsif ( ($HTML5Media{codecs} =~ /^vorbis$/) && ($HTML5Media{extension} eq 'webm') ) {
$HTML5Media{mime} = 'audio/webm';
}
}
### …or just from file extension
else {
if ( $HTML5Media{extension} eq 'ogv' ) {
$HTML5Media{mime} = 'video/ogg';
$HTML5Media{codecs} = 'theora,vorbis';
}
if ( $HTML5Media{extension} eq 'oga' ) {
$HTML5Media{mime} = 'audio/ogg';
$HTML5Media{codecs} = 'vorbis';
}
elsif ( $HTML5Media{extension} eq 'spx' ) {
$HTML5Media{mime} = 'audio/ogg';
$HTML5Media{codecs} = 'speex';
}
elsif ( $HTML5Media{extension} eq 'opus' ) {
$HTML5Media{mime} = 'audio/ogg';
$HTML5Media{codecs} = 'opus';
}
elsif ( $HTML5Media{extension} eq 'vtt' ) {
$HTML5Media{mime} = 'text/vtt';
}
}
# codecs
if ( $HTML5Media{codecs} ) {
$HTML5Media{codecblock} = '; codecs="' . $HTML5Media{codecs} . '"';
}
else {
$HTML5Media{codecblock} = '';
}
# type
if ( $HTML5Media{mime} ) {
$HTML5Media{typeblock} = ' type=\'' . $HTML5Media{mime} . $HTML5Media{codecblock} . '\'';
}
else {
$HTML5Media{typeblock} = '';
}
# element
if ( $HTML5Media{mime} =~ /audio/ ) {
$HTML5Media{type} = 'audio';
}
elsif ( $HTML5Media{mime} =~ /video/ ) {
$HTML5Media{type} = 'video';
}
elsif ( $HTML5Media{mime} =~ /text/ ) {
$HTML5Media{type} = 'track';
}
# push
if ( $HTML5Media{srcblock} && $HTML5Media{type} ) {
push (@HTML5Media_sets, \%HTML5Media);
}
}
# parent element
for my $i ( 0 .. $#HTML5Media_sets ) {
if ( ($HTML5Media_sets[$i]{mime}) && ($HTML5Media_sets[$i]{mime} =~ /audio/) ) {
if ( $HTML5MediaParent ne 'video' ) {
$HTML5MediaParent = 'audio';
$HTML5MediaWidth = '';
}
}
elsif ( ($HTML5Media_sets[$i]{mime}) && ($HTML5Media_sets[$i]{mime} =~ /video/) ) {
$HTML5MediaParent = 'video';
$HTML5MediaWidth = ' width="480"';
}
}
# child element
for my $j ( 0 .. $#HTML5Media_sets ) {
if ( ($HTML5Media_sets[$j]{type}) && ( ($HTML5Media_sets[$j]{type} eq 'video') || ($HTML5Media_sets[$j]{type} eq 'audio') ) ) {
if ( $HTML5Media_sets[$j]{type} eq $HTML5MediaParent ) {
$HTML5Media_sets[$j]{child} = 'source';
}
}
else {
$HTML5Media_sets[$j]{child} = $HTML5Media_sets[$j]{type};
}
}
# template parameters
if ( (scalar(@HTML5Media_sets) > 0) && ($HTML5MediaParent) ) {
$template->param(
HTML5MediaEnabled => 1,
HTML5MediaSets => \@HTML5Media_sets,
HTML5MediaParent => $HTML5MediaParent,
HTML5MediaWidth => $HTML5MediaWidth);
}
return $template;
}
1;

7
catalogue/detail.pl

@ -40,6 +40,7 @@ use C4::VirtualShelves;
use C4::XSLT;
use C4::Images;
use Koha::DateUtils;
use C4::HTML5Media;
# use Smart::Comments;
@ -379,6 +380,12 @@ if ( C4::Context->preference("LocalCoverImages") == 1 ) {
$template->{VARS}->{localimages} = \@images;
}
# HTML5 Media
if ( (C4::Context->preference("HTML5MediaEnabled") eq 'staff') || (C4::Context->preference("HTML5MediaEnabled") eq 'both') ) {
$template = C4::HTML5Media->gethtml5media($template,$record);
}
# Get OPAC URL
if (C4::Context->preference('OPACBaseURL')){
$template->param( OpacUrl => C4::Context->preference('OPACBaseURL') );

2
installer/data/mysql/sysprefs.sql

@ -400,3 +400,5 @@ INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('
INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('OpacSeparateHoldings', '0', 'Separate current branch holdings from other holdings (OPAC)', NULL, 'YesNo');
INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('OpacSeparateHoldingsBranch', 'homebranch', 'Branch used to separate holdings (OPAC)', 'homebranch|holdingbranch', 'Choice');
INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('RenewalSendNotice','0', NULL, '', 'YesNo');
INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('HTML5MediaEnabled','not','Show a tab with a HTML5 media player for files catalogued in field 856','not|opac|staff|both','Choice');
INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('HTML5MediaExtensions','webm|ogg|ogv|oga|vtt','Media file extensions','','free');

8
installer/data/mysql/updatedatabase.pl

@ -6309,6 +6309,14 @@ if ( C4::Context->preference("Version") < TransformToNum($DBversion) ) {
SetVersion($DBversion);
}
$DBversion = 'XXX';
if ( C4::Context->preference("Version") < TransformToNum($DBversion) ) {
$dbh->do("INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('HTML5MediaEnabled','not','Show a HTML5 media player in a tab on opac-detail.pl for media files catalogued in field 856.','not|opac|staff|both','Choice');");
$dbh->do("INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('HTML5MediaExtensions','webm|ogg|ogv|oga|vtt','Media file extensions','','free');");
print "Upgrade to $DBversion done (Add HTML5MediaEnabled and HTML5MediaExtensions sysprefs)\n";
SetVersion ($DBversion);
}
=head1 FUNCTIONS
=head2 TableExists($table)

14
koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/enhanced_content.pref

@ -286,3 +286,17 @@ Enhanced Content:
yes: Allow
no: "Don't allow"
- multiple images to be attached to each bibliographic record.
HTML5 Media:
-
- Show a tab with a HTML5 media player for files catalogued in field 856
- pref: HTML5MediaEnabled
choices:
not: "not at all."
opac: "in the OPAC."
staff: "in the staff client."
both: "in OPAC and staff client."
-
- Media file extensions
- pref: HTML5MediaExtensions
class: multi
- (separated with |).

17
koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/detail.tt

@ -272,7 +272,8 @@ function verify_images() {
[% IF ( subscriptionsnumber ) %]<li><a href="#subscriptions">Subscriptions</a></li>[% END %]
[% IF ( FRBRizeEditions ) %][% IF ( XISBNS ) %]<li><a href="#editions">Editions</a></li>[% END %][% END %]
[% IF ( LocalCoverImages ) %][% IF ( localimages || CAN_user_tools_upload_local_cover_images ) %]<li><a href="#images">Images</a></li>[% END %][% END %]
</ul>
[% IF ( HTML5MediaEnabled ) %][% IF ( HTML5MediaSets ) %]<li><a href="#html5media">Play media</a></li>[% END %][% END %]
</ul>
[% BLOCK items_table %]
<table>
@ -587,6 +588,20 @@ function verify_images() {
</div>
[% END %]
[% IF ( HTML5MediaEnabled ) %]
<div id="html5media">
<p>
<[% HTML5MediaParent %][% HTML5MediaWidth %] controls preload=none>
[% FOREACH HTML5MediaSet IN HTML5MediaSets %]
<[% HTML5MediaSet.child %] src="[% HTML5MediaSet.srcblock %]"[% HTML5MediaSet.typeblock %] />
[% END %]
[[% HTML5MediaParent %] tag not supported by your browser.]
</[% HTML5MediaParent %]>
</p>
</div>
[% END %]
</div><!-- /bibliodetails -->
<div class="yui-g" id="export" style="margin-top: 1em;">

19
koha-tmpl/opac-tmpl/prog/en/modules/opac-detail.tt

@ -16,6 +16,7 @@
<link rel="stylesheet" type="text/css" href="/opac-tmpl/prog/en/css/jquery.rating.css" />[% END %]
[% IF ( OpacHighlightedWords ) %]<script type="text/javascript" src="[% themelang %]/lib/jquery/plugins/jquery.highlight-3.js"></script>[% END %]
<script type="text/JavaScript" language="JavaScript">
//<![CDATA[
@ -718,6 +719,11 @@ YAHOO.util.Event.onContentReady("furtherm", function () {
[% IF ( OPACLocalCoverImages && localimages.size ) %]
<li id="tab_images"><a href="#images">Images</a></li>
[% END %]
[% IF ( HTML5MediaEnabled ) %][% IF ( HTML5MediaSets ) %]
<li id="tab_html5media"><a href="#html5media">Play media</a></li>
[% END %][% END %]
</ul>
[% IF ( serialcollection ) %]
@ -1053,6 +1059,19 @@ YAHOO.util.Event.onContentReady("furtherm", function () {
</table>
</div>[% END %][% END %]
[% IF ( HTML5MediaEnabled ) %]
<div id="html5media">
<p>
<[% HTML5MediaParent %][% HTML5MediaWidth %] controls preload=none>
[% FOREACH HTML5MediaSet IN HTML5MediaSets %]
<[% HTML5MediaSet.child %] src="[% HTML5MediaSet.srcblock %]"[% HTML5MediaSet.typeblock %] />
[% END %]
[[% HTML5MediaParent %] tag not supported by your browser.]
</[% HTML5MediaParent %]>
</p>
</div>
[% END %]
[% IF ( OPACLocalCoverImages && localimages.size ) %]
<div id="images">
<p>Click on an image to view it in the image viewer</p>

6
opac/opac-detail.pl

@ -49,6 +49,7 @@ use MARC::Field;
use List::MoreUtils qw/any none/;
use C4::Images;
use Koha::DateUtils;
use C4::HTML5Media;
BEGIN {
if (C4::Context->preference('BakerTaylorEnabled')) {
@ -776,6 +777,11 @@ if (C4::Context->preference("OPACLocalCoverImages")){
$template->param(OPACLocalCoverImages => 1);
}
# HTML5 Media
if ( (C4::Context->preference("HTML5MediaEnabled") eq 'opac') || (C4::Context->preference("HTML5MediaEnabled") eq 'both') ) {
$template = C4::HTML5Media->gethtml5media($template,$record);
}
my $syndetics_elements;
if ( C4::Context->preference("SyndeticsEnabled") ) {

Loading…
Cancel
Save