ADBTuner: A "channel tuning" application for networked Google TV / Android TV devices

I'm using Sling right now. Pretty solid so far. I've not mapped all the channels over, just the ones I wanted that weren't available via TVE. Here's the json for what I have.

I did add ESPN as a backup channel even though that has TVE access.

[{"provider_name": "Sling", "number": 30.1, "name": "ESPN", "url": "https://watch.sling.com/1/channel/ca0cad8dbb4a4e68962810d8a6aa8b6a/watch", "package_name": "com.sling", "alternate_package_name": "", "tvc_guide_stationid": "32645", "guide_offset_hours": "", "configuration_uuid": "8ec77d65-30d6-46a3-8045-282571cff8d8"}, {"provider_name": "Sling", "number": 35, "name": "NFL Network", "url": "https://watch.sling.com/1/channel/8a595ee9235f4d7f8b95dd35d268cdd5/watch", "package_name": "com.sling", "alternate_package_name": "", "tvc_guide_stationid": "45399", "guide_offset_hours": "", "configuration_uuid": "8ec77d65-30d6-46a3-8045-282571cff8d8"}, {"provider_name": "Sling", "number": 41, "name": "HGTV", "url": "https://watch.sling.com/1/channel/eebd3fb41ae04dc785767c0b4b0f34c0/watch", "package_name": "com.sling", "alternate_package_name": "", "tvc_guide_stationid": "49788", "guide_offset_hours": "", "configuration_uuid": "8ec77d65-30d6-46a3-8045-282571cff8d8"}, {"provider_name": "Sling", "number": 51, "name": "TLC", "url": "https://watch.sling.com/1/channel/793b8cc7bdca43d9acb91432e1ccd24d/watch", "package_name": "com.sling", "alternate_package_name": "", "tvc_guide_stationid": "11158", "guide_offset_hours": "", "configuration_uuid": "8ec77d65-30d6-46a3-8045-282571cff8d8"}, {"provider_name": "Sling", "number": 60, "name": "Travel", "url": "https://watch.sling.com/1/channel/2b9b9f1be4984590a4d30529bebef33b/watch", "package_name": "com.sling", "alternate_package_name": "", "tvc_guide_stationid": "59303", "guide_offset_hours": "", "configuration_uuid": "8ec77d65-30d6-46a3-8045-282571cff8d8"}, {"provider_name": "Sling", "number": 70, "name": "Food Network", "url": "https://watch.sling.com/1/channel/eca5bf0184054d4cb938c0476adc99db/watch", "package_name": "com.sling", "alternate_package_name": "", "tvc_guide_stationid": "50747", "guide_offset_hours": "", "configuration_uuid": "8ec77d65-30d6-46a3-8045-282571cff8d8"}, {"provider_name": "Sling", "number": 80, "name": "CNN", "url": "https://watch.sling.com/1/channel/24696f5c20ad4d1490111064f0b32dc1/watch", "package_name": "com.sling", "alternate_package_name": "", "tvc_guide_stationid": "58646", "guide_offset_hours": "", "configuration_uuid": "8ec77d65-30d6-46a3-8045-282571cff8d8"}, {"provider_name": "Sling", "number": 81, "name": "MS NOW", "url": "https://watch.sling.com/1/channel/b708785d33964014896ab636042af863/watch", "package_name": "com.sling", "alternate_package_name": "", "tvc_guide_stationid": "67636", "guide_offset_hours": "", "configuration_uuid": "8ec77d65-30d6-46a3-8045-282571cff8d8"}, {"provider_name": "Sling", "number": 83, "name": "CNN Headline News", "url": "https://watch.sling.com/1/channel/bb0fdf8d3383417d8da4ef9a31b35237/watch", "package_name": "com.skip", "alternate_package_name": "", "tvc_guide_stationid": "10145", "guide_offset_hours": "", "configuration_uuid": "8ec77d65-30d6-46a3-8045-282571cff8d8"}, {"provider_name": "Sling", "number": 84, "name": "BBC News", "url": "https://watch.sling.com/1/channel/5a29a05259624e25968227103f1771f4/watch", "package_name": "com.sling", "alternate_package_name": "", "tvc_guide_stationid": "89690", "guide_offset_hours": "", "configuration_uuid": "8ec77d65-30d6-46a3-8045-282571cff8d8"}, {"provider_name": "Sling", "number": 95, "name": "Discovery Channel", "url": "https://watch.sling.com/1/channel/73653704f85b4bde9855ef29a6d3196e/watch", "package_name": "com.sling", "alternate_package_name": "", "tvc_guide_stationid": "56905", "guide_offset_hours": "", "configuration_uuid": "8ec77d65-30d6-46a3-8045-282571cff8d8"}, {"provider_name": "Sling", "number": 110, "name": "Comedy Central", "url": "https://watch.sling.com/1/channel/29938328f60d447299ec48511a09ebab/watch", "package_name": "com.sling", "alternate_package_name": "", "tvc_guide_stationid": "62420", "guide_offset_hours": "", "configuration_uuid": "8ec77d65-30d6-46a3-8045-282571cff8d8"}, {"provider_name": "Sling", "number": 120, "name": "TBS", "url": "https://watch.sling.com/1/channel/6f8a36632f45462db3b843ed96a1f96c/watch", "package_name": "com.sling", "alternate_package_name": "", "tvc_guide_stationid": "58515", "guide_offset_hours": "", "configuration_uuid": "8ec77d65-30d6-46a3-8045-282571cff8d8"}, {"provider_name": "Sling", "number": 121, "name": "TNT", "url": "https://watch.sling.com/1/channel/23a92a8fb160489b97fd746536551d50/watch", "package_name": "com.sling", "alternate_package_name": "", "tvc_guide_stationid": "42642", "guide_offset_hours": "", "configuration_uuid": "8ec77d65-30d6-46a3-8045-282571cff8d8"}, {"provider_name": "Sling", "number": 122, "name": "tru", "url": "https://watch.sling.com/1/channel/1ed623f9dc97498cbe332bd5216a87c1/watch", "package_name": "com.sling", "alternate_package_name": "", "tvc_guide_stationid": "64490", "guide_offset_hours": "", "configuration_uuid": "8ec77d65-30d6-46a3-8045-282571cff8d8"}, {"provider_name": "Sling", "number": 123, "name": "USA", "url": "https://watch.sling.com/1/channel/35b320ac77ce4a2fbaf685e401933dc1/watch", "package_name": "com.sling", "alternate_package_name": "", "tvc_guide_stationid": "11207", "guide_offset_hours": "", "configuration_uuid": "8ec77d65-30d6-46a3-8045-282571cff8d8"}, {"provider_name": "Sling", "number": 125, "name": "BBC America", "url": "https://watch.sling.com/1/channel/4ce1c9ae62e94d19a7c23c680928ccd1/watch", "package_name": "com.sling", "alternate_package_name": "", "tvc_guide_stationid": "64492", "guide_offset_hours": "", "configuration_uuid": "8ec77d65-30d6-46a3-8045-282571cff8d8"}, {"provider_name": "Sling", "number": 129, "name": "IFC", "url": "https://watch.sling.com/1/channel/d990d3f3d1a04c92ab2d1c76fba0b072/watch", "package_name": "com.sling", "alternate_package_name": "", "tvc_guide_stationid": "59444", "guide_offset_hours": 0, "configuration_uuid": "8ec77d65-30d6-46a3-8045-282571cff8d8"}, {"provider_name": "Sling", "number": 141, "name": "Lifetime", "url": "https://watch.sling.com/1/channel/170d51e754ad458eb912ae89d1254ca2/browse", "package_name": "com.sling", "alternate_package_name": "", "tvc_guide_stationid": "10918", "guide_offset_hours": 0, "configuration_uuid": "8ec77d65-30d6-46a3-8045-282571cff8d8"}, {"provider_name": "Sling", "number": 170, "name": "MGM+", "url": "https://watch.sling.com/1/channel/1594693b9724433086fb3f55d3f2e5a8/watch", "package_name": "com.sling", "alternate_package_name": "", "tvc_guide_stationid": "103828", "guide_offset_hours": "", "configuration_uuid": "8ec77d65-30d6-46a3-8045-282571cff8d8"}, {"provider_name": "Sling", "number": 173, "name": "AMC", "url": "https://watch.sling.com/1/channel/8da93b497e644312b17d2420f1cb77f4/watch", "package_name": "com.sling", "alternate_package_name": "", "tvc_guide_stationid": "59337", "guide_offset_hours": 0, "configuration_uuid": "8ec77d65-30d6-46a3-8045-282571cff8d8"}, {"provider_name": "Sling", "number": 200, "name": "AXS TV", "url": "https://watch.sling.com/1/channel/e52be4a2480d4113802cd37e533ce78e/watch", "package_name": "com.sling", "alternate_package_name": "", "tvc_guide_stationid": "28506", "guide_offset_hours": "", "configuration_uuid": "8ec77d65-30d6-46a3-8045-282571cff8d8"}, {"provider_name": "Sling", "number": 210, "name": "SyFy", "url": "https://watch.sling.com/1/channel/385c71f4210f457eb393041e36ed50b2/watch", "package_name": "com.sling", "alternate_package_name": "", "tvc_guide_stationid": "11097", "guide_offset_hours": "", "configuration_uuid": "8ec77d65-30d6-46a3-8045-282571cff8d8"}, {"provider_name": "Sling", "number": 220, "name": "Nick Jr.", "url": "https://watch.sling.com/1/channel/e1b9ccf5df644012bdcfe5ca8a68f1d2/watch", "package_name": "com.sling", "alternate_package_name": "", "tvc_guide_stationid": "82649", "guide_offset_hours": "", "configuration_uuid": "8ec77d65-30d6-46a3-8045-282571cff8d8"}]```

Apparently I can't attach a json file.  If you drop this in notepad and save as a json file, you should be able to import then.

The easy way to do this is to use this Project One-Click Action, that will grab all of the Sling channels you're subscribed to, add them to ADBTuner, and create a CDVR Custom Channel Source for them.

This Action can be run whenever you want to keep your list of subscribed channels synchronized with your ADBTuner and CDVR channels. This is particularly nice if/when you change your Sling subscription to add or drop a package.

We've all had TVE fail from time-to-time for whatever reason, and by having all of your Sling channels setup -- whether available via TVE or not, a failed TVE tune will automatically roll-over to ADBTuner:

Thanks for the pointer. I do notice the channel mapping isn't running as intended (I believe). I installed an updated ADBTuner and notice now the individual channels have a "sort order" where the channels are being populated.

I haven't installed the latest development build yet. Are you saying this happened using the Project One-Click Action? That could be correct though, since Sling doesn't have channel numbers (unlike say DirecTV), the value there should null. And the new sort order field is likely assigned by ADBTuner when the channel is created.

Also, if this was done using the Action, I'm trying to populate as many of the Gracenote IDs as possible. I see this one is missing, what do your other channels look like?

Yes, used the One Click Action. Several had Gracenotes but some were missing. Quick scan the missing channels that aren't "preview channels" were:

MGM+ Drive-In
NFL Network Alternative
Paramount Network
UPtv
Investigation Discovery
Local Now
Sling Scapes
Sing Scapes 2

Basically the only channel worth noting is Paramount Network.

I just have the base Orange+Blue plan, so not sure if others would be missing in their addons.

Could you add the item_id to each of these channels you listed? If so, I'll add them to a reference file that contains that number and the Gracenote ID.

I'm looking for the number between channel/ and /watch in the URL for that channel. That way the next guy, or you the next time you update, will have the Gracenote IDs added.

Item_ID? Is that the alphanumeric specific id in the channels web address when selecting the channel in the guide (not the individual show but the channel)?

Yes. In your example, it ends up here in your ADBTuner channels:

Gallery = 18a65b3c87cf4239911ddd1c4af0135d
NFL Network Alternative = 831685a48158424ca4d1263de3292bc1
MGM+ Drive In = 1594693b9724433086fb3f55d3f2e5a8
Paramount = e8cabe959f194a7b97b1c807dc9b267e
UPtv = 829dc2f739614cc7a353b6c59586033b
Investigation Discovery = 065f55e5000448869547c8d24da0b999
Local Now = eb9a3b106bfb44049d208a961608352d
Sling Scapes = b7a9b86cb0124c11b51a7364d8fd30ce
Sling Scapes 2 = 88c7f83ca15d4ab3948b9420d81d13fd/

1 Like

Development build 20251226-1 contains a fix for channels that are added via the API with a null channel number. The display channel number field will no longer be set to the string "None."

3 Likes

@turtletank

I'm trying to resolve an issue where the profile screen appears to be detected, and then it looks like ADBTuner circles back to look for a profile screen again:

2025-12-26 18:43:58.909 - stream - [Tune (HGHizcemnHVwAGnQav4U5P)] Tuning to Paramount+ 1 on firestick-rack1

2025-12-26 18:43:58.910 - stream - [Tune (HGHizcemnHVwAGnQav4U5P)] Using channel configuration: FruitDeepLinks - Parmount+ v2.0 (FireTV and AndroidTV) (62a01c95-94f8-41b7-b56b-4838859ab42d)

2025-12-26 18:43:59.276 - lib.adb - [Tune (HGHizcemnHVwAGnQav4U5P)] ADB: firestick-rack1 - input keyevent KEYCODE_WAKEUP

2025-12-26 18:44:00.474 - lib.adb - [Tune (HGHizcemnHVwAGnQav4U5P)] ADB: firestick-rack1 - pidof com.cbs.ott

2025-12-26 18:44:00.738 - stream - [Tune (HGHizcemnHVwAGnQav4U5P)] Resolving dynamic URL (http://htpc6:6655/api/adb/lanes/pplus/1/deeplink?format=json) for channel.

2025-12-26 18:44:00.759 - stream - [Tune (HGHizcemnHVwAGnQav4U5P)] Retrieved dynamic URL data: {'channel_id': 'pplus01', 'channel_name': 'CBS Sports', 'deeplink': 'pplus://www.paramountplus.com/live-tv/stream/english-football-league/50b859e1-5ad1-4876-a849-029728788d78?searchReferral=appleatv&source=spotlight', 'deeplink_format': 'scheme', 'event_end_utc': '2025-12-26T19:05:00+00:00', 'event_start_utc': '2025-12-26T13:30:00+00:00', 'lane_number': 1, 'provider_code': 'pplus', 'start_utc': '2025-12-26T13:30:00+00:00', 'status': 'success', 'stop_utc': '2025-12-26T19:05:00+00:00', 'title': 'EFL Championship: The Golazo Show'}

2025-12-26 18:44:00.759 - stream - [Tune (HGHizcemnHVwAGnQav4U5P)] Using pplus://www.paramountplus.com/live-tv/stream/english-football-league/50b859e1-5ad1-4876-a849-029728788d78?searchReferral=appleatv&source=spotlight to load channel.

2025-12-26 18:44:00.759 - lib.adb - [Tune (HGHizcemnHVwAGnQav4U5P)] ADB: firestick-rack1 - input keyevent KEYCODE_MEDIA_STOP

2025-12-26 18:44:02.453 - lib.adb - [Tune (HGHizcemnHVwAGnQav4U5P)] ADB: firestick-rack1 - am force-stop com.cbs.ott

2025-12-26 18:44:02.916 - lib.adb - [Tune (HGHizcemnHVwAGnQav4U5P)] ADB: firestick-rack1 - am start -W -a android.intent.action.VIEW -d 'pplus://www.paramountplus.com/live-tv/stream/english-football-league/50b859e1-5ad1-4876-a849-029728788d78?searchReferral=appleatv&source=spotlight' 'com.cbs.ott'

2025-12-26 18:44:04.364 - stream - [Tune HGHizcemnHVwAGnQav4U5P] Waiting 3 seconds to allow sleeping device to setup.

2025-12-26 18:44:10.292 - stream - [Tune HGHizcemnHVwAGnQav4U5P] Waiting for playback start. Status: unknown

2025-12-26 18:44:11.292 - lib.adb - [Tune (HGHizcemnHVwAGnQav4U5P)] Checking for profile screen

2025-12-26 18:44:15.133 - lib.adb - [Tune (HGHizcemnHVwAGnQav4U5P)] Checking for profile screen

2025-12-26 18:44:15.440 - server - 

--------------------------------------------------

Tuner "firestick-rack1" is currently in use and locked.


Tune ID: N/A

Channel: Paramount+ 1

Lock Obtained: 2025-12-26 18:43:58 (0.29 minutes ago)

Last Seen: N/A

Bytes Transferred: None

Remote User Agent:

N/A

--------------------------------------------------

2025-12-26 18:44:16.123 - lib.adb - [Tune (HGHizcemnHVwAGnQav4U5P)] On screen text: 'who's watching?

select or create a profile. have kids? keep them safe with kids mode!

scott add profile

edit profiles'

2025-12-26 18:44:16.123 - lib.adb - [Tune (HGHizcemnHVwAGnQav4U5P)] Matched 'who's watching'.

2025-12-26 18:44:16.124 - stream - [Tune HGHizcemnHVwAGnQav4U5P] Profile screen detected.

2025-12-26 18:44:16.124 - lib.adb - [Tune (HGHizcemnHVwAGnQav4U5P)] ADB: firestick-rack1 - input keyevent KEYCODE_DPAD_CENTER

2025-12-26 18:44:17.923 - stream - [Tune HGHizcemnHVwAGnQav4U5P] Redirecting to stream after 19.02 seconds. Tuning is still in progress.

2025-12-26 18:44:17.923 - uvicorn.access - 100.98.232.107:0 - "GET /stream/756?web-preview HTTP/1.1" 307

2025/12/26 18:44:18 [PROXY] 100.98.232.107 -> GET "/proxy/3?requestKey=HGHizcemnHVwAGnQav4U5P" -> "http://encoder_48007/0.ts"

2025-12-26 18:44:19.062 - lib.adb - [Tune (HGHizcemnHVwAGnQav4U5P)] Checking for profile screen

2025-12-26 18:44:21.892 - lib.adb - [Tune (HGHizcemnHVwAGnQav4U5P)] Checking for profile screen

2025-12-26 18:44:23.081 - lib.adb - [Tune (HGHizcemnHVwAGnQav4U5P)] On screen text: 'wrexham vs. sheffield united

(euve) 10:00 am

re) start from beginning'

2025-12-26 18:44:24.967 - lib.adb - [Tune (HGHizcemnHVwAGnQav4U5P)] Checking for profile screen

2025-12-26 18:44:26.092 - lib.adb - [Tune (HGHizcemnHVwAGnQav4U5P)] On screen text: 'wrexham vs. sheffield united

(euve) 10:00 am

re) start from beginning'

2025-12-26 18:44:27.959 - lib.adb - [Tune (HGHizcemnHVwAGnQav4U5P)] Checking for profile screen

2025-12-26 18:44:29.106 - lib.adb - [Tune (HGHizcemnHVwAGnQav4U5P)] On screen text: 'wrexham vs. sheffield united

(euve) 10:00 am

re) start from beginning'

2025-12-26 18:44:30.991 - lib.adb - [Tune (HGHizcemnHVwAGnQav4U5P)] Checking for profile screen

2025-12-26 18:44:32.076 - lib.adb - [Tune (HGHizcemnHVwAGnQav4U5P)] On screen text: 'wrexham vs. sheffield united

(euve) 10:00 am

re) start from beginning'

2025-12-26 18:44:34.040 - lib.adb - [Tune (HGHizcemnHVwAGnQav4U5P)] Checking for profile screen

2025-12-26 18:44:35.116 - lib.adb - [Tune (HGHizcemnHVwAGnQav4U5P)] On screen text: 'wrexham vs. sheffield united

(euve) 10:00 am

re) start from beginning'

2025-12-26 18:44:37.008 - lib.adb - [Tune (HGHizcemnHVwAGnQav4U5P)] Checking for profile screen

2025-12-26 18:44:38.146 - lib.adb - [Tune (HGHizcemnHVwAGnQav4U5P)] On screen text: 'wrexham vs. sheffield united

(euve) 10:00 am

re) start from beginning'

2025-12-26 18:44:40.036 - stream - [Tune HGHizcemnHVwAGnQav4U5P] Maximum wait time exceeded. Giving up after 41.13 seconds. [Tune HGHizcemnHVwAGnQav4U5P] Display was off, application (com.cbs.ott) was running.

2025-12-26 18:44:40.036 - tuner_management - [Tune HGHizcemnHVwAGnQav4U5P] Released tuner (3).

2025-12-26 18:44:40.036 - lib.adb - [Tune (HGHizcemnHVwAGnQav4U5P)] ADB: Stopping media playback.

2025-12-26 18:44:40.036 - lib.adb - [Tune (HGHizcemnHVwAGnQav4U5P)] ADB: firestick-rack1 - input keyevent KEYCODE_MEDIA_STOP

2025-12-26 18:44:40.810 - lib.adb - [Tune (HGHizcemnHVwAGnQav4U5P)] ADB: firestick-rack1 - input keyevent KEYCODE_MEDIA_PAUSE

When I was working with your codebase a couple of months ago, I remember encountering a similar issue based on what you have setup to trigger after 15 seconds -- and the fact that several other parameters weren't being taken into account.

Sorry I can't be more specific, but I abandoned that previous work -- as you've been moving the project forward. :slight_smile:

EDIT: Also, on the subject of profile screens, would you be willing to add a "custom text to detect" option to Custom Configurations? This would be great for matching something like a username, which would be unique to a given installation, or for dealing with new apps with unique profile screen text.

FYI, that Paramount is a "free preview" since I am in my first month of my service, so that may not be the permanent link?

1 Like

So it looks as though the "who's watching" screen is being cleared, but the app is loading a second dialog window in which the user can select between "Watch Live" and "Start From Beginning" and there is nothing in place to clear that.

I just pushed an update to the development version (20251227-5) in which the profile screen commands can now be managed as part of configurations.

The default commands as specified in the included configurations:

"tune_match_text_commands": [
    {
        "match_text": [
            "who's watching",
            "choose an account",
            "edit profiles"
        ],
        "commands": [
            "input keyevent KEYCODE_DPAD_CENTER"
        ],
        "check_after_seconds": 5
    }
]

This will match any of the strings included in the match_text array and all of the commands specified in the commands array will be executed when a string is matched

For your purposes you can probably just modify it as follows:

"tune_match_text_commands": [
    {
        "match_text": [
            "who's watching",
            "choose an account",
            "edit profiles",
            "watch live"
        ],
        "commands": [
            "input keyevent KEYCODE_DPAD_CENTER"
        ],
        "check_after_seconds": 5
    }
]

If you need to execute different commands you can add a second dictionary instead of just modifying the default.

For example:

"tune_match_text_commands": [
  {
      "match_text": [
          "who's watching",
          "choose an account",
          "edit profiles"
      ],
      "commands": [
          "input keyevent KEYCODE_DPAD_CENTER"
      ],
      "check_after_seconds": 5
  },
  {
      "match_text": [
          "watch live"
      ],
      "commands": [
          "input keyevent KEYCODE_DPAD_CENTER"
      ],
      "check_after_seconds": 5
  }
]

Let me know if this resolves your issue.

As a side note, check_for_and_clear_whos_watching_prompts has been removed from global_options, but should work as it did in the past for custom configurations that were created before this change.

2 Likes

Fantastic! This looks like it has the potential to work very nicely with all of these event-based streams we're integrating into ADBTuner via the work of @KineticMan. It may be a couple of days before I can give you feedback on this. Many thanks.