implement simple multi disc support (#687)

* add disc field to songs table via migration

* add disc field to song model

* collect disc information in file sync process

* sort song list by disc and track number in album context

* check the disc field in file test

* remove nullable flag from disc field in add_disc_into_songs migration

* fix php code style issues

* fix js code style

* fix sort usage in song-list

* sort songs by inserting into queue by clicking the album/artist item play button (album_id, disc, track)

* add disc to sync tags in media model
This commit is contained in:
Fiete Börner 2017-12-03 11:02:31 +01:00 committed by Phan An
parent a98dc2774f
commit 4298774e7f
10 changed files with 53 additions and 5 deletions

View file

@ -136,6 +136,7 @@ class File
'title' => basename($this->path, '.'.pathinfo($this->path, PATHINFO_EXTENSION)), // default to be file name 'title' => basename($this->path, '.'.pathinfo($this->path, PATHINFO_EXTENSION)), // default to be file name
'length' => $info['playtime_seconds'], 'length' => $info['playtime_seconds'],
'track' => (int) $track, 'track' => (int) $track,
'disc' => (int) array_get($info, 'comments.part_of_a_set.0', 1),
'lyrics' => '', 'lyrics' => '',
'cover' => array_get($info, 'comments.picture', [null])[0], 'cover' => array_get($info, 'comments.picture', [null])[0],
'path' => $this->path, 'path' => $this->path,

View file

@ -24,6 +24,7 @@ use YouTube;
* @property float length * @property float length
* @property string lyrics * @property string lyrics
* @property int track * @property int track
* @property int disc
* @property int album_id * @property int album_id
* @property int id * @property int id
* @property int artist_id * @property int artist_id
@ -50,6 +51,7 @@ class Song extends Model
'length' => 'float', 'length' => 'float',
'mtime' => 'int', 'mtime' => 'int',
'track' => 'int', 'track' => 'int',
'disc' => 'int',
]; ];
/** /**

View file

@ -28,6 +28,7 @@ class Media
'title', 'title',
'length', 'length',
'track', 'track',
'disc',
'lyrics', 'lyrics',
'cover', 'cover',
'mtime', 'mtime',

View file

@ -0,0 +1,32 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddDiscIntoSongs extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('songs', function (Blueprint $table) {
$table->integer('disc')->after('track')->default(1);
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('songs', function (Blueprint $table) {
$table->dropColumn('disc');
});
}
}

View file

@ -36,6 +36,7 @@
</template> </template>
<script> <script>
import { orderBy } from 'lodash'
import { pluralize } from '@/utils' import { pluralize } from '@/utils'
import { queueStore, artistStore, sharedStore } from '@/stores' import { queueStore, artistStore, sharedStore } from '@/stores'
import { playback, download } from '@/services' import { playback, download } from '@/services'
@ -72,7 +73,7 @@ export default {
*/ */
play (e) { play (e) {
if (e.metaKey || e.ctrlKey) { if (e.metaKey || e.ctrlKey) {
queueStore.queue(this.album.songs) queueStore.queue(orderBy(this.album.songs, ['disc', 'track']))
} else { } else {
playback.playAllInAlbum(this.album, false) playback.playAllInAlbum(this.album, false)
} }

View file

@ -28,6 +28,7 @@
</template> </template>
<script> <script>
import { orderBy } from 'lodash'
import { pluralize } from '@/utils' import { pluralize } from '@/utils'
import { artistStore, queueStore, sharedStore } from '@/stores' import { artistStore, queueStore, sharedStore } from '@/stores'
import { playback, download } from '@/services' import { playback, download } from '@/services'
@ -68,7 +69,7 @@ export default {
*/ */
play (e) { play (e) {
if (e.metaKey || e.ctrlKey) { if (e.metaKey || e.ctrlKey) {
queueStore.queue(this.artist.songs) queueStore.queue(orderBy(this.artist.songs, ['album_id', 'disc', 'track']))
} else { } else {
playback.playAllByArtist(this.artist, false) playback.playAllByArtist(this.artist, false)
} }

View file

@ -49,7 +49,7 @@
<script> <script>
import isMobile from 'ismobilejs' import isMobile from 'ismobilejs'
import { each } from 'lodash' import { each, orderBy as _orderBy } from 'lodash'
import { filterBy, orderBy, event, pluralize, $ } from '@/utils' import { filterBy, orderBy, event, pluralize, $ } from '@/utils'
import { playlistStore, queueStore, songStore, favoriteStore } from '@/stores' import { playlistStore, queueStore, songStore, favoriteStore } from '@/stores'
@ -203,9 +203,18 @@ export default {
this.order *= -1 this.order *= -1
} }
if (this.type === 'album') {
this.sortKey = this.sortKey ? this.sortKey : ['song.track']
}
this.sortingByAlbum = Array.isArray(this.sortKey) && this.sortKey[0] === 'song.album.name' this.sortingByAlbum = Array.isArray(this.sortKey) && this.sortKey[0] === 'song.album.name'
this.sortingByArtist = Array.isArray(this.sortKey) && this.sortKey[0] === 'song.album.artist.name' this.sortingByArtist = Array.isArray(this.sortKey) && this.sortKey[0] === 'song.album.artist.name'
this.songRows = orderBy(this.songRows, this.sortKey, this.order) this.songRows = orderBy(this.songRows, this.sortKey, this.order)
if (this.type === 'album') {
this.songRows = _orderBy(this.songRows, 'song.disc')
}
}, },
/** /**

View file

@ -418,7 +418,7 @@ export const playback = {
playAllByArtist ({ songs }, shuffled = true) { playAllByArtist ({ songs }, shuffled = true) {
shuffled shuffled
? this.queueAndPlay(songs, true) ? this.queueAndPlay(songs, true)
: this.queueAndPlay(orderBy(songs, 'album_id', 'track')) : this.queueAndPlay(orderBy(songs, ['album_id', 'disc', 'track']))
}, },
/** /**
@ -430,6 +430,6 @@ export const playback = {
playAllInAlbum ({ songs }, shuffled = true) { playAllInAlbum ({ songs }, shuffled = true) {
shuffled shuffled
? this.queueAndPlay(songs, true) ? this.queueAndPlay(songs, true)
: this.queueAndPlay(orderBy(songs, 'track')) : this.queueAndPlay(orderBy(songs, ['disc', 'track']))
} }
} }

View file

@ -32,6 +32,7 @@ class FileTest extends TestCase
'compilation' => false, 'compilation' => false,
'title' => 'Amet', 'title' => 'Amet',
'track' => 5, 'track' => 5,
'disc' => 3,
'lyrics' => "Foo\rbar", 'lyrics' => "Foo\rbar",
'cover' => [ 'cover' => [
'data' => file_get_contents(__DIR__.'/../blobs/cover.png'), 'data' => file_get_contents(__DIR__.'/../blobs/cover.png'),

Binary file not shown.