rompr www

This commit is contained in:
qo-op 2020-12-12 03:06:33 +01:00
parent d2e02277d2
commit 467a426bf5
1839 changed files with 335422 additions and 0 deletions

41
www/jukebox/404.php Normal file
View File

@ -0,0 +1,41 @@
<?php
include('includes/vars.php');
include("includes/functions.php");
$base_url = get_base_url();
$request = $_SERVER['REQUEST_URI'];
logger::log('REDIRECT','Uri is',$_SERVER['REQUEST_URI']);
if (preg_match('#prefs/userstreams/.*\.jpg#', $request)) {
$redirect = $base_url.'/newimages/broadcast.svg';
logger::log("404", "Request for missing userstream image. Redirecting to ".$redirect);
header("HTTP/1.1 307 Temporary Redirect");
header("Location: ".$redirect);
} else if (preg_match('#prefs/podcasts/.*\.jpg#', $request) ||
preg_match('#prefs/podcasts/.*\.png#', $request)) {
$redirect = $base_url.'/newimages/podcast-logo.svg';
logger::log("404", "Request for missing podcast image. Redirecting to ".$redirect);
header("HTTP/1.1 307 Temporary Redirect");
header("Location: ".$redirect);
} else {
header("HTTP/1.1 404 Not Found");
?>
<html>
<head>
<link rel="stylesheet" type="text/css" href="css/layout-january.css" />
<link rel="stylesheet" type="text/css" href="themes/Darkness.css" />
<title>Badgers!</title>
</head>
<body>
<br><br><br>
<table align="center"><tr><td><img src="newimages/favicon-196.png"></td></tr></table>
<h2 align="center">404 Error!</h2>
<br><br>
<h2 align="center">It's all gone horribly wrong</h2>
<br><br>
<?php
print '<h3 align="center">The document &quot;'.$request."&quot; doesn't exist. Are you sure you know what you're doing?</h3>";
?>
</body>
</html>
<?php
}
?>

22
www/jukebox/INSTALL.txt Normal file
View File

@ -0,0 +1,22 @@
==================
= Installing RompR
==================
Please read the installation instructions here:
http://sourceforge.net/p/rompr/wiki/Installation/
MacOS X Users
=============
Please read the instructions here:
http://sourceforge.net/p/rompr/wiki/Installation%20on%20Mac%20OS%20X/
Windows Users
=============
First, install a better operating system, then read this file again :)
Actually, it may well be possible to get this to run on Windows, if mpd or mopidy can be got
to work then there's probably a LAMP stack for Windows that will run apache and php
OK. But I don't intend to go buy a Windows computer just to find out.

23
www/jukebox/LICENSE.txt Normal file
View File

@ -0,0 +1,23 @@
# (C) Fat German Productions/Mark Greenwood 2017
SEE includes/license.html
CREDITS
=======
This program makes use of lots of other stuff which are all released
under their own licenses, just to make it complicated.
The original inspiration came from phpMP, and the original core of this app was lifted
directly from there. It's grown quite a lot since then.
jquery (http://jquery.com) and the jquery UI framework (http://jqueryui.com)
are probably released under the GPL or something. I dunno, their websites aren't
very clear on that point.
The md5 hashing algorithm code was taken from http://pajhome.org.uk/crypt/md5
and is released under a BSD license
The jquery form plugin comes from http://malsup.com/jquery/form/
and also has two licenses.

23
www/jukebox/README.md Normal file
View File

@ -0,0 +1,23 @@
# RompЯ
This is a browser-based client for Mopidy and MPD, which are both music players.
You can use RompЯ to control a music player on another device or on your computer. Because it runs in a web browser you can run it ony any device - your laptop,tablet, or phone can all be used to control your music player.
It has a rich and beautiful interface which is intended to sort your music, manage radio stations, browse and subscribe to podcasts.
When used with Mopidy you can listen to Spotify and make use of RompЯ's incredible music discovery features which will help to introduce you to new music.
## Installation from GitHub
Please see the [New Project Homepage](https://fatg3erman.github.io/RompR/)
![](docs/images/rompr-1.png)
![](docs/images/rompr-on-a-phone.png)
### What people are saying about RompЯ
* “Best interface to mpd / mopidy ever. A real must!”
* “Best browser based frontend to mpd I've ever seen!! Thank you!”
* “Rompr is a wonderful web based interface client to mpd.”
* “Great Project! I use it everyday already. I hope for VK-support soon. Thanks!”
* “I tired now a fiew clients to control my mopidy server running on Raspberry. rompr is far the best one, easy to install, very fast, good design and useful features.”
* “This application is amazing and easy to setup. I love it.”
* “Wow! Great stuff! I was searching for something like that for months!”

13
www/jukebox/README_ru.md Normal file
View File

@ -0,0 +1,13 @@
# RompЯ
Это браузерный клиент для музыкальных проигрывателей Mopidy и MPD.
RompЯ можно использовать для управления музыкальным проигрывателем на удалённом или локальном компьютере. Поскольку он работает в веб-браузере, вы можете запускать его на любом устройстве - ноутбуке, планшете или телефоне для управления вашим музыкальным проигрывателем..
Он имеет богатый и красивый интерфейс, который предназначен для сортировки музыки, управления радиостанциями, просмотра и подписки на подкасты.
При использовании с Mopidy вы можете слушать Spotify, которые помогут вам познакомиться с новой музыкой.
## Установка с GitHub
Инструкция [Новая Страница проекта](https://fatg3erman.github.io/RompR/)
![](docs/images/rompr-1.png)
![](docs/images/rompr-on-a-phone.png)

BIN
www/jukebox/REC/REC.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

450
www/jukebox/REC/bootstrap.css vendored Normal file
View File

@ -0,0 +1,450 @@
/*! normalize.css v7.0.0 | MIT License | github.com/necolas/normalize.css */
/* Document
========================================================================== */
/**
* 1. Correct the line height in all browsers.
* 2. Prevent adjustments of font size after orientation changes in
* IE on Windows Phone and in iOS.
*/
html {
line-height: 1.15; /* 1 */
-ms-text-size-adjust: 100%; /* 2 */
-webkit-text-size-adjust: 100%; /* 2 */
}
/* Sections
========================================================================== */
/**
* Remove the margin in all browsers (opinionated).
margin: 0;
*/
body {
margin-left:auto;
margin-right:auto;
width:98%;
}
/**
* Add the correct display in IE 9-.
*/
article,
aside,
footer,
header,
nav,
section {
display: block;
}
/**
* Correct the font size and margin on `h1` elements within `section` and
* `article` contexts in Chrome, Firefox, and Safari.
*/
h1 {
font-size: 2em;
margin: 0.67em 0;
}
/* Grouping content
========================================================================== */
/**
* Add the correct display in IE 9-.
* 1. Add the correct display in IE.
*/
figcaption,
figure,
main { /* 1 */
display: block;
}
/**
* Add the correct margin in IE 8.
*/
figure {
margin: 1em 40px;
}
/**
* 1. Add the correct box sizing in Firefox.
* 2. Show the overflow in Edge and IE.
*/
hr {
box-sizing: content-box; /* 1 */
height: 0; /* 1 */
overflow: visible; /* 2 */
}
/**
* 1. Correct the inheritance and scaling of font size in all browsers.
* 2. Correct the odd `em` font sizing in all browsers.
*/
pre {
font-family: monospace, monospace; /* 1 */
font-size: 1em; /* 2 */
}
/* Text-level semantics
========================================================================== */
/**
* 1. Remove the gray background on active links in IE 10.
* 2. Remove gaps in links underline in iOS 8+ and Safari 8+.
*/
a {
background-color: transparent; /* 1 */
-webkit-text-decoration-skip: objects; /* 2 */
}
/**
* 1. Remove the bottom border in Chrome 57- and Firefox 39-.
* 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
*/
abbr[title] {
border-bottom: none; /* 1 */
text-decoration: underline; /* 2 */
text-decoration: underline dotted; /* 2 */
}
/**
* Prevent the duplicate application of `bolder` by the next rule in Safari 6.
*/
b,
strong {
font-weight: inherit;
}
/**
* Add the correct font weight in Chrome, Edge, and Safari.
*/
b,
strong {
font-weight: bolder;
}
/**
* 1. Correct the inheritance and scaling of font size in all browsers.
* 2. Correct the odd `em` font sizing in all browsers.
*/
code,
kbd,
samp {
font-family: monospace, monospace; /* 1 */
font-size: 1em; /* 2 */
}
/**
* Add the correct font style in Android 4.3-.
*/
dfn {
font-style: italic;
}
/**
* Add the correct background and color in IE 9-.
*/
mark {
background-color: #ff0;
color: #000;
}
/**
* Add the correct font size in all browsers.
*/
small {
font-size: 80%;
}
/**
* Prevent `sub` and `sup` elements from affecting the line height in
* all browsers.
*/
sub,
sup {
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline;
}
sub {
bottom: -0.25em;
}
sup {
top: -0.5em;
}
/* Embedded content
========================================================================== */
/**
* Add the correct display in IE 9-.
*/
audio,
video {
display: inline-block;
}
/**
* Add the correct display in iOS 4-7.
*/
audio:not([controls]) {
display: none;
height: 0;
}
/**
* Remove the border on images inside links in IE 10-.
*/
img {
border-style: none;
}
/**
* Hide the overflow in IE.
*/
svg:not(:root) {
overflow: hidden;
}
/* Forms
========================================================================== */
/**
* 1. Change the font styles in all browsers (opinionated).
* 2. Remove the margin in Firefox and Safari.
*/
button,
input,
optgroup,
select,
textarea {
font-family: sans-serif; /* 1 */
font-size: 100%; /* 1 */
line-height: 1.15; /* 1 */
margin: 0; /* 2 */
}
/**
* Show the overflow in IE.
* 1. Show the overflow in Edge.
*/
button,
input { /* 1 */
overflow: visible;
}
/**
* Remove the inheritance of text transform in Edge, Firefox, and IE.
* 1. Remove the inheritance of text transform in Firefox.
*/
button,
select { /* 1 */
text-transform: none;
}
/**
* 1. Prevent a WebKit bug where (2) destroys native `audio` and `video`
* controls in Android 4.
* 2. Correct the inability to style clickable types in iOS and Safari.
*/
button,
html [type="button"], /* 1 */
[type="reset"],
[type="submit"] {
-webkit-appearance: button; /* 2 */
}
/**
* Remove the inner border and padding in Firefox.
*/
button::-moz-focus-inner,
[type="button"]::-moz-focus-inner,
[type="reset"]::-moz-focus-inner,
[type="submit"]::-moz-focus-inner {
border-style: none;
padding: 0;
}
/**
* Restore the focus styles unset by the previous rule.
*/
button:-moz-focusring,
[type="button"]:-moz-focusring,
[type="reset"]:-moz-focusring,
[type="submit"]:-moz-focusring {
outline: 1px dotted ButtonText;
}
/**
* Correct the padding in Firefox.
*/
fieldset {
padding: 0.35em 0.75em 0.625em;
}
/**
* 1. Correct the text wrapping in Edge and IE.
* 2. Correct the color inheritance from `fieldset` elements in IE.
* 3. Remove the padding so developers are not caught out when they zero out
* `fieldset` elements in all browsers.
*/
legend {
box-sizing: border-box; /* 1 */
color: inherit; /* 2 */
display: table; /* 1 */
max-width: 100%; /* 1 */
padding: 0; /* 3 */
white-space: normal; /* 1 */
}
/**
* 1. Add the correct display in IE 9-.
* 2. Add the correct vertical alignment in Chrome, Firefox, and Opera.
*/
progress {
display: inline-block; /* 1 */
vertical-align: baseline; /* 2 */
}
/**
* Remove the default vertical scrollbar in IE.
*/
textarea {
overflow: auto;
}
/**
* 1. Add the correct box sizing in IE 10-.
* 2. Remove the padding in IE 10-.
*/
[type="checkbox"],
[type="radio"] {
box-sizing: border-box; /* 1 */
padding: 0; /* 2 */
}
/**
* Correct the cursor style of increment and decrement buttons in Chrome.
*/
[type="number"]::-webkit-inner-spin-button,
[type="number"]::-webkit-outer-spin-button {
height: auto;
}
/**
* 1. Correct the odd appearance in Chrome and Safari.
* 2. Correct the outline style in Safari.
*/
[type="search"] {
-webkit-appearance: textfield; /* 1 */
outline-offset: -2px; /* 2 */
}
/**
* Remove the inner padding and cancel buttons in Chrome and Safari on macOS.
*/
[type="search"]::-webkit-search-cancel-button,
[type="search"]::-webkit-search-decoration {
-webkit-appearance: none;
}
/**
* 1. Correct the inability to style clickable types in iOS and Safari.
* 2. Change font properties to `inherit` in Safari.
*/
::-webkit-file-upload-button {
-webkit-appearance: button; /* 1 */
font: inherit; /* 2 */
}
/* Interactive
========================================================================== */
/*
* Add the correct display in IE 9-.
* 1. Add the correct display in Edge, IE, and Firefox.
*/
details, /* 1 */
menu {
display: block;
}
/*
* Add the correct display in all browsers.
*/
summary {
display: list-item;
}
/* Scripting
========================================================================== */
/**
* Add the correct display in IE 9-.
*/
canvas {
display: inline-block;
}
/**
* Add the correct display in IE.
*/
template {
display: none;
}
/* Hidden
========================================================================== */
/**
* Add the correct display in IE 10-.
*/
[hidden] {
display: none;
}

BIN
www/jukebox/REC/fond.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 382 KiB

View File

@ -0,0 +1,134 @@
<?php
/*
* THIS CODE IS RELATED TO zen/_CopyLaRadio shell's
DONE!!!? WRITE THAT CODE IN infobar2.js : arrount line 158 before "return lines;"
// ZEEBOX HACK ZONE
var host = window.location.hostname;
var reclink = 'http://' + host + ':10010/_CopyLaRadio/youtube-dl.php?q=REC&artist=' + escape(encodeURIComponent(npinfo.Artist)) + '&title=' + escape(encodeURIComponent(npinfo.Title)) + '&radio='+ escape(encodeURIComponent(npinfo.Album)) +'&maxResults=1';
var zcopylink = ' <a id="REC" title="Enregistrer sur Youtube" href="#" onclick=\'javascript:window.open("'+ reclink +'","REC","menubar=no, scrollbars=no, top=10, left=10, width=320, height=400");return false;\'>[REC]</a>';
zcopylink += ' <a title="RECHERCHE LIBRE" href="'+ reclink +'" target="youtube">*</a>';
lines[0].text += zcopylink;
// ZEEBOX HACK ZONE
*/
// RUN CLI if($argc>1) parse_str(implode('&',array_slice($argv, 1)), $_REQUEST);
$search=$radio=$artist=$title=$lnk=$lnkform=$cmd=$len="";
$search = trim(urldecode($_REQUEST['q']));
$radio = urldecode($_REQUEST['radio']);
$artist = urldecode($_REQUEST['artist']);
$title = urldecode($_REQUEST['title']);
$lnk = trim(urldecode($_REQUEST['lnk']));
$cmd="$radio|$artist|$title";
$len=strlen($artist.$title);
//$result='<a href="#null" onclick="javascript:window.close();"><img src="./REC.png"></a><br>';
$result='<a href="" target="copylaradio"><img src="./REC.png"></a><br>';
if( $radio == "" ) { $radio = "CopyLaRadio"; }
if( $radio == "Nova zz" ) {
$artist = "undefined";
$title = "undefined";
}
// Write request for copy.sh triggering
if( $search == "REC" ) {
$result.='<h2>♫ '.$radio.' ♫</h2>';
// LINK RECEIVED
if ($lnk) {
$artist="";
// Not making double request
if( ! exec('grep '.escapeshellarg($lnk).' /tmp/ytdl.list') ) {
// file_put_contents("/tmp/ytdl.list","CopyLibre||$lnk\n", FILE_APPEND);
// instead of using a relay daemon to monitor a /tmp shared file, we are going to send sbot message to make it. #zenyta SSB message.
shell_exec('/var/www/loveland/_CopyLaRadio/sbotc_zenyta.sh '. $lnk);
}
$result.='<p><a href="'.$lnk.'" target="check">LIEN: '.$lnk.'</a></p>';
// TRACK COPY (not for undefined or local file)
} else if ($radio && $artist != $title && $artist != "undefined" && $title != "undefined" && strlen(explode(".", $title)[1]) != 3 && explode(".", $title)[1] != "opus" ) {
// Not making double request
if( ! exec('grep '.escapeshellarg($cmd).' /tmp/ytdl.list') ) {
// shell_exec('/home/pi/G1sms+/_CopyLaRadio/parle.sh "Enregistrement ajouté."');
shell_exec('/var/www/loveland/_CopyLaRadio/artist_song_to_sbotc_zenyta.sh "'. $artist . '" "' . $title .'"');
} else {
shell_exec('/var/www/loveland/_CopyLaRadio/parle.sh "Copie déjà lancée"');
}
$result.='<a style="color:#FFFFFF" href="https://www.youtube.com/results?search_query='.urlencode($artist).'%20'.urlencode($title).'" target="check">
<h4>'.$artist.' / '.$title.'</h4>
</a>';
// RADIO EXTERNAL TRACK SCRAPERs ....
} else if($radio != "" && $artist == "undefined" && $title == "undefined" ){
shell_exec('/var/www/loveland/_CopyLaRadio/parle.sh "Recherche externe pour '.$radio.'"');
file_put_contents("/tmp/youtube-dl.log", "/home/pi/G1sms+/_CopyLaRadio/libradio/".escapeshellcmd($radio).".php".PHP_EOL, FILE_APPEND);
if ( file_exists("/home/pi/G1sms+/_CopyLaRadio/libradio/".escapeshellcmd($radio).".php") ) {
file_put_contents("/tmp/ytdl.list","$radio||".PHP_EOL, FILE_APPEND);
} else {
shell_exec('/var/www/loveland/_CopyLaRadio/parle.sh "Aucun module"');
}
} else {
shell_exec('/var/www/loveland/_CopyLaRadio/parle.sh "Identification imprécise. Podcast? Fichier local?"');
}
}
$ytform = '<form action="./youtube-dl.php" method="GET">
<div>
<h3>ARTISTE: <input type="search" id="artist" name="artist" size="17" placeholder="Indiquez un artiste" value="'.$artist.'"></h3>
<h3>TITRE: <input type="search" id="title" name="title" size="20" placeholder="Titre de la chanson" value="'.$title.'"></h3>
</div>
<input type="hidden" id="radio" name="radio" value="'.$radio.'">
<input type="hidden" id="q" name="q" value="REC">
<br>
<input type="submit" value="♫ Copie Youtube ♫">
</form>
';
$lnkform.='<form action="./youtube-dl.php" method="GET">
<a href="https://youtube.com" target="search"><img src="./youtube.png"></a>
<p><h1>youtube-dl</h1>
<a style="color:#FFFFFF" href="https://ytdl-org.github.io/youtube-dl/supportedsites.html" target="_blank">- Sites compatibles -</a>
<input type="search" id="lnk" name="lnk" placeholder="Inscrivez le lien à copier" value="" size="40">
<input type="hidden" id="q" name="q" value="REC">
</p>
<div>
<input type="submit" value="Copie du Lien #zenyta">
</div>
</form>';
?>
<!doctype html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="">
<meta name="author" content="fred" >
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" >
<title><?php echo $search;?> - Recherche YouTube & Copie privée</title>
<link href="./bootstrap.css" rel="stylesheet">
</head>
<body style='background: url("./fond.jpg") no-repeat scroll center center / cover rgb(0, 0, 0); color:#FFFFFF;'>
<section class="content-section text-center">
<div class="container-fluid">
<div class="container" id="result" >
<div class="col-lg-8 col-lg-offset-2 page-scroll">
<ul>
<?php echo $result; ?>
<hr>
</ul>
<ul>
<?php echo $ytform; ?>
<hr>
<?php echo $lnkform; ?>
<hr>
</ul>
</div>
</div>
</div>
</section>
</body>
</html>

BIN
www/jukebox/REC/youtube.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

9
www/jukebox/_header Normal file
View File

@ -0,0 +1,9 @@
## Pages On This website
[Home](https://fatg3erman.github.io/RompR/)
[Recommended Linux Installation - with Nginx](https://fatg3erman.github.io/RompR/Recommended-Installation-on-Linux)
[Alternative Linux Installation - with Apache](https://fatg3erman.github.io/RompR/Installation-on-Linux-Alternative-Method)
[Troubleshooting](https://fatg3erman.github.io/RompR/Troubleshooting)

266
www/jukebox/albumart.php Normal file
View File

@ -0,0 +1,266 @@
<?php
define('ROMPR_IS_LOADING', true);
require_once ("includes/vars.php");
require_once ("includes/functions.php");
require_once ("international.php");
require_once ('utils/imagefunctions.php');
require_once ("backends/sql/backend.php");
require_once ("player/".$prefs['player_backend']."/player.php");
$only_plugins_on_menu = false;
$skin = "desktop";
set_version_string();
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<title>RompЯ Album Art</title>
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Expires" content="0" />
<?php
print '<script type="application/json" name="translations">'."\n".json_encode($translations)."\n</script>\n";
print '<script type="application/json" name="prefs">'."\n".json_encode($prefs)."\n</script>\n";
print '<link rel="stylesheet" type="text/css" href="css/layout-january.css?version=?'.ROMPR_VERSION.'" />'."\n";
print '<link rel="stylesheet" type="text/css" href="skins/desktop/skin.css?version=='.ROMPR_VERSION.'" />'."\n";
print '<link rel="stylesheet" type="text/css" href="css/albumart.css?version=?'.ROMPR_VERSION.'" />'."\n";
?>
<link rel="stylesheet" id="theme" type="text/css" />
<link type="text/css" href="css/jquery.mCustomScrollbar.css" rel="stylesheet" />
<?php
$scripts = array(
"jquery/jquery-3.3.1.min.js",
"jquery/jquery-migrate-3.0.1.js",
"ui/functions.js",
"ui/prefs.js",
"ui/language.js",
"jquery/jquery-ui.min-19.1.18.js",
"jquery/jquery.mCustomScrollbar.concat.min-3.1.5.js",
"includes/globals.js",
"ui/uifunctions.js",
"ui/metahandlers.js",
"ui/widgets.js",
"ui/debug.js",
"ui/coverscraper.js",
"ui/albumart.js"
);
foreach ($scripts as $i) {
logger::mark("INIT", "Loading ".$i);
print '<script type="text/javascript" src="'.$i.'?version='.ROMPR_VERSION.'"></script>'."\n";
}
include ("includes/globals.php");
?>
</head>
<body class="desktop">
<div id="pset" class="invisible"></div>
<div id="pmaxset" class="invisible"></div>
<div id="pbgset" class="invisible"></div>
<div class="albumcovers">
<div class="infosection">
<table width="100%">
<?php
print '<tr>
<td colspan="4"><h2>'.get_int_text("albumart_title").'</h2></td>
<td class="outer" align="right" colspan="1"><button id="finklestein">'.get_int_text("albumart_onlyempty").'</button></td>
</tr>';
print '<tr>
<td class="outer" id="totaltext"></td>
<td colspan="3"><div class="invisible" id="progress"></div></td>
<td class="outer" align="right"><button id="harold">'.get_int_text("albumart_getmissing").'</button></td>
</tr>';
// <td class="outer" align="right"><button id="doobag">'.get_int_text("albumart_findsmall").'</button></td>
print '<tr>
<td class="outer" id="infotext"></td>
<td colspan="3" align="center"><div class="inner" id="status">'.get_int_text('label_loading').'</div></td>
<td class="outer styledinputs" align="right"><input type="checkbox" class="topcheck" id="dinkytoys"><label for="dinkytoys" onclick="toggleLocal()">Ignore Local Images</label></td>
</tr>';
print '<tr>
<td colspan="4"></td>
<td class="outer styledinputs" align="right"><input type="checkbox" class="topcheck" id="poobag"><label for="poobag" onclick="toggleScrolling()">Follow Progress</label></td>
</tr>';
?>
</table>
</div>
</div>
<div id="wobblebottom">
<div id="artistcoverslist" class="tleft noborder">
<div class="noselection fullwidth">
<?php
if ($mysqlc) {
print '<div class="containerbox menuitem clickable clickselectartist selected" id="allartists"><div class="expand" class="artistrow">'.get_int_text("albumart_allartists").'</div></div>';
print '<div class="containerbox menuitem clickable clickselectartist" id="savedplaylists"><div class="expand" class="artistrow">Saved Playlists</div></div>';
print '<div class="containerbox menuitem clickable clickselectartist" id="radio"><div class="expand" class="artistrow">'.get_int_text("label_yourradio").'</div></div>';
do_artists_db_style();
}
?>
</div>
</div>
<div id="coverslist" class="tleft noborder">
<?php
// Do Local Albums
$count = 0;
$albums_without_cover = 0;
do_covers_db_style();
do_playlists();
do_radio_stations();
print '</div>';
print "</div>\n";
print "</div>\n";
print '<script language="JavaScript">'."\n";
print 'var numcovers = '.$count.";\n";
print 'var albums_without_cover = '.$albums_without_cover.";\n";
print "</script>\n";
print "</body>\n";
print "</html>\n";
function do_artists_db_style() {
$alist = get_list_of_artists();
foreach ($alist as $artist) {
print '<div class="containerbox menuitem clickable clickselectartist';
print '" id="artistname'.$artist['Artistindex'].'">';
print '<div class="expand" class="artistrow">'.$artist['Artistname'].'</div>';
print '</div>';
}
}
function do_covers_db_style() {
global $count;
global $albums_without_cover;
$alist = get_list_of_artists();
foreach ($alist as $artist) {
print '<div class="cheesegrater" name="artistname'.$artist['Artistindex'].'">';
print '<div class="albumsection">';
print '<div class="tleft"><h2>'.$artist['Artistname'].'</h2></div><div class="tright rightpad"><button class="invisible" onclick="getNewAlbumArt(\'#album'.$count.'\')">'.get_int_text("albumart_getthese").'</button></div>';
print "</div>\n";
print '<div id="album'.$count.'" class="containerbox fullwidth bigholder wrap">';
$blist = get_list_of_albums($artist['Artistindex']);
foreach ($blist as $album) {
print '<div class="fixed albumimg closet">';
print '<div class="covercontainer">';
$class = "clickable clickicon clickalbumcover droppable";
$src = "";
if ($album['Image'] && $album['Image'] !== "") {
$src = $album['Image'];
} else {
$class = $class . " notexist";
$albums_without_cover++;
}
print '<input name="albumpath" type="hidden" value="'.get_album_directory($album['Albumindex'], $album['AlbumUri']).'" />';
print '<input name="searchterm" type="hidden" value="'.rawurlencode($artist['Artistname']." ".munge_album_name($album['Albumname'])).'" />';
print '<img class="'.$class.'" name="'.$album['ImgKey'].'"';
if ($src != "") {
print ' src="'.$src.'" ';
}
print '/>';
print '<div>'.$album['Albumname'].'</div>';
print '</div>';
print '</div>';
$count++;
}
print "</div>\n";
print "</div>\n";
}
}
function do_radio_stations() {
global $count;
global $albums_without_cover;
$playlists = get_user_radio_streams();
if (count($playlists) > 0) {
print '<div class="cheesegrater" name="radio">';
print '<div class="albumsection">';
print '<div class="tleft"><h2>Radio Stations</h2></div><div class="tright rightpad"><button class="invisible" onclick="getNewAlbumArt(\'#album'.$count.'\')">'.get_int_text("albumart_getthese").'</button></div>';
print "</div>\n";
print '<div id="album'.$count.'" class="containerbox fullwidth bigholder wrap">';
foreach ($playlists as $file) {
print '<div class="fixed albumimg closet">';
print '<div class="covercontainer">';
$class = "";
$src = "";
if ($file['Image']) {
$src = $file['Image'];
} else {
$class = " notexist";
$albums_without_cover++;
}
print '<input name="searchterm" type="hidden" value="'.rawurlencode($file['StationName']).'" />';
print '<input name="artist" type="hidden" value="STREAM" />';
print '<input name="album" type="hidden" value="'.rawurlencode($file['StationName']).'" />';
$albumimage = new baseAlbumImage(array('artist' => 'STREAM', 'album' => $file['StationName']));
print '<img class="clickable clickicon clickalbumcover droppable'.$class.'" name="'.$albumimage->get_image_key().'"';
if ($src != "") {
print ' src="'.$src.'" ';
}
print '/>';
print '<div>'.htmlentities($file['StationName']).'</div>';
print '</div>';
print '</div>';
$count++;
}
print "</div>\n";
print "</div>\n";
}
}
function do_playlists() {
global $count;
global $albums_without_cover;
global $PLAYER_TYPE;
logger::log("PLAYLISTART", "Player type is", $PLAYER_TYPE);
$player = new $PLAYER_TYPE();
$playlists = $player->get_stored_playlists(false);
if (!is_array($playlists)) {
$playlists = array();
}
$plfiles = glob('prefs/userplaylists/*');
foreach ($plfiles as $f) {
$playlists[] = basename($f);
}
print '<div class="cheesegrater" name="savedplaylists">';
print '<div class="albumsection">';
print '<div class="tleft"><h2>Saved Playlists</h2></div>';
print "</div>\n";
print '<div id="album'.$count.'" class="containerbox fullwidth bigholder wrap">';
sort($playlists, SORT_STRING);
foreach ($playlists as $pl) {
logger::log("PLAYLISTART", "Playlist",$pl);
print '<div class="fixed albumimg closet">';
print '<div class="covercontainer">';
$class = "";
$albumimage = new baseAlbumImage(array('artist' => 'PLAYLIST', 'album' => $pl));
$src = $albumimage->get_image_if_exists();
if ($src === null) {
$class = " plimage notfound";
$src = '';
$albums_without_cover++;
}
$plsearch = preg_replace('/ \(by .*?\)$/', '', $pl);
print '<input name = "searchterm" type="hidden" value="'.rawurlencode($plsearch).'" />';
print '<input name="artist" type="hidden" value="PLAYLIST" />';
print '<input name="album" type="hidden" value="'.rawurlencode($pl).'" />';
print '<img class="clickable clickicon clickalbumcover droppable playlistimage'.$class.'" name="'.$albumimage->get_image_key().'"';
if ($src != "") {
print ' src="'.$src.'" ';
}
print '/>';
print '<div>'.htmlentities($pl).'</div>';
print '</div>';
print '</div>';
$count++;
}
print "</div>\n";
print "</div>\n";
}
?>

1
www/jukebox/albumart/.empty Executable file
View File

@ -0,0 +1 @@

331
www/jukebox/albums.php Normal file
View File

@ -0,0 +1,331 @@
<?php
// Automatic Collection Updates can be performed using cURL:
// curl -b "currenthost=Default;player_backend=mpd" http://localhost/rompr/albums.php?rebuild > /dev/null
// where currenthost is the name of one of the Players defined in the Configuration menu
// and player_backend MUST be mpd or mopidy, depending on what your player is.
// You can also use eg -b "debug_enabled=8;currenthost=MPD;player_backend=mpd"
// to get more debug info in the webserver error log.
require_once ("includes/vars.php");
require_once ("includes/functions.php");
require_once ("utils/imagefunctions.php");
require_once ("international.php");
require_once ("backends/sql/backend.php");
$error = 0;
logger::trace("TIMINGS", "======================================================================");
$initmem = memory_get_usage();
logger::trace("COLLECTION", "Memory Used is ".$initmem);
$now2 = time();
switch (true) {
case array_key_exists('item', $_REQUEST):
logit('item');
// Populate a dropdown in the collection or search results
dumpAlbums($_REQUEST['item']);
break;
case array_key_exists('mpdsearch', $_REQUEST):
logit('mpdsearch');
// Handle an mpd-style search request
require_once ("player/".$prefs['player_backend']."/player.php");
require_once ("collection/collection.php");
$trackbytrack = true;
$doing_search = true;
mpd_search();
break;
case array_key_exists('browsealbum', $_REQUEST):
logit('browsealbum');
// Populate a spotify album in mopidy's search results - as spotify doesn't return all tracks
require_once ("player/".$prefs['player_backend']."/player.php");
require_once ("collection/collection.php");
$trackbytrack = true;
$doing_search = true;
browse_album();
break;
case array_key_exists("rawterms", $_REQUEST):
logit('rawterms');
// Handle an mpd-style search request requiring tl_track format results
// Note that raw_search uses the collection models but not the database
// hence $trackbytrack must be false
logger::log("MPD SEARCH", "Doing RAW search");
require_once ("player/".$prefs['player_backend']."/player.php");
require_once ("collection/collection.php");
require_once ("collection/dbsearch.php");
$doing_search = true;
raw_search();
break;
case array_key_exists('terms', $_REQUEST):
logit('terms');
// SQL database search request
require_once ("player/".$prefs['player_backend']."/player.php");
require_once ("collection/collection.php");
require_once ("collection/dbsearch.php");
$doing_search = true;
database_search();
break;
case array_key_exists('rebuild', $_REQUEST):
logit('rebuild');
// This is a request to rebuild the music collection
require_once ("player/".$prefs['player_backend']."/player.php");
require_once ("collection/collection.php");
$trackbytrack = true;
update_collection();
break;
default:
logger::fail("ALBUMS", "Couldn't figure out what to do!");
break;
}
logger::trace("TIMINGS", "== Collection Update And Send took ".format_time(time() - $now2));
$peakmem = memory_get_peak_usage();
$ourmem = $peakmem - $initmem;
logger::trace("TIMINGS", "Peak Memory Used Was ".number_format($peakmem)." bytes - meaning we used ".number_format($ourmem)." bytes.");
logger::trace("TIMINGS", "======================================================================");
function logit($key) {
logger::log("COLLECTION", "Request is",$key,"=",$_REQUEST[$key]);
}
function checkDomains($d) {
if (array_key_exists('domains', $d)) {
return $d['domains'];
}
logger::debug("SEARCH", "No search domains in use");
return false;
}
function mpd_search() {
global $dbterms, $skin, $PLAYER_TYPE;
// If we're searching for tags or ratings it would seem sensible to only search the database
// HOWEVER - we could be searching for genre or performer or composer - which will not match in the database
// For those cases ONLY, controller.js will call into this instead of database_search, and we set $dbterms
// to make the collection check everything it finds against the database
$cmd = $_REQUEST['command'];
$domains = checkDomains($_REQUEST);
foreach ($_REQUEST['mpdsearch'] as $key => $term) {
switch ($key) {
case 'tag':
case 'rating':
$dbterms[$key] = $term;
break;
case 'any':
// This makes a search term of 'Madness My Girl' into
// search any Madness any My any Girl
// which seems to produce better results with Spotify. But probably doesn't with Google Play, which
// only uses the first term. Soundcloud concatenates them all back into one term again. What does MPD do?
foreach ($term as $t) {
$terms = explode(' ',$t);
foreach ($terms as $tom) {
$cmd .= " ".$key.' "'.format_for_mpd(html_entity_decode(trim($tom))).'"';
}
}
break;
default:
foreach ($term as $t) {
$cmd .= " ".$key.' "'.format_for_mpd(html_entity_decode(trim($t))).'"';
}
break;
}
}
logger::log("MPD SEARCH", "Search command : ".$cmd);
if ($_REQUEST['resultstype'] == "tree") {
require_once ("player/mpd/filetree.php");
require_once ("skins/".$skin."/ui_elements.php");
$player = new fileCollector();
$player->doFileSearch($cmd, $domains);
} else {
cleanSearchTables();
prepareCollectionUpdate();
$collection = new musicCollection();
$player = new $PLAYER_TYPE();
$player->populate_collection($cmd, $domains, $collection);
$collection->tracks_to_database();
close_transaction();
dumpAlbums($_REQUEST['dump']);
remove_findtracks();
}
}
function browse_album() {
global $PLAYER_TYPE, $skin;
$a = preg_match('/(a|b)(.*?)(\d+|root)/', $_REQUEST['browsealbum'], $matches);
if (!$a) {
print '<h3>'.get_int_text("label_general_error").'</h3>';
logger::error("DUMPALBUMS", "Browse Album Failed - regexp failed to match", $_REQUEST['browsealbum']);
return false;
}
$why = $matches[1];
$what = $matches[2];
$who = $matches[3];
$albumlink = get_albumlink($who);
if (substr($albumlink, 0, 8) == 'podcast+') {
require_once ('includes/podcastfunctions.php');
logger::log("ALBUMS", "Browsing For Podcast ".substr($albumlink, 9));
$podid = getNewPodcast(substr($albumlink, 8), 0, false);
logger::trace("ALBUMS", "Ouputting Podcast ID ".$podid);
outputPodcast($podid, false);
} else {
if (preg_match('/^.+?:artist:/', $albumlink)) {
remove_album_from_database($who);
}
$player = new $PLAYER_TYPE();
$collection = new musicCollection();
$cmd = 'find file "'.$albumlink.'"';
logger::log("MPD", "Doing Album Browse : ".$cmd);
prepareCollectionUpdate();
$player->populate_collection($cmd, false, $collection);
$collection->tracks_to_database(true);
close_transaction();
remove_findtracks();
if (preg_match('/^.+?:album:/', $albumlink)) {
// Just occasionally, the spotify album originally returned by search has an incorrect AlbumArtist
// When we browse the album the new tracks therefore get added to a new album, while the original tracks
// remain attached to the old one. This is where we use do_tracks_from_database with an array of albumids
// which joins them together into a virtual album, with the track ordering correct
print do_tracks_from_database($why, $what, find_justadded_albums(), true);
} else {
$artistarray = find_justadded_artists();
$do_controlheader = true;
foreach ($artistarray as $artistid) {
do_albums_from_database($why, 'album', $artistid, false, false, true, $do_controlheader);
$do_controlheader = false;
}
}
}
}
function raw_search() {
global $PLAYER_TYPE, $doing_search;
$domains = checkDomains($_REQUEST);
$collection = new musicCollection();
$found = 0;
logger::trace("MPD SEARCH", "checkdb is ".$_REQUEST['checkdb']);
if ($_REQUEST['checkdb'] !== 'false') {
logger::trace("MPD SEARCH", " ... checking database first ");
$found = doDbCollection($_REQUEST['rawterms'], $domains, "RAW", $collection);
if ($found > 0) {
logger::log("MPD SEARCH", " ... found ".$found." matches in database");
}
}
if ($found == 0) {
$cmd = $_REQUEST['command'];
foreach ($_REQUEST['rawterms'] as $key => $term) {
$cmd .= " ".$key.' "'.format_for_mpd(html_entity_decode($term[0])).'"';
}
logger::log("MPD SEARCH", "Search command : ".$cmd);
$doing_search = true;
$player = new $PLAYER_TYPE();
$player->populate_collection($cmd, $domains, $collection);
// For backends that don't support multiple parameters (Google Play)
// This'll return nothing for Spotify, so it's OK. It might help SoundCloud too.
$cmd = $_REQUEST['command'].' any ';
$parms = array();
if (array_key_exists('artist', $_REQUEST['rawterms'])) {
$parms[] = format_for_mpd(html_entity_decode($_REQUEST['rawterms']['artist'][0]));
}
if (array_key_exists('title', $_REQUEST['rawterms'])) {
$parms[] = format_for_mpd(html_entity_decode($_REQUEST['rawterms']['title'][0]));
}
if (count($parms) > 0) {
$cmd .= '"'.implode(' ',$parms).'"';
logger::log("MPD SEARCH", "Search command : ".$cmd);
$doing_search = true;
$collection->filter_duplicate_tracks();
$player->populate_collection($cmd, $domains, $collection);
}
}
print json_encode($collection->tracks_as_array());
}
function database_search() {
$tree = null;
$domains = checkDomains($_REQUEST);
if ($_REQUEST['resultstype'] == "tree") {
$tree = new mpdlistthing(null);
} else {
cleanSearchTables();
open_transaction();
}
$fcount = doDbCollection($_REQUEST['terms'], $domains, $_REQUEST['resultstype'], $tree);
if ($_REQUEST['resultstype'] == "tree") {
printFileSearch($tree, $fcount);
} else {
close_transaction();
dumpAlbums($_REQUEST['dump']);
}
}
function update_collection() {
global $PLAYER_TYPE;
// Check that an update is not currently in progress
// and create the update lock if not
if (collectionUpdateRunning()) {
header('HTTP/1.1 500 Internal Server Error');
print get_int_text('error_nocol');
exit(0);
}
if (file_exists('prefs/monitor')) {
unlink('prefs/monitor');
}
// Send some dummy data back to the browser, then close the connection
// so that the browser doesn't time out and retry
$sapi_type = php_sapi_name();
logger::log('COLLECTION','SAPI Name is',$sapi_type);
if (preg_match('/fpm/', $sapi_type) || preg_match('/fcgi/', $sapi_type)) {
logger::mark('COLLECTION', 'Closing Request The FastCGI Way');
print('<html></html>');
fastcgi_finish_request();
} else {
logger::mark('COLLECTION', 'Closing Request The Apache Way');
ob_end_clean();
ignore_user_abort(true); // just to be safe
ob_start();
print('<html></html>');
$size = ob_get_length();
header("Content-Length: $size");
header("Content-Encoding: none");
header("Connection: close");
ob_end_flush();
ob_flush();
flush();
if (ob_get_contents()) {
ob_end_clean();
}
}
if (session_id()) {
session_write_close();
}
// Browser is now happy. Now we can do our work in peace.
cleanSearchTables();
prepareCollectionUpdate();
$player = new $PLAYER_TYPE();
$player->musicCollectionUpdate();
tidy_database();
remove_findtracks();
// Add a marker to the monitor file to say we've finished
$player->collectionUpdateDone();
// Clear the update lock
clearUpdateLock();
}
?>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,301 @@
<?php
$mysqlc = null;
if (array_key_exists('collection_type', $prefs)) {
include("backends/sql/".$prefs['collection_type']."/specifics.php");
}
function probe_database() {
// In the case where collection_type is not set, probe to see which type of DB to use
// This keeps the behaviour the same as previous versions which auto-detected
// the database type. This does mean we get some duplicate code but this is
// so much better for the user.
global $mysqlc, $prefs;
logger::mark("SQL_CONNECT", "Probing Database Type");
logger::log("SQL_CONNECT", "Attempting to connect to MYSQL Server");
try {
if (is_numeric($prefs['mysql_port'])) {
logger::trace("SQL_CONNECT", "Connecting using hostname and port");
$dsn = "mysql:host=".$prefs['mysql_host'].";port=".$prefs['mysql_port'].";dbname=".$prefs['mysql_database'];
} else {
logger::trace("SQL_CONNECT", "Connecting using unix socket");
$dsn = "mysql:unix_socket=".$prefs['mysql_port'].";dbname=".$prefs['mysql_database'];
}
$mysqlc = new PDO($dsn, $prefs['mysql_user'], $prefs['mysql_password']);
logger::mark("SQL_CONNECT", "Connected to MySQL");
$prefs['collection_type'] = 'mysql';
} catch (Exception $e) {
logger::warn("SQL_CONNECT", "Couldn't connect to MySQL - ".$e);
$mysqlc = null;
}
if ($mysqlc == null) {
logger::log("SQL_CONNECT", "Attempting to use SQLite Database");
try {
$dsn = "sqlite:prefs/collection.sq3";
$mysqlc = new PDO($dsn);
logger::mark("MYSQL", "Connected to SQLite");
$prefs['collection_type'] = 'sqlite';
} catch (Exception $e) {
logger::fail("MYSQL", "Couldn't use SQLite Either - ".$e);
$mysqlc = null;
}
}
}
//
// Initialisation
//
function show_sql_error($text = "", $stmt = null) {
global $mysqlc;
logger::error("MYSQL ERROR", $text,":",$mysqlc->errorInfo()[1],":",$mysqlc->errorInfo()[2]);
if ($stmt !== null) {
logger::error("STMT ERROR", $text,":",$stmt->errorInfo()[1],":",$stmt->errorInfo()[2]);
}
}
//
// Queries
//
function generic_sql_query($qstring, $return_boolean = false, $return_type = PDO::FETCH_ASSOC, $return_value = null, $value_default = null, $return_rowcount = false ) {
global $mysqlc;
logger::debug("GENERIC_SQL", $qstring);
$retval = true;
if (($result = @$mysqlc->query($qstring)) !== false) {
logger::debug("GENERIC_SQL", "Done : ".($result->rowCount())." rows affected");
if ($return_value !== null) {
$arr = $result->fetch(PDO::FETCH_ASSOC);
$retval = ($arr) ? $arr[$return_value] : $value_default;
} else if ($return_boolean) {
$retval = true;
} else if ($return_rowcount) {
return $result->rowCount();
} else {
$retval = $result->fetchAll($return_type);
}
} else {