Closed aesculus closed 3 years ago
Yes please provide details on how to achieve this. This would be a nice feature to include in Squeezer.
OK. Easiest feature request you will ever see. Turns out I was able to do it on my side. I still have some issues getting icons in the menu supported so I may need some help there.
But I do have a question for you: You have your choice of the plugin menu appearing in one of two places: It can go into the Extra menu or the Settings menu.
The purpose of the plugin menu is to allow the user to control some of the amplifiers audio settings during playback. Such items as surround sound mode, dynamic volume, room equalizer etc.
Good to hear that you got it working.
I suppose most users would expect these kind of controls to go into the Settings menu, so this is what I prefer.
Let me know if you need any help with the icons.
Here's a thread for another plugin developer, which had icon issues. Maybe it has helpful information: nikclayton/android-squeezer/issues/681
OK. For V4 of the plugin I am pretty sure I can support the plugin menus with the Squeezer Settings menu. So far my tests have proven OK.
However none of the menu's show any of the icons. In the case of the main icon just a blank icon shows. For the menu icons there is no blank icon placeholder.
I reviewed the link you sent above and that is not my problem. My plugin follows the html path and there are also no errors in the server.log file.
Here is what I would like for you to test if you can. You probably don't have a Denon or Marrantz AVR so we will have to hack the code in order for you to show the menus.
Install V3 of the DenonAvpControl plugin via the Plugins tab in the Settings of the LMS
It should prompt you to restart LMS
Go to a player in Settings and choose the DenonAVP/AVRControl pulldown on the player
Enter a fake ip address on your network since it won't find a AVR
Make sure Main zone is selected
Select: Enable audio settings menus
Make sure the Enable Plugin is selected.
Select Apply
Now you will need to modify a few lines of code in the plugin on your LMS server
Go to where the plugin is installed and edit Plugin.pm
Look for line 210 and change 'settingsPlayer' to 'settings'
Comment out lines 252-255
Note that line 249 is the reference to the main menu icon. Lets start with this one
Save the file.
Now restart LMS
Once LMS is running load Squeezer and turn on the selected player the plugin is assigned to
You should see DenonAVP/AVRControl in the list in Settings
Note the icon will probably be blank.
You will probably get all sorts of errors from the plugin because there is no response to various requests but I am hoping this will not interfere with the test to load the plugin menu.
I have now tried the plugin.
The reason there is no icon in the settings menu, and no icon placeholder is because of this structure returned by the plugin:
{
"text": "DenonAvpControl",
"id": "pluginDenonAvpControl",
"menuIcon": "plugins/DenonAvpControl/html/images/audysseysettings.png",
"actions": {
"go": {
"cmd": [
"avpTop"
],
"player": 0
}
},
"node": "settings",
"weight": 9
}
Squeezer looks for an "icon" or an "icon-id" in this structure. If that is not found it looks for those in a "window" structure inside this structure. In this case there is a "menuIcon" which we don't look for.
In order for Squeezer to use a list with icons, there must to be a window structure either in the structure above, or in the top level of the response data when executing the go action. This window structure has to have a "windowStyle" entry with value "home_menu" or "icon_list", i.e: "window": { "windowStyle": "icon_list" }
.
As a test i extended Squeezer to look for "menuIcon" and "menuIconID", and forced the icon_list layout. The results are below, and shows an issue when the dark theme (the default) is selected. I don't know what to do about that. Maybe check how the spotty does, it has similar icons.
Also the menuIconID icons doesn't show. I included a log-line below.
2021-04-03 18:42:14.378 12983-13042/uk.org.ngo.squeezer E/ImageFetcher: Error in downloadUrlToStream - http://10.0.2.2:9000/dynamicplaylist: java.io.FileNotFoundException: http://10.0.2.2:9000/dynamicplaylist
Thanks for the info. The iPeng app in iOS uses a different structure. I will have to add and adopt for your means.
I was able to force the main icon by using "icon" instead of menuIcon but interestingly using just icon failed in the load because it was a reserved name. Also this failed to work for the sub menu icons using the url scheme.
I think the icon-ids may not be working because I suspect those were specific to iPeng so I will need to create similar icons for you.
On that aspect can you point me to the specs you want an icon to be? Also I only have light icons. Do you have a separate tag to assign to the dark icons?
Making some progress here. I snagged an example icon from Spotty so I know what the characteristics are. I used that icon in the main plugin title and also used another in each of the menu items.
I used the format: "icon: => $icon
where $icon points to the png file within the html.
It shows in the Settings just fine with the plugin name and also when the Plugin menu appears with the title of the plugin.
But each item within the plugin menu does not have an icon or an icon placeholder. But if I select each item then the icon that is supposed to be in the menu list IS in the title for that menu function.
So my question is: What key do you use to display an icon in a sub menu title? It does not appear to be "icon".
There should be no special requirements for Squeezer. All I have is this documentation for the sub.menus: https://wiki.slimdevices.com/index.php/SBS_SqueezePlay_interface This defines the icon/icon-id i mentioned. It also defines the window fields. The "windowStyle": "icon_list" is not documented. I think this is the preferred method now. However I also support "menuStyle": "album", which is mentioned in the above documentation.
For the home menu items, in this case the Denon menu entry in the settings menu, I have this: https://wiki.slimdevices.com/index.php/SqueezePlayAndSqueezeCenterPlugins.html This doesn't define anything about the icons, so I use the same semantics as for the sub-menus. Some standard menu entries does not return an icon. For those I've had to embed the icon in the Squeezer app, mapped via the id-field of the menu item.
Here's an example of the structure returned from a "standard" entry in the settings menu:
{
"node": "settings",
"weight": 1,
"text": "Don't Stop The Music",
"id": "settingsDontStopTheMusic",
"window": {
"icon-id": "plugins/DontStopTheMusic/html/images/icon.png"
},
"actions": {
"go": {
"cmd": [
"dontstopthemusicsetting"
],
"player": 0
}
}
}
I don't know about icon specs. For the size I think 512x512, will look OK in all layouts. About the colour I'm not aware of any mechanism to control whether to get light or dark icons. Maybe use a color or shade which works on both a light and a dark background.
I will try the window technique but I think I get the same results doing it the way I am.
Can you look at the Audio menu in Settings? It has a sub menu with icons too, but interestingly on my phone the icons are not showing. I would like my menu too look like the Audio menu should.
I would like to know what structure this has.
Sure, here is the structure for the Audio menu. I don't think it applies to your use case, because it's included in the response from the "menu" command, documented in the home item items link above. Look for "node": "settingsAudio" entries. This also explains why there is no icons, I'm apparently supposed to embed the icons in the app, and hardcode them to the id (or iconStyle).
I also included the response for the spotty top menu, which is a plugin like yours.
They're quite long, so I tried to fold them, hope all the info is there.
Home menu:
{ "data": { "item_loop": [ { "text": "My Music", "weight": 11, "id": "myMusic", "isANode": 1, "node": "home" }, { "weight": 100, "id": "favorites", "node": "home", "actions": { "go": { "params": { "menu": "favorites" }, "cmd": [ "favorites", "items" ] } }, "text": "Favorites" }, { "node": "home", "id": "opmlappgallery", "weight": 90, "uuid": "855EC660-D604-4B08-B06C-E6991DA83D34", "window": { "icon-id": "plugins/AppGallery/html/images/icon.png", "titleStyle": "album" }, "displayWhenOff": 0, "actions": { "go": { "cmd": [ "appgallery", "items" ], "player": 0, "params": { "menu": "appgallery" } } }, "text": "App Gallery" }, { "id": "settingsDontStopTheMusic", "node": "settings", "actions": { "go": { "player": 0, "cmd": [ "dontstopthemusicsetting" ] } }, "weight": 1, "window": { "icon-id": "plugins/DontStopTheMusic/html/images/icon.png" }, "text": "Don't Stop The Music" }, { "displayWhenOff": 0, "window": { "icon-id": "plugins/ExtendedBrowseModes/html/icon.png", "titleStyle": "album" }, "uuid": "6e5e0a00-e18a-11e3-8b68-0800200c9a66", "weight": 100, "id": "opmlselectVirtualLibrary", "node": "myMusic", "text": "Library Views", "actions": { "go": { "cmd": [ "selectVirtualLibrary", "items" ], "params": { "menu": "selectVirtualLibrary" }, "player": 0 } } }, { "node": "extras", "id": "opmlimagebrowser", "weight": 1000, "uuid": "e102b4d0-b86a-11e0-aff2-0800200c9a66", "window": { "titleStyle": "album", "icon-id": "plugins/ImageBrowser/html/images/icon.png" }, "displayWhenOff": 0, "actions": { "go": { "cmd": [ "imagebrowser", "items" ], "params": { "menu": "imagebrowser" }, "player": 0 } }, "text": "Image Browser" }, { "weight": 80, "uuid": "2E3ACD53-B9A8-4440-9C5B-517B1EB28E34", "id": "opmlmyapps", "node": "home", "displayWhenOff": 0, "window": { "titleStyle": "album", "icon-id": "plugins/MyApps/html/images/icon.png" }, "actions": { "go": { "player": 0, "params": { "menu": "myapps" }, "cmd": [ "myapps", "items" ] } }, "text": "My Apps" }, { "weight": 110, "uuid": "21865f76-C204-475C-B46E-50370DAC7EDE", "id": "opmlselectRemoteLibrary", "node": "myMusic", "displayWhenOff": 0, "window": { "titleStyle": "album", "icon-id": "plugins/RemoteLibrary/html/icon.png" }, "actions": { "go": { "cmd": [ "selectRemoteLibrary", "items" ], "player": 0, "params": { "menu": "selectRemoteLibrary" } } }, "text": "Remote Music Libraries" }, { "id": "settingsRescan", "node": "advancedSettings", "actions": { "go": { "player": 0, "cmd": [ "rescanplugin", "menu" ] } }, "text": "Rescan Music Library" }, { "text": "Random Mix", "window": { "titleStyle": "random" }, "windowStyle": "text_list", "weight": 60, "id": "randomplay", "isANode": 1, "node": "myMusic" }, { "text": "Stop Random Mix", "weight": 100, "nextWindow": "refresh", "style": "itemplay", "id": "randomdisable", "node": "randomplay", "actions": { "play": { "cmd": [ "randomplay", "disable" ], "player": 0 }, "go": { "player": 0, "cmd": [ "randomplay", "disable" ] } } }, { "id": "randomchooselibrary", "node": "randomplay", "actions": { "go": { "cmd": [ "randomplaylibrarylist" ], "player": 0 } }, "weight": 55, "window": { "titleStyle": "random" }, "text": "Use library view" }, { "id": "randomchoosegenres", "actions": { "go": { "cmd": [ "randomplaygenrelist" ], "player": 0 } }, "node": "randomplay", "weight": 50, "window": { "titleStyle": "random" }, "text": "Choose Genres" }, { "text": "Year Mix", "style": "itemplay", "nextWindow": "nowPlaying", "weight": 40, "id": "randomyears", "node": "randomplay", "actions": { "go": { "player": 0, "cmd": [ "randomplay", "year" ] }, "play": { "cmd": [ "randomplay", "year" ], "player": 0 } } }, { "text": "Artist Mix", "node": "randomplay", "id": "randomartists", "actions": { "go": { "cmd": [ "randomplay", "contributors" ], "player": 0 }, "play": { "cmd": [ "randomplay", "contributors" ], "player": 0 } }, "style": "itemplay", "nextWindow": "nowPlaying", "weight": 30 }, { "text": "Album Mix", "id": "randomalbums", "node": "randomplay", "actions": { "go": { "cmd": [ "randomplay", "albums" ], "player": 0 }, "play": { "cmd": [ "randomplay", "albums" ], "player": 0 } }, "style": "itemplay", "nextWindow": "nowPlaying", "weight": 20 }, { "text": "Song Mix", "id": "randomtracks", "node": "randomplay", "actions": { "play": { "player": 0, "cmd": [ "randomplay", "tracks" ] }, "go": { "cmd": [ "randomplay", "tracks" ], "player": 0 } }, "nextWindow": "nowPlaying", "weight": 10, "style": "itemplay" }, { "window": { "titleStyle": "album", "icon-id": "/plugins/TuneIn/html/images/radiopresets.png" }, "displayWhenOff": 0, "id": "opmlpresets", "node": "radios", "uuid": null, "weight": 5, "text": "My Presets", "actions": { "go": { "cmd": [ "presets", "items" ], "params": { "menu": "presets" }, "player": 0 } } }, { "text": "Local", "actions": { "go": { "player": 0, "params": { "menu": "local" }, "cmd": [ "local", "items" ] } }, "displayWhenOff": 0, "window": { "titleStyle": "album", "icon-id": "/plugins/TuneIn/html/images/radiolocal.png" }, "uuid": null, "weight": 20, "id": "opmllocal", "node": "radios" }, { "uuid": null, "weight": 30, "node": "radios", "id": "opmlmusic", "displayWhenOff": 0, "window": { "titleStyle": "album", "icon-id": "/plugins/TuneIn/html/images/radiomusic.png" }, "actions": { "go": { "cmd": [ "music", "items" ], "params": { "menu": "music" }, "player": 0 } }, "text": "Music" }, { "actions": { "go": { "params": { "menu": "news" }, "player": 0, "cmd": [ "news", "items" ] } }, "text": "News", "id": "opmlnews", "node": "radios", "weight": 45, "uuid": null, "window": { "icon-id": "/plugins/TuneIn/html/images/radionews.png", "titleStyle": "album" }, "displayWhenOff": 0 }, { "text": "Sports", "actions": { "go": { "cmd": [ "sports", "items" ], "player": 0, "params": { "menu": "sports" } } }, "window": { "icon-id": "/plugins/TuneIn/html/images/radiosports.png", "titleStyle": "album" }, "displayWhenOff": 0, "id": "opmlsports", "node": "radios", "uuid": null, "weight": 40 }, { "window": { "titleStyle": "album", "icon-id": "/plugins/TuneIn/html/images/radiotalk.png" }, "displayWhenOff": 0, "node": "radios", "id": "opmltalk", "uuid": null, "weight": 50, "text": "Talk", "actions": { "go": { "cmd": [ "talk", "items" ], "params": { "menu": "talk" }, "player": 0 } } }, { "displayWhenOff": 0, "window": { "titleStyle": "album", "icon-id": "/plugins/TuneIn/html/images/radioworld.png" }, "uuid": null, "weight": 60, "node": "radios", "id": "opmlworld", "text": "World", "actions": { "go": { "params": { "menu": "world" }, "player": 0, "cmd": [ "world", "items" ] } } }, { "text": "By Language", "actions": { "go": { "player": 0, "params": { "menu": "language" }, "cmd": [ "language", "items" ] } }, "displayWhenOff": 0, "window": { "titleStyle": "album", "icon-id": "/plugins/TuneIn/html/images/radioworld.png" }, "uuid": null, "weight": 56, "id": "opmllanguage", "node": "radios" }, { "actions": { "go": { "params": { "menu": "search", "search": "__TAGGEDINPUT__" }, "player": 0, "cmd": [ "search", "items" ] } }, "text": "Search", "input": { "softbutton2": "Delete", "help": { "text": "Use the scroll wheel to change letters, then press the center button to select that letter. Press the center button again to start your search." }, "title": "Search", "processingPopup": { "text": "Searching..." }, "len": 1, "softbutton1": "Insert" }, "node": "radios", "id": "opmlsearch", "uuid": null, "weight": 110, "window": { "titleStyle": "album", "icon-id": "/plugins/TuneIn/html/images/radiosearch.png" }, "displayWhenOff": 0 }, { "displayWhenOff": 0, "window": { "titleStyle": "album", "icon-id": "/plugins/TuneIn/html/images/podcasts.png" }, "uuid": null, "weight": 70, "node": "radios", "id": "opmlpodcast", "text": "Podcasts", "actions": { "go": { "cmd": [ "podcast", "items" ], "params": { "menu": "podcast" }, "player": 0 } } }, { "uuid": null, "weight": 10, "id": "opmlpicks", "node": "radios", "displayWhenOff": 0, "window": { "titleStyle": "album", "icon-id": "http://www.mysqueezebox.com/static/images/icons/picks.png" }, "actions": { "go": { "cmd": [ "picks", "items" ], "player": 0, "params": { "menu": "picks" } } }, "text": "Staff Picks" }, { "id": "playerpower", "actions": { "do": { "player": 0, "cmd": [ "power", 0 ] } }, "node": "home", "weight": 100, "text": "Turn Off Lounge Squeezebox" }, { "text": "Audio", "weight": 35, "node": "settings", "id": "settingsAudio", "isANode": 1 }, { "weight": 20, "choiceStrings": [ "Off", "Song", "Playlist" ], "selectedIndex": 1, "id": "settingsRepeat", "node": "settings", "actions": { "do": { "choices": [ { "cmd": [ "playlist", "repeat", "0" ], "player": 0 }, { "player": 0, "cmd": [ "playlist", "repeat", "1" ] }, { "cmd": [ "playlist", "repeat", "2" ], "player": 0 } ] } }, "text": "Repeat" }, { "text": "Shuffle", "actions": { "do": { "choices": [ { "cmd": [ "playlist", "shuffle", "0" ], "player": 0 }, { "player": 0, "cmd": [ "playlist", "shuffle", "1" ] }, { "cmd": [ "playlist", "shuffle", "2" ], "player": 0 } ] } }, "id": "settingsShuffle", "node": "settings", "selectedIndex": 1, "weight": 10, "choiceStrings": [ "Off", "Song", "Album" ] }, { "id": "settingsAlarm", "node": "settings", "actions": { "go": { "player": 0, "cmd": [ "alarmsettings" ] } }, "weight": 29, "text": "Alarm Clock" }, { "actions": { "go": { "player": 0, "cmd": [ "jivefixedvolumesettings" ] } }, "iconStyle": "hm_settingsAudio", "id": "settingsFixedVolume", "node": "settingsAudio", "weight": 100, "text": "Fixed Volume" }, { "text": "Sleep", "weight": 65, "id": "settingsSleep", "actions": { "go": { "player": 0, "cmd": [ "sleepsettings" ] } }, "node": "settings" }, { "text": "Synchronize", "weight": 70, "node": "settings", "id": "settingsSync", "actions": { "go": { "player": 0, "cmd": [ "syncsettings" ] } } }, { "text": "Squeezebox Information", "weight": 100, "actions": { "go": { "params": { "menu": 1 }, "cmd": [ "systeminfo", "items" ] } }, "node": "advancedSettings", "id": "settingsInformation" }, { "text": "Squeezebox Name", "node": "settings", "id": "settingsPlayerNameChange", "actions": { "do": { "cmd": [ "name" ], "params": { "playername": "__INPUT__" }, "player": 0 } }, "input": { "initialText": "Lounge Squeezebox", "len": 1, "softbutton1": "Insert", "help": { "text": "Use the scroll wheel to change letters, then press the center button to select that letter. Press the center button again to change the name of your player." }, "softbutton2": "Delete", "allowedChars": " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()_+{}|:\\\"'<>?-=,./~`[];0123456789" }, "weight": 67 }, { "iconStyle": "hm_settingsAudio", "node": "settingsAudio", "id": "settingsXfade", "actions": { "go": { "cmd": [ "crossfadesettings" ], "player": 0 } }, "weight": 30, "text": "Crossfade" }, { "actions": { "go": { "player": 0, "cmd": [ "replaygainsettings" ] } }, "id": "settingsReplayGain", "node": "settingsAudio", "iconStyle": "hm_settingsAudio", "weight": 40, "text": "Volume Adjustment" }, { "text": "Last.fm Audioscrobbler", "weight": 100, "id": "audioscrobbler", "node": "advancedSettings", "actions": { "go": { "cmd": [ "audioscrobbler", "settings" ], "player": 0 } } }, { "text": "Radio", "window": { "menuStyle": "album" }, "weight": 20, "actions": { "go": { "params": { "menu": "radio" }, "cmd": [ "radios" ] } }, "node": "home", "id": "radios" }, { "text": "Albums Sort Method", "weight": 105, "node": "advancedSettings", "id": "settingsAlbumSettings", "actions": { "go": { "params": { "menu": "radio" }, "cmd": [ "jivealbumsortsettings" ] } }, "iconStyle": "hm_advancedSettings" }, { "actions": { "go": { "params": { "role_id": "ALBUMARTIST", "menu": 1, "mode": "artists" }, "cmd": [ "browselibrary", "items" ] } }, "id": "myMusicArtistsAlbumArtists", "node": "myMusic", "weight": 9, "homeMenuText": "Browse Album Artists", "icon": "html/images/artists.png", "text": "Album Artists" }, { "weight": 20, "id": "myMusicAlbums", "node": "myMusic", "actions": { "go": { "params": { "menu": 1, "mode": "albums" }, "cmd": [ "browselibrary", "items" ] } }, "text": "Albums", "homeMenuText": "Browse Albums" }, { "text": "New Music", "homeMenuText": "New Music", "weight": 50, "id": "myMusicNewMusic", "actions": { "go": { "cmd": [ "browselibrary", "items" ], "params": { "sort": "new", "wantMetadata": "1", "menu": 1, "mode": "albums" } } }, "node": "myMusic" }, { "text": "Search", "weight": 90, "actions": { "go": { "params": { "mode": "search", "menu": 1 }, "cmd": [ "browselibrary", "items" ] } }, "id": "myMusicSearch", "node": "myMusic" }, { "text": "All Artists", "icon": "html/images/artists.png", "homeMenuText": "All Artists", "weight": 11, "node": "myMusic", "actions": { "go": { "cmd": [ "browselibrary", "items" ], "params": { "role_id": "ALBUMARTIST,ARTIST,BAND,COMPOSER,CONDUCTOR,TRACKARTIST", "mode": "artists", "menu": 1 } } }, "id": "myMusicArtistsAllArtists" }, { "id": "myMusicArtistsComposers", "actions": { "go": { "cmd": [ "browselibrary", "items" ], "params": { "role_id": "2", "menu": 1, "mode": "myMusicArtistsComposers" } } }, "node": "myMusic", "weight": "12", "homeMenuText": "Composers", "icon": "html/images/artists.png", "text": "Composers" }, { "weight": 40, "node": "myMusic", "id": "myMusicYears", "actions": { "go": { "params": { "mode": "years", "menu": 1 }, "cmd": [ "browselibrary", "items" ] } }, "text": "Years", "homeMenuText": "Browse Years" }, { "icon": "html/images/albums.png", "text": "Compilations", "homeMenuText": "Compilations", "weight": 22, "node": "myMusic", "id": "myMusicAlbumsVariousArtists", "actions": { "go": { "params": { "artist_id": "2473", "menu": 1, "mode": "vaalbums" }, "cmd": [ "browselibrary", "items" ] } } }, { "weight": 70, "actions": { "go": { "cmd": [ "browselibrary", "items" ], "params": { "mode": "bmf", "menu": 1 } } }, "node": "myMusic", "id": "myMusicMusicFolder", "text": "Music Folder", "homeMenuText": "Music Folder" }, { "weight": 30, "node": "myMusic", "actions": { "go": { "params": { "menu": 1, "mode": "genres" }, "cmd": [ "browselibrary", "items" ] } }, "id": "myMusicGenres", "text": "Genres", "homeMenuText": "Browse Genres" }, { "node": "myMusic", "id": "myMusicPlaylists", "actions": { "go": { "cmd": [ "browselibrary", "items" ], "params": { "mode": "playlists", "menu": 1 } } }, "weight": 80, "homeMenuText": "Playlists", "text": "Playlists" }, { "text": "Deezer", "actions": { "go": { "params": { "menu": "deezer" }, "player": 0, "cmd": [ "deezer", "items" ] } }, "isApp": 1, "displayWhenOff": 0, "window": { "icon-id": "https://www.mysqueezebox.com/static/images/icons/deezer.png", "titleStyle": "album" }, "uuid": "5B30DC4B-FACD-455D-8385-D0B030DED8A7", "weight": 25, "id": "opmldeezer", "node": "" }, { "weight": 26, "node": "", "id": "opmlradiotime", "isApp": 1, "displayWhenOff": 0, "window": { "icon-id": "https://www.mysqueezebox.com/static/images/icons/tuneinradio.png" }, "actions": { "go": { "params": { "opml_url": "http://opml.radiotime.com/Index.aspx?username=kaaholst@gmail.com&partnerId=16", "menu": "opml_generic" }, "player": 0, "cmd": [ "opml_generic", "items" ] } }, "text": "TuneIn Radio" }, { "actions": { "go": { "player": 0, "params": { "menu": "spotty" }, "cmd": [ "spotty", "items" ] } }, "text": "Spotty", "id": "opmlspotty", "node": "", "stringToken": null, "uuid": "21cbb80e-67b8-44a8-a662-21c6c7ae5260", "weight": 27, "window": { "titleStyle": "album", "icon-id": "plugins/Spotty/html/images/93aac68fb06348598c1e67734dfaceee.png" }, "displayWhenOff": 0, "isApp": 1 }, { "displayWhenOff": 0, "isApp": 1, "window": { "icon-id": "https://www.mysqueezebox.com/static/images/icons/bbc.png" }, "weight": 28, "node": "", "id": "opmlbbc", "text": "BBC", "actions": { "go": { "cmd": [ "opml_generic", "items" ], "params": { "menu": "opml_generic", "opml_url": "https://www.mysqueezebox.com/api/bbc/v1/opml" }, "player": 0 } } }, { "actions": { "go": { "cmd": [ "globalsearch", "items" ], "params": { "search": "__TAGGEDINPUT__", "menu": "globalsearch" } } }, "homeMenuText": "Search", "text": "Search", "node": "home", "id": "globalSearch", "input": { "help": { "text": "Use the scroll wheel to change letters, then press the center button to select that letter. Press the center button again to start your search." }, "processingPopup": { "text": "Searching..." }, "len": 1 }, "weight": 22, "window": { "text": "Search" } } ], "count": 59, "offset": 0 }, "ext": { "priority": "" }, "id": "47", "channel": "/0e1a126d/slim/request/4" }
Spotty top menu:
{ "ext": { "priority": "" }, "data": { "offset": 0, "count": 12, "window": { "windowStyle": "home_menu" }, "item_loop": [ { "addAction": "go", "icon": "plugins/Spotty/html/images/home.png", "text": "Home", "type": "link", "actions": { "go": { "cmd": [ "spotty", "items" ], "params": { "item_id": "0", "menu": "spotty" } } } }, { "addAction": "go", "icon": "plugins/Spotty/html/images/search.png", "text": "Search", "type": "link", "actions": { "go": { "cmd": [ "spotty", "items" ], "params": { "item_id": "1", "menu": "spotty" } } } }, { "addAction": "go", "icon": "plugins/Spotty/html/images/news.png", "text": "What's New", "type": "link", "actions": { "go": { "cmd": [ "spotty", "items" ], "params": { "item_id": "2", "menu": "spotty" } } } }, { "icon": "plugins/Spotty/html/images/toptracks.png", "text": "Top Tracks", "params": { "item_id": "3", "isContextMenu": 1 }, "type": "playlist" }, { "addAction": "go", "icon": "plugins/Spotty/html/images/genres.png", "text": "Genres and Moods", "type": "link", "actions": { "go": { "cmd": [ "spotty", "items" ], "params": { "item_id": "4", "menu": "spotty" } } } }, { "addAction": "go", "icon": "plugins/Spotty/html/images/inbox.png", "text": "Nattens bedste musik", "actions": { "go": { "cmd": [ "spotty", "items" ], "params": { "item_id": "5", "menu": "spotty" } } } }, { "icon": "plugins/Spotty/html/images/playlist.png", "text": "Songs", "params": { "item_id": "6", "isContextMenu": 1 }, "type": "playlist" }, { "addAction": "go", "icon": "plugins/Spotty/html/images/album.png", "text": "Albums", "type": "link", "actions": { "go": { "cmd": [ "spotty", "items" ], "params": { "item_id": "7", "menu": "spotty" } } } }, { "addAction": "go", "icon": "plugins/Spotty/html/images/artist.png", "text": "Artists", "type": "link", "actions": { "go": { "cmd": [ "spotty", "items" ], "params": { "item_id": "8", "menu": "spotty" } } } }, { "addAction": "go", "icon": "plugins/Spotty/html/images/playlist.png", "text": "Playlists", "type": "link", "actions": { "go": { "cmd": [ "spotty", "items" ], "params": { "item_id": "9", "menu": "spotty" } } } }, { "addAction": "go", "icon": "plugins/Spotty/html/images/podcasts.png", "text": "Podcasts", "type": "link", "actions": { "go": { "cmd": [ "spotty", "items" ], "params": { "item_id": "10", "menu": "spotty" } } } }, { "addAction": "go", "icon": "plugins/Spotty/html/images/playlist.png", "text": "Transfer Playback", "type": "link", "actions": { "go": { "cmd": [ "spotty", "items" ], "params": { "item_id": "11", "menu": "spotty" } } } } ], "base": { "actions": { "add": { "itemsParams": "params", "cmd": [ "spotty", "playlist", "add" ], "params": { "menu": "spotty" }, "player": 0 }, "play": { "itemsParams": "params", "cmd": [ "spotty", "playlist", "play" ], "params": { "menu": "spotty" }, "nextWindow": "nowPlaying", "player": 0 }, "more": { "itemsParams": "params", "window": { "isContextMenu": 1 }, "cmd": [ "spotty", "items" ], "params": { "menu": "spotty" }, "player": 0 }, "go": { "itemsParams": "params", "cmd": [ "spotty", "items" ], "params": { "menu": "spotty" } }, "add-hold": { "itemsParams": "params", "cmd": [ "spotty", "playlist", "insert" ], "params": { "menu": "spotty" }, "player": 0 }, "playControl": { "itemsParams": "playControlParams", "window": { "isContextMenu": 1 }, "cmd": [ "spotty", "items" ], "params": { "useContextMenu": "1", "_index": "0", "_quantity": "50", "menu": "spotty" }, "player": 0 } } } }, "channel": "/522668d7/slim/request/3", "id": "25" } ```
Thanks for the details. Unfortunately I don't have a Spotify account so can't test Spotty beyond the title. :-(
Anyway I can use the materials you attached and try various techniques and see what results. So far "icon" and "icon-id" see to net the same results. Have not tried the windows techniques yet.
Also interesting is that I made a new main icon. When the app first loaded it was a shell but going into the menu the icon appeared and then was good in the Settings menu too after. Maybe a timing thing.
I have tried all the various techniques to display the icons. I have made all new icons. All show up in the app in the panel titles and in the Settings menu, but the menu of my plugin doesn't show the icons in the menu.
Attached is all the files needed. You will need to unzip these and place them in the plugin cache as above and set line 268 in Plugin.pm to true to get the menu to load on your system.
Can you tell me why the icons are not appearing in the menu?
I managed to show the icons in the menu by adding this at line 382 in Plugin.pm: $request->addResult("window", { "windowStyle" => "icon_list" }); I don't know if this a proper way to do it, but I hope this helps. Note that the user can select large artwork in the view menu, which gives the second screenshot.
That was the ticket. :-)
I noticed that command in one of the samples you provided before but had no idea what it did. Now we know.
Job done. Thank you so much.
Just in case you see this comment: Have you ever seen a menu item that was disabled? I am trying to programmatically enable and disable plugin menu items but am not aware of how to do that. Not certain how to set the state.
To my knowledge there is no concept of disabled menu items in https://wiki.slimdevices.com/index.php/SqueezePlayAndSqueezeCenterPlugins. If you mean an item which should not be displayed in the app, I would except the item to just not be in the response. If you mean an item which is only displayed (i.e can not be selected) you can add an item with no "go" or "do" action. Or maybe you meant something else?
Note:
Thanks for looking into this for me. I found the same results but was hoping you might have come across something different. I guess the developers did not think this was a needed feature.
In my case I have a item within one menu that toggles the ability for another menu item to be relevant. So today if that state is not set I just don't show the related menu item in the main plugin menu list. This to me is wrong since that feature is still there, just not relevant and the moment.
I looked at other PERL examples and they had "state=>disabled" but alas this does nothing in the plugin menus.
So I am thinking of changing my menu so the major items are always showing but if you wander into the menu that is irrelevant it will be empty. I can add a small note to it as you suggest in the "textarea" that the current state for that item is off.
What you suggest, I think will work.
If we are talking about the menu items which are created in "sub avpTop", I think we have another option. If you omit the "go => { ... }" block (or the whole actions => { .. }" block), Squeezer will display a disabled menu item.
To have the menu reloaded when the ability is toggled, you can use the nextWindow property.
These behaviours are defined here: https://wiki.slimdevices.com/index.php/SBS_SqueezePlay_interface
That is interesting about just leaving the 'go' empty. That certain takes away the action.
Now I would need to find a way to gray out the text. That I think is achievable.
I did code up the ability to remove the sub menu items on the fly and have the plugin dynamically ask for it's menu to rebuilt when the state changes to a certain value. I spotted this on your post 2 above.
# update the plugin menu
$log->debug("Refreshing menus after DynEq setting");
Slim::Control::Jive::refreshPluginMenus($client);
Now I would need to find a way to gray out the text. That I think is achievable.
Maybe I should fix this on my end. I recently updated the library to display lists, and apparently this feature got lost in the translation.
I did code up the ability to remove the sub menu items on the fly and have the plugin dynamically ask for it's menu to rebuilt when the state changes to a certain value. I spotted this on your post 2 above
Does this work? I would suspect that this code uses sends "menustatus" command, which Squeezer uses for the home menu (https://wiki.slimdevices.com/index.php/SqueezePlayAndSqueezeCenterPlugins). To make Squeezer reload plugin menus use the nextWindow (refresh, parent, refreshOrigin) property, defined here. (https://wiki.slimdevices.com/index.php/SBS_SqueezePlay_interface#.3Citem_fields.3E)
Slim::Control::Jive::refreshPluginMenus($client);
works great with Squeezer. I change a parameter in the go of one menu item and then call this. Then back out of the menu, go to the menu item that needs updating and voila, the changes are there. :-)
I noticed on the last version of Squeezer (2.2.4) that menus that don't have actions become visual gray (disabled). Nice job.
Thank you!
I had this release coming up, so I thought I'd put it in right away.
Incidently there also icons for the Audio submenu in the Settings menu.
One quick question: The audio icons are the right size. My icons get kind of big on my submenus? Can you determine why? I wonder if I am missing a size parameter or something?
Just a tiny request. Sometimes I add a text element as an instruction or a label to the menu. These have no actions. But with the new 'no action' graying out feature they show up as gray and are harder to read.
Thoughts on how we leave straight text alone but gray out things like radios, checks and sliders with no action element?
I think it would be fairly simple implement your suggestion. It is not standard however so I would prefer if you would help check it out. If I prepare an apk, are you then able to try it?
About the icon size Squeezer uses the same size for all icons. I think the icons which appear smaller has an inset build into the icon.
I am totally willing to iterate with you on various APKs.
I agree it's definite fringe case stuff. Sort of BAU for me. :-)
I thought that was the case with the icons but I put an insert into the one and it still stayed the same. Perhaps there is some buffering going on? Attached is the icon in question. I put a empty border around it to match the others but it still fills the available space.
Ok here's an APK.
This also has the mute buttons I prepared for your fellow DENON plugin developer.
I wasn't able to find any disabled radios or checkboxes, so I hope it works. I opted to make text item with no action slightly greyed out, and checkboxes and radios more greyed out (i.e. disabled).
Squeezer caches the icons to reduce memory traffic. If you clear the cache you should be able to see the changes in your icon. Maybe that's an issue?
I could not see any difference between a text without action and a disabled checkbox.
Where do you clear the cache?
Oops you are right! I've updated the apk in the link, please try again.
I think how to clear the cache varies depending on the phone manufacturer. I long press on the Squeezer app and select App Info. From there I select storage / Clear storage / Clear Cache.
Otherwise bring down the notifications, select settings / app setting and find the Squeezer app. In there should be possibility to clear the cache.
Much nicer
Finally found out how to clear the cache on Squeezer on my phone. That was the trick to get the new icon loaded.
So all is good for now. :-)
I have developed the https://github.com/aesculus/denonavpcontrol plugin for LMS. It allows apps like Squeezer to control the Denon/Marrantz AVRs through the LMS devices. This all works transparently today for Squeezer.
There is one feature that I think would compliment Squeezer with my plugin. That is the ability to adjust some of the AVRs features within Squeezer. Today the iPeng iOS app supports this feature.
Would you be interested in looking in what changes would be required to Squeezer to support this? If I recall it is just an extension of the LMS API, but I would need to go back to my notes to tell for sure. It is very minor and once complete you would never have to code anything again even if I change the menu of the plugin.
Chris