Daniel@0: /* Part of DML (Digital Music Laboratory) Daniel@0: Copyright 2014-2015 Samer Abdallah, University of London Daniel@0: Daniel@0: This program is free software; you can redistribute it and/or Daniel@0: modify it under the terms of the GNU General Public License Daniel@0: as published by the Free Software Foundation; either version 2 Daniel@0: of the License, or (at your option) any later version. Daniel@0: Daniel@0: This program is distributed in the hope that it will be useful, Daniel@0: but WITHOUT ANY WARRANTY; without even the implied warranty of Daniel@0: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the Daniel@0: GNU General Public License for more details. Daniel@0: Daniel@0: You should have received a copy of the GNU General Public Daniel@0: License along with this library; if not, write to the Free Software Daniel@0: Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Daniel@0: */ Daniel@0: Daniel@0: :- module(cp_audio, Daniel@0: [ audio_player//1 Daniel@0: , audio_player//2 Daniel@0: , audio_decoration//3 Daniel@0: , spectrogram//2 Daniel@0: , audio_link/3 Daniel@0: , audio_file/3 Daniel@0: , audio_playlist//2 Daniel@0: , finder_player/2 Daniel@0: , finder_player/3 Daniel@0: ]). Daniel@0: Daniel@0: :- use_module(library(http/http_dispatch)). Daniel@0: :- use_module(library(http/http_path)). Daniel@0: :- use_module(library(http/html_write)). Daniel@0: :- use_module(library(http/html_head)). Daniel@0: :- use_module(library(http/js_write)). Daniel@0: :- use_module(library(semweb/rdf_db)). Daniel@0: :- use_module(library(semweb/rdf_label),[rdf_label/2]). Daniel@0: :- use_module(library(dcg_core)). Daniel@0: :- use_module(library(httpfiles)). Daniel@0: :- use_module(library(optutils)). Daniel@0: :- use_module(components(icons)). Daniel@0: Daniel@0: :- multifile audio_link/3, audio_file/3. Daniel@0: :- rdf_meta audio_link(r,-,-). Daniel@0: Daniel@0: :- html_resource(js('add_dummy_iframe.js'), [requires(jquery)]). Daniel@0: Daniel@0: Daniel@0: %% audio_decoration(+Type:oneof([none,link,player]), +Links:list(pair(url,maybe(filetype))), +Content:phrase) is det. Daniel@0: % Daniel@0: % Emits the HTML content specified by Content, but optionally decorated with controls Daniel@0: % that allow any associated audio to be played. Links is a list of pairs of links to audio Daniel@0: % content with an optional filetype, where a filetype is a standard audiofile extension like Daniel@0: % mp3, ogg, wav etc. Daniel@0: audio_decoration(none,_,Link) --> phrase(Link). Daniel@0: Daniel@0: audio_decoration(link,[URL|_],Link) --> Daniel@0: html_requires(font_awesome), Daniel@0: html_requires(js('add_dummy_iframe.js')), Daniel@0: html(span( [ a([href(URL),target(dummy)],\icon(play)) Daniel@0: , &(nbsp), a([href('about:blank'),target(dummy)],\icon(stop)) Daniel@0: , &(ensp), \Link Daniel@0: ])). Daniel@0: Daniel@0: audio_decoration(player,URLS,Link) --> Daniel@0: html(span(style="display:inline-block;width=auto", Daniel@0: [ div(\audio_player(URLS)), div(\Link) ])). Daniel@0: Daniel@0: audio_player(Links) --> audio_player(Links,[]). Daniel@0: audio_player(Links,Attribs) --> Daniel@0: html(audio([ controls, preload=none | Attribs ], Daniel@0: [ \seqmap(audio_source,Links), Daniel@0: "Your browser does not support HTML5 audio." ])). Daniel@0: Daniel@0: audio_playlist(ID,Links) --> Daniel@0: % html_requires(js('playlist.js')), Daniel@0: {http_absolute_location(js('playlist.js'),PlaylistJS,[])}, Daniel@0: {Links=[item(Src1,_,_)|_]}, Daniel@0: html( div(class(playlist), Daniel@0: [ style([ 'div.playlist ul {list-style-type:none; margin:0px;padding:0px;height:10em;overflow:auto }' Daniel@0: , 'div.playlist li div {display:block}' Daniel@0: , 'div.playlist li div a {color:#ccc;text-decoration:none;overflow-x:hidden}' Daniel@0: , 'div.playlist li div a:hover {color:white}' Daniel@0: , 'div.playlist li.active {color:black;background-color:#eee}' Daniel@0: , 'div.playlist li.active div a {color:black}' Daniel@0: , 'div.playlist {padding:1ex;background-color:#222;width:400px;border-radius:1ex}' Daniel@0: ]) Daniel@0: , audio([ id('~w-audio'-[ID]), controls, preload=none ], Daniel@0: [ source([src=Src1],[]), "Your browser does not support HTML5 audio." ]) Daniel@0: , ul(id('~w-list'-[ID]), \alinks(1,Links)) Daniel@0: , \js_script({|javascript(PlaylistJS,ID)|| Daniel@0: $.getScript(PlaylistJS, function(x,y,z){init_playlist(ID)})|}) Daniel@0: % , script(type('text/javascript'),'init_playlist(~w)'-ID) Daniel@0: ])). Daniel@0: Daniel@0: alinks(NSelected,Links) --> alinks(NSelected,1,Links). Daniel@0: alinks(_,_,[]) --> !. Daniel@0: alinks(N,N,[Item|Links]) --> !, {succ(N,M)}, html(li(class(active),\alink(Item))), alinks(N,M,Links). Daniel@0: alinks(S,N,[Item|Links]) --> !, {succ(N,M)}, html(li(\alink(Item))), alinks(S,M,Links). Daniel@0: alink(item(URL,Label,Page)) --> Daniel@0: html(div([ a([href(Page),target('_blank')],\icon('external-link')),' ' Daniel@0: , a([class(audio),href(URL)],Label)])). Daniel@0: Daniel@0: Daniel@0: audio_source(URL-Fmt) --> Daniel@0: ( {Fmt=just(Type), mime_type(Type,MimeType)} Daniel@0: -> html(source([src=URL,type=MimeType],[])) Daniel@0: ; html(source([src=URL],[])) Daniel@0: ). Daniel@0: Daniel@0: Daniel@0: %% spectrogram(+URI, +Options) is det. Daniel@0: % Daniel@0: % Emits HTML for a spectrogram viewer for a given recording URI. The viewer Daniel@0: % includes controls for controlling the time window extracted from the full signal. Daniel@0: spectrogram(URI,Opts) --> Daniel@0: { seqmap( option_default_select, Daniel@0: [offset(Off), length(Len), width(W), height(H)], Daniel@0: [0, 60, 15, 7], Daniel@0: Opts,Opts1), Daniel@0: http_link_to_id(spectrogram_window, Daniel@0: [ uri(URI), offset(Off), length(Len), width(W), height(H) | Opts1 ], Daniel@0: SpectroURL ) Daniel@0: }, Daniel@0: html_requires(font_awesome), Daniel@0: html(iframe([ frameborder=0, seamless=seamless, src=SpectroURL, Daniel@0: scrolling=no, style="width:100%;height:~dcm"-[H] ],[])). Daniel@0: Daniel@0: :- meta_predicate finder_player(1,-). Daniel@0: %% finder_player(+Finder:pred(-uri), -Player:html_term) is det. Daniel@0: finder_player(Finder,html(\audio_playlist(ID,Items))) :- Daniel@0: gensym(pl,ID), Daniel@0: findall(item(H,L,P),( call(Finder,X), Daniel@0: http_link_to_id(list_resource,[r(X)],P), Daniel@0: audio_link(X,H,_), Daniel@0: rdf_label(X,L) Daniel@0: ), Items). Daniel@0: Daniel@0: %% finder_player(@URI:uri, +Finder:goal, -Player:html_term) is det. Daniel@0: :- meta_predicate finder_player(-,0,-). Daniel@0: finder_player(R,Goal,Player) :- finder_player(call1(R,Goal),Player). Daniel@0: call1(R,Goal,R) :- call(Goal). Daniel@0: