kiall / android-tvheadend

Android + TV Headend + TV Input Framework
Apache License 2.0
191 stars 61 forks source link

EDL Support #242

Open TheDiamondPicks opened 6 years ago

TheDiamondPicks commented 6 years ago

I've been looking into adding EDL support (in order to skip commercials, when used in conjunction with another program, e.g. comskip). As I am not entirely familiar with how HTSP works, specifically with regards to the library this project uses, so I need some help implementing the needed code.

EDL support is documented in the HTSP documentation page (https://tvheadend.org/projects/tvheadend/wiki/Htsp), under getDvrCutpoints

At this stage I have this code, which doesn't appear to work (I just wanted to see if I could get the data, its in TVHeadendPlayer at the moment (likely the wrong place to put it)):

HashMap<String, HashMap<String, String>> items = new HashMap<>();
        HashMap<String, String> id = new HashMap<>();
        id.put("id", recordingUri.toString().replace("htsp://dvrfile/", ""));
        items.put("getDvrCutpoints", id);
        HtspMessage message = new HtspMessage(items);
        try {
            mConnection.getMessageDispatcher().addMessageListener(new HtspMessage.Listener() {
                @Override
                public Handler getHandler() {
                    return null;
                }

                @Override
                public void onMessage(@NonNull HtspMessage htspMessage) {
                    Log.d("Messages", htspMessage.toString());
                }
            });
            mConnection.getMessageDispatcher().sendMessage(message);
        } catch (HtspNotConnectedException e) {
            e.printStackTrace();
        }

What is the correct way to implement this?

kiall commented 6 years ago

Something like this is what you want for calling out and getting the cutpoints, though it probably needs splitting up a bit, as we would need the addMessageListener just once, but the ability to fetch the cutpoints multiple times:

    HtspMessage message = new HtspMessage();
    message.put("method", "getDvrCutpoints");
    message.put("id", Integer.parseInt(recordingUri.getPath().substring(1)));

    try {
        mConnection.addMessageListener(new HtspMessage.Listener() {
            @Override
            public Handler getHandler() {
                return null;
            }

            @Override
            public void onMessage(@NonNull HtspMessage message) {
                HtspMessage[] cutpoints = message.getHtspMessageArray("cutpoints", null);

                // TODO: Null check...

                for (HtspMessage cutpoint : cutpoints) {
                    Log.d(TAG,"Cutpoint: Type=" + message.getInteger("type"));
                }
            }
        });
        mConnection.sendMessage(message);
    } catch (HtspNotConnectedException e) {
        e.printStackTrace();
    }

As for where it belongs, humm. I suspect TvheadendPlayer is currently the right place for the parsed data to end up - it's the player, and it should be responsible for monitoring the current presentation timestamp, and triggering the seek where necessary. The code above can be called from TvheadendPlayer.buildHtspRecordingMediaSource or maybe TvheadendPlayer.onLoadingChanged.

Looking at the hacky fast forward / rewind code I pushed a few minutes, as well as things like the radio info screens, I'd like to at some point refactor those behavious out of the main player class - but - thats future plans ;)

TheDiamondPicks commented 6 years ago

Awesome, thanks for that. I'll implement EDL support tonight.

TheDiamondPicks commented 6 years ago

I've come across bit of a stumbling block - the Target in #createMessage doesn't seem to get called for me. I suspect this is due to the same issue that means the current time is stuck on 0:00 (the duration seems to be fine). I don't know enough about ExoPlayer to try fixing this though.

kiall commented 6 years ago

If you're still stuck, post the code to a PR and I'll see if I can spot anything on Tuesday (holidays until then!)