Skip to content

omnibase/music API reference

Floor
Prepared structure · Omnibase
Version
main
Verified for real
Its README does not say
Licence
MIT
composer require omnibase/music:dev-main

Read from the package's own PHP files at the commit ac40ed8ecbd0: its namespaces, classes, interfaces and enums, their public constants, properties and methods with their PHPDoc, and the options its factories take. Nothing of it is run.

Base\Music

  • MusicBundle class

    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.

    3 methods

Base\Music\Admin\Widget

  • LatestReleaseWidgetType class

    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.

    4 methods

Base\Music\Command

  • PeaksCommand class

    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.

    1 method

  • PostersCommand class

    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.

    1 method

Base\Music\Controller\Admin\Crud

  • InstrumentCrudController class

    The instrument: its maker, its year and place, its story, who lends it, a picture.

    3 methods

  • LabelCrudController class

    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.

    3 methods

  • PerformerCrudController class

    Who plays with the musician: a name, what they play, a site; their order in the billing.

    3 methods

  • PlaylistCrudController class

    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.

    4 methods

  • ReleaseCrudController class

    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.

    10 methods

  • VideoCrudController class

    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.

    8 methods

  • WorkCrudController class

    The repertoire: who wrote it, what, for whom, how long; visible on /repertoire or kept aside.

    4 methods

Base\Music\Controller\Client

  • HeroFrameController class

    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.

    1 method · 1 constant

  • MusicController class

    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.

    9 methods

Base\Music\DependencyInjection

Base\Music\Entity

  • Instrument class

    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.

    28 methods

  • Label class

    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.

    20 methods

  • Performer class

    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".

    12 methods

  • Playlist class

    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.

    20 methods

  • Release class

    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()).

    49 methods

  • Track class

    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()).

    43 methods

  • Video class

    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.

    35 methods

  • Work class

    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.

    27 methods

Base\Music\Enum

  • Formation enum

    What a work is written for: the first way the repertoire is grouped.

    1 method · 6 cases

  • PerformerKind enum

    Who plays with the musician: a person, an ensemble, an orchestra, the one who conducts.

    1 method · 4 cases

  • Period enum

    When a work was written, in the broad strokes a programme uses.

    1 method · 5 cases

  • PlaylistKind enum

    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.

    1 method · 3 cases

  • ReleaseType enum

    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.

    2 methods · 5 cases

Base\Music\Form

  • LinksType class

    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.

    3 methods

  • TrackType class

    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`).

    2 methods

Base\Music\Repository

Base\Music\Service

  • Availability class

    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).

    5 methods · 2 constants

  • HeroFrame class

    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.

    3 methods · 2 constants

  • ImportReport class

    What Importer did to a release: what it filled, how many tracks it touched, and which catalogues did not answer.

    3 methods · 5 properties

  • Importer class

    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.

    7 methods

  • JsonLd class

    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.

    3 methods

  • Peaks class

    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.

    5 methods · 2 constants

  • Player class

    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.

    10 methods · 3 constants

  • Plays class

    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).

    3 methods · 1 constant

  • PosterPicker class

    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.

    4 methods

Base\Music\Twig

  • MusicExtension class

    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.

    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(): string

Modern layout: the class lives in src/, the bundle root is the package root.

MusicBundle::build()

public function build(ContainerBuilder $container): void

Base\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(): string

LatestReleaseWidgetType::getTemplate()

public function getTemplate(): string

LatestReleaseWidgetType::getTemplateVars()

public function getTemplateVars(MenuItem $widget): array

Base\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(): string

InstrumentCrudController::getPreferredIcon()

public static function getPreferredIcon(): ?string

InstrumentCrudController::configureFields()

public function configureFields(string $pageName): iterable

LabelCrudController 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(): string

LabelCrudController::getPreferredIcon()

public static function getPreferredIcon(): ?string

LabelCrudController::configureFields()

public function configureFields(string $pageName): iterable

PerformerCrudController 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(): string

PerformerCrudController::getPreferredIcon()

public static function getPreferredIcon(): ?string

PerformerCrudController::configureFields()

public function configureFields(string $pageName): iterable

PlaylistCrudController 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(): string

PlaylistCrudController::getPreferredIcon()

public static function getPreferredIcon(): ?string

PlaylistCrudController::configureFilters()

public function configureFilters(Filters $filters): Filters

PlaylistCrudController::configureFields()

public function configureFields(string $pageName): iterable

ReleaseCrudController 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): void

ReleaseCrudController::getEntityFqcn()

public static function getEntityFqcn(): string

ReleaseCrudController::getPreferredIcon()

public static function getPreferredIcon(): ?string

ReleaseCrudController::configureFilters()

public function configureFilters(Filters $filters): Filters

ReleaseCrudController::configureFields()

public function configureFields(string $pageName): iterable

ReleaseCrudController::configureActions()

public function configureActions(Actions $actions): Actions

ReleaseCrudController::complete()

public function complete(string $entityId): Response

What the catalogues know of this record, into its empty fields.

ReleaseCrudController::peaks()

public function peaks(string $entityId): Response

The waveforms of this record's excerpts, with ffmpeg.

ReleaseCrudController::lookup()

public function lookup(Request $request): Response

One URL (any platform) or one UPC: the record it names, made or completed.

ReleaseCrudController::createEntity()

public function createEntity(string $entityFqcn): object

VideoCrudController 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): void

VideoCrudController::getEntityFqcn()

public static function getEntityFqcn(): string

VideoCrudController::getPreferredIcon()

public static function getPreferredIcon(): ?string

VideoCrudController::configureFilters()

public function configureFilters(Filters $filters): Filters

VideoCrudController::configureFields()

public function configureFields(string $pageName): iterable

VideoCrudController::configureActions()

public function configureActions(Actions $actions): Actions

VideoCrudController::poster()

public function poster(string $entityId): Response

The 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): object

WorkCrudController 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(): string

WorkCrudController::getPreferredIcon()

public static function getPreferredIcon(): ?string

WorkCrudController::configureFilters()

public function configureFilters(Filters $filters): Filters

WorkCrudController::configureFields()

public function configureFields(string $pageName): iterable

Base\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): Response

MusicController 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(): Response

MusicController::repertoire()

public function repertoire(Request $request): Response

MusicController::videos()

public function videos(): Response

MusicController::video()

public function video(string $slug): Response

MusicController::instrument()

public function instrument(): Response

MusicController::full()

public function full(string $slug): JsonResponse

For 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): Response

One 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): Response

Last, 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(): TreeBuilder

MusicExtension class

class MusicExtension extends AbstractBaseExtension MusicExtension.php:11

MusicExtension::getConfiguration()

public function getConfiguration(array $config, ContainerBuilder $container): MusicConfiguration

MusicExtension::load()

public function load(array $configs, ContainerBuilder $container): void

Base\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(): string

Instrument::getId()

public function getId(): ?int

Instrument::getName()

public function getName(): ?string

Instrument::setName()

public function setName(?string $name): self

Instrument::getKind()

public function getKind(): ?string

Instrument::setKind()

public function setKind(?string $kind): self

Instrument::getMaker()

public function getMaker(): ?string

Instrument::setMaker()

public function setMaker(?string $maker): self

Instrument::getYear()

public function getYear(): ?int

Instrument::setYear()

public function setYear(?int $year): self

Instrument::getPlace()

public function getPlace(): ?string

Instrument::setPlace()

public function setPlace(?string $place): self

Instrument::getOrigin()

public function getOrigin(): string

"Cremona, 1690".

Instrument::getModel()

public function getModel(): ?string

Instrument::setModel()

public function setModel(?string $model): self

Instrument::getProvenance()

public function getProvenance(): ?string

Instrument::setProvenance()

public function setProvenance(?string $provenance): self

Instrument::getLoan()

public function getLoan(): ?string

Instrument::setLoan()

public function setLoan(?string $loan): self

Instrument::getImage()

public function getImage(): ?string

Instrument::getImageFile()

public function getImageFile(): ?File

Instrument::setImage()

public function setImage($image): self

Instrument::getDescription()

public function getDescription(): ?string

Instrument::setDescription()

public function setDescription(?string $description): self

Instrument::isVisible()

public function isVisible(): bool

Instrument::setVisible()

public function setVisible(bool $visible): self

Instrument::isFeatured()

public function isFeatured(): bool

Instrument::setFeatured()

public function setFeatured(bool $featured): self

Label 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(): string

Label::getId()

public function getId(): ?int

Label::getName()

public function getName(): ?string

Label::setName()

public function setName(?string $name): self

Label::getSlug()

public function getSlug(): ?string

Label::setSlug()

public function setSlug(?string $slug): self
public function getLogo(): ?string

Label::getLogoFile()

public function getLogoFile(): ?File
public function setLogo($logo): self

Label::getUrl()

public function getUrl(): ?string

Label::setUrl()

public function setUrl(?string $url): self

Label::getShopUrl()

public function getShopUrl(): ?string

Label::setShopUrl()

public function setShopUrl(?string $shopUrl): self

Label::getReleaseUrlPattern()

public function getReleaseUrlPattern(): ?string

Label::setReleaseUrlPattern()

public function setReleaseUrlPattern(?string $pattern): self

Label::getCountry()

public function getCountry(): ?string

Label::setCountry()

public function setCountry(?string $country): self

Label::getDescription()

public function getDescription(): ?string

Label::setDescription()

public function setDescription(?string $description): self

Label::releaseUrl()

public function releaseUrl(Release $release): ?string

The 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(): string

Performer::getId()

public function getId(): ?int

Performer::getName()

public function getName(): ?string

Performer::setName()

public function setName(?string $name): self

Performer::getKind()

public function getKind(): PerformerKind

Performer::setKind()

public function setKind(PerformerKind $kind): self

Performer::getRole()

public function getRole(): ?string

Performer::setRole()

public function setRole(?string $role): self

Performer::getUrl()

public function getUrl(): ?string

Performer::setUrl()

public function setUrl(?string $url): self

Performer::getPosition()

public function getPosition(): int

Performer::setPosition()

public function setPosition(?int $position): self

Playlist 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(): string

Playlist::getId()

public function getId(): ?int

Playlist::getTitle()

public function getTitle(): ?string

Playlist::setTitle()

public function setTitle(?string $title): self

Playlist::getSlug()

public function getSlug(): ?string

Playlist::setSlug()

public function setSlug(?string $slug): self

Playlist::getUrl()

public function getUrl(): ?string

Playlist::setUrl()

public function setUrl(?string $url): self

Playlist::getPlatform()

public function getPlatform(): ?Platform

The 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.

public function getLink(): ?PlatformLink

What Omnisong's Embedder is given.

Playlist::getKind()

public function getKind(): PlaylistKind

Playlist::setKind()

public function setKind(PlaylistKind $kind): self

Playlist::getDescription()

public function getDescription(): ?string

Playlist::setDescription()

public function setDescription(?string $description): self

Playlist::isFeatured()

public function isFeatured(): bool

Playlist::setFeatured()

public function setFeatured(bool $featured): self

Playlist::getPosition()

public function getPosition(): int

Playlist::setPosition()

public function setPosition(?int $position): self

Playlist::isVisible()

public function isVisible(): bool

Playlist::setVisible()

public function setVisible(bool $visible): self

Release 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(): ?array
public function __toLink(array $routeParameters = [], int $referenceType = UrlGeneratorInterface::ABSOLUTE_PATH): ?string

Release::__construct()

public function __construct(?\Base\Entity\User $owner = null, ?Thread $parent = null, ?string $title = null, ?string $slug = null)

Release::__toString()

public function __toString(): string

Release::getType()

public function getType(): ReleaseType

Release::setType()

public function setType(ReleaseType $type): self

Release::getLabel()

public function getLabel(): ?Label

Release::setLabel()

public function setLabel(?Label $label): self

Release::getLabelUrl()

public function getLabelUrl(): ?string

Release::setLabelUrl()

public function setLabelUrl(?string $labelUrl): self

Release::getCatalogue()

public function getCatalogue(): ?string

Release::setCatalogue()

public function setCatalogue(?string $catalogue): self

Release::getUpc()

public function getUpc(): ?string

Release::setUpc()

public function setUpc(?string $upc): self

Release::getReleasedAt()

public function getReleasedAt(): ?\DateTimeInterface

Release::setReleasedAt()

public function setReleasedAt(?\DateTimeInterface $releasedAt): self

Release::isUpcoming()

public function isUpcoming(): bool

Release::setUpcoming()

public function setUpcoming(bool $upcoming): self

Release::getPresaveUrl()

public function getPresaveUrl(): ?string

Release::setPresaveUrl()

public function setPresaveUrl(?string $presaveUrl): self

Release::getCover()

public function getCover(): ?string

Release::getCoverFile()

public function getCoverFile(): ?File

Release::setCover()

public function setCover($cover): self

Release::hasCover()

public function hasCover(): bool

Release::getCoverUrl()

public function getCoverUrl(): ?string

Release::setCoverUrl()

public function setCoverUrl(?string $coverUrl): self

Release::getArtwork()

public function getArtwork(): ?string

The 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.

public function getLinks(): array
Returns

platform value => URL, as typed in the back office

public function setLinks(?array $links): self
public function setLink(Platform $platform, ?string $url): self
public function getPlatformLinks(): PlatformLinks

Where 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().

public function getLabelLink(): ?PlatformLink

What "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(): ?string

Release::setAwards()

public function setAwards(?string $awards): self

Release::getAwardList()

public function getAwardList(): array

The 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(): Collection

Release::addPerformer()

public function addPerformer(Performer $performer): self

Release::removePerformer()

public function removePerformer(Performer $performer): self

Release::getTracks()

public function getTracks(): Collection

Release::addTrack()

public function addTrack(Track $track): self

Release::removeTrack()

public function removeTrack(Track $track): self

Release::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(): int

How many times the site's player played its tracks, all together.

Release::getDuration()

public function getDuration(): ?int

Seconds, all tracks together; null as long as one has no duration.

Release::isFeatured()

public function isFeatured(): bool

Release::setFeatured()

public function setFeatured(bool $featured): self

Release::isOut()

public function isOut(): bool

Out: not announced only, and its date (when it has one) is behind us.

Release::publish()

public function publish(bool $published = true, ?\DateTimeInterface $at = null): self

Publish 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(): string

Track::getId()

public function getId(): ?int

Track::getRelease()

public function getRelease(): ?Release

Track::setRelease()

public function setRelease(?Release $release): self

Track::getPosition()

public function getPosition(): ?int

Track::setPosition()

public function setPosition(?int $position): self

Track::getDisc()

public function getDisc(): int

Track::setDisc()

public function setDisc(?int $disc): self

Track::getTitle()

public function getTitle(): ?string

Track::setTitle()

public function setTitle(?string $title): self

Track::getWork()

public function getWork(): ?Work

Track::setWork()

public function setWork(?Work $work): self

Track::getMovement()

public function getMovement(): ?string

Track::setMovement()

public function setMovement(?string $movement): self

Track::getDisplayTitle()

public function getDisplayTitle(): string

What the list shows: the title typed, else the work and its movement.

Track::getDuration()

public function getDuration(): ?int

Track::setDuration()

public function setDuration(?int $duration): self

Track::getDurationText()

public function getDurationText(): string

"4:07", "1:02:45"; "" without a duration.

Track::formatDuration()

public static function formatDuration(null|int|float $seconds): string

Seconds as a sleeve prints them: m:ss, h:mm:ss from an hour on.

Track::getIsrc()

public function getIsrc(): ?string

Track::setIsrc()

public function setIsrc(?string $isrc): self

Track::getPreviewUrl()

public function getPreviewUrl(): ?string

Track::setPreviewUrl()

public function setPreviewUrl(?string $previewUrl): self

Track::getSample()

public function getSample(): ?string

Track::getSampleFile()

public function getSampleFile(): ?File

Track::getSampleUrl()

public function getSampleUrl(): ?string

The 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): self

Track::hasSample()

public function hasSample(): bool

Track::isWhole()

public function isWhole(): bool

The 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): self

Track::getPlays()

public function getPlays(): int

Track::hasAudio()

public function hasAudio(): bool

Something an <audio> can play: the site's excerpt or a catalogue's preview.

Track::getPeaks()

public function getPeaks(): ?array

Track::setPeaks()

public function setPeaks(?array $peaks): self

Track::getPerformers()

public function getPerformers(): ?string

Track::setPerformers()

public function setPerformers(?string $performers): self

Track::getAvailableFrom()

public function getAvailableFrom(): ?\DateTimeImmutable

Track::setAvailableFrom()

public function setAvailableFrom(?\DateTimeInterface $availableFrom): self

Track::isOutOn()

public function isOutOn(\DateTimeInterface $day): bool

Whether 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(): ?\DateTimeInterface

The day it will be heard, when that is not yet: its own, else its release's.

Track::getBlockedIn()

public function getBlockedIn(): array

Track::setBlockedIn()

public function setBlockedIn(?iterable $countries): self

Track::isBlockedIn()

public function isBlockedIn(?string $country): bool

Video 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(): ?array
public function __toLink(array $routeParameters = [], int $referenceType = UrlGeneratorInterface::ABSOLUTE_PATH): ?string

Video::__construct()

public function __construct(?\Base\Entity\User $owner = null, ?Thread $parent = null, ?string $title = null, ?string $slug = null)

Video::__toString()

public function __toString(): string

Video::getFile()

public function getFile(): ?string

Video::setFile()

public function setFile($file): self

Video::getYoutubeId()

public function getYoutubeId(): ?string

Video::setYoutubeId()

public function setYoutubeId(?string $youtubeId): self

The id, or any YouTube address holding it (watch?v=, youtu.be/, /embed/, /shorts/, /live/).

Video::getVimeoId()

public function getVimeoId(): ?string

Video::setVimeoId()

public function setVimeoId(?string $vimeoId): self

The id, or a vimeo.com address ending with it.

Video::isLocal()

public function isLocal(): bool

Hosted by the site: a <video>, no third party.

Video::getEmbedUrl()

public function getEmbedUrl(bool $autoplay = true): ?string

The 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(): ?string

Its page on the platform, for a visitor who would rather watch it there.

Video::isPlayable()

public function isPlayable(): bool

Video::getPoster()

public function getPoster(): ?string

Video::getPosterUrl()

public function getPosterUrl(): ?string

The 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(): ?File

Video::setPoster()

public function setPoster($poster): self

Video::getDuration()

public function getDuration(): ?int

Video::setDuration()

public function setDuration(?int $duration): self

Video::getDurationText()

public function getDurationText(): string

Video::isFeatured()

public function isFeatured(): bool

Video::setFeatured()

public function setFeatured(bool $featured): self

Video::getWork()

public function getWork(): ?Work

Video::setWork()

public function setWork(?Work $work): self

Video::getRelease()

public function getRelease(): ?Release

Video::setRelease()

public function setRelease(?Release $release): self

Video::getRecordedAt()

public function getRecordedAt(): ?\DateTimeInterface

Video::setRecordedAt()

public function setRecordedAt(?\DateTimeInterface $recordedAt): self

Video::getVenue()

public function getVenue(): ?string

Video::setVenue()

public function setVenue(?string $venue): self

Video::getPerformers()

public function getPerformers(): Collection

Video::addPerformer()

public function addPerformer(Performer $performer): self

Video::removePerformer()

public function removePerformer(Performer $performer): self

Video::publish()

public function publish(bool $published = true, ?\DateTimeInterface $at = null): self

Publish 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(): string

Work::getId()

public function getId(): ?int

Work::getComposer()

public function getComposer(): ?string

Work::setComposer()

public function setComposer(?string $composer): self

Work::getComposerSortKey()

public function getComposerSortKey(): string

What the composers are sorted by: the last word of the name ("Glière").

Work::getTitle()

public function getTitle(): ?string

Work::setTitle()

public function setTitle(?string $title): self

Work::getOpus()

public function getOpus(): ?string

Work::setOpus()

public function setOpus(?string $opus): self

Work::getFullTitle()

public function getFullTitle(): string

"Harp Concerto in E-flat major, op. 74".

Work::getYear()

public function getYear(): ?int

Work::setYear()

public function setYear(?int $year): self

Work::getInstrumentation()

public function getInstrumentation(): ?string

Work::setInstrumentation()

public function setInstrumentation(?string $instrumentation): self

Work::getFormation()

public function getFormation(): Formation

Work::setFormation()

public function setFormation(Formation $formation): self

Work::getDuration()

public function getDuration(): ?int

Work::setDuration()

public function setDuration(?int $duration): self

Work::getMovements()

public function getMovements(): ?string

Work::setMovements()

public function setMovements(?string $movements): self

Work::getMovementList()

public function getMovementList(): array

Work::getPeriod()

public function getPeriod(): ?Period

Work::setPeriod()

public function setPeriod(?Period $period): self

Work::isVisible()

public function isVisible(): bool

Work::setVisible()

public function setVisible(bool $visible): self

Work::getPosition()

public function getPosition(): int

Work::setPosition()

public function setPosition(?int $position): self

Base\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(): int

The 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(): string

schema.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(): int

Oldest 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 ARTIST = 'artist'

PlaylistKind::rank()

public function rank(): int

The 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(): string

schema.org's albumProductionType / albumReleaseType, for the JSON-LD.

ReleaseType::fromCatalogue()

public static function fromCatalogue(?string $type): self

The 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): void

LinksType::configureOptions()

public function configureOptions(OptionsResolver $resolver): void

LinksType::platforms()

public static function platforms(array $exclude = [Platform::LABEL, Platform::SHOP]): array

The 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): void

TrackType::configureOptions()

public function configureOptions(OptionsResolver $resolver): void

Base\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(): ?Instrument

The 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): ?Label

The 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): ?Playlist

The 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(): array

The 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): array

The 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(): ?Release

The featured release, or the newest one out.

ReleaseRepository::findOnePublished()

public function findOnePublished(string $slug): ?Release

ReleaseRepository::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(): int

The tracks the player has nothing to play for: no excerpt of the site's, no preview.

TrackRepository::countPlay()

public function countPlay(Track $track): void

One more play of a track: added in the database itself, so two listeners at once are two plays.

TrackRepository::countPlays()

public function countPlays(): int

The 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(): ?Video

The featured video, or the newest one.

VideoRepository::findOnePublished()

public function findOnePublished(string $slug): ?Video

VideoRepository::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(): array

WorkRepository::findVisibleGrouped()

public function findVisibleGrouped(string $by = self::BY_FORMATION): array

The 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): array

Base\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): ?array

Why $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): bool

Availability::country()

public function country(): ?string

The visitor's country (ISO 3166, "FR"), null when nothing says it.

Availability::countryOf()

public static function countryOf(?Request $request): ?string

HeroFrame 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): void

HeroFrame::reset()

public function reset(): void

ImportReport 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 $found
public readonly array $filled

the fields that were empty and are not any more

public readonly int $tracksCreated
public readonly int $tracksUpdated
public readonly array $incomplete

the 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 = [])
$filled

the fields that were empty and are not any more

$incomplete

the catalogues that could not be reached: ask again later

ImportReport::isUnavailable()

public function isUnavailable(): bool

Nothing found because a catalogue was down - not because the release does not exist.

ImportReport::changedSomething()

public function changedSomething(): bool

Importer 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(): bool

False when Omnisong's bundle is not registered: there is no catalogue to ask.

Importer::reference()

public function reference(string $value): Reference

What a loose string names (a URL, a UPC/EAN, an ISRC), for the site's country.

Importer::referenceOf()

public function referenceOf(Release $release): ?Reference

What 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): ImportReport

Fills 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): ?Release

One 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 = []): ImportReport

What 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(): ?string

The 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): array

Peaks 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 = 200

How many bars a waveform has.

const RATE = 8000

What 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(): bool

Whether ffmpeg answers (ffmpeg -version); asked once.

Peaks::compute()

public function compute(Track $track, int $count = self::COUNT): bool

Computes 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): array

Raw 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'])
$full

the platforms "Listen in full" offers, in order

Player::full()

public function full(Release $release): array

The 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): bool

Whether "Listen in full" has a platform to offer for the release, without building its iframes.

Player::playlist()

public function playlist(Playlist $playlist): ?Embed

A playlist's (or a profile's) iframe; null when its platform cannot be embedded.

Player::source()

public function source(Track $track): ?array

The 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(): bool

Whether music.player.order lets the embeds in at all.

Player::embed()

public function embed(Release $release, ?Platform $platform = null, ?EmbedOptions $options = null): ?Embed

The 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.

public function embedLink(PlatformLink $link, ?EmbedOptions $options = null): ?Embed

One link's iframe, through Omnisong's Embedder; null when it cannot be embedded.

Player::options()

public function options(): EmbedOptions

The 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 = 20

Seconds 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)
$classifier

Base\Service\Analytics\UserAgentClassifier (classify(?string): string)

Plays::count()

public function count(Track $track, ?string $address, ?string $userAgent): bool

Whether this play was counted.

Plays::isRobot()

public function isRobot(?string $userAgent): bool

PosterPicker 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): bool

Gives $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): float

How 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): \GdImage

The 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(): array

MusicExtension::getFilters()

public function getFilters(): array

MusicExtension::platformIcon()

public static function platformIcon(Platform|string|null $platform): string

The 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): string

Who 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.