#7: Implement back-end handling of mixed losslessness track collections

This commit is contained in:
Kelvin 2016-07-11 12:43:10 +01:00
parent 2c3ef557af
commit 63d4063ccc
8 changed files with 108 additions and 68 deletions

View file

@ -21,6 +21,7 @@
namespace Poniverse\Ponyfm; namespace Poniverse\Ponyfm;
use Poniverse\Ponyfm\Models\Album; use Poniverse\Ponyfm\Models\Album;
use Poniverse\Ponyfm\Models\Track;
use ZipStream; use ZipStream;
class AlbumDownloader class AlbumDownloader
@ -43,6 +44,11 @@ class AlbumDownloader
public function download() public function download()
{ {
// Check whether the format is lossless yet not all master files are lossless
$isLosslessFormatWithLossyTracks = in_array($this->_format, Track::$LosslessFormats)
&& !$this->_album->hasLosslessTracksOnly()
&& $this->_album->hasLosslessTracks();
$zip = new ZipStream($this->_album->user->display_name.' - '.$this->_album->title.'.zip'); $zip = new ZipStream($this->_album->user->display_name.' - '.$this->_album->title.'.zip');
$zip->setComment( $zip->setComment(
'Album: '.$this->_album->title."\r\n". 'Album: '.$this->_album->title."\r\n".
@ -69,8 +75,15 @@ class AlbumDownloader
continue; continue;
} }
if ($isLosslessFormatWithLossyTracks && $track->isMasterLossy()) {
$masterFormatName = $track->getMasterFormatName();
$zip->addLargeFile($track->getFileFor($masterFormatName),
$directory . $track->getDownloadFilenameFor($masterFormatName));
} else {
$zip->addLargeFile($track->getFileFor($this->_format), $zip->addLargeFile($track->getFileFor($this->_format),
$directory.$track->getDownloadFilenameFor($this->_format)); $directory . $track->getDownloadFilenameFor($this->_format));
}
$notes .= $notes .=
$track->track_number.'. '.$track->title."\r\n". $track->track_number.'. '.$track->title."\r\n".
$track->description."\r\n". $track->description."\r\n".

View file

@ -81,7 +81,7 @@ class AlbumsController extends Controller
App::abort(404); App::abort(404);
} }
if (!$album->hasLosslessTracksOnly() && in_array($formatName, Track::$LosslessFormats)) { if (!$album->hasLosslessTracks() && in_array($formatName, Track::$LosslessFormats)) {
App::abort(404); App::abort(404);
} }

View file

@ -82,7 +82,7 @@ class PlaylistsController extends Controller
App::abort(404); App::abort(404);
} }
if (!$this->hasLosslessTracksOnly() && in_array($formatName, Track::$LosslessFormats)) { if (!$playlist->hasLosslessTracks() && in_array($formatName, Track::$LosslessFormats)) {
App::abort(404); App::abort(404);
} }

View file

@ -142,9 +142,8 @@ class Album extends Model implements Searchable, Commentable, Favouritable
} }
$formats = []; $formats = [];
$hasLosslessTracks = $album->hasLosslessTracksOnly();
foreach (Track::$Formats as $name => $format) { foreach (Track::$Formats as $name => $format) {
if (!$hasLosslessTracks && in_array($name, Track::$LosslessFormats)) { if (in_array($name, Track::$LosslessFormats) && !$album->hasLosslessTracksOnly() && !$album->hasLosslessTracks()) {
continue; continue;
} }
@ -253,34 +252,6 @@ class Album extends Model implements Searchable, Commentable, Favouritable
return action('AlbumsController@getDownload', ['id' => $this->id, 'extension' => Track::$Formats[$format]['extension']]); return action('AlbumsController@getDownload', ['id' => $this->id, 'extension' => Track::$Formats[$format]['extension']]);
} }
public function getFilesize($format)
{
$tracks = $this->tracks;
if (!count($tracks)) {
return 0;
}
return Cache::remember($this->getCacheKey('filesize-'.$format), 1440, function() use ($tracks, $format) {
$size = 0;
foreach ($tracks as $track) {
/** @var $track Track */
// Ensure that only downloadable tracks are added onto the file size
if ($track->is_downloadable == 1) {
try {
$size += $track->getFilesize($format);
} catch (TrackFileNotFoundException $e) {
// do nothing - this track won't be included in the download
}
}
}
return $size;
});
}
public function getCoverUrl($type = Image::NORMAL) public function getCoverUrl($type = Image::NORMAL)
{ {
if (!$this->hasCover()) { if (!$this->hasCover()) {

View file

@ -117,9 +117,8 @@ class Playlist extends Model implements Searchable, Commentable, Favouritable
} }
$formats = []; $formats = [];
$hasLosslessTracks = $playlist->hasLosslessTracksOnly();
foreach (Track::$Formats as $name => $format) { foreach (Track::$Formats as $name => $format) {
if (!$hasLosslessTracks && in_array($name, Track::$LosslessFormats)) { if (in_array($name, Track::$LosslessFormats) && !$playlist->hasLosslessTracksOnly() && !$playlist->hasLosslessTracks()) {
continue; continue;
} }
@ -272,33 +271,6 @@ class Playlist extends Model implements Searchable, Commentable, Favouritable
return action('PlaylistsController@getDownload', ['id' => $this->id, 'format' => Track::$Formats[$format]['extension']]); return action('PlaylistsController@getDownload', ['id' => $this->id, 'format' => Track::$Formats[$format]['extension']]);
} }
public function getFilesize($format)
{
$tracks = $this->tracks;
if (!count($tracks)) {
return 0;
}
return Cache::remember($this->getCacheKey('filesize-'.$format), 1440, function() use ($tracks, $format) {
$size = 0;
foreach ($tracks as $track) {
/** @var $track Track */
// Ensure that only downloadable tracks are added onto the file size
if ($track->is_downloadable == 1) {
try {
$size += $track->getFilesize($format);
} catch (TrackFileNotFoundException $e) {
// do nothing - this track won't be included in the download
}
}
}
return $size;
});
}
public function getCoverUrl($type = Image::NORMAL) public function getCoverUrl($type = Image::NORMAL)
{ {
if ($this->tracks->count() == 0) { if ($this->tracks->count() == 0) {

View file

@ -639,6 +639,11 @@ class Track extends Model implements Searchable, Commentable, Favouritable
return $this->trackFiles->where('is_master', true)->first(); return $this->trackFiles->where('is_master', true)->first();
} }
public function getMasterFormatName() : string
{
return $this->getMasterTrackFile()->format;
}
public function isMasterLossy() : bool public function isMasterLossy() : bool
{ {
return $this->getMasterTrackFile()->isLossy(); return $this->getMasterTrackFile()->isLossy();

View file

@ -21,6 +21,7 @@
namespace Poniverse\Ponyfm; namespace Poniverse\Ponyfm;
use Poniverse\Ponyfm\Models\Playlist; use Poniverse\Ponyfm\Models\Playlist;
use Poniverse\Ponyfm\Models\Track;
use ZipStream; use ZipStream;
class PlaylistDownloader class PlaylistDownloader
@ -43,6 +44,11 @@ class PlaylistDownloader
public function download() public function download()
{ {
// Check whether the format is lossless yet not all master files are lossless
$isLosslessFormatWithLossyTracks = in_array($this->_format, Track::$LosslessFormats)
&& !$this->_playlist->hasLosslessTracksOnly()
&& $this->_playlist->hasLosslessTracks();
$zip = new ZipStream($this->_playlist->user->display_name.' - '.$this->_playlist->title.'.zip'); $zip = new ZipStream($this->_playlist->user->display_name.' - '.$this->_playlist->title.'.zip');
$zip->setComment( $zip->setComment(
'Playlist: '.$this->_playlist->title."\r\n". 'Playlist: '.$this->_playlist->title."\r\n".
@ -69,8 +75,15 @@ class PlaylistDownloader
continue; continue;
} }
$trackTarget = $track->downloadDirectory.'/'.$track->getDownloadFilenameFor($this->_format); if ($isLosslessFormatWithLossyTracks && $track->isMasterLossy()) {
$masterFormatName = $track->getMasterFormatName();
$trackTarget = $track->downloadDirectory . '/' . $track->getDownloadFilenameFor($masterFormatName);
$zip->addLargeFile($track->getFileFor($masterFormatName), $trackTarget);
} else {
$trackTarget = $track->downloadDirectory . '/' . $track->getDownloadFilenameFor($this->_format);
$zip->addLargeFile($track->getFileFor($this->_format), $trackTarget); $zip->addLargeFile($track->getFileFor($this->_format), $trackTarget);
}
$notes .= $notes .=
$index.'. '.$track->title."\r\n". $index.'. '.$track->title."\r\n".
$track->description."\r\n". $track->description."\r\n".

View file

@ -26,7 +26,9 @@ use File;
use Illuminate\Database\Eloquent\Collection; use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\Relation; use Illuminate\Database\Eloquent\Relations\Relation;
use Illuminate\Support\Facades\Cache;
use Poniverse\Ponyfm\Jobs\EncodeTrackFile; use Poniverse\Ponyfm\Jobs\EncodeTrackFile;
use Poniverse\Ponyfm\Models\Track;
use Poniverse\Ponyfm\Models\TrackFile; use Poniverse\Ponyfm\Models\TrackFile;
@ -125,6 +127,24 @@ trait TrackCollection
])->where('format', $format)->get(); ])->where('format', $format)->get();
} }
/**
* Returns a boolean based on whether at least one (@link TrackFile)
* for this (@link TrackCollection)'s tracks has a lossless master file.
*
* @return bool
*/
public function hasLosslessTracks() : bool
{
$hasLosslessTracks = false;
foreach ($this->tracks as $track) {
if (!$track->isMasterLossy()) {
$hasLosslessTracks = true;
break;
}
}
return $hasLosslessTracks;
}
/** /**
* Returns a boolean based on whether all (@link TrackFile)s * Returns a boolean based on whether all (@link TrackFile)s
* for this (@link TrackCollection)'s tracks have lossless master files. * for this (@link TrackCollection)'s tracks have lossless master files.
@ -133,13 +153,59 @@ trait TrackCollection
*/ */
public function hasLosslessTracksOnly() : bool public function hasLosslessTracksOnly() : bool
{ {
$hasLosslessTracksOnly = false;
foreach ($this->tracks as $track) {
if (!$track->isMasterLossy()) {
$hasLosslessTracksOnly = true; $hasLosslessTracksOnly = true;
foreach ($this->tracks as $track) {
if ($track->isMasterLossy()) {
$hasLosslessTracksOnly = false;
break; break;
} }
} }
return $hasLosslessTracksOnly; return $hasLosslessTracksOnly;
} }
/**
* Gets the filesize in bytes for a (@link Album) or (@link Playlist) based on a format.
*
* @param $format
* @return int
*/
public function getFilesize($format) : int
{
$tracks = $this->tracks;
if (!count($tracks)) {
return 0;
}
return Cache::remember($this->getCacheKey('filesize-'.$format), 1440, function() use ($tracks, $format) {
$size = 0;
// Check whether the format is lossless yet not all master files are lossless
$isLosslessFormatWithLossyTracks = in_array($format, Track::$LosslessFormats)
&& !$this->hasLosslessTracksOnly()
&& $this->hasLosslessTracks();
foreach ($tracks as $track) {
/** @var $track Track */
// Ensure that only downloadable tracks are added onto the file size
if (!$track->is_downloadable) {
continue;
}
try {
// Get the file size corresponding to the losslessness of the track master file and format specified
if ($isLosslessFormatWithLossyTracks && $track->isMasterLossy()) {
$size += $track->getFilesize($track->getMasterFormatName());
} else {
$size += $track->getFilesize($format);
}
} catch (TrackFileNotFoundException $e) {
// do nothing - this track won't be included in the download
}
}
return $size;
});
}
} }