Skip to content

Commit

Permalink
Merge pull request #125 from glowspace/develop
Browse files Browse the repository at this point in the history
support for rendering of musicxml externals
  • Loading branch information
thes01 authored Feb 13, 2024
2 parents 7eec273 + c9d390e commit 116a9aa
Show file tree
Hide file tree
Showing 25 changed files with 2,198 additions and 2,280 deletions.
40 changes: 40 additions & 0 deletions app/Jobs/RenderExternalMusicXml.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?php

namespace App\Jobs;

use App\External;
use App\Services\ExternalMusicXmlService;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;


class RenderExternalMusicXml implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

protected $external_id;

/**
* Create a new job instance.
*
* @return void
*/
public function __construct($external_id)
{
$this->external_id = $external_id;
}

/**
* Execute the job.
*
* @return void
*/
public function handle(ExternalMusicXmlService $mxml_service)
{
$external = External::find($this->external_id);
$mxml_service->renderExternalMusicXml($external);
}
}
11 changes: 8 additions & 3 deletions app/Listeners/ExternalCreated.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@

namespace App\Listeners;

use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;

use App\Events\ExternalCreated as ExternalCreatedEvent;
use App\Helpers\ExternalMediaLink;
use App\Jobs\RenderExternalMusicXml;
use App\Services\ExternalMusicXmlService;
use Illuminate\Support\Str;

class ExternalCreated
Expand All @@ -30,11 +30,16 @@ public function __construct()
public function handle(ExternalCreatedEvent $event)
{
$media_link = new ExternalMediaLink($event->external->url);
$media_type = $media_link->getExternalMediaType();

$event->external->update([
'is_uploaded' => Str::contains($event->external->url, url('')),
'media_type' => $media_link->getExternalMediaType(),
'media_type' => $media_type,
'content_type' => $media_link->getExternalContentType()
]);

if (ExternalMusicXmlService::isMediaTypeRenderable($media_type)) {
RenderExternalMusicXml::dispatch($event->external->id);
}
}
}
7 changes: 7 additions & 0 deletions app/Providers/AppServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace App\Providers;

use App\Services\ExternalMusicXmlService;
use App\Services\LilypondPartsService;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\ServiceProvider;
Expand Down Expand Up @@ -92,6 +93,12 @@ public function register()
$this->app->singleton(RenderedScoreService::class, function () {
return new RenderedScoreService();
});
$this->app->singleton(ExternalMusicXmlService::class, function () {
return new ExternalMusicXmlService(
app(LilypondClientService::class),
app(RenderedScoreService::class)
);
});
$this->app->singleton(SongLyricModelService::class, function () {
return new SongLyricModelService(new SongLyricBibleReferenceService());
});
Expand Down
18 changes: 15 additions & 3 deletions app/RenderedScore.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use App\Services\RenderedScoreService;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Support\Facades\Storage;

class RenderedScore extends Model
{
Expand Down Expand Up @@ -46,9 +47,20 @@ public function scopeSvg($query)
return $query->where('filetype', 'svg');
}

public function getPublicUrlPrefixAttribute()
public function getPublicUrlAttribute()
{
// this is actually served by nginx
return url("/rendered_scores/$this->filename");
// this should actually be served by nginx
return url("/$this->filepath");
}

public function getFilepathAttribute()
{
return "rendered_scores/$this->filename.$this->filetype";
}

public function getContentsAttribute()
{
$path = Storage::path($this->filepath);
return file_get_contents($path);
}
}
36 changes: 36 additions & 0 deletions app/Services/ExternalMusicXmlService.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

namespace App\Services;

use App\External;
use Illuminate\Support\Facades\Storage;

class ExternalMusicXmlService
{
protected LilypondClientService $ly_service;
protected RenderedScoreService $rs_service;

public function __construct(LilypondClientService $ly_service, RenderedScoreService $rs_service)
{
$this->ly_service = $ly_service;
$this->rs_service = $rs_service;
}

public static function isMediaTypeRenderable(string $media_type) {
return $media_type == 'file/xml' || $media_type == 'file/mxml';
}

// is called by RenderExternalMusicXml job
public function renderExternalMusicXml(External $external)
{
if (!self::isMediaTypeRenderable($external->media_type)) {
logger('ExternalMusicXmlService: Not rendering, expected media type file/xml or file/mxml, but got ' . $external->media_type);
return;
}

$contents = file_get_contents(Storage::path($external->filepath));
$data = $this->ly_service->doClientRenderSvgFromXml($contents);

$this->rs_service->createMusicXmlRenderedScore($external, $data['svg']);
}
}
15 changes: 15 additions & 0 deletions app/Services/LilypondClientService.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,21 @@ public function doClientRenderPdf($src)
return $data;
}

// kind-of-beta support for rendering from XML (via Verovio)
public function doClientRenderSvgFromXml(string $src)
{
$res = $this->client->renderXml($src);
$data = [
'svg' => $res->isSuccessful() ? $this->client->getResultOutputFile($res) : '',
'log' => $this->client->getResultLog($res)
];
$this->client->deleteResult($res);

logger('Verovio MusicXML render, ' . config('lilypond_renderer.host'));

return $data;
}

public function makeSvgFast($lilypond, $key_major = null)
{
$data = $this->doClientRenderSvg($this->makeLilypondBasicTemplate($lilypond, $key_major), false);
Expand Down
20 changes: 20 additions & 0 deletions app/Services/RenderedScoreService.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace App\Services;

use App\Author;
use App\External;
use App\LilypondPartsSheetMusic;
use App\SongLyric;
use App\RenderedScore;
Expand Down Expand Up @@ -84,6 +85,25 @@ public function createLilypondRenderedScore(LilypondPartsSheetMusic $lp, $render
$lp->rendered_scores()->save($rs);
}

public function createMusicXmlRenderedScore(External $external, string $data) {
$primary_filetype = 'svg';
$primary_filename = $this->makeFile($data, $primary_filetype);

// and save the new one into db
$rs = new RenderedScore([
// currently the musicxml rendering provides no way to configure the render output
// (it is hardcoded in the lilypond server renderer)
'render_config' => [],
'render_config_hash' => $this->getRenderConfigHash([]),
'filename' => $primary_filename,
'filetype' => $primary_filetype,
'secondary_filetypes' => array_keys([]),
'frontend_display_order' => null
]);

$external->rendered_scores()->save($rs);
}

// todo: call this on soft deleting SongLyric
public function destroyRenderedScore(RenderedScore $score)
{
Expand Down
5 changes: 5 additions & 0 deletions app/SongLyric.php
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,11 @@ public function lilypond_rendered_scores(): HasManyThrough
return $this->hasManyThrough(RenderedScore::class, LilypondPartsSheetMusic::class, null, 'lilypond_parts_sheet_music_id');
}

public function external_rendered_scores(): HasManyThrough
{
return $this->hasManyThrough(RenderedScore::class, External::class, null, 'external_id');
}

// -----------

public function arrangements(): HasMany
Expand Down
7 changes: 5 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
"mll-lab/laravel-graphql-playground": "^2.6",
"nuwave/lighthouse": "^5.55",
"predis/predis": "^1.1",
"proscholy/lilypond-renderer-client": "0.10.*",
"proscholy/lilypond-renderer-client": "0.11.*",
"sentry/sentry-laravel": "^2.12",
"snoeren-development/laravel-discord-webhook-channel": "^1.4",
"spatie/flysystem-dropbox": "^2.0",
Expand Down Expand Up @@ -85,7 +85,10 @@
"config": {
"preferred-install": "dist",
"sort-packages": true,
"optimize-autoloader": true
"optimize-autoloader": true,
"allow-plugins": {
"php-http/discovery": true
}
},
"minimum-stability": "dev",
"prefer-stable": true
Expand Down
Loading

0 comments on commit 116a9aa

Please sign in to comment.