Dup Ver Goto 📝

AudioPlayer_01

PT2/lang/php/examples does not exist
To
218 lines, 627 words, 4669 chars Page 'AudioPlayer_01' does not exist.

This is a simple example of how to play audio.

playaudio.php

<?php

$qs = $_SERVER['QUERY_STRING'];
$fn = urldecode($qs);
$path = "/music/$fn";
if( file_exists($path) ) {
  $mime = mime_content_type($path);
  header('Content-Type: audio/mpeg');
  header('Content-length: ' . filesize($path));
  $fh = fopen($path, 'rb');
  fpassthru($fh);
  fclose($fh);
} else {
  http_response_code(404);
  echo "does not exist: $path";
  exit();
}

playmusic.php

<?php

function show_player($path,$rpath,$mime) {
  $xs = explode("/",$path);
  $fn = array_pop($xs);
  $enc = urlencode($rpath);
?><!DOCTYPE html>
<html>
<head>
<title>Audio: <?php echo $fn; ?></title>
</head>
<body>
<h1><?php echo $fn; ?></h1>
<p class='path'><?php echo $rpath; ?></p>
<div class='player'>
<audio controls src="/playaudio.php?<?php echo $enc; ?>"></audio>
</div>
</body>
</html><?php
}

$qs = $_SERVER['QUERY_STRING'];
$fn = urldecode($qs);
$path = "/music/$fn";
if( file_exists($path) ) {
  $mime = mime_content_type($path);
  show_player($path,$fn,$mime);
} else {
  echo "does not exist: $path";
}

tr.php

The sqlite3 database /music/music.byword.db contains a single table with two columns: word and paths. The paths column contains JSON-encoded lists of paths. These indices are made by a python script and the find command.

<?php

$dbfn = "/music/music.byword.db";
if( ! file_exists($dbfn) ) {
  echo "no db";
  exit();
}

$db = new SQLite3($dbfn, SQLITE3_OPEN_READWRITE);
function get1($word) {
  global $db;
  $stmt = $db->prepare("SELECT paths FROM tracks_by_word WHERE word = :word");
  $stmt->bindValue(":word",$word);
  $result = $stmt->execute();
  $got = $result->fetchArray(SQLITE3_NUM);
  if( $got === false ) {
    echo "got false";
    return [];
  }
  $got = $got[0];
  $paths = json_decode($got);
  return $paths;
}

$qs = $_SERVER['QUERY_STRING'];
$qs = strtolower($qs);
$ws = explode("/",$qs);

$all = false;
$words = [];
foreach($ws as $word) {
  if( $word == ".a" ) {
    $all = true;
  } else if( $word !== "" ) {
    array_push($words,$word);
  }
}

if( count($words) == 0 ) {
  echo "no words";
  exit();
}



if( $all ) {
  $found = [];
  echo "all words: ".implode(", ",$words);
  $word1 = array_shift($words);
  $f = get1($word1);
  foreach($f as $p) {
    $found[$p] = true;
  }
  foreach($words as $word) {
    $f = get1($word);
    $g = [];
    foreach($f as $x) {
      $g[$x] = true;
    }
    foreach($found as $k => $v) {
      if( !array_key_exists($k,$g) ) {
        unset($found[$k]);
      }
    }
  }
} else {
  echo "any words: ".implode(", ",$words);
  $found = [];
  foreach($words as $word) {
    $f = get1($word);
    foreach($f as $p) {
      $found[$p] = true;
    }
  }
}
// print results
{
  $found = array_keys($found);
  if( count($found) == 0 ) {
    echo "found nothing";
    exit();
  }
  sort($found);
  echo "<ol>\n";
  foreach($found as $path) {
    if( preg_match('@\.\./@',$path) ) {
      echo ".. in path";
      exit();
    }
    $p = urlencode($path);
    $url = "/playmusic.php?$p";
    echo "<li><a target='_blank' href='$url'>$path</a></li>\n";
  }
  echo "</ol>\n";
}

mkwordidx

Takes file index (produced using find), splits at non-alphanumeric into words, converts to lowercase, and makes a dict mapping word to path.

import json, re
from collections import defaultdict

d = defaultdict(list)
a = open("music.index.txt").read().rstrip().splitlines()
for x in a:
  if x.startswith("./"):
    x = x[2:]
  y = x.lower()
  y = re.sub(r"[^a-zA-A0-9]+","_",y)
  y = re.sub(r"__+","_",y)
  xs = y.split("_")
  for word in xs:
    if word != "":
      d[word].append(x)

with open("music.byword.json","wt") as f:
  json.dump(d,f)

mkwordsql

Reads the JSON from above and inserts it into an sqlite3 database.

import json, sqlite3, os

with open("music.byword.json") as f:
  d = json.load(f)

dbfn = "music.byword.db"
if os.path.exists(dbfn):
  os.unlink(dbfn)

con = sqlite3.connect(dbfn)
cur = con.cursor()
cur.execute("CREATE TABLE tracks_by_word ( word PRIMARY KEY, paths )")
data = [ (word, json.dumps(paths)) for word, paths in d.items() ]
cur.executemany("INSERT INTO tracks_by_word ( word, paths ) VALUES ( ?, ? )", data )

con.commit()

con.close()

Find

The list of filenames is made by

find . -type f | grep -P '(mp3|m4a|wav|flac)$' > music.index.txt