Skip to content

07 Customisation

CraigD edited this page Dec 20, 2023 · 9 revisions

If you wish to modify the look or layout of Material, you can do so by placing CSS files within a material-skin/css/ sub-folder of your LMS's prefs folder. These should be named as follows:

  • prefs/material-skin/css/desktop.css
  • prefs/material-skin/css/mobile.css

You may also specify the custom CSS as part of Material's URL, therefore allowing per-device CSS changes. e.g.

  • http://<yourserver>:9000/material/?css=my-phone will use prefs/material-skin/css/my-phone.css as the custom CSS file.

Themes & colours

To install custom themes, place CSS files within a material-skin/themes/dark/ or material-skin/themes/light/ sub-folder of your LMS's prefs folder. For colours, place CSS files within material-skin/colors/ sub-folder. e.g.

  • prefs/material-skin/themes/dark/New-Theme.css
  • prefs/material-skin/colors/pink.css

This will add an New Theme entry to Material's theme selector, and add pink to the colour choice. The format of these files should be based upon one of Material's existing theme, or colour, files.

Backdrops

To install custom backdrops, create browse.jpg, nowplaying.jpg, or queue.jpg within a material-skin/backdrops/sub-folder of your LMS's prefs folder. For colours, place CSS files within material-skin/colors/ sub-folder. e.g.

  • prefs/material-skin/backdrops/browse.jpg for the browse view
  • prefs/material-skin/backdrops/nowplaying.jpg for the nowplaying and MAI views
  • prefs/material-skin/backdrops/queue.jpg for the queue view

Custom menu entries and actions

Material will look for material-skin/actions.json within your LMS's prefs folder. If found, then Material will add the actions from this onto various context menus. This JSON file lists various "sections", and each of these can have a list of actions. The sections are:

  • system will add actions to the top level of the main menu (accessed via the three-dotted icon top right)
  • settings will add actions to the 'Settings' sub-menu of the main menu.
  • server-dialog will add actions to the menu on the server settings dialog.
  • <player MAC address> will add actions to player settings dialog, and player menu in the 'Manager players' dialog, for the specified player.
  • allplayers will add actions as per <player MAC address> but for all players.
  • players will add actions to the main player selection menu. To restrict an action to specific players list player IDs in a "players" array (see example below).
  • artist, album, album-track, genre, year, playlist, and playlist-track will add actions to the context menu of the relevant item type when browsing.
  • track will add actions to the now-playing context menu.
  • queue-track will add actions to the context menu of queue tracks.

This file has the following format:

{
  "system":[
    {
      "title":"A page to embed in Material",
      "iframe":"http://address/to/embed",
      "locked":true,
      "icon":"link",
      "toolbar":{
        "title":"Title \u2022 $NAME"
      }
    },
    {
      "title":"A page to launch in a new window/tab",
      "weblink":"http://some/site"
    },
    {
      "title":"A command to run on the LMS server",
      "command":"ls /tmp/ &",
      "prompt":"Do this command?"
    }
  ],
  "settings":[
    {
      "title":"A settings page",
      "weblink":"http://some/site?lang=$LANG"
    },
  ],
  "server-dialog":[
    {
      "title":"Say Hello",
      "script":"window.alert('Hello')",
      "svg":"hello"
    }
  ],
  "allplayers":[
    {
      "title":"A command to run on the LMS server",
      "command":"echo \"Player MAC:$ID Player Name:$NAME\""
    },
    {
      "title":"A command only shown if browser URL hostname is 127.0.0.1 or localhost",
      "command":"blah_blah",
      "localonly":"true"
    }
  ],
  "players":[
    {
      "title":"A command to run on the LMS server",
      "command":"echo \"Player MAC:$ID Player Name:$NAME\""
    },
    {
      "title":"A command to run on the LMS server, but only for certain players",
      "command":"blah_blah",
      "players":["01:02:03:04:05:06", "aa:bb:cc:dd:ee:ff"]
    }
  ],
  "ab:cd:de:01:02:03":[
    ...
  ],
  "artist":[
    {
      "title":"Dynamic playlists",
      "lmsbrowse":{
        "command":["dynamicplaylist", "mixjive"],
        "params":["artist_id:$ARTISTID"]
      },
      "svg":"dice-list"
    }
  ],
  "album":[
    {
      "title":"Play album",
      "lmscommand":["playlistcontrol", "cmd:load", "album_id:$ALBUMID"],
      "icon":"play"
    }
  ],
  "track":[
    {
      "title":"Show album details",
      "weblink":"http://some/site/$ALBUMID"
    },
    {
      "title":"Copy file location",
      "script":"lmsCommand('$ID', ['status', '-', '1', 'tags:u']).then(({data}) => {copyTextToClipboard(decodeURI(data.result.playlist_loop[0].url));});",
      "icon":"file_copy"
    }
  ],
  "queue-track":[
    {
      "title":"Show image",
      "script":"bus.$emit('dlg.open', 'gallery', [$IMAGE], 0);",
      "icon":"photo"
     }
  ],
  "notifications":[
    {
      "id":"xxx",
      "script":"bus.$emit('showMessage', 'Hello')"
    }
  ]
}

Actions can be trigger one of the following:

  • iframe URLs are loaded within Material (as happens for server settings, etc), and weblink URLs are loaded in a new window (or tab).
  • command is a command to run on the LMS server. NOTE: No validation takes place, and commands are invoked as is. If LMS is on Linux then use & to run a command in the background - otherwise you could stall LMS.
  • script should contain valid javascript and will run in the user's browser.
  • lmscommand should be a JSONRPC command.
  • Likewise, lmsbrowse should be a JSONRPC command which will produce a list of items. lmsbrowse has command and params parts; LMS list commands have a start position and count argument. lmsbrowse will build the full JSONRCP command as follows: [lmsbrowse.command, 0, 25000, lmsbrowse.params]

"locked":true will hide the action until the password entered in Material's settings page matches that set in the Material Skin server settings.

icon can be set to the name of an icon from the Material icon font. See https://material.io/resources/icons/?style=baseline for a list of icons that can be used.

If icon is not set, then svg maybe used to specify an SVG image instead. This should be the SVG filename without path or extension. Either a Material shipped SVG can be used, or an SVG file installed into material-skin/images/ within your LMS's prefs folder. Material will recolour any #000 fill or stroke in the SVG with Material's text colour.

Set prompt to a query string to confirm with the user whether to perform the action or not.

toolbar:title may be used to specify the title shown in Material's toolbar when using an embedded iframe.

$ID will be replaced by the player's ID (its MAC address), and $NAME will be replaced by the player's name.

$HOST will be replaced with the hostname from the page's URL (i.e. window.location.hostname)

$LANG will be replaced with LMS's language setting.

$ARTISTID, $ARTISTNAME, $ALBUMID, $ALBUMNAME, $TRACKID, $TRACKNAME, $TRACKNUM, $DISC, $GENREID, $GENRENAME, $COMPOSER, $CONDUCTOR, $BAND, $YEAR, and $IMAGE will be replaced with the relevant track details. Please note that some (e.g. $COMPOSER, $CONDUCTOR, $BAND) will only be accessible from the now-playing context menu.

If you have multiple players, then player actions will be accessible from the 'Manage players' dialog. Player actions will be listed in the menu accessible from the Player settings dialog toolbar.

The notifications section is for actions invoked from notifications and is described later on. These actions have an id parameter instead of title as they are linked via id and no title is ever shown.

Custom javascript

Material, as of v1.9.0, can also load a user-created Javascript file. To use this, place your javascript in:

  • prefs/material-skin/custom.js

Custom window title

By default Material use 'Logitech Media Server' as its window title. This can be overridden (as of 2.6.1) by specifying alternatives in Material's server-side preference file - prefs/plugin/material-skin.prefs - e.g.

windowTitle: 'Alternative Title'
shortTitle: 'ST'

Hiding LMS settings sections

To hide an LMS setting section you need to know the ID of an element within the section. Material will then traverse its parents until the settingSection is found - and then this is removed from the DOM. IDs are specified in Material's server-side preference file - prefs/plugin/material-skin.prefs - as a comma separated list - e.g. the following would hide the media dirs section:

hideSettings: 'mediadirs1'