APL Tablo Client

Awhile back I started down the road of writing my own Tablo Client that had all of the features I wanted. There were two standard things I wanted to be able to do that I couldn’t do in most of the clients I had access to at the time, one that I still can’t get anywhere else.

I wanted a client that allowed me to monitor what was being recorded on my Tablo ‘soon’, and I wanted the ability to blacklist shows that I didn’t care to monitor. The purpose of the blacklist was to allow me to see new things coming up on my Tablo that I hadn’t already made a decision to either record or ignore, new series, new movies, new sporting events. I recently signed up for the Developer access to the Tablo API to give me a better understanding of all of the features, and have been improving my app with that information. At this point I have a Java based app that allows me to discover the Tablos on my network, see all of the shows currently available, take a look at the upcoming recordings, and existing recordings, allow me to export and save those recordings, or watch them directly from the client, and delete them when I’m done. I’m wanting to work on the ability to change the schedule of shows via my client as well, and manage that blacklist that I’m developing…I plan on releasing this thing ‘soon’ for you all to benefit from my effort, but I want to know from you, what features does a client need to have to make it usable for you?

Would you use this to watch live TV? (this is something I don’t currently do much of)

What are your thoughts and comments thus far with nothing more to look at than my words.

[EDIT]
Please find the tool, as it sits today, available for download from here
http://remedylegacy.com/tablo/
I’ll keep that page updated with more information as I develop the documentation for the tool and as it moves toward what it will become with your input and guidance :slight_smile:

4 Likes

All I need is some way to see an actual schedule! Despite using the “optimized for Chrome” browser, I don’t actually have “Access to all Tablo screens and filters” (Tablo Apps & Compatible Devices) and there is not Upcoming. Just a screen full of possibilities in Scheduled tab.

I presume I’d need a JRE? just for this? Beyond that, I’ve become content using capto along with wrapto for exporting, allowing me to watch how I want. Automate downloads, hyper-organizing with custom naming options.

If I can schedule shows, then maybe see show currently available. As for watching live TV… I have a TV for that.

Review some post from Tablo, years ago they say there were going to release features soon… so when you post here, releasing 'soon` :rofl:

Ok…with interest in showing my true intent, I’ll make ‘soon’ be today, right now
(check my first post for download link)

I’ve only used a couple of java applications in the past regularly. I installed openjdk-11-jre. It’s what was readily available in Debian’s repository

 java --version
openjdk 11.0.4 2019-07-16
OpenJDK Runtime Environment (build 11.0.4+11-post-Debian-1)
OpenJDK 64-Bit Server VM (build 11.0.4+11-post-Debian-1, mixed mode, sharing)

, a path to Oracle may exists but… :man_shrugging: Here’s what I tried - and ended up with:

java -jar APLTablo.jar
Exception in thread "main" java.lang.NoClassDefFoundError: javafx/application/Application
	at java.base/java.lang.ClassLoader.defineClass1(Native Method)
	at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1016)
	at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:174)
	at java.base/java.net.URLClassLoader.defineClass(URLClassLoader.java:550)
	at java.base/java.net.URLClassLoader$1.run(URLClassLoader.java:458)
	at java.base/java.net.URLClassLoader$1.run(URLClassLoader.java:452)
	at java.base/java.security.AccessController.doPrivileged(Native Method)
	at java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:451)
	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:588)
	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
	at java.base/java.lang.Class.forName0(Native Method)
	at java.base/java.lang.Class.forName(Class.java:398)
	at org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader.main(JarRsrcLoader.java:56)
Caused by: java.lang.ClassNotFoundException: javafx.application.Application
	at java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:471)
	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:588)
	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
	... 13 more

APLTablo.jar APLTablo.properties Template.mlt are all together.

Ok, so this id compiled against Java 8, but it’s not complaining about that, what it’s complaining about is lack of JavaFX, I’ve never used OpenJDK, so I don’t know if JavaFX is included, this is a GUI app, so York need top do display respect and all that fun stuff if on linux, can you look for JavaFX libraries for OpenJDK?

I’d like to see an easy to use app to remove commercials, shrink file size, and export to plex at a designated time nightly. I’d like to see something like this for Mac OS X that is easy to use and maintain.

I have no coding experience at all. Just sharing a wish list…

installed
openjfx - " JavaFX/OpenJFX - Rich client application platform for Java"
jarwrapper - " Run executable Java .jar files"

not there yet. The wrapper, in case the it’s executable, or just launches with out the java -jar

Either results with the same discouraging error :frowning_face: I’ve added --show-module-resolution if it provides any more info for you (I see lines something requires something while most are something:something but maybe that’s good) I did not install jdk…

 java --show-module-resolution -jar APLTablo.jar
root java.sql jrt:/java.sql
root java.rmi jrt:/java.rmi
root jdk.management.jfr jrt:/jdk.management.jfr
root jdk.jdi jrt:/jdk.jdi
root java.logging jrt:/java.logging
root java.transaction.xa jrt:/java.transaction.xa
root java.xml.crypto jrt:/java.xml.crypto
root jdk.xml.dom jrt:/jdk.xml.dom
root java.xml jrt:/java.xml
root jdk.jfr jrt:/jdk.jfr
root java.datatransfer jrt:/java.datatransfer
root jdk.httpserver jrt:/jdk.httpserver
root jdk.net jrt:/jdk.net
root java.naming jrt:/java.naming
root java.desktop jrt:/java.desktop
root java.prefs jrt:/java.prefs
root java.net.http jrt:/java.net.http
root jdk.compiler jrt:/jdk.compiler
root java.security.sasl jrt:/java.security.sasl
root jdk.jconsole jrt:/jdk.jconsole
root jdk.attach jrt:/jdk.attach
root java.base jrt:/java.base
root jdk.javadoc jrt:/jdk.javadoc
root jdk.jshell jrt:/jdk.jshell
root java.sql.rowset jrt:/java.sql.rowset
root jdk.sctp jrt:/jdk.sctp
root jdk.jsobject jrt:/jdk.jsobject
root java.management jrt:/java.management
root jdk.unsupported jrt:/jdk.unsupported
root java.smartcardio jrt:/java.smartcardio
root jdk.scripting.nashorn jrt:/jdk.scripting.nashorn
root java.instrument jrt:/java.instrument
root java.security.jgss jrt:/java.security.jgss
root jdk.management jrt:/jdk.management
root jdk.security.auth jrt:/jdk.security.auth
root java.compiler jrt:/java.compiler
root java.scripting jrt:/java.scripting
root jdk.dynalink jrt:/jdk.dynalink
root jdk.unsupported.desktop jrt:/jdk.unsupported.desktop
root jdk.accessibility jrt:/jdk.accessibility
root jdk.jartool jrt:/jdk.jartool
root java.management.rmi jrt:/java.management.rmi
root jdk.security.jgss jrt:/jdk.security.jgss
jdk.security.jgss requires java.security.jgss jrt:/java.security.jgss
jdk.security.jgss requires java.security.sasl jrt:/java.security.sasl
jdk.security.jgss requires java.logging jrt:/java.logging
java.management.rmi requires java.naming jrt:/java.naming
java.management.rmi requires java.rmi jrt:/java.rmi
java.management.rmi requires java.management jrt:/java.management
jdk.accessibility requires java.desktop jrt:/java.desktop
jdk.unsupported.desktop requires java.desktop jrt:/java.desktop
jdk.dynalink requires java.logging jrt:/java.logging
jdk.security.auth requires java.security.jgss jrt:/java.security.jgss
jdk.security.auth requires java.naming jrt:/java.naming
jdk.management requires java.management jrt:/java.management
java.security.jgss requires java.naming jrt:/java.naming
jdk.scripting.nashorn requires jdk.dynalink jrt:/jdk.dynalink
jdk.scripting.nashorn requires java.logging jrt:/java.logging
jdk.scripting.nashorn requires java.scripting jrt:/java.scripting
jdk.jsobject requires java.desktop jrt:/java.desktop
java.sql.rowset requires java.sql jrt:/java.sql
java.sql.rowset requires java.naming jrt:/java.naming
java.sql.rowset requires java.logging jrt:/java.logging
jdk.jshell requires jdk.jdi jrt:/jdk.jdi
jdk.jshell requires jdk.internal.ed jrt:/jdk.internal.ed
jdk.jshell requires java.compiler jrt:/java.compiler
jdk.jshell requires jdk.internal.le jrt:/jdk.internal.le
jdk.jshell requires jdk.internal.opt jrt:/jdk.internal.opt
jdk.jshell requires jdk.compiler jrt:/jdk.compiler
jdk.jshell requires java.prefs jrt:/java.prefs
jdk.jshell requires java.logging jrt:/java.logging
jdk.javadoc requires jdk.compiler jrt:/jdk.compiler
jdk.javadoc requires java.xml jrt:/java.xml
jdk.javadoc requires java.compiler jrt:/java.compiler
jdk.attach requires jdk.internal.jvmstat jrt:/jdk.internal.jvmstat
jdk.jconsole requires jdk.internal.jvmstat jrt:/jdk.internal.jvmstat
jdk.jconsole requires jdk.management jrt:/jdk.management
jdk.jconsole requires java.rmi jrt:/java.rmi
jdk.jconsole requires java.desktop jrt:/java.desktop
jdk.jconsole requires java.management jrt:/java.management
jdk.jconsole requires jdk.management.agent jrt:/jdk.management.agent
jdk.jconsole requires jdk.attach jrt:/jdk.attach
jdk.jconsole requires java.management.rmi jrt:/java.management.rmi
java.security.sasl requires java.logging jrt:/java.logging
jdk.compiler requires java.compiler jrt:/java.compiler
java.prefs requires java.xml jrt:/java.xml
java.desktop requires java.prefs jrt:/java.prefs
java.desktop requires java.datatransfer jrt:/java.datatransfer
java.desktop requires java.xml jrt:/java.xml
java.naming requires java.security.sasl jrt:/java.security.sasl
jdk.xml.dom requires java.xml jrt:/java.xml
java.xml.crypto requires java.logging jrt:/java.logging
java.xml.crypto requires java.xml jrt:/java.xml
jdk.jdi requires jdk.jdwp.agent jrt:/jdk.jdwp.agent
jdk.jdi requires jdk.attach jrt:/jdk.attach
jdk.management.jfr requires java.management jrt:/java.management
jdk.management.jfr requires jdk.jfr jrt:/jdk.jfr
jdk.management.jfr requires jdk.management jrt:/jdk.management
java.rmi requires java.logging jrt:/java.logging
java.sql requires java.transaction.xa jrt:/java.transaction.xa
java.sql requires java.xml jrt:/java.xml
java.sql requires java.logging jrt:/java.logging
jdk.management.agent requires java.management.rmi jrt:/java.management.rmi
jdk.management.agent requires java.management jrt:/java.management
java.desktop binds jdk.unsupported.desktop jrt:/jdk.unsupported.desktop
jdk.dynalink binds jdk.scripting.nashorn jrt:/jdk.scripting.nashorn
java.management binds java.management.rmi jrt:/java.management.rmi
java.management binds jdk.management jrt:/jdk.management
java.management binds jdk.management.jfr jrt:/jdk.management.jfr
jdk.jshell binds jdk.editpad jrt:/jdk.editpad
java.datatransfer binds java.desktop jrt:/java.desktop
java.scripting binds jdk.scripting.nashorn jrt:/jdk.scripting.nashorn
java.compiler binds jdk.compiler jrt:/jdk.compiler
java.compiler binds jdk.javadoc jrt:/jdk.javadoc
jdk.internal.jvmstat binds jdk.jstatd jrt:/jdk.jstatd
java.naming binds jdk.naming.rmi jrt:/jdk.naming.rmi
java.naming binds jdk.naming.dns jrt:/jdk.naming.dns
java.base binds jdk.zipfs jrt:/jdk.zipfs
java.base binds jdk.localedata jrt:/jdk.localedata
java.base binds java.security.sasl jrt:/java.security.sasl
java.base binds java.security.jgss jrt:/java.security.jgss
java.base binds jdk.crypto.ec jrt:/jdk.crypto.ec
java.base binds java.naming jrt:/java.naming
java.base binds java.xml.crypto jrt:/java.xml.crypto
java.base binds java.smartcardio jrt:/java.smartcardio
java.base binds jdk.crypto.cryptoki jrt:/jdk.crypto.cryptoki
java.base binds jdk.security.jgss jrt:/jdk.security.jgss
java.base binds jdk.jlink jrt:/jdk.jlink
java.base binds jdk.jartool jrt:/jdk.jartool
java.base binds jdk.javadoc jrt:/jdk.javadoc
java.base binds jdk.jdeps jrt:/jdk.jdeps
java.base binds jdk.compiler jrt:/jdk.compiler
java.base binds java.desktop jrt:/java.desktop
java.base binds jdk.security.auth jrt:/jdk.security.auth
java.base binds java.management jrt:/java.management
java.base binds java.logging jrt:/java.logging
java.base binds jdk.charsets jrt:/jdk.charsets
jdk.jdeps requires java.compiler jrt:/java.compiler
jdk.jdeps requires jdk.compiler jrt:/jdk.compiler
jdk.jlink requires jdk.internal.opt jrt:/jdk.internal.opt
jdk.jlink requires jdk.jdeps jrt:/jdk.jdeps
jdk.crypto.cryptoki requires jdk.crypto.ec jrt:/jdk.crypto.ec
jdk.naming.dns requires java.naming jrt:/java.naming
jdk.naming.rmi requires java.naming jrt:/java.naming
jdk.naming.rmi requires java.rmi jrt:/java.rmi
jdk.jstatd requires jdk.internal.jvmstat jrt:/jdk.internal.jvmstat
jdk.jstatd requires java.rmi jrt:/java.rmi
jdk.editpad requires jdk.internal.ed jrt:/jdk.internal.ed
jdk.editpad requires java.desktop jrt:/java.desktop
Exception in thread "main" java.lang.NoClassDefFoundError: javafx/application/Application
	at java.base/java.lang.ClassLoader.defineClass1(Native Method)
	at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1016)
	at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:174)
	at java.base/java.net.URLClassLoader.defineClass(URLClassLoader.java:550)
	at java.base/java.net.URLClassLoader$1.run(URLClassLoader.java:458)
	at java.base/java.net.URLClassLoader$1.run(URLClassLoader.java:452)
	at java.base/java.security.AccessController.doPrivileged(Native Method)
	at java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:451)
	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:588)
	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
	at java.base/java.lang.Class.forName0(Native Method)
	at java.base/java.lang.Class.forName(Class.java:398)
	at org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader.main(JarRsrcLoader.java:56)
Caused by: java.lang.ClassNotFoundException: javafx.application.Application
	at java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:471)
	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:588)
	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
	... 13 more

Because JavaFX isn’t included with your JDK, you may need to add a -cp in there to include the JavaFX libraries in the run-time.

This article seems to give some suggestions on the subject

The package name is misleading openjdk11- [jre|jdk]. I have the jfx… may end up up with the entire jdk, and stuff.

So, I’ve built in support for the ComSkip capability, and used an MLT format and a tool named Shotcut (https://shotcut.org/) that marks where it thinks commercials are, allows you to remove the commercials yourself, and re-encode the file at whatever level you want without the commercials…it’s not automatic, but it allows full control

The Exports are done in a Plex friendly naming convention…but not yet in an automated fashion…you need to tell it which ones you want to export with a right click…but I do want to add some automation.

I certainly don’t want to discount this up and coming new app!

“shrink file size” is vaguely ambiguous. Commercial skip is still left to thumb taps of the media player. capto is a pre-compiled perl executable with a Mac version. wrapto is a straight up python script. If you want straight up plex, you might not ever need the wrapper. I use the system scheduler to export programs daily or weekly.

Still, I too am working to see how I can benefit from APL Tablo Client.

–it’s never good enough! at some point you have to accept it works just fine and find something else to obsess over.:neutral_face:

The way I’m doing commercial skip is to actually remove the commercials from the file. I’m using the data that either I generate, or the data that Tablo’s providing on where the commercials are, and providing an MLT file that is used in Shotcut…I then load the file up in Shotcut and remove the relevant sections and re-save the mlt, I then essentially remove the segments that have commercials and provide an updated mp4 file that doesn’t have that segment of video, so the resulting file only has what you specified for video

Were you able to get it running and did you find the Scheduled function useful?

ok, from what I’ve gotten out of it and following some of it’s links. these are sniplets:

it appears that you MUST use one of the JavaFX packaging tools

When you use one of those packaging methods, in addition to all of your application’s code and resources, it also adds the following to your output JAR file:

and all works fine. If I remove the extra com.javafx.main files, the app does not run.

Although I don’t have any java development knowledge, I open the jar in an archiver, no fx anything.

according to Deploying JavaFX Applications: Packaging Basics | JavaFX 2 Tutorials and Documentation users shouldn’t need anything special outside a run-time environment.

By default, JavaFX packaging tools produce a package that includes everything needed to provide a good user experience for various user environments, including:

Ensuring that the required Java and JavaFX Runtimes are installed

Autodownloading missing dependencies or offering to install them as needed

I suspect your IDE and/or developer system is configured to find anything for executing java apps. Then again, since I don’t actually know, I may be misinterpreting all of this and need to get back to R&D myself.

So…the problem with ‘self contained’ packages, as the link you provided indicates…it’s self contained, and must be provided for each environment intended to be run on…the JAR I produced is cross platform capable, but requires that you have both the JRE and JavaFX that is compatible…I’m happy to work through this and try what I can to find the largest of the pitfalls :). I’m running on Windows with OracleJDK, you are running on Linux with OpenJDK…so I expect there to be problems. I have a Linux box here and would be happy to try to get it running on my CentOS and see what I can do.

My non-developer understanding, if packed with javaFX packager, jfxrt.jar - or some fx jar would be included in the distributed package.


and no path to /com/javafx/main/

JavaFX Exception in thread "main" java.lang.NoClassDefFoundError: javafx/application/Application - Stack Overflow #13 as these are all for creating packages, not necessarily running them.

I hesitantly looked into (Sun) Oracle JavaSE (what is “S” it used to be R… run-time environment)
https://www.java.com/en/download/linux_manual.jsp

Oracle also provides the latest OpenJDK release under the open source GPL License at jdk.java.net.

https://openjdk.java.net/

© 2019 Oracle Corporation and/or its affiliates

4.3. Performance

There is no real technical difference between the two since the build process for the Oracle JDK is based on that of OpenJDK .

When it comes to performance, Oracle’s is much better regarding responsiveness>and JVM performance . It puts more focus on stability due to the importance it gives to >its enterprise customers.

4.5. Development and Popularity

Oracle JDK is fully developed by Oracle Corporation whereas the OpenJDK is developed by Oracle, OpenJDK, and the Java Community . However, the top-notch companies like Red Hat, Azul Systems, IBM, Apple Inc., SAP AG also take an active part in its development.

I’m looking specifically, although all the naming is similar, there is a difference with a Java SE Runtime Environment and Java SE Development Kit. Runtime Evnironment for end-users/consumers vs Java DK for developing and deploying apps.

Certainly…the JDK is for compiling Java code, the JRE is for running it…the JDK comes with a JRE, because if you are going to be compiling it, you are likely to be running it as well :). I may have misspoke earlier, I said the difference was that I was running Oracle and you were running Open…the real/true difference may be that I was running 8 and you were running 11. In Oracle 8 the JavaFX was included with the JRE, in 11, it’s not…so, what I need to be able to do is figure out what needs to be packaged where to make this run properly on Java 11…which may mean that I need to have different distributions with different jfxrt.jar included for Linux vs Windows…I’m not 100% sure on that but I’m looking into it to figure it out :slight_smile:

Linux vs Windows… there are the same/different versions for each platform, don’t see how it’s a platform issue as much as a version conflict at best.

This gets better. Look to Oracle to install 8. https://www.oracle.com/technetwork/java/javase/downloads/index.html tells me 12 is the latest release for the Java SE Platform - aka current? Looks like 11 was/is LTS. Then 8, guess 9 and 10 didn’t make it :frowning_face:. Do I really want the older version?

Certified System Configurations doesn’t list Debian, although it has Ubuntu. I suspect due to Wayland being default installation. I don’t use Wayland, and if Ubuntu with Xorg, it’s just that Debian is famous for being stable when they release “stable”.

Then reading Java SE Documentation I noticed -

Note on Data Collection

  • Information about the data Oracle collects during the installation and auto-update of the Java Runtime Environment (HTML, PDF)

do we really need this?


useless trivia. I recall reading when Oracle aquired Sun Microsystems it “killed” one of the oldest domain names. sun.com comes in 12th in the list of public registered domain names.