View | Details | Raw Unified | Return to bug 8377
Collapse All | Expand All

(-)a/Koha/HTML5Media.pm (+227 lines)
Line 0 Link Here
1
package Koha::HTML5Media;
2
3
# Copyright 2012 Mirko Tietgen
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it under the
8
# terms of the GNU General Public License as published by the Free Software
9
# Foundation; either version 2 of the License, or (at your option) any later
10
# version.
11
#
12
# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
13
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
14
# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
15
#
16
# You should have received a copy of the GNU General Public License along
17
# with Koha; if not, write to the Free Software Foundation, Inc.,
18
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19
20
use strict;
21
use warnings;
22
23
use C4::Context;
24
use MARC::Field;
25
26
27
=head1 HTML5Media
28
29
Koha::HTML5Media
30
31
=head1 Description
32
33
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.
34
35
=cut
36
37
=head2 gethtml5media
38
39
Get all relevant data from field 856. Takes $template and $record in the subroutine call, sets appropriate params.
40
41
=cut
42
43
sub gethtml5media {
44
    my $self = shift;
45
    my $template = shift;
46
    my $record = shift;
47
    my @HTML5Media_sets = ();
48
    my @HTML5Media_fields = $record->field(856);
49
    my $HTML5MediaParent;
50
    my $HTML5MediaWidth;
51
    my @HTML5MediaExtensions = split( /\|/, C4::Context->preference("HTML5MediaExtensions") );
52
    my $marcflavour          = C4::Context->preference("marcflavour");
53
    foreach my $HTML5Media_field (@HTML5Media_fields) {
54
        my %HTML5Media;
55
        # protocol
56
        if ( $HTML5Media_field->indicator(1) eq '1' ) {
57
            $HTML5Media{protocol} = 'ftp';
58
        }
59
        elsif ( $HTML5Media_field->indicator(1) eq '4' ) {
60
            $HTML5Media{protocol} = 'http';
61
        }
62
        elsif ( $HTML5Media_field->indicator(1) eq '7' ) {
63
            if ($marcflavour eq 'MARC21' || $marcflavour eq 'NORMARC') {
64
                $HTML5Media{protocol} = $HTML5Media_field->subfield('2');
65
            }
66
            elsif ($marcflavour eq 'UNIMARC') {
67
                $HTML5Media{protocol} = $HTML5Media_field->subfield('y');
68
            }
69
        }
70
        else {
71
            $HTML5Media{protocol} = 'http';
72
        }
73
        # user
74
        if ( $HTML5Media_field->subfield('l') ) {
75
            $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.
76
        }
77
        elsif ( $HTML5Media_field->subfield('h') ) {
78
            $HTML5Media{username} = $HTML5Media_field->subfield('h');
79
        }
80
        # user/pass
81
        if ( $HTML5Media{username} && $HTML5Media_field->subfield('k') ) {
82
            $HTML5Media{loginblock} = $HTML5Media{username} . ':' . $HTML5Media_field->subfield('k') . '@';
83
        }
84
        elsif ( $HTML5Media{username} ) {
85
            $HTML5Media{loginblock} = $HTML5Media{username} . '@';
86
        }
87
        else {
88
            $HTML5Media{loginblock} = '';
89
        }
90
        # port
91
        if ( $HTML5Media_field->subfield('p') ) {
92
            $HTML5Media{portblock} = ':' . $HTML5Media_field->subfield('k');
93
        }
94
        else {
95
            $HTML5Media{portblock} = '';
96
        }
97
        # src
98
        if ( $HTML5Media_field->subfield('u') ) {
99
            $HTML5Media{srcblock} = $HTML5Media_field->subfield('u');
100
        }
101
        elsif ( $HTML5Media_field->subfield('a') && $HTML5Media_field->subfield('d') && $HTML5Media_field->subfield('f') ) {
102
            $HTML5Media{host}        = $HTML5Media_field->subfield('a');
103
            $HTML5Media{host}        =~ s/(^\/|\/$)//g;
104
            $HTML5Media{path}        = $HTML5Media_field->subfield('d');
105
            $HTML5Media{path}        =~ s/(^\/|\/$)//g;
106
            $HTML5Media{file}        = $HTML5Media_field->subfield('f');
107
            $HTML5Media{srcblock}    = $HTML5Media{protocol} . '://' . $HTML5Media{loginblock} . $HTML5Media{host} . $HTML5Media{portblock} . '/' . $HTML5Media{path} . '/' . $HTML5Media{file};
108
        }
109
        else {
110
            next; # no file to play
111
        }
112
        # extension
113
        $HTML5Media{extension} = ($HTML5Media{srcblock} =~ m/([^.]+)$/)[0];
114
        if ( !grep /$HTML5Media{extension}/, @HTML5MediaExtensions ) {
115
            next; # not a specified media file
116
        }
117
        # mime
118
        if ( $HTML5Media_field->subfield('c') ) {
119
            $HTML5Media{codecs} = $HTML5Media_field->subfield('c');
120
        }
121
        ### from subfield q…
122
        if ( $HTML5Media_field->subfield('q') ) {
123
            $HTML5Media{mime} = $HTML5Media_field->subfield('q');
124
        }
125
        ### …or from file extension and codecs…
126
        elsif ( $HTML5Media{codecs} ) {
127
            if ( $HTML5Media{codecs} =~ /theora.*vorbis/ ) {
128
                $HTML5Media{mime} = 'video/ogg';
129
            }
130
            elsif ( $HTML5Media{codecs} =~ /vp8.*vorbis/ ) {
131
                $HTML5Media{mime} = 'video/webm';
132
            }
133
            elsif ( ($HTML5Media{codecs} =~ /^vorbis$/) && ($HTML5Media{extension} eq 'ogg') ) {
134
                $HTML5Media{mime} = 'audio/ogg';
135
            }
136
            elsif ( ($HTML5Media{codecs} =~ /^vorbis$/) && ($HTML5Media{extension} eq 'webm') ) {
137
                $HTML5Media{mime} = 'audio/webm';
138
            }
139
        }
140
        ### …or just from file extension
141
        else {
142
            if ( $HTML5Media{extension} eq 'ogv' ) {
143
                $HTML5Media{mime} = 'video/ogg';
144
                $HTML5Media{codecs} = 'theora,vorbis';
145
            }
146
            if ( $HTML5Media{extension} eq 'oga' ) {
147
                $HTML5Media{mime} = 'audio/ogg';
148
              $HTML5Media{codecs} = 'vorbis';
149
            }
150
            elsif ( $HTML5Media{extension} eq 'spx' ) {
151
                $HTML5Media{mime} = 'audio/ogg';
152
                $HTML5Media{codecs} = 'speex';
153
            }
154
            elsif ( $HTML5Media{extension} eq 'opus' ) {
155
                $HTML5Media{mime} = 'audio/ogg';
156
                $HTML5Media{codecs} = 'opus';
157
            }
158
            elsif ( $HTML5Media{extension} eq 'vtt' ) {
159
                $HTML5Media{mime} = 'text/vtt';
160
            }
161
        }
162
        # codecs
163
        if ( $HTML5Media{codecs} ) {
164
            $HTML5Media{codecblock} = '; codecs="' . $HTML5Media{codecs} . '"';
165
        }
166
        else {
167
            $HTML5Media{codecblock} = '';
168
        }
169
        # type
170
        if ( $HTML5Media{mime} ) {
171
            $HTML5Media{typeblock} = ' type=\'' . $HTML5Media{mime} . $HTML5Media{codecblock} . '\'';
172
        }
173
        else {
174
          $HTML5Media{typeblock} = '';
175
        }
176
        # element
177
        if ( $HTML5Media{mime} =~ /audio/ ) {
178
            $HTML5Media{type} = 'audio';
179
        }
180
        elsif ( $HTML5Media{mime} =~ /video/ ) {
181
            $HTML5Media{type} = 'video';
182
        }
183
        elsif ( $HTML5Media{mime} =~ /text/ ) {
184
            $HTML5Media{type} = 'track';
185
        }
186
        # push
187
        if ( $HTML5Media{srcblock} && $HTML5Media{type} ) {
188
            push (@HTML5Media_sets, \%HTML5Media);
189
        }
190
    }
191
    # parent element
192
    for my $i ( 0 .. $#HTML5Media_sets ) {
193
        if ( ($HTML5Media_sets[$i]{mime}) && ($HTML5Media_sets[$i]{mime} =~ /audio/) ) {
194
            if ( $HTML5MediaParent ne 'video' ) {
195
                $HTML5MediaParent = 'audio';
196
                $HTML5MediaWidth = '';
197
            }
198
        }
199
        elsif ( ($HTML5Media_sets[$i]{mime}) && ($HTML5Media_sets[$i]{mime} =~ /video/) ) {
200
            $HTML5MediaParent = 'video';
201
            $HTML5MediaWidth = ' width="480"';
202
        }
203
    }
204
    # child element
205
    for my $j ( 0 .. $#HTML5Media_sets ) {
206
        if ( ($HTML5Media_sets[$j]{type}) && ( ($HTML5Media_sets[$j]{type} eq 'video') || ($HTML5Media_sets[$j]{type} eq 'audio') ) ) {
207
            if ( $HTML5Media_sets[$j]{type} eq $HTML5MediaParent ) {
208
                $HTML5Media_sets[$j]{child} = 'source';
209
            }
210
        }
211
        else {
212
            $HTML5Media_sets[$j]{child} = $HTML5Media_sets[$j]{type};
213
        }
214
    }
215
    # template parameters
216
    if ( (scalar(@HTML5Media_sets) > 0) && ($HTML5MediaParent) ) {
217
        $template->param(
218
            HTML5MediaEnabled  => 1,
219
            HTML5MediaSets     => \@HTML5Media_sets,
220
            HTML5MediaParent   => $HTML5MediaParent,
221
            HTML5MediaWidth    => $HTML5MediaWidth);
222
    }
223
    return $template;
224
}
225
226
1;
227
(-)a/catalogue/detail.pl (+7 lines)
Lines 40-45 use C4::VirtualShelves; Link Here
40
use C4::XSLT;
40
use C4::XSLT;
41
use C4::Images;
41
use C4::Images;
42
use Koha::DateUtils;
42
use Koha::DateUtils;
43
use Koha::HTML5Media;
43
44
44
# use Smart::Comments;
45
# use Smart::Comments;
45
46
Lines 397-402 if ( C4::Context->preference("LocalCoverImages") == 1 ) { Link Here
397
    $template->{VARS}->{localimages} = \@images;
398
    $template->{VARS}->{localimages} = \@images;
398
}
399
}
399
400
401
# HTML5 Media
402
if ( (C4::Context->preference("HTML5MediaEnabled") eq 'staff') || (C4::Context->preference("HTML5MediaEnabled") eq 'both') ) {
403
    $template = Koha::HTML5Media->gethtml5media($template,$record);
404
}
405
406
400
# Get OPAC URL
407
# Get OPAC URL
401
if (C4::Context->preference('OPACBaseURL')){
408
if (C4::Context->preference('OPACBaseURL')){
402
     $template->param( OpacUrl => C4::Context->preference('OPACBaseURL') );
409
     $template->param( OpacUrl => C4::Context->preference('OPACBaseURL') );
(-)a/installer/data/mysql/sysprefs.sql (+2 lines)
Lines 375-377 INSERT INTO systempreferences (variable,value,options,explanation,type) VALUES ( Link Here
375
INSERT INTO systempreferences (variable,value,explanation,type) VALUES('EnableBorrowerFiles','0','If enabled, allows librarians to upload and attach arbitrary files to a borrower record.','YesNo');
375
INSERT INTO systempreferences (variable,value,explanation,type) VALUES('EnableBorrowerFiles','0','If enabled, allows librarians to upload and attach arbitrary files to a borrower record.','YesNo');
376
INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('UpdateTotalIssuesOnCirc','0','Whether to update the totalissues field in the biblio on each circ.',NULL,'YesNo');
376
INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('UpdateTotalIssuesOnCirc','0','Whether to update the totalissues field in the biblio on each circ.',NULL,'YesNo');
377
INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('IntranetSlipPrinterJS','','Use this JavaScript for printing slips. Define at least function printThenClose(). For use e.g. with Firefox PlugIn jsPrintSetup, see http://jsprintsetup.mozdev.org/','','Free');
377
INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('IntranetSlipPrinterJS','','Use this JavaScript for printing slips. Define at least function printThenClose(). For use e.g. with Firefox PlugIn jsPrintSetup, see http://jsprintsetup.mozdev.org/','','Free');
378
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');
379
INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('HTML5MediaExtensions','webm|ogg|ogv|oga|vtt','Media file extensions','','free');
(-)a/installer/data/mysql/updatedatabase.pl (+8 lines)
Lines 5566-5571 if (C4::Context->preference("Version") < TransformToNum($DBversion)) { Link Here
5566
    SetVersion ($DBversion);
5566
    SetVersion ($DBversion);
5567
}
5567
}
5568
5568
5569
$DBversion = 'XXX';
5570
if ( C4::Context->preference("Version") < TransformToNum($DBversion) ) {
5571
   $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');");
5572
   $dbh->do("INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('HTML5MediaExtensions','webm|ogg|ogv|oga|vtt','Media file extensions','','free');");
5573
   print "Upgrade to $DBversion done (Add HTML5MediaEnabled and HTML5MediaExtensions sysprefs)\n";
5574
   SetVersion ($DBversion);
5575
}
5576
5569
=head1 FUNCTIONS
5577
=head1 FUNCTIONS
5570
5578
5571
=head2 TableExists($table)
5579
=head2 TableExists($table)
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/enhanced_content.pref (+14 lines)
Lines 336-338 Enhanced Content: Link Here
336
                  yes: Allow
336
                  yes: Allow
337
                  no: "Don't allow"
337
                  no: "Don't allow"
338
            - multiple images to be attached to each bibliographic record.
338
            - multiple images to be attached to each bibliographic record.
339
    HTML5 Media:
340
        -
341
            - Show a tab with a HTML5 media player for files catalogued in field 856
342
            - pref: HTML5MediaEnabled
343
              choices:
344
                  not: "not at all."
345
                  opac: "in the OPAC."
346
                  staff: "in the staff client."
347
                  both: "in OPAC and staff client."
348
        -
349
            - Media file extensions
350
            - pref: HTML5MediaExtensions
351
              class: multi
352
            - (separated with |).
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/detail.tt (-1 / +16 lines)
Lines 262-268 function verify_images() { Link Here
262
[% IF ( FRBRizeEditions ) %][% IF ( XISBNS ) %]<li><a href="#editions">Editions</a></li>[% END %][% END %]
262
[% IF ( FRBRizeEditions ) %][% IF ( XISBNS ) %]<li><a href="#editions">Editions</a></li>[% END %][% END %]
263
[% IF ( AmazonSimilarItems ) %]<li><a href="#related">Related titles</a></li>[% END %]
263
[% IF ( AmazonSimilarItems ) %]<li><a href="#related">Related titles</a></li>[% END %]
264
[% IF ( LocalCoverImages ) %][% IF ( localimages || CAN_user_tools_upload_local_cover_images ) %]<li><a href="#images">Images</a></li>[% END %][% END %]
264
[% IF ( LocalCoverImages ) %][% IF ( localimages || CAN_user_tools_upload_local_cover_images ) %]<li><a href="#images">Images</a></li>[% END %][% END %]
265
 </ul>
265
[% IF ( HTML5MediaEnabled ) %][% IF ( HTML5MediaSets ) %]<li><a href="#html5media">Play media</a></li>[% END %][% END %]
266
</ul>
266
267
267
<div id="holdings">
268
<div id="holdings">
268
[% IF ( count ) %]
269
[% IF ( count ) %]
Lines 566-571 function verify_images() { Link Here
566
</div>
567
</div>
567
[% END %]
568
[% END %]
568
569
570
[% IF ( HTML5MediaEnabled ) %]
571
<div id="html5media">
572
        <p>
573
        <[% HTML5MediaParent %][% HTML5MediaWidth %] controls preload=none>
574
          [% FOREACH HTML5MediaSet IN HTML5MediaSets %]
575
            <[% HTML5MediaSet.child  %] src="[% HTML5MediaSet.srcblock %]"[% HTML5MediaSet.typeblock %] />
576
          [% END %]
577
            [[% HTML5MediaParent %] tag not supported by your browser.]
578
        </[% HTML5MediaParent %]>
579
        </p>
580
</div>
581
[% END %]
582
583
569
</div><!-- /bibliodetails -->
584
</div><!-- /bibliodetails -->
570
585
571
<div class="yui-g" id="export" style="margin-top: 1em;">
586
<div class="yui-g" id="export" style="margin-top: 1em;">
(-)a/koha-tmpl/opac-tmpl/prog/en/modules/opac-detail.tt (+21 lines)
Lines 12-17 Link Here
12
[% IF ( OpacStarRatings != 'disable' ) %]<script type="text/javascript" src="/opac-tmpl/prog/en/lib/jquery/plugins/jquery.rating.js"></script>
12
[% IF ( OpacStarRatings != 'disable' ) %]<script type="text/javascript" src="/opac-tmpl/prog/en/lib/jquery/plugins/jquery.rating.js"></script>
13
<link rel="stylesheet" type="text/css" href="/opac-tmpl/prog/en/css/jquery.rating.css" />[% END %]
13
<link rel="stylesheet" type="text/css" href="/opac-tmpl/prog/en/css/jquery.rating.css" />[% END %]
14
14
15
15
<script type="text/JavaScript" language="JavaScript">
16
<script type="text/JavaScript" language="JavaScript">
16
//<![CDATA[
17
//<![CDATA[
17
18
Lines 678-683 YAHOO.util.Event.onContentReady("furtherm", function () { Link Here
678
[% IF ( OPACLocalCoverImages ) %][% IF ( localimages ) %]
679
[% IF ( OPACLocalCoverImages ) %][% IF ( localimages ) %]
679
    <li id="tab_images"><a href="#images">Images</a></li>
680
    <li id="tab_images"><a href="#images">Images</a></li>
680
[% END %][% END %]
681
[% END %][% END %]
682
683
684
[% IF ( HTML5MediaEnabled ) %][% IF ( HTML5MediaSets ) %]
685
    <li id="tab_html5media"><a href="#html5media">Play media</a></li>
686
[% END %][% END %]
687
681
</ul>
688
</ul>
682
689
683
[% IF ( serialcollection ) %]
690
[% IF ( serialcollection ) %]
Lines 1165-1170 YAHOO.util.Event.onContentReady("furtherm", function () { Link Here
1165
[% END %]
1172
[% END %]
1166
1173
1167
1174
1175
[% IF ( HTML5MediaEnabled ) %]
1176
<div id="html5media">
1177
        <p>
1178
        <[% HTML5MediaParent %][% HTML5MediaWidth %] controls preload=none>
1179
          [% FOREACH HTML5MediaSet IN HTML5MediaSets %]
1180
            <[% HTML5MediaSet.child  %] src="[% HTML5MediaSet.srcblock %]"[% HTML5MediaSet.typeblock %] />
1181
          [% END %]
1182
            [[% HTML5MediaParent %] tag not supported by your browser.]
1183
        </[% HTML5MediaParent %]>
1184
        </p>
1185
</div>
1186
[% END %]
1187
1188
1168
[% IF ( OPACLocalCoverImages ) %]
1189
[% IF ( OPACLocalCoverImages ) %]
1169
<div id="images">
1190
<div id="images">
1170
<p>Click on an image to view it in the image viewer</p>
1191
<p>Click on an image to view it in the image viewer</p>
(-)a/opac/opac-detail.pl (-1 / +8 lines)
Lines 49-54 use MARC::Field; Link Here
49
use List::MoreUtils qw/any none/;
49
use List::MoreUtils qw/any none/;
50
use C4::Images;
50
use C4::Images;
51
use Koha::DateUtils;
51
use Koha::DateUtils;
52
use Koha::HTML5Media;
52
53
53
BEGIN {
54
BEGIN {
54
	if (C4::Context->preference('BakerTaylorEnabled')) {
55
	if (C4::Context->preference('BakerTaylorEnabled')) {
Lines 747-752 if (C4::Context->preference("OPACLocalCoverImages")){ Link Here
747
		$template->param(OPACLocalCoverImages => 1);
748
		$template->param(OPACLocalCoverImages => 1);
748
}
749
}
749
750
751
752
# HTML5 Media
753
if ( (C4::Context->preference("HTML5MediaEnabled") eq 'opac') || (C4::Context->preference("HTML5MediaEnabled") eq 'both') ) {
754
    $template = Koha::HTML5Media->gethtml5media($template,$record);
755
}
756
757
750
# Amazon.com Stuff
758
# Amazon.com Stuff
751
if ( C4::Context->preference("OPACAmazonEnabled") ) {
759
if ( C4::Context->preference("OPACAmazonEnabled") ) {
752
    $template->param( AmazonTld => get_amazon_tld() );
760
    $template->param( AmazonTld => get_amazon_tld() );
753
- 

Return to bug 8377