bendavid / aiopylgtv

Library to control webOS based LG Tv devices
MIT License
143 stars 47 forks source link

Support for current playback state #39

Open MindFreeze opened 2 years ago

MindFreeze commented 2 years ago

There is no way AFAIK to get the current state of the TV. Is it playing or paused. This is very useful for automations. Also when my oled tv is in screensaver mode on a puased video, I have to call PLAY up to 3 times to get it to resume the video, but there is no way to know if any of the calls actually worked or just woke up the TV.

Is this doable?

P.S. knowing if the screensaver is on would be great too.

poroping commented 2 years ago

I'm interested in this too. I have a rooted TV and was playing around and seems like I can monitor the state of the video using ls-monitor:

/ # ls-monitor --filter=com.webos.surfacemanager
Time    Status  Prot    Type    Serial          Sender          Destination             Method                                  Payload
9810.346 TX  return     75              com.webos.service.tvpower (/var/run/ls2/EejC8l)         com.webos.surfacemanager (/var/run/ls2/CtDEkV)  «{ "returnValue": true, "state": "Screen Saver", "processing": "Screen On" }»
9810.348 TX  return     25              com.webos.applicationManager (/var/run/ls2/cmsT5I)              com.webos.surfacemanager (/var/run/ls2/CtDEkV)  «{"appId":"com.webos.app.screensaver","status":"closing","processId":"9106","type":"qml"}»
9810.353 TX  return     75              com.webos.service.tvpower (/var/run/ls2/EejC8l)         com.webos.surfacemanager (/var/run/ls2/CtDEkV)  «{ "returnValue": true, "state": "Active" }»
9810.355 RX return      25              com.webos.surfacemanager (/var/run/ls2/CtDEkV)          com.webos.applicationManager (/var/run/ls2/cmsT5I)      «{"appId":"com.webos.app.screensaver","status":"closing","processId":"9106","type":"qml"}»
9810.356 RX return      75              com.webos.surfacemanager (/var/run/ls2/CtDEkV)          com.webos.service.tvpower (/var/run/ls2/EejC8l) «{ "returnValue": true, "state": "Screen Saver", "processing": "Screen On" }»
9810.356 RX return      75              com.webos.surfacemanager (/var/run/ls2/CtDEkV)          com.webos.service.tvpower (/var/run/ls2/EejC8l) «{ "returnValue": true, "state": "Active" }»
9810.450 TX  return     31              com.webos.surfacemanager (/var/run/ls2/CtDEkV)          com.webos.applicationManager (/var/run/ls2/cmsT5I)      «{
    "foregroundAppInfo": [
        {
            "appId": "netflix",
            "processId": "4353",
            "windowGroup": false,
            "windowId": "",
            "windowType": "_WEBOS_WINDOW_TYPE_CARD"
        }
    ],
    "returnValue": true
}
»
9810.455 TX  return     25              com.webos.applicationManager (/var/run/ls2/cmsT5I)              com.webos.surfacemanager (/var/run/ls2/CtDEkV)  «{"appId":"com.webos.app.screensaver","status":"stop","processId":"9106","type":"qml"}»
9810.456 TX  return     303             com.webos.applicationManager (/var/run/ls2/cmsT5I)              com.webos.surfacemanager (/var/run/ls2/CtDEkV)  «{"running":[{"id":"com.webos.app.hdmi1","webprocessid":"","defaultWindowType":"card","appType":"native","processid":"1450"},{"id":"youtube.leanback.v4","webprocessid":"3861","defaultWindowType":"card","appType":"web","processid":"3861"},{"id":"netflix","webprocessid":"","defaultWindowType":"card","appType":"native_mvpd","processid":"4353"},{"id":"com.emby.app","webprocessid":"8865","defaultWindowType":"card","appType":"web","processid":"8865"},{"id":"com.webos.app.container","webprocessid":"9009","defaultWindowType":"card","appType":"web","processid":"9009"},{"id":"com.webos.app.browser","webprocessid":"","defaultWindowType":"card","appType":"native_builtin","processid":"9021"}],"returnValue":true}»
9810.460 RX return      25              com.webos.surfacemanager (/var/run/ls2/CtDEkV)          com.webos.applicationManager (/var/run/ls2/cmsT5I)      «{"appId":"com.webos.app.screensaver","status":"stop","processId":"9106","type":"qml"}»
9810.460 RX return      303             com.webos.surfacemanager (/var/run/ls2/CtDEkV)          com.webos.applicationManager (/var/run/ls2/cmsT5I)      «{"running":[{"id":"com.webos.app.hdmi1","webprocessid":"","defaultWindowType":"card","appType":"native","processid":"1450"},{"id":"youtube.leanback.v4","webprocessid":"3861","defaultWindowType":"card","appType":"web","processid":"3861"},{"id":"netflix","webprocessid":"","defaultWindowType":"card","appType":"native_mvpd","processid":"4353"},{"id":"com.emby.app","webprocessid":"8865","defaultWindowType":"card","appType":"web","processid":"8865"},{"id":"com.webos.app.container","webprocessid":"9009","defaultWindowType":"card","appType":"web","processid":"9009"},{"id":"com.webos.app.browser","webprocessid":"","defaultWindowType":"card","appType":"native_builtin","processid":"9021"}],"returnValue":true}»
9810.463 RX return      31              com.webos.applicationManager (/var/run/ls2/cmsT5I)              com.webos.surfacemanager (/var/run/ls2/CtDEkV)  «{
    "foregroundAppInfo": [
        {
            "appId": "netflix",
            "processId": "4353",
            "windowGroup": false,
            "windowId": "",
            "windowType": "_WEBOS_WINDOW_TYPE_CARD"
        }
    ],
    "returnValue": true
}
»
9810.467 TX  return     99              com.webos.service.acb (/var/run/ls2/040eXP)             com.webos.surfacemanager (/var/run/ls2/CtDEkV)  «{ "foregroundAppInfo": [ { "appId": "netflix", "windowType": "_WEBOS_WINDOW_TYPE_CARD", "acbs": [ { "pipelineId": "_lpPnaAWWEgYetM", "playerType": "direct audio", "playStateNow": "playing", "playStateNext": "playing", "isFullScreen": false, "positionX": -1, "positionY": -1, "width": -1, "height": -1 }, { "pipelineId": "_kfZdZS2etj5ydM", "playerType": "video", "playStateNow": "paused", "playStateNext": "paused", "isFullScreen": true, "positionX": 0, "positionY": 0, "width": 1920, "height": 1080 } ] } ] }»
9810.468 RX return      99              com.webos.surfacemanager (/var/run/ls2/CtDEkV)          com.webos.service.acb (/var/run/ls2/040eXP)     «{ "foregroundAppInfo": [ { "appId": "netflix", "windowType": "_WEBOS_WINDOW_TYPE_CARD", "acbs": [ { "pipelineId": "_lpPnaAWWEgYetM", "playerType": "direct audio", "playStateNow": "playing", "playStateNext": "playing", "isFullScreen": false, "positionX": -1, "positionY": -1, "width": -1, "height": -1 }, { "pipelineId": "_kfZdZS2etj5ydM", "playerType": "video", "playStateNow": "paused", "playStateNext": "paused", "isFullScreen": true, "positionX": 0, "positionY": 0, "width": 1920, "height": 1080 } ] } ] }»
9810.667 TX  return     99              com.webos.service.acb (/var/run/ls2/040eXP)             com.webos.surfacemanager (/var/run/ls2/CtDEkV)  «{ "foregroundAppInfo": [ { "appId": "netflix", "windowType": "_WEBOS_WINDOW_TYPE_CARD", "acbs": [ { "pipelineId": "_lpPnaAWWEgYetM", "playerType": "direct audio", "playStateNow": "playing", "playStateNext": "playing", "isFullScreen": false, "positionX": -1, "positionY": -1, "width": -1, "height": -1 }, { "pipelineId": "_kfZdZS2etj5ydM", "playerType": "video", "playStateNow": "paused", "playStateNext": "playing", "isFullScreen": true, "positionX": 0, "positionY": 0, "width": 1920, "height": 1080 } ] } ] }»
9810.667 TX  return     99              com.webos.service.acb (/var/run/ls2/040eXP)             com.webos.surfacemanager (/var/run/ls2/CtDEkV)  «{ "foregroundAppInfo": [ { "appId": "netflix", "windowType": "_WEBOS_WINDOW_TYPE_CARD", "acbs": [ { "pipelineId": "_lpPnaAWWEgYetM", "playerType": "direct audio", "playStateNow": "playing", "playStateNext": "playing", "isFullScreen": false, "positionX": -1, "positionY": -1, "width": -1, "height": -1 }, { "pipelineId": "_kfZdZS2etj5ydM", "playerType": "video", "playStateNow": "playing", "playStateNext": "playing", "isFullScreen": true, "positionX": 0, "positionY": 0, "width": 1920, "height": 1080 } ] } ] }»
9810.668 RX return      99              com.webos.surfacemanager (/var/run/ls2/CtDEkV)          com.webos.service.acb (/var/run/ls2/040eXP)     «{ "foregroundAppInfo": [ { "appId": "netflix", "windowType": "_WEBOS_WINDOW_TYPE_CARD", "acbs": [ { "pipelineId": "_lpPnaAWWEgYetM", "playerType": "direct audio", "playStateNow": "playing", "playStateNext": "playing", "isFullScreen": false, "positionX": -1, "positionY": -1, "width": -1, "height": -1 }, { "pipelineId": "_kfZdZS2etj5ydM", "playerType": "video", "playStateNow": "paused", "playStateNext": "playing", "isFullScreen": true, "positionX": 0, "positionY": 0, "width": 1920, "height": 1080 } ] } ] }»
9810.669 RX return      99              com.webos.surfacemanager (/var/run/ls2/CtDEkV)          com.webos.service.acb (/var/run/ls2/040eXP)     «{ "foregroundAppInfo": [ { "appId": "netflix", "windowType": "_WEBOS_WINDOW_TYPE_CARD", "acbs": [ { "pipelineId": "_lpPnaAWWEgYetM", "playerType": "direct audio", "playStateNow": "playing", "playStateNext": "playing", "isFullScreen": false, "positionX": -1, "positionY": -1, "width": -1, "height": -1 }, { "pipelineId": "_kfZdZS2etj5ydM", "playerType": "video", "playStateNow": "playing", "playStateNext": "playing", "isFullScreen": true, "positionX": 0, "positionY": 0, "width": 1920, "height": 1080 } ] } ] }»
9811.002 TX  return     80              com.webos.bootManager (/var/run/ls2/wfhnrn)             com.webos.surfacemanager (/var/run/ls2/CtDEkV)  «{"firstAppLaunched":true,"returnValue":true,"subscribed":true,"bootTarget":"hardware","bootStatus":"normal","firstAppId":"com.webos.app.hdmi1","signals":{"boot-done":true,"core-boot-done":true,"datastore-init-start":true,"minimal-boot-done":true,"init-boot-done":true,"snapshot-resume-done":true,"rest-boot-done":true},"powerStatus":"active"}»
9811.002 RX return      80              com.webos.surfacemanager (/var/run/ls2/CtDEkV)          com.webos.bootManager (/var/run/ls2/wfhnrn)     «{"firstAppLaunched":true,"returnValue":true,"subscribed":true,"bootTarget":"hardware","bootStatus":"normal","firstAppId":"com.webos.app.hdmi1","signals":{"boot-done":true,"core-boot-done":true,"datastore-init-start":true,"minimal-boot-done":true,"init-boot-done":true,"snapshot-resume-done":true,"rest-boot-done":true},"powerStatus":"active"}»
9815.388 TX  return     99              com.webos.service.acb (/var/run/ls2/040eXP)             com.webos.surfacemanager (/var/run/ls2/CtDEkV)  «{ "foregroundAppInfo": [ { "appId": "netflix", "windowType": "_WEBOS_WINDOW_TYPE_CARD", "acbs": [ { "pipelineId": "_lpPnaAWWEgYetM", "playerType": "direct audio", "playStateNow": "playing", "playStateNext": "playing", "isFullScreen": false, "positionX": -1, "positionY": -1, "width": -1, "height": -1 }, { "pipelineId": "_kfZdZS2etj5ydM", "playerType": "video", "playStateNow": "playing", "playStateNext": "paused", "isFullScreen": true, "positionX": 0, "positionY": 0, "width": 1920, "height": 1080 } ] } ] }»
9815.388 TX  return     99              com.webos.service.acb (/var/run/ls2/040eXP)             com.webos.surfacemanager (/var/run/ls2/CtDEkV)  «{ "foregroundAppInfo": [ { "appId": "netflix", "windowType": "_WEBOS_WINDOW_TYPE_CARD", "acbs": [ { "pipelineId": "_lpPnaAWWEgYetM", "playerType": "direct audio", "playStateNow": "playing", "playStateNext": "playing", "isFullScreen": false, "positionX": -1, "positionY": -1, "width": -1, "height": -1 }, { "pipelineId": "_kfZdZS2etj5ydM", "playerType": "video", "playStateNow": "paused", "playStateNext": "paused", "isFullScreen": true, "positionX": 0, "positionY": 0, "width": 1920, "height": 1080 } ] } ] }»
9815.388 RX return      99              com.webos.surfacemanager (/var/run/ls2/CtDEkV)          com.webos.service.acb (/var/run/ls2/040eXP)     «{ "foregroundAppInfo": [ { "appId": "netflix", "windowType": "_WEBOS_WINDOW_TYPE_CARD", "acbs": [ { "pipelineId": "_lpPnaAWWEgYetM", "playerType": "direct audio", "playStateNow": "playing", "playStateNext": "playing", "isFullScreen": false, "positionX": -1, "positionY": -1, "width": -1, "height": -1 }, { "pipelineId": "_kfZdZS2etj5ydM", "playerType": "video", "playStateNow": "playing", "playStateNext": "paused", "isFullScreen": true, "positionX": 0, "positionY": 0, "width": 1920, "height": 1080 } ] } ] }»
9815.389 RX return      99              com.webos.surfacemanager (/var/run/ls2/CtDEkV)          com.webos.service.acb (/var/run/ls2/040eXP)     «{ "foregroundAppInfo": [ { "appId": "netflix", "windowType": "_WEBOS_WINDOW_TYPE_CARD", "acbs": [ { "pipelineId": "_lpPnaAWWEgYetM", "playerType": "direct audio", "playStateNow": "playing", "playStateNext": "playing", "isFullScreen": false, "positionX": -1, "positionY": -1, "width": -1, "height": -1 }, { "pipelineId": "_kfZdZS2etj5ydM", "playerType": "video", "playStateNow": "paused", "playStateNext": "paused", "isFullScreen": true, "positionX": 0, "positionY": 0, "width": 1920, "height": 1080 } ] } ] }»

The interesting payload is this JSON:

{
    "foregroundAppInfo": [
        {
            "appId": "netflix",
            "windowType": "_WEBOS_WINDOW_TYPE_CARD",
            "acbs": [
                {
                    "pipelineId": "_lpPnaAWWEgYetM",
                    "playerType": "direct audio",
                    "playStateNow": "playing",
                    "playStateNext": "playing",
                    "isFullScreen": false,
                    "positionX": -1,
                    "positionY": -1,
                    "width": -1,
                    "height": -1
                },
                {
                    "pipelineId": "_kfZdZS2etj5ydM",
                    "playerType": "video",
                    "playStateNow": "playing",
                    "playStateNext": "paused",
                    "isFullScreen": true,
                    "positionX": 0,
                    "positionY": 0,
                    "width": 1920,
                    "height": 1080
                }
            ]
        }
    ]
}

"playerType": "video" and "playStateNow" seem to represent whether the TV is outputting video independent of what application it is, "appId" represents the current app.

Not sure if this is something that can be subscribed to via the API? Understand root access is not something everyone has.

edit:

Seems if we can subscribe to com.webos.service.acb/getForegroundAppInfo it might be possible to monitor video state.

/ # luna-send -i 'luna://com.webos.service.acb/getForegroundAppInfo' '{"subscribe":true}'
{ "returnValue": true, "appId": "netflix", "windowType": "_WEBOS_WINDOW_TYPE_CARD", "acbs": [ { "pipelineId": "_lpPnaAWWEgYetM", "playerType": "direct audio", "playStateNow": "playing", "playStateNext": "playing", "isFullScreen": false, "positionX": -1, "positionY": -1, "width": -1, "height": -1 }, { "pipelineId": "_2EYuiC4Xbzl2X9", "playerType": "video", "playStateNow": "paused", "playStateNext": "paused", "isFullScreen": true, "positionX": 0, "positionY": 0, "width": 1920, "height": 1080 } ], "subscribed": true }
{ "appId": "netflix", "windowType": "_WEBOS_WINDOW_TYPE_CARD", "acbs": [ { "pipelineId": "_lpPnaAWWEgYetM", "playerType": "direct audio", "playStateNow": "playing", "playStateNext": "playing", "isFullScreen": false, "positionX": -1, "positionY": -1, "width": -1, "height": -1 }, { "pipelineId": "_2EYuiC4Xbzl2X9", "playerType": "video", "playStateNow": "paused", "playStateNext": "playing", "isFullScreen": true, "positionX": 0, "positionY": 0, "width": 1920, "height": 1080 } ] }
{ "appId": "netflix", "windowType": "_WEBOS_WINDOW_TYPE_CARD", "acbs": [ { "pipelineId": "_lpPnaAWWEgYetM", "playerType": "direct audio", "playStateNow": "playing", "playStateNext": "playing", "isFullScreen": false, "positionX": -1, "positionY": -1, "width": -1, "height": -1 }, { "pipelineId": "_2EYuiC4Xbzl2X9", "playerType": "video", "playStateNow": "playing", "playStateNext": "playing", "isFullScreen": true, "positionX": 0, "positionY": 0, "width": 1920, "height": 1080 } ] }
{ "appId": "netflix", "windowType": "_WEBOS_WINDOW_TYPE_CARD", "acbs": [ { "pipelineId": "_lpPnaAWWEgYetM", "playerType": "direct audio", "playStateNow": "playing", "playStateNext": "playing", "isFullScreen": false, "positionX": -1, "positionY": -1, "width": -1, "height": -1 }, { "pipelineId": "_2EYuiC4Xbzl2X9", "playerType": "video", "playStateNow": "playing", "playStateNext": "paused", "isFullScreen": true, "positionX": 0, "positionY": 0, "width": 1920, "height": 1080 } ] }
{ "appId": "netflix", "windowType": "_WEBOS_WINDOW_TYPE_CARD", "acbs": [ { "pipelineId": "_lpPnaAWWEgYetM", "playerType": "direct audio", "playStateNow": "playing", "playStateNext": "playing", "isFullScreen": false, "positionX": -1, "positionY": -1, "width": -1, "height": -1 }, { "pipelineId": "_2EYuiC4Xbzl2X9", "playerType": "video", "playStateNow": "paused", "playStateNext": "paused", "isFullScreen": true, "positionX": 0, "positionY": 0, "width": 1920, "height": 1080 } ] }
bashbers commented 2 years ago

@poroping Did you create a mvp by chance? Im currently looking to resolve this issue aswell.

MindFreeze commented 2 years ago

@bashbers I tried hard to get this info but this is only available from inside the TV and not exposed over the network at all. My next step is to create a simple backgroud app for webos that publishes such info to MQTT. The app should not need root and should be installable with dev-manager-desktop . Hope to have a crack at it this week.

thecode commented 2 years ago

You can find all of them here: https://www.webosose.org/docs/reference/ This one is interesting: https://www.webosose.org/docs/reference/ls2-api/com-webos-service-mediacontroller/#getmediaplaystatus

bashbers commented 2 years ago

@MindFreeze thats great news! If you want you could link the repository here so I can help. Don't have much dev experience for WebOS (read: none), but I do know JS.

MindFreeze commented 2 years ago

I am also new to WebOS development and it is terrible so far. Half the things simply don't work and no one seems to care. The latest emulator is broken but I managed to get going with v5. Now my latest problem is that service debugging doesn't work.

I know what I have to do but it is quite difficult without any debugging or even logging.

poroping commented 2 years ago

I haven't had time to work on this further. Was kinda just hoping someone else could do the legwork ;) My approach was going to add some API endpoint that could subscribe and poll to these media events.

bashbers commented 2 years ago

Ill look into extending the existing SSAP server in order for HA to automatically discover the new luna endpoint.

MindFreeze commented 2 years ago

I give up on the app idea. My TV from 2018 only has WebOS 3.9, which runs nodejs 0.12.2 . Nothing works for such old versions, even the build tools, like babel, don't support them anymore.

On top of that there seems to be no reliable way to auto start the service when the TV turns on.

LG's own docs are trash and don't care about older versions. Guess my next TV is not going to be LG.

SLG commented 2 years ago

HI there! I've found out a way to get updates for the play/pause state from my LG TV: https://github.com/SLG/tv-service

ammgws commented 2 years ago

Link is broken?

SLG commented 2 years ago

Link is broken?

Nope, it was private. Changed to public!