<?php if (!defined('PmWiki')) exit();
/**
  \file  audio5.php
  \brief  HTML5 Audio Support for PmWiki
  
  This recipe provides the HTML5 <audio> tag for PmWiki. 
  
  Copyright 2012, 2013, 2015, 2022 Tom Gem <tomgem@me.com>, 
    an adaptation of HTML5audio.php by GNUZoo, 
    copyright 2007, 2010 GNUZoo <guru@gnuzoo.org>

  This program 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.

  Full documentation: 
    http://www.pmwiki.org/wiki/Cookbook/Audio5
  
  Version history:
    2012-11-01 - initial release
    2013-10-23 - added support for the track element (subtitles)
        - removed necessity to use the (:audio file:) markup without file extensions
        - audio format order is now configurable
        - audio5 now shows upload links if no audio files are found
        - added php5.2 as a requirement on the recipe page
    2013-12-03 - added support for attachments on other groups/pages (:audio group/page/file:)
    2015-10-05 - added support for php 5.5 (replaced Markup with Markup_e)
    2022-10-29 - added support for php 8
    2022-10-30 - replaced all tabs with spaces
*/

// recipe version
$RecipeInfo['Audio5']['Version'] = '2022-10-30';

// get and set defaults
SDV($AudioPreload, 'auto');  // default is to load audio when page loads (auto|metadata|none)
SDV($AudioAutoplay, 0);      // default is not to autoplay audio (0|1)
SDV($AudioControls, 1);      // default is a player with controls (0|1)
SDV($AudioLoop, 0);          // default is not to loop audio (0|1)
SDVA($AudioExtensions, array('mp3','ogg','wav'));  // default audio format order
SDVA($TrackExtensions, array('srt','vtt'));        // default track format order (reverse order)

// text which will be shown in old browsers instead of audio
SDV($AudioNotSupportedText, 'Sorry, your browser does not support HTML5 audio.'); 

// use this if your audios are not stored as 'attachments' of your wiki pages
// example setting for config.php (note the trailing slash): 
// $AudioUrl = 'http://server.example.com/path/to/audiofolder/';
SDV($AudioUrl, 0); 

// get the currently active language. only used by the track (subtitles) element
if (isset($XLLangs['0'])) { $AudioLang = $XLLangs['0']; } else { $AudioLang = 'en'; }

// audio markup definition
Markup('Audio5', 'fulltext', 
    '/\\(:(audio)(\\s.*?)?:\\)/i', 
    "mu_Audio5");

function mu_Audio5($m) {
  return Audio5($m[1],$m[2]);
}

// main (and only) function
function Audio5($name, $args) {  
  // those are needed here
  global  $pagename, $PageUrl, $UploadDir, $UploadPrefixFmt, $UploadUrlFmt, $EnableDirectDownload, 
      $AudioAutoplay, $AudioControls, $AudioLoop, $AudioPreload, 
      $AudioExtensions, $TrackExtensions, $AudioNotSupportedText, $AudioLang, $AudioUrl;
    
  // a little helper
  $nl = "\n";
  
  // parse arguments
  $args = ParseArgs($args);
  
  // get audio file basename and dirname
  $AudioFile = pathinfo($args[''][0], PATHINFO_FILENAME);
  $AudioDirName = pathinfo($args[''][0], PATHINFO_DIRNAME);
    
  // get the path to the upload dir
  if ($AudioDirName == ".") {
    // the attachment can be found on the same group/page 
    $AudioDir = FmtPageName($UploadDir.$UploadPrefixFmt, $pagename);
  } else { 
    // the attachment can be found on another group/page 
    $AudioDirUnix = str_replace('.', '/', $AudioDirName);
    $AudioDir = $UploadDir.'/'.$AudioDirUnix;
  }
  
  // get audio src url
  $AudioAttached = 0;
  if (empty($AudioUrl)) {
    // respect setting of $EnableDirectDownload 
    // please note, audio playback does not work with most browsers if $EnableDirectDownload=0; is set 
    if (IsEnabled($EnableDirectDownload, 1)) {
      if ($AudioDirName == ".") {
        // the attachment can be found on the same group/page 
        $AudioUrl = FmtPageName($UploadUrlFmt.$UploadPrefixFmt.'/', $pagename);
      } else { 
        // the attachment can be found on another group/page 
        $AudioUrl = $UploadUrlFmt.'/'.$AudioDirUnix.'/';
      }
    } else {
      // note, attachments on other groups/pages will not work if $EnableDirectDownload=0 is set
      $AudioUrl = FmtPageName('$PageUrl?action=download&upname=', $pagename);
    }
    $AudioAttached = 1;
  }
  
  // assemble complete audio source url
  $AudioSrc = $AudioUrl.$AudioFile;
  
  // start gathering audio options
  $AudioOpt = ' ';

  // get and set preload behaviour
  if (isset($args['preload'])) { $AudioPreload = $args['preload']; }
  $AudioOpt = $AudioOpt.'preload="'.$AudioPreload.'" ';

  // get and set boolean audio attributes
  if (isset($args['autoplay'])) {
    if (!empty($args['autoplay'])) { $AudioOpt = $AudioOpt.'autoplay="autoplay" '; }
  } else {
    if (!empty($AudioAutoplay)) { $AudioOpt = $AudioOpt.'autoplay="autoplay" '; }
  }
  if (isset($args['controls'])) {
    if (!empty($args['controls'])) { $AudioOpt = $AudioOpt.'controls="controls" '; }
  } else {
    if (!empty($AudioControls)) { $AudioOpt = $AudioOpt.'controls="controls" '; }
  }
  if (isset($args['loop'])) {
    if (!empty($args['loop'])) { $AudioOpt = $AudioOpt.'loop="loop" '; }
  } else {
    if (!empty($AudioLoop)) { $AudioOpt = $AudioOpt.'loop="loop" '; }
  }
    
  // search for existing audio files and add them to the <audio> tag if they do
  $Audios = '';
  $AudioFound = 0;
  
  foreach ($AudioExtensions as $Extension) {
    $AudioPath = $AudioDir.'/'.$AudioFile.'.'.$Extension;
    
    // can't check if audios exist if $AudioUrl was set manually - if so, just add them all
    if (file_exists($AudioPath) || empty($AudioAttached)) {
      if ($Extension == 'mp3') { $AudioType = 'type="audio/mpeg"'; } 
      elseif ($Extension == 'wav') { $AudioType = 'type="audio/wave"'; }
      else { $AudioType = 'type="audio/'.$Extension.'"'; }
      
      $Audios = $Audios.'<source src="'.$AudioSrc.'.'.$Extension.'" '.$AudioType.' />'.$nl;
      $AudioFound = 1;
    }
  }

  // search for existing track files (subtitles) and add the last match to the <video> tag
  $TrackAttribute = '';
  $TrackFile = '';
  
  foreach ($TrackExtensions as $Extension) {
    $TrackPath = $AudioDir.'/'.$AudioFile.'.'.$Extension;
    
    // can't check if a track file exists if $AudioUrl was set manually - if so, just add it
    if (file_exists($TrackPath) || empty($AudioAttached)) {
      $TrackSrc = $AudioSrc.'.'.$Extension;
      $TrackAttribute = 'poster="'.$TrackSrc.'"';
      $TrackFile = '<track src="'.$TrackSrc.'" kind="subtitles" srclang="'.$AudioLang.'" label="'.$AudioFile.'" default />';
    }
  }
  
  // generate and return html for the wiki page
  if ($AudioFound == 1) {
    return Keep('<audio'.$AudioOpt.'>'.$nl.$Audios.$TrackFile.$nl.'<p class="noaudio">'.$AudioNotSupportedText.'</p>'.$nl.'</audio>');
  } else {
    // show upload links if no audio files can be found
    $AudioUpload = '';
    $AudioUploadlink = FmtPageName('$PageUrl?action=upload&upname=', $pagename);

    foreach ($AudioExtensions as $Extension) {
      $AudioUpload = $AudioUpload.'<a rel="nofollow" class="createlinktext" href="'.$AudioUploadlink.$AudioFile.'.'.$Extension.'">'.$AudioFile.'.'.$Extension.'</a>';
      $AudioUpload = $AudioUpload.'<a rel="nofollow" class="createlink" href="'.$AudioUploadlink.$AudioFile.'.'.$Extension.'">&nbsp;&Delta;&nbsp;</a>';
    }
    return Keep('<p class="noaudio">No audio files ('.$AudioUpload.') found.</p>');
  }
}