Lue dans les fichiers PHP du paquet au commit ac40ed8ecbd0 : ses espaces de noms, classes, interfaces et énumérations, leurs constantes, propriétés et méthodes publiques avec leur PHPDoc, et les options que prennent ses fabriques. Rien n’en est exécuté.
MusicBundleclassA musician's site on top of omnibase's Thread: a Release and a Video ARE threads (JOINED subclasses); a label, a track, a work, an instrument and a performer are plain rows. The label goes first, everywhere.
3 methods
LatestReleaseWidgetTypeclassThe dashboard's tile: the last record out, the next one announced, and how many tracks the player has nothing to play for (no excerpt, no preview), and how many times the site's player played. `yield MenuItem::block('music_latest', ...)` in the dashboard's configureWidgetItems() places it.
4 methods
PeaksCommandclassComputes the waveforms of the tracks' excerpts with ffmpeg: those that have none yet, all of them again with --all, one with --track. Without ffmpeg it says so and leaves: the player draws a plain line instead.
1 method
PostersCommandclassGives the videos without a poster the best of their own frames (Service\PosterPicker): every video again with --all, one with --video. A poster uploaded by hand is kept unless --all.
1 method
Base\Music\Controller\Admin\Crud
InstrumentCrudControllerclassThe instrument: its maker, its year and place, its story, who lends it, a picture.
3 methods
LabelCrudControllerclassThe labels: a name, a logo, a site, a shop, and how the page of one of its records is written ({catalogue}, {upc}, {slug}) - with that, a record needs only its number to link to its label.
3 methods
PerformerCrudControllerclassWho plays with the musician: a name, what they play, a site; their order in the billing.
3 methods
PlaylistCrudControllerclassThe playlists and profiles on the platforms: the address is enough, the platform is read off it. The musician's profile ("Artist") is what "Listen in full" opens on /music; the others follow it.
4 methods
ReleaseCrudControllerclassThe discography in the back office: a record's label and number, its date, its sleeve, its tracks (each with its excerpt or a catalogue's preview), its links, its prizes, its liner notes. Three buttons do the typing: "Complete" asks the catalogues (Omnisong) what they know of it, "Look up" makes a record from one URL or UPC, "Waveforms" draws its tracks' peaks with ffmpeg. Nothing typed by hand is ever overwritten.
10 methods
VideoCrudControllerclassThe films: a file of the site's, or a YouTube or Vimeo address (the id is read off it), a poster - always: the embed loads only on a click, the poster is what is seen until then - where and when, what was played.
8 methods
WorkCrudControllerclassThe repertoire: who wrote it, what, for whom, how long; visible on /repertoire or kept aside.
4 methods
HeroFrameControllerclassWhere the "Reframe" of the home page's picture is kept (public/js/hero-frame.js): an administrator drags the picture, zooms, saves - without leaving the page.
1 method · 1 constant
MusicControllerclassThe musician's pages: the discography (the featured record first, then the others, the announced ones, the films), one record with its label, its player and its notes, the repertoire, the films, the instrument.
9 methods
Base\Music\DependencyInjection
MusicConfigurationclass1 method
MusicExtensionclass2 methods
InstrumentclassWhat the musician plays: a Francesco Ruggeri violin, Cremona 1690; a concert harp. Its maker, its year and place, the model it follows, whose hands it went through, and the foundation that lends it when one does.
28 methods
LabelclassThe house a recording came out on - ES-DUR, FARAO classics - and the one the site puts forward: its logo next to the cover, "released by" above the track list, "buy it at the label" before any streaming platform.
20 methods
PerformerclassWho plays with the musician: a pianist, a quartet, an orchestra, its conductor. Shared by the releases and the videos; music_performers() writes the line under a title: "with Guillaume Vincent, piano".
12 methods
PlaylistclassA playlist or a profile on a streaming platform - Spotify, Apple Music, Deezer, YouTube, SoundCloud - played in its own iframe, on a click. What is listened to there, by a listener logged in on the platform, counts as a stream for the musician; a 30 s preview of the site's player does not.
20 methods
ReleaseclassAn album, a single, an EP: what the musician recorded. An omnibase thread - title, headline, excerpt and text translated (the text is the liner notes), slug, publication state and date - written in the back office (Controller\Admin\Crud\ReleaseCrudController), with on top what a record is: its label and its number there, its UPC, its date, its cover, its tracks, who plays on it, the prizes it won, and where it is listened to or bought - the label first (getPlatformLinks()).
49 methods
TrackclassOne recording of a release: its disc and its place, its title - or the work it is (Work) and which movement - its length, the ISRC that names it everywhere, and what the site's player plays for it: the site's own file (sample) first - an excerpt, or the whole track (whole) - else a catalogue's 30 seconds (previewUrl). plays counts the times the site's player played it (TrackRepository::countPlay()).
43 methods
VideoclassA film of the musician playing: a file of the site's, or a video on YouTube or Vimeo. An omnibase thread for its title, its text and its publication; on top, its poster, where and when it was filmed, the work played and the release it belongs to. An embed never loads with the page: the poster and a play button first, the iframe on the click.
35 methods
WorkclassA piece of the repertoire: who wrote it, its title and its number, what it is written for, how long it lasts, its movements. The /repertoire page lists the visible ones - what a programmer reads before writing - and a track or a video can say which work it is.
27 methods
FormationenumWhat a work is written for: the first way the repertoire is grouped.
1 method · 6 cases
PerformerKindenumWho plays with the musician: a person, an ensemble, an orchestra, the one who conducts.
1 method · 4 cases
PeriodenumWhen a work was written, in the broad strokes a programme uses.
1 method · 5 cases
PlaylistKindenumWhat a playlist is: the musician's own records, the musician's picks (colleagues, recordings loved), or the musician's profile on a platform (its top tracks) - the one "Listen in full" opens first.
1 method · 3 cases
ReleaseTypeenumWhat a release is. A string enum (not omnibase's EnumType) so the column reads plainly in the database and in the admin's filters.
2 methods · 5 cases
LinksTypeclassA release's links in the back office: one address per platform, in the order the site shows them (Platform::rank()), bound to the json column Release::$links (platform value => URL). The label's own page is not here - it is the Label's pattern, or the release's labelUrl - nor its shop.
3 methods
TrackTypeclassOne track of a release in the back office: its place, its title - or the work and the movement - its length, its ISRC, the site's file (an upload: an excerpt, or the whole track) and a catalogue's preview, the day it can be heard (a single before its album) and the countries it is not played in, and how many times it was played. The waveform is not typed: it is computed (the "Waveforms" action, or `music:peaks`).
2 methods
InstrumentRepositoryclass3 methods
LabelRepositoryclass2 methods
PerformerRepositoryclass1 method
PlaylistRepositoryclass3 methods
ReleaseRepositoryclass6 methods
TrackRepositoryclass5 methods
VideoRepositoryclass5 methods
WorkRepositoryclass4 methods · 4 constants
AvailabilityclassWhether a track can be heard here and now: not before its day (a track kept for its album's release, while a single of it is out already), and not in a country its rights stop at (Track::$blockedIn, set by hand in the back office).
5 methods · 2 constants
HeroFrameclassThe home page's picture as an administrator frames it on the page: the point of the picture kept in view (an object-position, "52% 31%") and how close (1 to 2.5). Two settings, music.hero.position and music.hero.zoom; null puts the host's own framing back.
3 methods · 2 constants
ImportReportclassWhat Importer did to a release: what it filled, how many tracks it touched, and which catalogues did not answer.
3 methods · 5 properties
ImporterclassCompletes a release from what the catalogues know (Omnisong: Odesli for the links, iTunes for the tracks and their 30 s previews): one URL or one UPC, and the links to every platform, the UPC, the cover, the date, the label and the track list come in.
7 methods
JsonLdclassA release as schema.org reads it: a MusicAlbum by the musician, on its label (recordLabel), with its tracks, its catalogue number and its links (sameAs) - what search engines show next to the record.
3 methods
PeaksclassThe static waveform of a track's excerpt: ffmpeg decodes the file to raw mono PCM at 8 kHz, and the samples are reduced to 200 loudness values between 0 and 1 (reduce()), kept on the track. player.js draws them as bars with no decoding in the browser. Without ffmpeg nothing is computed - it is logged, and the player shows a plain progress line instead.
5 methods · 2 constants
PlayerclassWhat a track plays from, in the order music.player.order says: the site's own file (file: an excerpt, or the whole track), a catalogue's 30 s preview (preview), and - when there is no audio at all - the iframe of the first platform link Omnisong's Embedder can play (embed), loaded only on a click.
10 methods · 3 constants
PlaysclassOne play of a track, as player.js tells it once the visitor has heard it (30 seconds, or most of a shorter file). Counted once at a time for the same visitor on the same track (EVERY seconds: nobody hears it twice in less - a page reloaded, the same beacon sent again), never for a robot (a crawler's or an AI's user agent, or none: omnibase's UserAgentClassifier, when the core has it), and never for the people of the back office (the controller's business: it knows who signs in).
3 methods · 1 constant
PosterPickerclassA video's poster, chosen among its own frames with no artificial intelligence: a few pictures of the film - YouTube's frames at a quarter, a half and three quarters of it and the thumbnail its channel chose, Vimeo's thumbnail, a file of the site's own read by ffmpeg at several moments - each measured on a small copy, the black bars of a letterbox cut off first: its exposure (neither dark nor burnt), its contrast, its sharpness (a blurred or moving frame is soft), its colour, and how much of it is skin or the warm wood and gilding of an instrument (the musician, her harp, his violin) rather than an empty stage. The best one becomes the poster, a file of the site: a visitor's page asks nothing of the platform before a click.
4 methods
MusicExtensionclassWhat a host's own pages ask the music: the player's bar (once, in the layout), a release's player and links - the label first - the last releases and films for a home page, the hero film, the instrument, the line of who plays with the musician, and durations as a sleeve prints them.
5 methods
Base\Music
MusicBundle class
class MusicBundle extends AbstractBaseBundle MusicBundle.php:14
A musician's site on top of omnibase's Thread: a Release and a Video ARE threads (JOINED subclasses); a label, a track, a work, an instrument and a performer are plain rows. The label goes first, everywhere.
MusicBundle::__construct()
public function __construct()MusicBundle::getPath()
public function getPath(): stringModern layout: the class lives in src/, the bundle root is the package root.
MusicBundle::build()
public function build(ContainerBuilder $container): voidBase\Music\Admin\Widget
LatestReleaseWidgetType class
final class LatestReleaseWidgetType implements DashboardWidgetTypeInterface LatestReleaseWidgetType.php:16
The dashboard's tile: the last record out, the next one announced, and
how many tracks the player has nothing to play for (no excerpt, no
preview), and how many times the site's player played. yield MenuItem::block('music_latest', ...) in the
dashboard's configureWidgetItems() places it.
LatestReleaseWidgetType::__construct()
public function __construct(readonly ReleaseRepository $releases, readonly TrackRepository $tracks)LatestReleaseWidgetType::getName()
public static function getName(): stringLatestReleaseWidgetType::getTemplate()
public function getTemplate(): stringLatestReleaseWidgetType::getTemplateVars()
public function getTemplateVars(MenuItem $widget): arrayBase\Music\Command
PeaksCommand class
class PeaksCommand extends Command PeaksCommand.php:20
Computes the waveforms of the tracks' excerpts with ffmpeg: those that have none yet, all of them again with --all, one with --track. Without ffmpeg it says so and leaves: the player draws a plain line instead.
PeaksCommand::__construct()
public function __construct(readonly TrackRepository $tracks, readonly Peaks $peaks, readonly EntityManagerInterface $entityManager)PostersCommand class
class PostersCommand extends Command PostersCommand.php:19
Gives the videos without a poster the best of their own frames (Service\PosterPicker): every video again with --all, one with --video. A poster uploaded by hand is kept unless --all.
PostersCommand::__construct()
public function __construct(readonly PosterPicker $picker, readonly EntityManagerInterface $entityManager)Base\Music\Controller\Admin\Crud
InstrumentCrudController class
class InstrumentCrudController extends AbstractCrudController InstrumentCrudController.php:15
The instrument: its maker, its year and place, its story, who lends it, a picture.
InstrumentCrudController::getEntityFqcn()
public static function getEntityFqcn(): stringInstrumentCrudController::getPreferredIcon()
public static function getPreferredIcon(): ?stringInstrumentCrudController::configureFields()
public function configureFields(string $pageName): iterableLabelCrudController class
class LabelCrudController extends AbstractCrudController LabelCrudController.php:19
The labels: a name, a logo, a site, a shop, and how the page of one of its records is written ({catalogue}, {upc}, {slug}) - with that, a record needs only its number to link to its label.
LabelCrudController::getEntityFqcn()
public static function getEntityFqcn(): stringLabelCrudController::getPreferredIcon()
public static function getPreferredIcon(): ?stringLabelCrudController::configureFields()
public function configureFields(string $pageName): iterablePerformerCrudController class
class PerformerCrudController extends AbstractCrudController PerformerCrudController.php:14
Who plays with the musician: a name, what they play, a site; their order in the billing.
PerformerCrudController::getEntityFqcn()
public static function getEntityFqcn(): stringPerformerCrudController::getPreferredIcon()
public static function getPreferredIcon(): ?stringPerformerCrudController::configureFields()
public function configureFields(string $pageName): iterablePlaylistCrudController class
class PlaylistCrudController extends AbstractCrudController PlaylistCrudController.php:22
The playlists and profiles on the platforms: the address is enough, the platform is read off it. The musician's profile ("Artist") is what "Listen in full" opens on /music; the others follow it.
PlaylistCrudController::getEntityFqcn()
public static function getEntityFqcn(): stringPlaylistCrudController::getPreferredIcon()
public static function getPreferredIcon(): ?stringPlaylistCrudController::configureFilters()
public function configureFilters(Filters $filters): FiltersPlaylistCrudController::configureFields()
public function configureFields(string $pageName): iterableReleaseCrudController class
class ReleaseCrudController extends AbstractCrudController ReleaseCrudController.php:46
The discography in the back office: a record's label and number, its date, its sleeve, its tracks (each with its excerpt or a catalogue's preview), its links, its prizes, its liner notes. Three buttons do the typing: "Complete" asks the catalogues (Omnisong) what they know of it, "Look up" makes a record from one URL or UPC, "Waveforms" draws its tracks' peaks with ffmpeg. Nothing typed by hand is ever overwritten.
ReleaseCrudController::setMusicServices()
public function setMusicServices(Importer $importer, Peaks $peaks): voidReleaseCrudController::getEntityFqcn()
public static function getEntityFqcn(): stringReleaseCrudController::getPreferredIcon()
public static function getPreferredIcon(): ?stringReleaseCrudController::configureFilters()
public function configureFilters(Filters $filters): FiltersReleaseCrudController::configureFields()
public function configureFields(string $pageName): iterableReleaseCrudController::configureActions()
public function configureActions(Actions $actions): ActionsReleaseCrudController::complete()
public function complete(string $entityId): ResponseWhat the catalogues know of this record, into its empty fields.
ReleaseCrudController::peaks()
public function peaks(string $entityId): ResponseThe waveforms of this record's excerpts, with ffmpeg.
ReleaseCrudController::lookup()
public function lookup(Request $request): ResponseOne URL (any platform) or one UPC: the record it names, made or completed.
ReleaseCrudController::createEntity()
public function createEntity(string $entityFqcn): objectVideoCrudController class
class VideoCrudController extends AbstractCrudController VideoCrudController.php:35
The films: a file of the site's, or a YouTube or Vimeo address (the id is read off it), a poster - always: the embed loads only on a click, the poster is what is seen until then - where and when, what was played.
VideoCrudController::setPosterPicker()
public function setPosterPicker(PosterPicker $posters): voidVideoCrudController::getEntityFqcn()
public static function getEntityFqcn(): stringVideoCrudController::getPreferredIcon()
public static function getPreferredIcon(): ?stringVideoCrudController::configureFilters()
public function configureFilters(Filters $filters): FiltersVideoCrudController::configureFields()
public function configureFields(string $pageName): iterableVideoCrudController::configureActions()
public function configureActions(Actions $actions): ActionsVideoCrudController::poster()
public function poster(string $entityId): ResponseThe best of the film's own frames as its poster (Service\PosterPicker), in place of the one it has.
VideoCrudController::createEntity()
public function createEntity(string $entityFqcn): objectWorkCrudController class
class WorkCrudController extends AbstractCrudController WorkCrudController.php:18
The repertoire: who wrote it, what, for whom, how long; visible on /repertoire or kept aside.
WorkCrudController::getEntityFqcn()
public static function getEntityFqcn(): stringWorkCrudController::getPreferredIcon()
public static function getPreferredIcon(): ?stringWorkCrudController::configureFilters()
public function configureFilters(Filters $filters): FiltersWorkCrudController::configureFields()
public function configureFields(string $pageName): iterableBase\Music\Controller\Client
HeroFrameController class
final class HeroFrameController extends AbstractController HeroFrameController.php:17
Where the "Reframe" of the home page's picture is kept (public/js/hero-frame.js): an administrator drags the picture, zooms, saves - without leaving the page.
const TOKEN = 'music-hero-frame'
HeroFrameController::save()
public function save(Request $request, HeroFrame $frame): ResponseMusicController class
class MusicController extends AbstractController MusicController.php:29
The musician's pages: the discography (the featured record first, then the others, the announced ones, the films), one record with its label, its player and its notes, the repertoire, the films, the instrument.
MusicController::__construct()
public function __construct(readonly ReleaseRepository $releases, readonly VideoRepository $videos, readonly WorkRepository $works, readonly InstrumentRepository $instruments, readonly PlaylistRepository $playlists, readonly TrackRepository $tracks, readonly Plays $plays, readonly JsonLd $jsonLd, readonly Player $player, readonly bool $withJsonLd = true, readonly bool $repertoire = true, readonly string $groupBy = WorkRepository::BY_FORMATION, readonly bool $instrument = true)MusicController::index()
public function index(): ResponseMusicController::repertoire()
public function repertoire(Request $request): ResponseMusicController::videos()
public function videos(): ResponseMusicController::video()
public function video(string $slug): ResponseMusicController::instrument()
public function instrument(): ResponseMusicController::full()
public function full(string $slug): JsonResponseFor the player's bar, wherever the visitor is: what its sheet says about the record, and "listen in full" - per platform, the iframe of the whole release (built by player.js only when asked for) and the record's page there, for "See the album".
MusicController::play()
public function play(int $id, Request $request): ResponseOne play of a track, told by player.js once the visitor has heard it (Service\Plays: once at a time for the same visitor, never a robot's).
The people of the back office are not counted.
MusicController::release()
public function release(string $slug): ResponseLast, so /music/{slug} never takes another page's path.
Base\Music\DependencyInjection
MusicConfiguration class
class MusicConfiguration extends AbstractBaseConfiguration MusicConfiguration.php:8
MusicConfiguration::getConfigTreeBuilder()
public function getConfigTreeBuilder(): TreeBuilderMusicExtension class
class MusicExtension extends AbstractBaseExtension MusicExtension.php:11
MusicExtension::getConfiguration()
public function getConfiguration(array $config, ContainerBuilder $container): MusicConfigurationMusicExtension::load()
public function load(array $configs, ContainerBuilder $container): voidBase\Music\Entity
Instrument class
class Instrument Instrument.php:17
What the musician plays: a Francesco Ruggeri violin, Cremona 1690; a concert harp. Its maker, its year and place, the model it follows, whose hands it went through, and the foundation that lends it when one does.
music_instrument() gives the featured one; /instrument shows the visible ones.
Instrument::__toString()
public function __toString(): stringInstrument::getId()
public function getId(): ?intInstrument::getName()
public function getName(): ?stringInstrument::setName()
public function setName(?string $name): selfInstrument::getKind()
public function getKind(): ?stringInstrument::setKind()
public function setKind(?string $kind): selfInstrument::getMaker()
public function getMaker(): ?stringInstrument::setMaker()
public function setMaker(?string $maker): selfInstrument::getYear()
public function getYear(): ?intInstrument::setYear()
public function setYear(?int $year): selfInstrument::getPlace()
public function getPlace(): ?stringInstrument::setPlace()
public function setPlace(?string $place): selfInstrument::getOrigin()
public function getOrigin(): string"Cremona, 1690".
Instrument::getModel()
public function getModel(): ?stringInstrument::setModel()
public function setModel(?string $model): selfInstrument::getProvenance()
public function getProvenance(): ?stringInstrument::setProvenance()
public function setProvenance(?string $provenance): selfInstrument::getLoan()
public function getLoan(): ?stringInstrument::setLoan()
public function setLoan(?string $loan): selfInstrument::getImage()
public function getImage(): ?stringInstrument::getImageFile()
public function getImageFile(): ?FileInstrument::setImage()
public function setImage($image): selfInstrument::getDescription()
public function getDescription(): ?stringInstrument::setDescription()
public function setDescription(?string $description): selfInstrument::isVisible()
public function isVisible(): boolInstrument::setVisible()
public function setVisible(bool $visible): selfInstrument::isFeatured()
public function isFeatured(): boolInstrument::setFeatured()
public function setFeatured(bool $featured): selfLabel class
class Label Label.php:21
The house a recording came out on - ES-DUR, FARAO classics - and the one the site puts forward: its logo next to the cover, "released by" above the track list, "buy it at the label" before any streaming platform.
A label knows its site, its shop, and how the page of one of its releases is written (releaseUrlPattern): with it a release needs nothing but its catalogue number to link to the label.
Label::__toString()
public function __toString(): stringLabel::getId()
public function getId(): ?intLabel::getName()
public function getName(): ?stringLabel::setName()
public function setName(?string $name): selfLabel::getSlug()
public function getSlug(): ?stringLabel::setSlug()
public function setSlug(?string $slug): selfLabel::getLogo()
public function getLogo(): ?stringLabel::getLogoFile()
public function getLogoFile(): ?FileLabel::setLogo()
public function setLogo($logo): selfLabel::getUrl()
public function getUrl(): ?stringLabel::setUrl()
public function setUrl(?string $url): selfLabel::getShopUrl()
public function getShopUrl(): ?stringLabel::setShopUrl()
public function setShopUrl(?string $shopUrl): selfLabel::getReleaseUrlPattern()
public function getReleaseUrlPattern(): ?stringLabel::setReleaseUrlPattern()
public function setReleaseUrlPattern(?string $pattern): selfLabel::getCountry()
public function getCountry(): ?stringLabel::setCountry()
public function setCountry(?string $country): selfLabel::getDescription()
public function getDescription(): ?stringLabel::setDescription()
public function setDescription(?string $description): selfLabel::releaseUrl()
public function releaseUrl(Release $release): ?stringThe page of one release at the label, from the pattern: null without a pattern, or when the release lacks what the pattern asks for (a pattern on {catalogue} says nothing of a release with no number).
Performer class
class Performer Performer.php:15
Who plays with the musician: a pianist, a quartet, an orchestra, its conductor. Shared by the releases and the videos; music_performers() writes the line under a title: "with Guillaume Vincent, piano".
Performer::__toString()
public function __toString(): stringPerformer::getId()
public function getId(): ?intPerformer::getName()
public function getName(): ?stringPerformer::setName()
public function setName(?string $name): selfPerformer::getKind()
public function getKind(): PerformerKindPerformer::setKind()
public function setKind(PerformerKind $kind): selfPerformer::getRole()
public function getRole(): ?stringPerformer::setRole()
public function setRole(?string $role): selfPerformer::getUrl()
public function getUrl(): ?stringPerformer::setUrl()
public function setUrl(?string $url): selfPerformer::getPosition()
public function getPosition(): intPerformer::setPosition()
public function setPosition(?int $position): selfPlaylist class
class Playlist Playlist.php:19
A playlist or a profile on a streaming platform - Spotify, Apple Music, Deezer, YouTube, SoundCloud - played in its own iframe, on a click. What is listened to there, by a listener logged in on the platform, counts as a stream for the musician; a 30 s preview of the site's player does not.
Playlist::__toString()
public function __toString(): stringPlaylist::getId()
public function getId(): ?intPlaylist::getTitle()
public function getTitle(): ?stringPlaylist::setTitle()
public function setTitle(?string $title): selfPlaylist::getSlug()
public function getSlug(): ?stringPlaylist::setSlug()
public function setSlug(?string $slug): selfPlaylist::getUrl()
public function getUrl(): ?stringPlaylist::setUrl()
public function setUrl(?string $url): selfPlaylist::getPlatform()
public function getPlatform(): ?PlatformThe platform, read off the address. Platform::fromUrl() knows an Apple Music album or song only, so a playlist or an artist there is recognised here by its host.
Playlist::getLink()
public function getLink(): ?PlatformLinkWhat Omnisong's Embedder is given.
Playlist::getKind()
public function getKind(): PlaylistKindPlaylist::setKind()
public function setKind(PlaylistKind $kind): selfPlaylist::getDescription()
public function getDescription(): ?stringPlaylist::setDescription()
public function setDescription(?string $description): selfPlaylist::isFeatured()
public function isFeatured(): boolPlaylist::setFeatured()
public function setFeatured(bool $featured): selfPlaylist::getPosition()
public function getPosition(): intPlaylist::setPosition()
public function setPosition(?int $position): selfPlaylist::isVisible()
public function isVisible(): boolPlaylist::setVisible()
public function setVisible(bool $visible): selfRelease class
class Release extends Thread implements LinkableInterface Release.php:31
An album, a single, an EP: what the musician recorded. An omnibase thread - title, headline, excerpt and text translated (the text is the liner notes), slug, publication state and date - written in the back office (Controller\Admin\Crud\ReleaseCrudController), with on top what a record is: its label and its number there, its UPC, its date, its cover, its tracks, who plays on it, the prizes it won, and where it is listened to or bought - the label first (getPlatformLinks()).
Release::__iconizeStatic()
public static function __iconizeStatic(): ?arrayRelease::__toLink()
public function __toLink(array $routeParameters = [], int $referenceType = UrlGeneratorInterface::ABSOLUTE_PATH): ?stringRelease::__construct()
public function __construct(?\Base\Entity\User $owner = null, ?Thread $parent = null, ?string $title = null, ?string $slug = null)Release::__toString()
public function __toString(): stringRelease::getType()
public function getType(): ReleaseTypeRelease::setType()
public function setType(ReleaseType $type): selfRelease::getLabel()
public function getLabel(): ?LabelRelease::setLabel()
public function setLabel(?Label $label): selfRelease::getLabelUrl()
public function getLabelUrl(): ?stringRelease::setLabelUrl()
public function setLabelUrl(?string $labelUrl): selfRelease::getCatalogue()
public function getCatalogue(): ?stringRelease::setCatalogue()
public function setCatalogue(?string $catalogue): selfRelease::getUpc()
public function getUpc(): ?stringRelease::setUpc()
public function setUpc(?string $upc): selfRelease::getReleasedAt()
public function getReleasedAt(): ?\DateTimeInterfaceRelease::setReleasedAt()
public function setReleasedAt(?\DateTimeInterface $releasedAt): selfRelease::isUpcoming()
public function isUpcoming(): boolRelease::setUpcoming()
public function setUpcoming(bool $upcoming): selfRelease::getPresaveUrl()
public function getPresaveUrl(): ?stringRelease::setPresaveUrl()
public function setPresaveUrl(?string $presaveUrl): selfRelease::getCover()
public function getCover(): ?stringRelease::getCoverFile()
public function getCoverFile(): ?FileRelease::setCover()
public function setCover($cover): selfRelease::hasCover()
public function hasCover(): boolRelease::getCoverUrl()
public function getCoverUrl(): ?stringRelease::setCoverUrl()
public function setCoverUrl(?string $coverUrl): selfRelease::getArtwork()
public function getArtwork(): ?stringThe sleeve to show, by its address: the upload's on the site ("/uploads/..."), else the catalogue's. The upload's own path is the file's on disk (/srv/app/public/uploads/...): the pages printed it as an image's src, and no browser could load it.
Release::getLinks()
public function getLinks(): array- Returns
platform value => URL, as typed in the back office
Release::setLinks()
public function setLinks(?array $links): selfRelease::setLink()
public function setLink(Platform $platform, ?string $url): selfRelease::getPlatformLinks()
public function getPlatformLinks(): PlatformLinksWhere it is, in the order the site shows it: the label first - at this release's own page there (labelUrl), else the one the label's pattern gives, else the label's site - then its shop, then the platforms by Platform::rank().
Release::getLabelLink()
public function getLabelLink(): ?PlatformLinkWhat "buy it at the label" opens: this record's own page there (labelUrl, or the label's pattern), else the label's shop, else its site.
Release::getAwards()
public function getAwards(): ?stringRelease::setAwards()
public function setAwards(?string $awards): selfRelease::getAwardList()
public function getAwardList(): arrayThe prizes, a line each: what was won, and who gave it when the line names them after a dash ("CD of the year — Radio România Muzical").
Release::getPerformers()
public function getPerformers(): CollectionRelease::addPerformer()
public function addPerformer(Performer $performer): selfRelease::removePerformer()
public function removePerformer(Performer $performer): selfRelease::getTracks()
public function getTracks(): CollectionRelease::addTrack()
public function addTrack(Track $track): selfRelease::removeTrack()
public function removeTrack(Track $track): selfRelease::getOrderedTracks()
public function getOrderedTracks(): array- Returns
by disc then place, whatever order they were added in
Release::getDiscs()
public function getDiscs(): array- Returns
disc => its tracks
Release::getPlays()
public function getPlays(): intHow many times the site's player played its tracks, all together.
Release::getDuration()
public function getDuration(): ?intSeconds, all tracks together; null as long as one has no duration.
Release::isFeatured()
public function isFeatured(): boolRelease::setFeatured()
public function setFeatured(bool $featured): selfRelease::isOut()
public function isOut(): boolOut: not announced only, and its date (when it has one) is behind us.
Release::publish()
public function publish(bool $published = true, ?\DateTimeInterface $at = null): selfPublish it now (or at $at), or take it back to draft.
Track class
class Track Track.php:20
One recording of a release: its disc and its place, its title - or the work it is (Work) and which movement - its length, the ISRC that names it everywhere, and what the site's player plays for it: the site's own file (sample) first - an excerpt, or the whole track (whole) - else a catalogue's 30 seconds (previewUrl). plays counts the times the site's player played it (TrackRepository::countPlay()).
The peaks are the excerpt's waveform, computed once (Service\Peaks,
music:peaks) and drawn by player.js with no decoding in the browser.
Track::__toString()
public function __toString(): stringTrack::getId()
public function getId(): ?intTrack::getRelease()
public function getRelease(): ?ReleaseTrack::setRelease()
public function setRelease(?Release $release): selfTrack::getPosition()
public function getPosition(): ?intTrack::setPosition()
public function setPosition(?int $position): selfTrack::getDisc()
public function getDisc(): intTrack::setDisc()
public function setDisc(?int $disc): selfTrack::getTitle()
public function getTitle(): ?stringTrack::setTitle()
public function setTitle(?string $title): selfTrack::getWork()
public function getWork(): ?WorkTrack::setWork()
public function setWork(?Work $work): selfTrack::getMovement()
public function getMovement(): ?stringTrack::setMovement()
public function setMovement(?string $movement): selfTrack::getDisplayTitle()
public function getDisplayTitle(): stringWhat the list shows: the title typed, else the work and its movement.
Track::getDuration()
public function getDuration(): ?intTrack::setDuration()
public function setDuration(?int $duration): selfTrack::getDurationText()
public function getDurationText(): string"4:07", "1:02:45"; "" without a duration.
Track::formatDuration()
public static function formatDuration(null|int|float $seconds): stringSeconds as a sleeve prints them: m:ss, h:mm:ss from an hour on.
Track::getIsrc()
public function getIsrc(): ?stringTrack::setIsrc()
public function setIsrc(?string $isrc): selfTrack::getPreviewUrl()
public function getPreviewUrl(): ?stringTrack::setPreviewUrl()
public function setPreviewUrl(?string $previewUrl): selfTrack::getSample()
public function getSample(): ?stringTrack::getSampleFile()
public function getSampleFile(): ?FileTrack::getSampleUrl()
public function getSampleUrl(): ?stringThe file's address on the site ("/uploads/..."), what the player loads: the upload's own path is the file's on disk (/srv/app/public/uploads/...), which no browser can load.
Track::setSample()
public function setSample($sample): selfTrack::hasSample()
public function hasSample(): boolTrack::isWhole()
public function isWhole(): boolThe site plays the track from its first note to its last: a file of its own, said to be whole.
Track::setWhole()
public function setWhole(?bool $whole): selfTrack::getPlays()
public function getPlays(): intTrack::hasAudio()
public function hasAudio(): boolSomething an <audio> can play: the site's excerpt or a catalogue's preview.
Track::getPeaks()
public function getPeaks(): ?arrayTrack::setPeaks()
public function setPeaks(?array $peaks): selfTrack::getPerformers()
public function getPerformers(): ?stringTrack::setPerformers()
public function setPerformers(?string $performers): selfTrack::getAvailableFrom()
public function getAvailableFrom(): ?\DateTimeImmutableTrack::setAvailableFrom()
public function setAvailableFrom(?\DateTimeInterface $availableFrom): selfTrack::isOutOn()
public function isOutOn(\DateTimeInterface $day): boolWhether it can be heard on $day: from its own date when it has one (a single before its album), else once its release is out.
Track::getOutDate()
public function getOutDate(): ?\DateTimeInterfaceThe day it will be heard, when that is not yet: its own, else its release's.
Track::getBlockedIn()
public function getBlockedIn(): arrayTrack::setBlockedIn()
public function setBlockedIn(?iterable $countries): selfTrack::isBlockedIn()
public function isBlockedIn(?string $country): boolVideo class
class Video extends Thread implements LinkableInterface Video.php:24
A film of the musician playing: a file of the site's, or a video on YouTube or Vimeo. An omnibase thread for its title, its text and its publication; on top, its poster, where and when it was filmed, the work played and the release it belongs to. An embed never loads with the page: the poster and a play button first, the iframe on the click.
Video::__iconizeStatic()
public static function __iconizeStatic(): ?arrayVideo::__toLink()
public function __toLink(array $routeParameters = [], int $referenceType = UrlGeneratorInterface::ABSOLUTE_PATH): ?stringVideo::__construct()
public function __construct(?\Base\Entity\User $owner = null, ?Thread $parent = null, ?string $title = null, ?string $slug = null)Video::__toString()
public function __toString(): stringVideo::getFile()
public function getFile(): ?stringVideo::setFile()
public function setFile($file): selfVideo::getYoutubeId()
public function getYoutubeId(): ?stringVideo::setYoutubeId()
public function setYoutubeId(?string $youtubeId): selfThe id, or any YouTube address holding it (watch?v=, youtu.be/, /embed/, /shorts/, /live/).
Video::getVimeoId()
public function getVimeoId(): ?stringVideo::setVimeoId()
public function setVimeoId(?string $vimeoId): selfThe id, or a vimeo.com address ending with it.
Video::isLocal()
public function isLocal(): boolHosted by the site: a <video>, no third party.
Video::getEmbedUrl()
public function getEmbedUrl(bool $autoplay = true): ?stringThe address of the player's iframe - youtube-nocookie.com, or player.vimeo.com with dnt=1 - null for a local film or none at all.
Only ever put in a data attribute: the iframe is made on the click.
Video::getWatchUrl()
public function getWatchUrl(): ?stringIts page on the platform, for a visitor who would rather watch it there.
Video::isPlayable()
public function isPlayable(): boolVideo::getPoster()
public function getPoster(): ?stringVideo::getPosterUrl()
public function getPosterUrl(): ?stringThe poster's address on the site ("/uploads/..."), what a page shows: the upload's own path can be the file's on disk (/srv/app/public/uploads/...), which no browser can load - as Track::getSampleUrl().
Video::getPosterFile()
public function getPosterFile(): ?FileVideo::setPoster()
public function setPoster($poster): selfVideo::getDuration()
public function getDuration(): ?intVideo::setDuration()
public function setDuration(?int $duration): selfVideo::getDurationText()
public function getDurationText(): stringVideo::isFeatured()
public function isFeatured(): boolVideo::setFeatured()
public function setFeatured(bool $featured): selfVideo::getWork()
public function getWork(): ?WorkVideo::setWork()
public function setWork(?Work $work): selfVideo::getRelease()
public function getRelease(): ?ReleaseVideo::setRelease()
public function setRelease(?Release $release): selfVideo::getRecordedAt()
public function getRecordedAt(): ?\DateTimeInterfaceVideo::setRecordedAt()
public function setRecordedAt(?\DateTimeInterface $recordedAt): selfVideo::getVenue()
public function getVenue(): ?stringVideo::setVenue()
public function setVenue(?string $venue): selfVideo::getPerformers()
public function getPerformers(): CollectionVideo::addPerformer()
public function addPerformer(Performer $performer): selfVideo::removePerformer()
public function removePerformer(Performer $performer): selfVideo::publish()
public function publish(bool $published = true, ?\DateTimeInterface $at = null): selfPublish it now (or at $at), or take it back to draft.
Work class
class Work Work.php:17
A piece of the repertoire: who wrote it, its title and its number, what it is written for, how long it lasts, its movements. The /repertoire page lists the visible ones - what a programmer reads before writing - and a track or a video can say which work it is.
Work::__toString()
public function __toString(): stringWork::getId()
public function getId(): ?intWork::getComposer()
public function getComposer(): ?stringWork::setComposer()
public function setComposer(?string $composer): selfWork::getComposerSortKey()
public function getComposerSortKey(): stringWhat the composers are sorted by: the last word of the name ("Glière").
Work::getTitle()
public function getTitle(): ?stringWork::setTitle()
public function setTitle(?string $title): selfWork::getOpus()
public function getOpus(): ?stringWork::setOpus()
public function setOpus(?string $opus): selfWork::getFullTitle()
public function getFullTitle(): string"Harp Concerto in E-flat major, op. 74".
Work::getYear()
public function getYear(): ?intWork::setYear()
public function setYear(?int $year): selfWork::getInstrumentation()
public function getInstrumentation(): ?stringWork::setInstrumentation()
public function setInstrumentation(?string $instrumentation): selfWork::getFormation()
public function getFormation(): FormationWork::setFormation()
public function setFormation(Formation $formation): selfWork::getDuration()
public function getDuration(): ?intWork::setDuration()
public function setDuration(?int $duration): selfWork::getMovements()
public function getMovements(): ?stringWork::setMovements()
public function setMovements(?string $movements): selfWork::getMovementList()
public function getMovementList(): arrayWork::getPeriod()
public function getPeriod(): ?PeriodWork::setPeriod()
public function setPeriod(?Period $period): selfWork::isVisible()
public function isVisible(): boolWork::setVisible()
public function setVisible(bool $visible): selfWork::getPosition()
public function getPosition(): intWork::setPosition()
public function setPosition(?int $position): selfBase\Music\Enum
Formation enum
enum Formation Formation.php:6
What a work is written for: the first way the repertoire is grouped.
case SOLO = 'solo'case CHAMBER = 'chamber'case CONCERTO = 'concerto'case ORCHESTRA = 'orchestra'case VOCAL = 'vocal'case OTHER = 'other'
Formation::rank()
public function rank(): intThe order of the repertoire page: alone first, then with others.
PerformerKind enum
enum PerformerKind PerformerKind.php:6
Who plays with the musician: a person, an ensemble, an orchestra, the one who conducts.
case PERSON = 'person'case ENSEMBLE = 'ensemble'case ORCHESTRA = 'orchestra'case CONDUCTOR = 'conductor'
PerformerKind::schema()
public function schema(): stringschema.org's type, for the JSON-LD.
Period enum
enum Period Period.php:6
When a work was written, in the broad strokes a programme uses.
case BAROQUE = 'baroque'case CLASSICAL = 'classical'case ROMANTIC = 'romantic'case MODERN = 'modern'case CONTEMPORARY = 'contemporary'
Period::rank()
public function rank(): intOldest first.
PlaylistKind enum
enum PlaylistKind PlaylistKind.php:10
What a playlist is: the musician's own records, the musician's picks (colleagues, recordings loved), or the musician's profile on a platform (its top tracks) - the one "Listen in full" opens first.
case OWN = 'own'case RECOMMENDED = 'recommended'case ARTIST = 'artist'
PlaylistKind::rank()
public function rank(): intThe order of the /music page: the profile, the records, the picks.
ReleaseType enum
enum ReleaseType ReleaseType.php:9
What a release is. A string enum (not omnibase's EnumType) so the column reads plainly in the database and in the admin's filters.
case ALBUM = 'album'case SINGLE = 'single'case EP = 'ep'case LIVE = 'live'case COMPILATION = 'compilation'
ReleaseType::schema()
public function schema(): stringschema.org's albumProductionType / albumReleaseType, for the JSON-LD.
ReleaseType::fromCatalogue()
public static function fromCatalogue(?string $type): selfThe type a catalogue (Omnisong\Model\Release) names, to ours.
Base\Music\Form
LinksType class
final class LinksType extends AbstractType LinksType.php:18
A release's links in the back office: one address per platform, in the order the site shows them (Platform::rank()), bound to the json column Release::$links (platform value => URL). The label's own page is not here - it is the Label's pattern, or the release's labelUrl - nor its shop.
LinksType::buildForm()
public function buildForm(FormBuilderInterface $builder, array $options): voidLinksType::configureOptions()
public function configureOptions(OptionsResolver $resolver): voidLinksType::platforms()
public static function platforms(array $exclude = [Platform::LABEL, Platform::SHOP]): arrayThe platforms a link can be typed for, in their rank.
TrackType class
class TrackType extends AbstractType TrackType.php:30
One track of a release in the back office: its place, its title - or
the work and the movement - its length, its ISRC, the site's file (an
upload: an excerpt, or the whole track) and a catalogue's preview, the
day it can be heard (a single before its album) and the countries it is
not played in, and how many times it was played. The waveform is not typed: it is
computed (the "Waveforms" action, or music:peaks).
The texts name their domain (@music.…): base-bundle gives every field the "fields" domain, which the form's own translation_domain does not reach.
TrackType::buildForm()
public function buildForm(FormBuilderInterface $builder, array $options): voidTrackType::configureOptions()
public function configureOptions(OptionsResolver $resolver): voidBase\Music\Repository
InstrumentRepository class
class InstrumentRepository extends ServiceEntityRepository InstrumentRepository.php:10
InstrumentRepository::__construct()
public function __construct(ManagerRegistry $registry)InstrumentRepository::findVisible()
public function findVisible(): array- Returns
the visible ones, the featured first
InstrumentRepository::findFeatured()
public function findFeatured(): ?InstrumentThe featured instrument, or the first visible one.
LabelRepository class
class LabelRepository extends ServiceEntityRepository LabelRepository.php:10
LabelRepository::__construct()
public function __construct(ManagerRegistry $registry)LabelRepository::findOneByName()
public function findOneByName(string $name): ?LabelThe label a catalogue names, whatever the case it writes it in ("Es-Dur", "ES-DUR").
PerformerRepository class
class PerformerRepository extends ServiceEntityRepository PerformerRepository.php:10
PerformerRepository::__construct()
public function __construct(ManagerRegistry $registry)PlaylistRepository class
class PlaylistRepository extends ServiceEntityRepository PlaylistRepository.php:11
PlaylistRepository::__construct()
public function __construct(ManagerRegistry $registry)PlaylistRepository::findVisible()
public function findVisible(?PlaylistKind $kind = null): array- Returns
the visible ones (of one kind), the featured first, then in their order
PlaylistRepository::findFeatured()
public function findFeatured(?PlaylistKind $kind = null): ?PlaylistThe featured playlist (of one kind), or the first visible one.
ReleaseRepository class
class ReleaseRepository extends ServiceEntityRepository ReleaseRepository.php:13
ReleaseRepository::__construct()
public function __construct(ManagerRegistry $registry)ReleaseRepository::findPublished()
public function findPublished(): arrayThe discography: every published release, the newest first - the announced ones included, they say so themselves.
ReleaseRepository::findLatest()
public function findLatest(int $limit = 3, ?ReleaseType $type = null): arrayThe last ones out (the announced ones left aside); of one type when asked - a home page shows the albums, not the singles between them.
ReleaseRepository::findFeatured()
public function findFeatured(): ?ReleaseThe featured release, or the newest one out.
ReleaseRepository::findOnePublished()
public function findOnePublished(string $slug): ?ReleaseReleaseRepository::findUpcoming()
public function findUpcoming(): array- Returns
announced or dated in the future, the nearest first
TrackRepository class
class TrackRepository extends ServiceEntityRepository TrackRepository.php:10
TrackRepository::__construct()
public function __construct(ManagerRegistry $registry)TrackRepository::countSilent()
public function countSilent(): intThe tracks the player has nothing to play for: no excerpt of the site's, no preview.
TrackRepository::countPlay()
public function countPlay(Track $track): voidOne more play of a track: added in the database itself, so two listeners at once are two plays.
TrackRepository::countPlays()
public function countPlays(): intThe plays of every track together.
TrackRepository::findWithSample()
public function findWithSample(bool $onlyWithoutPeaks = false): array- Returns
those with an excerpt of the site's - all of them, or only the ones whose waveform is missing
VideoRepository class
class VideoRepository extends ServiceEntityRepository VideoRepository.php:13
VideoRepository::__construct()
public function __construct(ManagerRegistry $registry)VideoRepository::findPublished()
public function findPublished(?int $limit = null): array- Returns
the published ones, the featured first, then the newest
VideoRepository::findFeatured()
public function findFeatured(): ?VideoThe featured video, or the newest one.
VideoRepository::findOnePublished()
public function findOnePublished(string $slug): ?VideoVideoRepository::findByRelease()
public function findByRelease(Release $release): array- Returns
the films of one release
WorkRepository class
class WorkRepository extends ServiceEntityRepository WorkRepository.php:10
const BY_FORMATION = 'formation'const BY_COMPOSER = 'composer'const BY_PERIOD = 'period'const GROUPS = [self::BY_FORMATION, self::BY_COMPOSER, self::BY_PERIOD]
WorkRepository::__construct()
public function __construct(ManagerRegistry $registry)WorkRepository::findVisible()
public function findVisible(): arrayWorkRepository::findVisibleGrouped()
public function findVisibleGrouped(string $by = self::BY_FORMATION): arrayThe repertoire as its page reads it: groups, and in each the composers (by surname) with their works. By formation the groups are the Formation values in their own order (solo, concerto, chamber...); by period the Period values, oldest first, the undated last under ''; by composer each composer is a group.
- Returns
group => composer => works
WorkRepository::group()
public static function group(iterable $works, string $by = self::BY_FORMATION): arrayBase\Music\Service
Availability class
class Availability Availability.php:21
Whether a track can be heard here and now: not before its day (a track kept for its album's release, while a single of it is out already), and not in a country its rights stop at (Track::$blockedIn, set by hand in the back office).
The visitor's country is the one the site is told: a country cookie, the
CDN's or the proxy's header (CF-IPCountry, X-Country), as the marketplace's
age gate reads it; else the region of the browser's first language
("de-CH": CH), a guess a visitor abroad may not fit. None known: nothing is
withheld for a country.
const LATER = 'later'const REGION = 'region'
Availability::__construct()
public function __construct(readonly ?RequestStack $requests = null)Availability::why()
public function why(Track $track): ?arrayWhy $track cannot be heard, null when it can: ['reason' => 'later', 'date' => its day or null] or ['reason' => 'region'].
Availability::allows()
public function allows(Track $track): boolAvailability::country()
public function country(): ?stringThe visitor's country (ISO 3166, "FR"), null when nothing says it.
Availability::countryOf()
public static function countryOf(?Request $request): ?stringHeroFrame class
final class HeroFrame HeroFrame.php:13
The home page's picture as an administrator frames it on the page: the point of the picture kept in view (an object-position, "52% 31%") and how close (1 to 2.5). Two settings, music.hero.position and music.hero.zoom; null puts the host's own framing back.
const POSITION = '/^\d{1,3}(\.\d{1,2})?% \d{1,3}(\.\d{1,2})?%$/'const MAX_ZOOM = 2.5
HeroFrame::__construct()
public function __construct(readonly SettingBagInterface $settings)HeroFrame::save()
public function save(?string $position, ?float $zoom): voidHeroFrame::reset()
public function reset(): voidImportReport class
final class ImportReport ImportReport.php:6
What Importer did to a release: what it filled, how many tracks it touched, and which catalogues did not answer.
public readonly bool $foundpublic readonly array $filledthe fields that were empty and are not any more
public readonly int $tracksCreatedpublic readonly int $tracksUpdatedpublic readonly array $incompletethe catalogues that could not be reached: ask again later
ImportReport::__construct()
public function __construct(public readonly bool $found, public readonly array $filled = [], public readonly int $tracksCreated = 0, public readonly int $tracksUpdated = 0, public readonly array $incomplete = [])$filledthe fields that were empty and are not any more
$incompletethe catalogues that could not be reached: ask again later
ImportReport::isUnavailable()
public function isUnavailable(): boolNothing found because a catalogue was down - not because the release does not exist.
ImportReport::changedSomething()
public function changedSomething(): boolImporter class
class Importer Importer.php:36
Completes a release from what the catalogues know (Omnisong: Odesli for the links, iTunes for the tracks and their 30 s previews): one URL or one UPC, and the links to every platform, the UPC, the cover, the date, the label and the track list come in.
It only ever fills what is empty: a field set by hand is never overwritten, a track is matched by its ISRC, else by its disc and place, and gets what it lacks. The label's own links are not taken from a catalogue: they come from the Label the release is given.
Nothing is flushed here. A catalogue that is down is not "not found": the report says which did not answer (ImportReport::$incomplete).
Importer::__construct()
public function __construct(readonly EntityManagerInterface $entityManager, readonly LabelRepository $labels, readonly ReleaseRepository $releases, readonly ?Catalog $catalog = null, readonly ?string $country = 'DE')Importer::isAvailable()
public function isAvailable(): boolFalse when Omnisong's bundle is not registered: there is no catalogue to ask.
Importer::reference()
public function reference(string $value): ReferenceWhat a loose string names (a URL, a UPC/EAN, an ISRC), for the site's country.
Importer::referenceOf()
public function referenceOf(Release $release): ?ReferenceWhat names a release for the catalogues: its UPC, else the first platform link it has.
Importer::complete()
public function complete(Release $release, ?Reference $reference = null): ImportReportFills the release's empty fields from the catalogues.
- Throws
OmnisongException what a catalogue throws beyond being down (a bad configuration...)
- Throws
InvalidArgumentException when the release has neither a UPC nor a link and no reference is given
Importer::import()
public function import(Reference $reference, ?ImportReport &$report = null): ?ReleaseOne URL or UPC to a release of the site: the one that already has this UPC, completed, or a new draft. Null when no catalogue knows it ($report says whether one was down). The new release is persisted, not flushed.
Importer::apply()
public function apply(Release $release, CatalogueRelease $found, array $incomplete = []): ImportReportWhat a catalogue found, onto the release: only the nulls are filled.
JsonLd class
class JsonLd JsonLd.php:14
A release as schema.org reads it: a MusicAlbum by the musician, on its label (recordLabel), with its tracks, its catalogue number and its links (sameAs) - what search engines show next to the record.
JsonLd::__construct()
public function __construct(readonly ?SettingBagInterface $settingBag = null, readonly ?string $artist = null)JsonLd::artist()
public function artist(): ?stringThe musician's name: music.artist, else the site's title (base.settings.title).
JsonLd::album()
public function album(Release $release, ?string $url = null, ?string $image = null): arrayPeaks class
class Peaks Peaks.php:17
The static waveform of a track's excerpt: ffmpeg decodes the file to raw mono PCM at 8 kHz, and the samples are reduced to 200 loudness values between 0 and 1 (reduce()), kept on the track. player.js draws them as bars with no decoding in the browser. Without ffmpeg nothing is computed - it is logged, and the player shows a plain progress line instead.
const COUNT = 200How many bars a waveform has.
const RATE = 8000What ffmpeg is asked for: samples a second, mono, signed 16 bits little-endian.
Peaks::__construct()
public function __construct(readonly ?LoggerInterface $logger = null, readonly string $ffmpeg = 'ffmpeg')Peaks::isAvailable()
public function isAvailable(): boolWhether ffmpeg answers (ffmpeg -version); asked once.
Peaks::compute()
public function compute(Track $track, int $count = self::COUNT): boolComputes and sets the peaks of a track's excerpt (nothing is flushed).
Of the uploaded excerpt, or else of the platform's preview. False when there is neither, no ffmpeg, or a file it cannot read.
Peaks::ofFile()
public function ofFile(string $path, int $count = self::COUNT): ?array- Returns
the peaks of an audio file, null when ffmpeg could not decode it
Peaks::reduce()
public static function reduce(string $pcm, int $count = self::COUNT): arrayRaw PCM (mono, signed 16 bits little-endian) to $count values in 0..1: the samples are cut in $count equal windows, each window gives its RMS, and the loudest window is 1. Fewer samples than $count give one value a sample; silence gives zeros; nothing gives nothing.
Player class
class Player Player.php:23
What a track plays from, in the order music.player.order says: the site's own file (file: an excerpt, or the whole track), a catalogue's 30 s preview (preview), and - when there is no audio at all - the iframe of the first platform link Omnisong's Embedder can play (embed), loaded only on a click.
const FILE = 'file'const PREVIEW = 'preview'const EMBED = 'embed'
Player::__construct()
public function __construct(readonly ?EmbedderInterface $embedder = null, readonly ?EmbedOptions $embedOptions = null, readonly ?LoggerInterface $logger = null, readonly array $order = [self::FILE, self::PREVIEW, self::EMBED], readonly string $theme = 'light', readonly array $full = ['spotify', 'apple_music', 'deezer'])$fullthe platforms "Listen in full" offers, in order
Player::full()
public function full(Release $release): arrayThe whole release on the platforms "Listen in full" offers (music.player.full), each an iframe built on a click: a listener logged in there streams it - and the stream counts for the musician, where a 30 s preview does not.
Player::listen()
public function listen(Release $release, ?string $fallback = null): array"Listen in full" as the player's bar asks for it, platform by platform: the iframe that plays the whole release there, and the release's own page on that platform - where a listener likes or saves it ("See the album"). With no page on the platform: the label's page of the record, then $fallback (the site's own page of it).
Player::hasFull()
public function hasFull(Release $release): boolWhether "Listen in full" has a platform to offer for the release, without building its iframes.
Player::playlist()
public function playlist(Playlist $playlist): ?EmbedA playlist's (or a profile's) iframe; null when its platform cannot be embedded.
Player::source()
public function source(Track $track): ?arrayThe source of one track for player.js: what it is and where it is.
Null when it has nothing to play (no file, no preview, no embed).
whole: the file is the track from end to end, not an excerpt.
Player::embedsAllowed()
public function embedsAllowed(): boolWhether music.player.order lets the embeds in at all.
Player::embed()
public function embed(Release $release, ?Platform $platform = null, ?EmbedOptions $options = null): ?EmbedThe iframe of a release on one platform, or on the first platform of its links the Embedder can play. Null when none can be, or when Omnisong's bundle is not registered.
Player::embedLink()
public function embedLink(PlatformLink $link, ?EmbedOptions $options = null): ?EmbedOne link's iframe, through Omnisong's Embedder; null when it cannot be embedded.
Player::options()
public function options(): EmbedOptionsThe site's options (Omnisong's own when its bundle defines them), on the theme music.player.theme names.
Plays class
class Plays Plays.php:20
One play of a track, as player.js tells it once the visitor has heard it (30 seconds, or most of a shorter file). Counted once at a time for the same visitor on the same track (EVERY seconds: nobody hears it twice in less - a page reloaded, the same beacon sent again), never for a robot (a crawler's or an AI's user agent, or none: omnibase's UserAgentClassifier, when the core has it), and never for the people of the back office (the controller's business: it knows who signs in).
Nothing about the listener is kept: the key is a hash of the address and the track, gone after EVERY seconds.
const EVERY = 20Seconds before the same visitor's play of the same track counts again.
Plays::__construct()
public function __construct(readonly TrackRepository $tracks, readonly CacheItemPoolInterface $cache, readonly ?object $classifier = null)$classifierBase\Service\Analytics\UserAgentClassifier (classify(?string): string)
Plays::count()
public function count(Track $track, ?string $address, ?string $userAgent): boolWhether this play was counted.
Plays::isRobot()
public function isRobot(?string $userAgent): boolPosterPicker class
class PosterPicker PosterPicker.php:25
A video's poster, chosen among its own frames with no artificial intelligence: a few pictures of the film - YouTube's frames at a quarter, a half and three quarters of it and the thumbnail its channel chose, Vimeo's thumbnail, a file of the site's own read by ffmpeg at several moments - each measured on a small copy, the black bars of a letterbox cut off first: its exposure (neither dark nor burnt), its contrast, its sharpness (a blurred or moving frame is soft), its colour, and how much of it is skin or the warm wood and gilding of an instrument (the musician, her harp, his violin) rather than an empty stage. The best one becomes the poster, a file of the site: a visitor's page asks nothing of the platform before a click.
PosterPicker::__construct()
public function __construct(readonly ?HttpClientInterface $http = null, readonly ?LoggerInterface $logger = null, readonly string $ffmpeg = 'ffmpeg')PosterPicker::pick()
public function pick(Video $video): boolGives $video the best of its frames as its poster; false when no frame could be had (no platform answer, no ffmpeg for a file of the site).
PosterPicker::score()
public static function score(\GdImage $picture): floatHow good a picture is as a poster, 0..1: exposure, contrast, sharpness, colour, and the share of skin and warm wood.
PosterPicker::uncropped()
public static function uncropped(\GdImage $picture): \GdImageThe picture without the black bars of a letterbox, above and below or on its sides.
Base\Music\Twig
MusicExtension class
final class MusicExtension extends AbstractExtension MusicExtension.php:33
What a host's own pages ask the music: the player's bar (once, in the layout), a release's player and links - the label first - the last releases and films for a home page, the hero film, the instrument, the line of who plays with the musician, and durations as a sleeve prints them.
MusicExtension::__construct()
public function __construct(readonly ReleaseRepository $releases, readonly VideoRepository $videos, readonly InstrumentRepository $instruments, readonly PlaylistRepository $playlists, readonly Player $player, readonly ?SettingBagInterface $settingBag = null, readonly ?Availability $availability = null, readonly bool $waves = true, readonly bool $liveWaves = true, readonly bool $labelFirst = true)MusicExtension::getFunctions()
public function getFunctions(): arrayMusicExtension::getFilters()
public function getFilters(): arrayMusicExtension::platformIcon()
public static function platformIcon(Platform|string|null $platform): stringThe Font Awesome classes of a platform's pill: its brand's mark where Font Awesome (free) draws one, else a neutral one - a record for the shops that sell files and discs, a note for the other streamers.
MusicExtension::performers()
public static function performers(Release|Video|null $subject): stringWho plays with the musician, as one line: "Guillaume Vincent, piano", "Ensemble Sur Le Pont, Michel Deneuve, conductor" - the template puts "with" before it in the visitor's language.