{"action":"created","comment":{"url":"https://api.github.com/repos/openhab/openhab2-addons/pulls/comments/165812097","pull_request_review_id":93814225,"id":165812097,"diff_hunk":"@@ -839,14 +869,134 @@ public void updateListener(SqueezeBoxPlayerEventListener listener) {\n                 } else if (function.equals(\"volume\")) {\n                     final int volume = (int) Double.parseDouble(value);\n                     updatePlayer(new PlayerUpdateEvent() {\n+\n                         @Override\n                         public void updateListener(SqueezeBoxPlayerEventListener listener) {\n                             listener.absoluteVolumeChangeEvent(mac, volume);\n                         }\n+\n                     });\n                 }\n             }\n         }\n+\n+        private void handleFavorites(String message) {\n+            logger.trace(\"Handle favorites message: {}\", message);\n+\n+            String[] messageParts = message.split(\"\\\\s\");\n+            if (messageParts.length == 2 && \"changed\".equals(messageParts[1])) {\n+                // LMS informing us that favorites have changed; request an update to the favorites list\n+                requestFavorites();\n+                return;\n+            }\n+            if (messageParts.length < 7) {\n+                logger.trace(\"No favorites in message.\");\n+                return;\n+            }\n+\n+            List<Favorite> favorites = new ArrayList<>();\n+            String title = \"\";\n+            String count = \"\";\n+            Favorite f = null;\n+            for (String part : messageParts) {\n+                String id;\n+                String name;\n+                String type;\n+                Boolean isaudio;\n+                Boolean hasitems;\n+\n+                // Title of Favorites\n+                if (part.startsWith(\"title%3A\")) {\n+                    title = decode(part.substring(\"title%3A\".length()));\n+                    logger.trace(\"Favorite title: {}\", title);\n+                }\n+                // Number of favorites in this message\n+                else if (part.startsWith(\"count%3A\")) {\n+                    count = part.substring(\"count%3A\".length());\n+                    logger.trace(\"Favorite count: {}\", count);\n+                }\n+                // Favorite ID (in form xxxxxxxxx.n)\n+                else if (part.startsWith(\"id%3A\")) {\n+                    id = part.substring(\"id%3A\".length());\n+                    f = new Favorite(id);\n+                    favorites.add(f);\n+                }\n+                // Favorite name\n+                else if (part.startsWith(\"name%3A\")) {\n+                    name = decode(part.substring(\"name%3A\".length()));\n+                    if (f != null) {\n+                        f.name = name;\n+                    }\n+                }\n+                // Favorite type\n+                else if (part.startsWith(\"type%3A\")) {\n+                    type = decode(part.substring(\"type%3A\".length()));\n+                    if (f != null) {\n+                        f.type = type;\n+                    }\n+                }\n+                // Favorite is audio\n+                else if (part.startsWith(\"isaudio%3A\")) {\n+                    isaudio = new Boolean(\"1\".matches(part.substring(\"isaudio%3A\".length())));\n+                    if (f != null) {\n+                        f.isaudio = isaudio;\n+                    }\n+                }\n+                // When \"1\", favorite is a submenu with additional favorites\n+                else if (part.startsWith(\"hasitems%3A\")) {\n+                    hasitems = new Boolean(\"1\".matches(part.substring(\"hasitems%3A\".length())));\n+                    if (f != null) {\n+                        if (hasitems) {\n+                            // Skip subfolders\n+                            favorites.remove(f);\n+                            f = null;\n+                        } else {\n+                            f.hasitems = hasitems;\n+                        }\n+                    }\n+                }\n+            }\n+            updatePlayersFavoritesList(favorites);\n+            updateChannelFavoritesList(favorites);\n+        }\n+\n+        private void updatePlayersFavoritesList(List<Favorite> favorites) {\n+            updatePlayer(new PlayerUpdateEvent() {\n+                @Override\n+                public void updateListener(SqueezeBoxPlayerEventListener listener) {\n+                    listener.updateFavoritesListEvent(favorites);\n+                }\n+            });\n+        }\n+\n+        private void updateChannelFavoritesList(List<Favorite> favorites) {\n+            final Channel channel = thing.getChannel(CHANNEL_FAVORITES_LIST);","path":"addons/binding/org.openhab.binding.squeezebox/src/main/java/org/openhab/binding/squeezebox/handler/SqueezeBoxServerHandler.java","position":286,"original_position":286,"commit_id":"290a8e37b8a54a6df7954749a6a84505ccc911aa","original_commit_id":"290a8e37b8a54a6df7954749a6a84505ccc911aa","user":{"login":"mhilbush","id":19286354,"avatar_url":"https://avatars2.githubusercontent.com/u/19286354?v=4","gravatar_id":"","url":"https://api.github.com/users/mhilbush","html_url":"https://github.com/mhilbush","followers_url":"https://api.github.com/users/mhilbush/followers","following_url":"https://api.github.com/users/mhilbush/following{/other_user}","gists_url":"https://api.github.com/users/mhilbush/gists{/gist_id}","starred_url":"https://api.github.com/users/mhilbush/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mhilbush/subscriptions","organizations_url":"https://api.github.com/users/mhilbush/orgs","repos_url":"https://api.github.com/users/mhilbush/repos","events_url":"https://api.github.com/users/mhilbush/events{/privacy}","received_events_url":"https://api.github.com/users/mhilbush/received_events","type":"User","site_admin":false},"body":"Ok. But why does BaseThingHandler expose both?\r\n","created_at":"2018-02-03T11:19:41Z","updated_at":"2018-02-03T11:19:41Z","html_url":"https://github.com/openhab/openhab2-addons/pull/3190#discussion_r165812097","pull_request_url":"https://api.github.com/repos/openhab/openhab2-addons/pulls/3190","author_association":"CONTRIBUTOR","_links":{"self":{"href":"https://api.github.com/repos/openhab/openhab2-addons/pulls/comments/165812097"},"html":{"href":"https://github.com/openhab/openhab2-addons/pull/3190#discussion_r165812097"},"pull_request":{"href":"https://api.github.com/repos/openhab/openhab2-addons/pulls/3190"}},"in_reply_to_id":165809460},"pull_request":{"url":"https://api.github.com/repos/openhab/openhab2-addons/pulls/3190","id":165832780,"html_url":"https://github.com/openhab/openhab2-addons/pull/3190","diff_url":"https://github.com/openhab/openhab2-addons/pull/3190.diff","patch_url":"https://github.com/openhab/openhab2-addons/pull/3190.patch","issue_url":"https://api.github.com/repos/openhab/openhab2-addons/issues/3190","number":3190,"state":"open","locked":false,"title":"[squeezebox] Add LMS favorites channels to server and player","user":{"login":"mhilbush","id":19286354,"avatar_url":"https://avatars2.githubusercontent.com/u/19286354?v=4","gravatar_id":"","url":"https://api.github.com/users/mhilbush","html_url":"https://github.com/mhilbush","followers_url":"https://api.github.com/users/mhilbush/followers","following_url":"https://api.github.com/users/mhilbush/following{/other_user}","gists_url":"https://api.github.com/users/mhilbush/gists{/gist_id}","starred_url":"https://api.github.com/users/mhilbush/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mhilbush/subscriptions","organizations_url":"https://api.github.com/users/mhilbush/orgs","repos_url":"https://api.github.com/users/mhilbush/repos","events_url":"https://api.github.com/users/mhilbush/events{/privacy}","received_events_url":"https://api.github.com/users/mhilbush/received_events","type":"User","site_admin":false},"body":"Signed-off-by: Mark Hilbush <mark@hilbush.com>\r\nAlso-by: Gregory Moyer <moyerg@syphr.com>\r\n\r\nAdd two new channels to enable use of the favorites list on the LMS (Logitech Media Server).\r\n\r\nAdd a readonly `favoritesList` channel of type String to the squeezebox server thing. \r\n- the SqueezeBox Server `favoritesList` channel is updated immediately when the binding starts, and whenever the favorites list is updated on the LMS (there’s an asynchronous notification from the LMS to the binding when the favorites list is updated).\r\n- the channel is formatted with comma-separated values of the form favoriteId=favoriteName, like this:\r\n```\r\n1=Rock,2=Folk,3=Classic Alternative\r\n```\r\n- there’s a config option that allows you to wrap the favoriteName with double quotes\r\n```\r\n1=\"Rock\",2=\"Folk\",3=\"Classic Alternative\"\r\n```\r\n- only favorites at the root level of the LMS favorites hierarchy are returned\r\n- the server handler sends the favorites list to the player handler\r\n\r\nAdd a `playFavorite` channel of type String to the squeezebox player thing.\r\n- when you send the favoriteId to an item linked to a player's `playFavorite` channel, it plays the favorite on that player.\r\n- the player uses the favorites list from the server handler to update the `playFavorite` channel's state description to include the favorites as options.\r\n\r\nDependencies: \r\n- Sitemap needs to be updated to be able to use the item's state options as the selection list whenever the state options change\r\n- HABpanel needs to be able to update the choices in the Selection widget whenever the state options change","created_at":"2018-01-29T22:13:08Z","updated_at":"2018-02-03T11:19:41Z","closed_at":null,"merged_at":null,"merge_commit_sha":"a9bbae36bde04231a1e44a9428a9334cc5ad3f52","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"milestone":null,"commits_url":"https://api.github.com/repos/openhab/openhab2-addons/pulls/3190/commits","review_comments_url":"https://api.github.com/repos/openhab/openhab2-addons/pulls/3190/comments","review_comment_url":"https://api.github.com/repos/openhab/openhab2-addons/pulls/comments{/number}","comments_url":"https://api.github.com/repos/openhab/openhab2-addons/issues/3190/comments","statuses_url":"https://api.github.com/repos/openhab/openhab2-addons/statuses/290a8e37b8a54a6df7954749a6a84505ccc911aa","head":{"label":"mhilbush:squeezebox-favorites","ref":"squeezebox-favorites","sha":"290a8e37b8a54a6df7954749a6a84505ccc911aa","user":{"login":"mhilbush","id":19286354,"avatar_url":"https://avatars2.githubusercontent.com/u/19286354?v=4","gravatar_id":"","url":"https://api.github.com/users/mhilbush","html_url":"https://github.com/mhilbush","followers_url":"https://api.github.com/users/mhilbush/followers","following_url":"https://api.github.com/users/mhilbush/following{/other_user}","gists_url":"https://api.github.com/users/mhilbush/gists{/gist_id}","starred_url":"https://api.github.com/users/mhilbush/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mhilbush/subscriptions","organizations_url":"https://api.github.com/users/mhilbush/orgs","repos_url":"https://api.github.com/users/mhilbush/repos","events_url":"https://api.github.com/users/mhilbush/events{/privacy}","received_events_url":"https://api.github.com/users/mhilbush/received_events","type":"User","site_admin":false},"repo":{"id":65158647,"name":"openhab2-addons","full_name":"mhilbush/openhab2-addons","owner":{"login":"mhilbush","id":19286354,"avatar_url":"https://avatars2.githubusercontent.com/u/19286354?v=4","gravatar_id":"","url":"https://api.github.com/users/mhilbush","html_url":"https://github.com/mhilbush","followers_url":"https://api.github.com/users/mhilbush/followers","following_url":"https://api.github.com/users/mhilbush/following{/other_user}","gists_url":"https://api.github.com/users/mhilbush/gists{/gist_id}","starred_url":"https://api.github.com/users/mhilbush/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mhilbush/subscriptions","organizations_url":"https://api.github.com/users/mhilbush/orgs","repos_url":"https://api.github.com/users/mhilbush/repos","events_url":"https://api.github.com/users/mhilbush/events{/privacy}","received_events_url":"https://api.github.com/users/mhilbush/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/mhilbush/openhab2-addons","description":"The next-generation open Home Automation Bus (openHAB)","fork":true,"url":"https://api.github.com/repos/mhilbush/openhab2-addons","forks_url":"https://api.github.com/repos/mhilbush/openhab2-addons/forks","keys_url":"https://api.github.com/repos/mhilbush/openhab2-addons/keys{/key_id}","collaborators_url":"https://api.github.com/repos/mhilbush/openhab2-addons/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/mhilbush/openhab2-addons/teams","hooks_url":"https://api.github.com/repos/mhilbush/openhab2-addons/hooks","issue_events_url":"https://api.github.com/repos/mhilbush/openhab2-addons/issues/events{/number}","events_url":"https://api.github.com/repos/mhilbush/openhab2-addons/events","assignees_url":"https://api.github.com/repos/mhilbush/openhab2-addons/assignees{/user}","branches_url":"https://api.github.com/repos/mhilbush/openhab2-addons/branches{/branch}","tags_url":"https://api.github.com/repos/mhilbush/openhab2-addons/tags","blobs_url":"https://api.github.com/repos/mhilbush/openhab2-addons/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/mhilbush/openhab2-addons/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/mhilbush/openhab2-addons/git/refs{/sha}","trees_url":"https://api.github.com/repos/mhilbush/openhab2-addons/git/trees{/sha}","statuses_url":"https://api.github.com/repos/mhilbush/openhab2-addons/statuses/{sha}","languages_url":"https://api.github.com/repos/mhilbush/openhab2-addons/languages","stargazers_url":"https://api.github.com/repos/mhilbush/openhab2-addons/stargazers","contributors_url":"https://api.github.com/repos/mhilbush/openhab2-addons/contributors","subscribers_url":"https://api.github.com/repos/mhilbush/openhab2-addons/subscribers","subscription_url":"https://api.github.com/repos/mhilbush/openhab2-addons/subscription","commits_url":"https://api.github.com/repos/mhilbush/openhab2-addons/commits{/sha}","git_commits_url":"https://api.github.com/repos/mhilbush/openhab2-addons/git/commits{/sha}","comments_url":"https://api.github.com/repos/mhilbush/openhab2-addons/comments{/number}","issue_comment_url":"https://api.github.com/repos/mhilbush/openhab2-addons/issues/comments{/number}","contents_url":"https://api.github.com/repos/mhilbush/openhab2-addons/contents/{+path}","compare_url":"https://api.github.com/repos/mhilbush/openhab2-addons/compare/{base}...{head}","merges_url":"https://api.github.com/repos/mhilbush/openhab2-addons/merges","archive_url":"https://api.github.com/repos/mhilbush/openhab2-addons/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/mhilbush/openhab2-addons/downloads","issues_url":"https://api.github.com/repos/mhilbush/openhab2-addons/issues{/number}","pulls_url":"https://api.github.com/repos/mhilbush/openhab2-addons/pulls{/number}","milestones_url":"https://api.github.com/repos/mhilbush/openhab2-addons/milestones{/number}","notifications_url":"https://api.github.com/repos/mhilbush/openhab2-addons/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/mhilbush/openhab2-addons/labels{/name}","releases_url":"https://api.github.com/repos/mhilbush/openhab2-addons/releases{/id}","deployments_url":"https://api.github.com/repos/mhilbush/openhab2-addons/deployments","created_at":"2016-08-07T23:23:22Z","updated_at":"2016-08-07T23:23:26Z","pushed_at":"2018-02-02T19:03:14Z","git_url":"git://github.com/mhilbush/openhab2-addons.git","ssh_url":"git@github.com:mhilbush/openhab2-addons.git","clone_url":"https://github.com/mhilbush/openhab2-addons.git","svn_url":"https://github.com/mhilbush/openhab2-addons","homepage":null,"size":92509,"stargazers_count":0,"watchers_count":0,"language":"Java","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"archived":false,"open_issues_count":0,"license":null,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"openhab:master","ref":"master","sha":"45e22c8a31c112842ff1fe12f99f6a6e71833054","user":{"login":"openhab","id":1007353,"avatar_url":"https://avatars0.githubusercontent.com/u/1007353?v=4","gravatar_id":"","url":"https://api.github.com/users/openhab","html_url":"https://github.com/openhab","followers_url":"https://api.github.com/users/openhab/followers","following_url":"https://api.github.com/users/openhab/following{/other_user}","gists_url":"https://api.github.com/users/openhab/gists{/gist_id}","starred_url":"https://api.github.com/users/openhab/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/openhab/subscriptions","organizations_url":"https://api.github.com/users/openhab/orgs","repos_url":"https://api.github.com/users/openhab/repos","events_url":"https://api.github.com/users/openhab/events{/privacy}","received_events_url":"https://api.github.com/users/openhab/received_events","type":"Organization","site_admin":false},"repo":{"id":19753195,"name":"openhab2-addons","full_name":"openhab/openhab2-addons","owner":{"login":"openhab","id":1007353,"avatar_url":"https://avatars0.githubusercontent.com/u/1007353?v=4","gravatar_id":"","url":"https://api.github.com/users/openhab","html_url":"https://github.com/openhab","followers_url":"https://api.github.com/users/openhab/followers","following_url":"https://api.github.com/users/openhab/following{/other_user}","gists_url":"https://api.github.com/users/openhab/gists{/gist_id}","starred_url":"https://api.github.com/users/openhab/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/openhab/subscriptions","organizations_url":"https://api.github.com/users/openhab/orgs","repos_url":"https://api.github.com/users/openhab/repos","events_url":"https://api.github.com/users/openhab/events{/privacy}","received_events_url":"https://api.github.com/users/openhab/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/openhab/openhab2-addons","description":"Add-ons for openHAB 2.x","fork":false,"url":"https://api.github.com/repos/openhab/openhab2-addons","forks_url":"https://api.github.com/repos/openhab/openhab2-addons/forks","keys_url":"https://api.github.com/repos/openhab/openhab2-addons/keys{/key_id}","collaborators_url":"https://api.github.com/repos/openhab/openhab2-addons/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/openhab/openhab2-addons/teams","hooks_url":"https://api.github.com/repos/openhab/openhab2-addons/hooks","issue_events_url":"https://api.github.com/repos/openhab/openhab2-addons/issues/events{/number}","events_url":"https://api.github.com/repos/openhab/openhab2-addons/events","assignees_url":"https://api.github.com/repos/openhab/openhab2-addons/assignees{/user}","branches_url":"https://api.github.com/repos/openhab/openhab2-addons/branches{/branch}","tags_url":"https://api.github.com/repos/openhab/openhab2-addons/tags","blobs_url":"https://api.github.com/repos/openhab/openhab2-addons/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/openhab/openhab2-addons/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/openhab/openhab2-addons/git/refs{/sha}","trees_url":"https://api.github.com/repos/openhab/openhab2-addons/git/trees{/sha}","statuses_url":"https://api.github.com/repos/openhab/openhab2-addons/statuses/{sha}","languages_url":"https://api.github.com/repos/openhab/openhab2-addons/languages","stargazers_url":"https://api.github.com/repos/openhab/openhab2-addons/stargazers","contributors_url":"https://api.github.com/repos/openhab/openhab2-addons/contributors","subscribers_url":"https://api.github.com/repos/openhab/openhab2-addons/subscribers","subscription_url":"https://api.github.com/repos/openhab/openhab2-addons/subscription","commits_url":"https://api.github.com/repos/openhab/openhab2-addons/commits{/sha}","git_commits_url":"https://api.github.com/repos/openhab/openhab2-addons/git/commits{/sha}","comments_url":"https://api.github.com/repos/openhab/openhab2-addons/comments{/number}","issue_comment_url":"https://api.github.com/repos/openhab/openhab2-addons/issues/comments{/number}","contents_url":"https://api.github.com/repos/openhab/openhab2-addons/contents/{+path}","compare_url":"https://api.github.com/repos/openhab/openhab2-addons/compare/{base}...{head}","merges_url":"https://api.github.com/repos/openhab/openhab2-addons/merges","archive_url":"https://api.github.com/repos/openhab/openhab2-addons/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/openhab/openhab2-addons/downloads","issues_url":"https://api.github.com/repos/openhab/openhab2-addons/issues{/number}","pulls_url":"https://api.github.com/repos/openhab/openhab2-addons/pulls{/number}","milestones_url":"https://api.github.com/repos/openhab/openhab2-addons/milestones{/number}","notifications_url":"https://api.github.com/repos/openhab/openhab2-addons/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/openhab/openhab2-addons/labels{/name}","releases_url":"https://api.github.com/repos/openhab/openhab2-addons/releases{/id}","deployments_url":"https://api.github.com/repos/openhab/openhab2-addons/deployments","created_at":"2014-05-13T19:41:58Z","updated_at":"2018-02-02T18:28:45Z","pushed_at":"2018-02-03T10:59:37Z","git_url":"git://github.com/openhab/openhab2-addons.git","ssh_url":"git@github.com:openhab/openhab2-addons.git","clone_url":"https://github.com/openhab/openhab2-addons.git","svn_url":"https://github.com/openhab/openhab2-addons","homepage":"","size":267485,"stargazers_count":729,"watchers_count":729,"language":"Java","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":1339,"mirror_url":null,"archived":false,"open_issues_count":422,"license":{"key":"epl-1.0","name":"Eclipse Public License 1.0","spdx_id":"EPL-1.0","url":"https://api.github.com/licenses/epl-1.0"},"forks":1339,"open_issues":422,"watchers":729,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/openhab/openhab2-addons/pulls/3190"},"html":{"href":"https://github.com/openhab/openhab2-addons/pull/3190"},"issue":{"href":"https://api.github.com/repos/openhab/openhab2-addons/issues/3190"},"comments":{"href":"https://api.github.com/repos/openhab/openhab2-addons/issues/3190/comments"},"review_comments":{"href":"https://api.github.com/repos/openhab/openhab2-addons/pulls/3190/comments"},"review_comment":{"href":"https://api.github.com/repos/openhab/openhab2-addons/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/openhab/openhab2-addons/pulls/3190/commits"},"statuses":{"href":"https://api.github.com/repos/openhab/openhab2-addons/statuses/290a8e37b8a54a6df7954749a6a84505ccc911aa"}},"author_association":"CONTRIBUTOR"}}
{"actor":{"display_login":"mhilbush"}}