2015-01-02 08:16:54 +00:00
|
|
|
<?php
|
|
|
|
namespace Entity;
|
|
|
|
|
2017-01-22 20:58:40 +00:00
|
|
|
use Doctrine\Common\Collections\ArrayCollection;
|
2015-01-02 08:16:54 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @Table(name="station_media", indexes={
|
2016-09-23 00:49:59 +00:00
|
|
|
* @index(name="search_idx", columns={"title", "artist", "album"})
|
|
|
|
* }, uniqueConstraints={
|
2016-11-22 05:09:18 +00:00
|
|
|
* @UniqueConstraint(name="path_unique_idx", columns={"path", "station_id"})
|
2015-01-02 08:16:54 +00:00
|
|
|
* })
|
2017-01-17 08:46:43 +00:00
|
|
|
* @Entity(repositoryClass="Entity\Repository\StationMediaRepository")
|
2015-01-02 08:16:54 +00:00
|
|
|
* @HasLifecycleCallbacks
|
|
|
|
*/
|
2016-05-02 08:18:32 +00:00
|
|
|
class StationMedia extends \App\Doctrine\Entity
|
2015-01-02 08:16:54 +00:00
|
|
|
{
|
|
|
|
/**
|
|
|
|
* @Column(name="id", type="integer")
|
|
|
|
* @Id
|
2016-05-15 09:31:21 +00:00
|
|
|
* @GeneratedValue(strategy="IDENTITY")
|
2015-01-02 08:16:54 +00:00
|
|
|
*/
|
|
|
|
protected $id;
|
|
|
|
|
|
|
|
/** @Column(name="station_id", type="integer") */
|
|
|
|
protected $station_id;
|
|
|
|
|
|
|
|
/** @Column(name="song_id", type="string", length=50, nullable=true) */
|
|
|
|
protected $song_id;
|
|
|
|
|
2016-05-16 13:21:51 +00:00
|
|
|
/** @Column(name="title", type="string", length=200, nullable=true) */
|
2015-01-02 08:16:54 +00:00
|
|
|
protected $title;
|
|
|
|
|
2016-05-16 13:21:51 +00:00
|
|
|
/** @Column(name="artist", type="string", length=200, nullable=true) */
|
2015-01-02 08:16:54 +00:00
|
|
|
protected $artist;
|
|
|
|
|
|
|
|
/** @Column(name="album", type="string", length=200, nullable=true) */
|
|
|
|
protected $album;
|
|
|
|
|
|
|
|
/** @Column(name="length", type="smallint") */
|
|
|
|
protected $length;
|
|
|
|
|
2016-05-04 00:03:28 +00:00
|
|
|
/** @Column(name="length_text", type="string", length=10, nullable=true) */
|
|
|
|
protected $length_text;
|
|
|
|
|
|
|
|
/** @Column(name="path", type="string", length=255, nullable=true) */
|
|
|
|
protected $path;
|
|
|
|
|
2016-05-15 09:31:21 +00:00
|
|
|
/** @Column(name="mtime", type="integer", nullable=true) */
|
|
|
|
protected $mtime;
|
|
|
|
|
2015-01-02 08:16:54 +00:00
|
|
|
/**
|
|
|
|
* @ManyToOne(targetEntity="Station", inversedBy="media")
|
|
|
|
* @JoinColumns({
|
|
|
|
* @JoinColumn(name="station_id", referencedColumnName="id", onDelete="CASCADE")
|
|
|
|
* })
|
|
|
|
*/
|
|
|
|
protected $station;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @ManyToOne(targetEntity="Song")
|
|
|
|
* @JoinColumns({
|
|
|
|
* @JoinColumn(name="song_id", referencedColumnName="id", onDelete="SET NULL")
|
|
|
|
* })
|
|
|
|
*/
|
|
|
|
protected $song;
|
|
|
|
|
2016-05-04 00:03:28 +00:00
|
|
|
/**
|
2016-05-15 09:31:21 +00:00
|
|
|
* @ManyToMany(targetEntity="StationPlaylist", inversedBy="playlists")
|
|
|
|
* @JoinTable(name="station_playlist_has_media",
|
|
|
|
* joinColumns={@JoinColumn(name="media_id", referencedColumnName="id", onDelete="CASCADE")},
|
|
|
|
* inverseJoinColumns={@JoinColumn(name="playlists_id", referencedColumnName="id", onDelete="CASCADE")}
|
|
|
|
* )
|
2016-05-04 00:03:28 +00:00
|
|
|
*/
|
|
|
|
protected $playlists;
|
|
|
|
|
2017-01-22 20:58:40 +00:00
|
|
|
public function __construct()
|
|
|
|
{
|
|
|
|
$this->length = 0;
|
|
|
|
$this->length_text = '0:00';
|
|
|
|
|
|
|
|
$this->mtime = 0;
|
|
|
|
|
|
|
|
$this->playlists = new ArrayCollection();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Return a list of supported formats.
|
|
|
|
*
|
|
|
|
* @return array
|
|
|
|
*/
|
|
|
|
public static function getSupportedFormats()
|
|
|
|
{
|
|
|
|
return ['mp3', 'ogg', 'm4a', 'flac'];
|
|
|
|
}
|
|
|
|
|
2016-05-15 09:31:21 +00:00
|
|
|
/**
|
|
|
|
* Process metadata information from media file.
|
|
|
|
*/
|
|
|
|
public function loadFromFile()
|
|
|
|
{
|
2017-01-22 20:58:40 +00:00
|
|
|
if (empty($this->path)) {
|
2016-05-15 09:31:21 +00:00
|
|
|
return false;
|
2017-01-22 20:58:40 +00:00
|
|
|
}
|
|
|
|
|
2016-05-15 09:31:21 +00:00
|
|
|
$media_base_dir = $this->station->getRadioMediaDir();
|
2017-01-22 20:58:40 +00:00
|
|
|
$media_path = $media_base_dir . '/' . $this->path;
|
2016-05-15 09:31:21 +00:00
|
|
|
|
|
|
|
// Only update metadata if the file has been updated.
|
|
|
|
$media_mtime = filemtime($media_path);
|
2017-01-22 20:58:40 +00:00
|
|
|
if ($media_mtime > $this->mtime || !$this->song) {
|
2016-05-15 09:31:21 +00:00
|
|
|
// Load metadata from MP3 file.
|
2016-09-09 05:07:40 +00:00
|
|
|
$id3 = new \getID3();
|
2016-05-15 09:31:21 +00:00
|
|
|
|
2016-09-09 05:07:40 +00:00
|
|
|
$id3->option_md5_data = true;
|
|
|
|
$id3->option_md5_data_source = true;
|
|
|
|
$id3->encoding = 'UTF-8';
|
|
|
|
|
|
|
|
$file_info = $id3->analyze($media_path);
|
2016-05-15 09:31:21 +00:00
|
|
|
|
2017-01-22 20:58:40 +00:00
|
|
|
if (isset($file_info['error'])) {
|
2016-12-31 03:55:04 +00:00
|
|
|
throw new \App\Exception($file_info['error'][0]);
|
2017-01-22 20:58:40 +00:00
|
|
|
}
|
2016-05-15 09:31:21 +00:00
|
|
|
|
|
|
|
$this->setLength($file_info['playtime_seconds']);
|
|
|
|
|
2016-11-14 05:38:59 +00:00
|
|
|
$tags_to_set = ['title', 'artist', 'album'];
|
2016-05-15 09:31:21 +00:00
|
|
|
|
2017-01-22 20:58:40 +00:00
|
|
|
if (!empty($file_info['tags'])) {
|
|
|
|
foreach ($file_info['tags'] as $tag_type => $tag_data) {
|
|
|
|
foreach ($tags_to_set as $tag) {
|
|
|
|
if (!empty($tag_data[$tag][0])) {
|
2016-11-14 05:38:59 +00:00
|
|
|
$this->{$tag} = $tag_data[$tag][0];
|
2017-01-22 20:58:40 +00:00
|
|
|
}
|
2016-11-14 05:38:59 +00:00
|
|
|
}
|
|
|
|
}
|
2016-05-15 09:31:21 +00:00
|
|
|
}
|
2016-11-14 05:38:59 +00:00
|
|
|
|
2017-01-22 20:58:40 +00:00
|
|
|
if (empty($this->title)) {
|
2016-05-15 09:31:21 +00:00
|
|
|
$path_parts = pathinfo($media_path);
|
|
|
|
$this->title = $path_parts['filename'];
|
|
|
|
}
|
|
|
|
|
2016-09-28 03:28:49 +00:00
|
|
|
$this->mtime = $media_mtime;
|
|
|
|
|
2017-01-22 20:58:40 +00:00
|
|
|
return [
|
|
|
|
'artist' => $this->artist,
|
|
|
|
'title' => $this->title,
|
|
|
|
];
|
2016-05-15 09:31:21 +00:00
|
|
|
}
|
2017-01-22 20:58:40 +00:00
|
|
|
|
2016-05-15 09:31:21 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2017-01-22 20:58:40 +00:00
|
|
|
public function setLength($length)
|
|
|
|
{
|
|
|
|
$length_min = floor($length / 60);
|
|
|
|
$length_sec = $length % 60;
|
|
|
|
|
|
|
|
$this->length = $length;
|
|
|
|
$this->length_text = $length_min . ':' . str_pad($length_sec, 2, '0', STR_PAD_LEFT);
|
|
|
|
}
|
|
|
|
|
2016-09-21 23:32:31 +00:00
|
|
|
/**
|
|
|
|
* Write modified metadata directly to the file as ID3 information.
|
|
|
|
*/
|
|
|
|
public function writeToFile()
|
|
|
|
{
|
|
|
|
$getID3 = new \getID3;
|
2017-01-22 20:58:40 +00:00
|
|
|
$getID3->setOption(['encoding' => 'UTF8']);
|
2016-09-21 23:32:31 +00:00
|
|
|
|
2017-01-22 20:58:40 +00:00
|
|
|
require_once(APP_INCLUDE_VENDOR . '/james-heinrich/getid3/getid3/write.php');
|
2016-09-21 23:32:31 +00:00
|
|
|
|
|
|
|
$tagwriter = new \getid3_writetags;
|
|
|
|
$tagwriter->filename = $this->getFullPath();
|
|
|
|
|
2017-01-22 20:58:40 +00:00
|
|
|
$tagwriter->tagformats = ['id3v1', 'id3v2.3'];
|
2016-09-21 23:32:31 +00:00
|
|
|
$tagwriter->overwrite_tags = true;
|
|
|
|
$tagwriter->tag_encoding = 'UTF8';
|
|
|
|
$tagwriter->remove_other_tags = true;
|
|
|
|
|
2017-01-22 20:58:40 +00:00
|
|
|
$tag_data = [
|
|
|
|
'title' => [$this->title],
|
|
|
|
'artist' => [$this->artist],
|
|
|
|
'album' => [$this->album],
|
|
|
|
];
|
2016-09-21 23:32:31 +00:00
|
|
|
|
|
|
|
$tagwriter->tag_data = $tag_data;
|
|
|
|
|
|
|
|
// write tags
|
2017-01-22 20:58:40 +00:00
|
|
|
if ($tagwriter->WriteTags()) {
|
2016-09-21 23:32:31 +00:00
|
|
|
$this->mtime = time();
|
|
|
|
return true;
|
|
|
|
}
|
2016-11-14 05:38:59 +00:00
|
|
|
}
|
|
|
|
|
2017-01-22 20:58:40 +00:00
|
|
|
public function getFullPath()
|
|
|
|
{
|
|
|
|
$media_base_dir = $this->station->getRadioMediaDir();
|
|
|
|
return $media_base_dir . '/' . $this->path;
|
|
|
|
}
|
|
|
|
|
2016-11-14 05:38:59 +00:00
|
|
|
/**
|
|
|
|
* Move this media file to the "not-processed" directory.
|
|
|
|
*/
|
|
|
|
public function moveToNotProcessed()
|
|
|
|
{
|
|
|
|
$old_path = $this->getFullPath();
|
|
|
|
|
|
|
|
$media_base_dir = $this->station->getRadioMediaDir();
|
2017-01-22 20:58:40 +00:00
|
|
|
$unprocessed_dir = $media_base_dir . '/not-processed';
|
2016-11-14 05:38:59 +00:00
|
|
|
|
|
|
|
@mkdir($unprocessed_dir);
|
|
|
|
|
2017-01-22 20:58:40 +00:00
|
|
|
$new_path = $unprocessed_dir . '/' . basename($this->path);
|
2016-11-14 05:38:59 +00:00
|
|
|
@rename($old_path, $new_path);
|
|
|
|
}
|
2014-02-21 09:25:10 +00:00
|
|
|
}
|