Skip to content

Commit

Permalink
Merge pull request #55 from KIMB-technologies/image-resize
Browse files Browse the repository at this point in the history
More with Logos
  • Loading branch information
kimbtech authored Mar 15, 2024
2 parents 2035a3d + f7c7bc9 commit e74a23a
Show file tree
Hide file tree
Showing 11 changed files with 136 additions and 22 deletions.
7 changes: 5 additions & 2 deletions Setup.md
Original file line number Diff line number Diff line change
Expand Up @@ -210,13 +210,15 @@ The JSON resource at `CONF_STREAM_JSON` should look like this:
"name": "Name A",
"url": "https://stream.example.com/file.mp3",
"live": false,
"proxy": true
"proxy": true,
"logo" : "https://stream.example.com/logo.png"
},
{
"name": "Name B",
"url": "http://stream.example.com/live.m3u",
"live": true,
"proxy": false
"proxy": false,
"logo" : "http://stream.example.com/live.png"
}
]
```
Expand All @@ -226,3 +228,4 @@ JSON list of objects with the following keys each:
- `url` Contains the url of the stream (either a file, .e.g., mp3, or a streamable ressource, e.g., m3u).
- `live` (optional, default `true`) Live streams can not be paused or fast forwarded, for non live streams the entire file needs to be available from the start.
- `proxy` (optional, default `false`) Use the internal proxy to allow https urls.
- `logo` (optional) Url to an image to display as logo in the radio's display.
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
2.9.0
2.9.1
2.9
2
2 changes: 1 addition & 1 deletion php/classes/Config.php
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ class Config {
/**
* The system's version.
*/
const VERSION = 'v2.9.0';
const VERSION = 'v2.9.1';

/**
* The real domain which should be used.
Expand Down
12 changes: 12 additions & 0 deletions php/classes/Inner.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,18 @@ public function __construct(int $id, Template $template){
$this->template = $template;
}

public function clearCache() : void {
if(Config::USE_LOGO_CACHE){
$this->template->setContent('CLEAR_CACHE', '');

if(isset($_GET['clear-logo-cache'])){
$this->html[] = '<span style="color:' . (
(new RadioLogo())->clearCache() ? 'green;">Cleared logo cache!' : 'red;">Error clearing logo cache!'
) .'</span>';
}
}
}

public function checkPost() : void {
if(isset( $_GET['radios'] ) && isset( $_POST['name'] )){
$this->html[] = '<span style="color:green;">Changed Radio stations!</span>';
Expand Down
9 changes: 7 additions & 2 deletions php/classes/OwnStreams.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,16 +43,21 @@ public function getStreams() : array {
if( !empty( $list ) ){

foreach( $list as $item ){

$urlOK = isset( $item['url'] ) && filter_var($item['url'], FILTER_VALIDATE_URL) !== false;
$streams[] = array(

$stream = array(
"name" => (!$urlOK ? "(url invalid!)" : '')
. (isset( $item['name'] ) && is_string($item['name']) ? $item["name"] : 'Invalid Name'),
"url" => $urlOK ? $item['url'] : '',
"live" => isset($item['live']) && is_bool($item['live']) ? $item['live'] : true,
"proxy" => isset($item['proxy']) && is_bool($item['proxy']) ? $item['proxy'] : false
);
// add logo if in json
if(isset($item['logo']) && filter_var($item['logo'], FILTER_VALIDATE_URL) !== false){
$stream['logo'] = $item['logo'];
}

$streams[] = $stream;
}
$this->redis->arraySet( 'list', $list, Config::CACHE_EXPIRE );
}
Expand Down
35 changes: 26 additions & 9 deletions php/classes/PodcastLoader.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,35 +42,52 @@ private static function loadFromNextcloud( string $url ) : array {
$useindex = !empty($matches[2]); // used index.php to access files?
$share = $matches[3]; // the token/ name of share

// do webdav request
$cont = stream_context_create( array(
"http" => array(
'method' => "PROPFIND",
"header" => "Authorization: Basic " . base64_encode($share . ':')
)
));
$data = file_get_contents( $server . '/public.php/webdav/', false, $cont );
$data = explode( '<d:href>', $data );


// parse webdav XML
$data = json_decode(json_encode(
simplexml_load_string( $data, 'SimpleXMLElement', 0, "d", true)
), true );

$poddata = array(
'title' => '',
'logo' => '',
'episodes' => array()
);
$eid = 1;

foreach($data as $d){
if( strpos( $d, 'audio' ) !== false ){
$fina = substr( $d, 0, strpos( $d, '</d:href>') );
$fina = substr( $fina, strrpos( $fina, '/' ) + 1 );
$fina = urldecode( $fina );
// iterate files
foreach($data["response"] as $r){

// get data from xml
$mime = $r["propstat"]["prop"]["getcontenttype"] ?? '';
$href = $r["href"] ?? '';

// get filename
$filename = urldecode(substr( $href, strrpos( $href, '/' ) + 1 ));
// get streaming/ web url
$streamurl = $server . ($useindex ? '/index.php' : '') . '/s/'. $share .'/download?path=%2F&files=' . rawurlencode( $filename );

// is this an audio file?
if( str_starts_with($mime, 'audio/') ){
$poddata['episodes'][$eid] = array(
'title' => $fina,
'title' => $filename,
'desc' => '',
'url' => $server . ($useindex ? '/index.php' : '') . '/s/'. $share .'/download?path=%2F&files=' . rawurlencode( $fina )
'url' => $streamurl
);
$eid++;
}
// it this a logo?
else if(str_starts_with($mime, 'image/') && str_starts_with($filename, "logo") ){
$poddata['logo'] = $streamurl;
}
}

return $poddata;
Expand Down
81 changes: 74 additions & 7 deletions php/classes/RadioLogo.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,19 @@ public function __construct(){
// check if image cache active and if cache folder writable
$this->useImageCache = Config::USE_LOGO_CACHE && is_writable(self::BASE_DIR);
}

public function clearCache() : bool {
if($this->useImageCache){
$ok = true;
foreach(scandir(self::BASE_DIR) as $d){
if(preg_match('/^[a-f0-9]{40}\.(image|error)$/', $d) === 1){
$ok &= unlink(self::BASE_DIR . '/' . $d);
}
}
return $ok;
}
return false;
}

public function logoUrl(string $logo) : string {
// empty or no url
Expand Down Expand Up @@ -83,20 +96,24 @@ private function fetchLogo(string $logo) : bool {
return false;
}

$tmpName = tempnam(sys_get_temp_dir(), 'conv');
if($mimetype == 'image/svg+xml'){
if(
self::svg2png($filename, $filename . '.cv')
&&
@rename($filename . '.cv', $filename)
){
return true;
if( self::svg2png($filename, $tmpName) ){
return rename($tmpName, $filename);
}
else {
unlink($filename);
return false;
}
}
else {

// resize file
// will only return true if resize done (false on error or if already small enough)
if(self::resize($filename, $mimetype, $tmpName)){
rename($tmpName, $filename);
}

return true;
}
}
Expand All @@ -107,11 +124,61 @@ private static function svg2png(string $inputSVG, string $outputPNG) : bool {
'--width', '256',
'--height', '256',
'--keep-aspect-ratio',
'--background-color', 'white',
'--format', 'png',
'-o', '"'.$outputPNG.'"',
'"'.$inputSVG.'"'
);
return exec(implode(' ', $command)) !== false;
exec(implode(' ', $command), result_code:$rs);
return $rs === 0;
}

private static function imageDimensions(string $file) : array {
$finfo = finfo_open(FILEINFO_CONTINUE);
$info = finfo_file($finfo, $file);
finfo_close($finfo);

// file info (including dimensions as ", 000 x 000,")
if(preg_match('/,(\d+)x(\d+),/', str_replace(' ', '', $info), $matches) === 1){
$width = intval($matches[1]);
$height = intval($matches[2]);

return [$width, $height];
}
else{
return [0, 0];
}
}

private static function resize(string $inputFile, string $inputMime, string $outputPNG) : bool {
// determine image dimensions
list($width, $height) = self::imageDimensions($inputFile);

// error
if($width == 0 || $height == 0){
// no resize
return false;
}

// do not resize if smaller than 256 px
if( $width <= 256 && $height <= 256 ){
// resize not necessary
return false;
}

// create an svg with image
$svgFile = "<svg xmlns='http://www.w3.org/2000/svg'
width='".$width."' height='".$height."' version='1.1'>
<image href='data:".$inputMime.";base64,".base64_encode(file_get_contents($inputFile))."'
width='".$width."' height='".$height."' />
</svg>";

// write to tmp
$inputSVG = tempnam(sys_get_temp_dir(), 'svg');
file_put_contents($inputSVG, $svgFile);

// create small png
return self::svg2png($inputSVG, $outputPNG);
}

}
Expand Down
1 change: 1 addition & 0 deletions php/classes/templates/list.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"%%ADD_HTML%%" : "",
"%%CLEAR_CACHE%%" : " display: none; ",
"%%RADIO_MAC%%" : "",
"%%RADIO_DOMAIN%%" : "",
"%%LOGIN_CODE%%" : "",
Expand Down
4 changes: 4 additions & 0 deletions php/classes/templates/list_de.html
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,10 @@ <h3 id="podcast">Podcasts</h3>
</script>

<h2>Vorschau</h2>
<div style="float:right; %%CLEAR_CACHE%%">
<a href="%%SERVERURL%%gui/?clear-logo-cache">Logo-Cache leeren</a>
</div>

<div id="apiviewer">
</div>
<div id="audiodiv">
Expand Down
4 changes: 4 additions & 0 deletions php/classes/templates/list_en.html
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,10 @@ <h3 id="podcast">Podcasts</h3>
</script>

<h2>Preview</h2>
<div style="float:right; %%CLEAR_CACHE%%">
<a href="%%SERVERURL%%gui/?clear-logo-cache" title="">Clear logo cache</a>
</div>

<div id="apiviewer">
</div>
<div id="audiodiv">
Expand Down
1 change: 1 addition & 0 deletions php/gui/index.php
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@

$inner = new Inner($login->getId(), $listTemplate);
$inner->checkPost();
$inner->clearCache();

$inner->radioForm();
$inner->podcastForm();
Expand Down

0 comments on commit e74a23a

Please sign in to comment.