Skip to content
Dag Wieers edited this page Feb 16, 2020 · 11 revisions

Introduction

Other video add-ons that provide playback of episodes can take control of the Up Next add-on by adhering to just one or two easy steps.

  1. On playback, send a notification to the Up Next add-on:

    • as sender plugin.video.foobar.SIGNAL (where plugin.video.foobar is the ID of your add-on)
    • as message use upnext_data
    • as data use a base64-encoded dictionary that includes:
      • information about the current episode (current_episode)
      • information about the next episode (next_episode)
      • a callback to start playing the next episode
        • either a plugin URL (play_url) to call for immediate playback (preferred)
        • or a dictionary (play_info) we send back verbatim to the calling add-on
      • optionally, a notification_time or notification_offset
  2. (Only when using play_info)
    During playback, wait for a notification from Up Next to start playing the next episode.

That completes the integration!

NOTE: The use of AddonSignals for communication is optional, for developers who prefer to implement this themselves look at the example source code.

Let us know when your add-on supports Up Next so we can add it to our list.

Data to send

The following data in JSON format should be sent to the Up Next add-on preferably as soon as playback begins.

This information should only be sent when the current item being played is an episode and there is an episode to watch next for that tv show.

The JSON object must contain three items:

  • current_episode - information about the current episode being played
  • next_episode - information about the next episode to be played, see Episode Details
  • play_info or play_url - information on how to play the next episode

And optionally one more item:

  • notification_time or notification_offset - influences the exact timing when to start the popup

Sending data to Up Next

We recommend using standard Kodi calls for sending the JSON RPC signal. See example source code for the required python code. For sending the JSON RPC signal, you would do this:

upnext_signal(sender='plugin.video.foobar', data=next_info)

If you do prefer to use AddonSignals, you would do something like:

AddonSignals.sendSignal('upnext_data', next_info, source_id='plugin.video.foobar')

NOTE: Sending this JSONRPC signal is best done from onAVStarted() on a Player instance. For Kodi v17, you can call onAVStarted() from onPlaybackStarted() as a workaround.

Your add-on will then need to support a callback mechanism to start playing the next episode.

Sender

The sender property (or source_id) that is sent with the signal message should be a unique id (for example the add-on id) that will subsequently be used to respond to calls to play the next episode.

next_info

Here is an example implementation for the next_info data structure:

next_info = dict(
    current_episode=dict(
        episodeid=item_details.id,
        tvshowid=item_details.series_id,
        title=item_details.name,
        art={
            'thumb': item_details.art.get('thumb', ''),
            'tvshow.clearart': item_details.art.get('tvshow.clearart', ''),
            'tvshow.clearlogo': item_details.art.get('tvshow.clearlogo', ''),
            'tvshow.fanart': item_details.art.get('tvshow.fanart', ''),
            'tvshow.landscape': item_details.art.get('tvshow.landscape', ''),
            'tvshow.poster': item_details.art.get('tvshow.poster', ''),
        },
        season=item_details.season_number,
        episode=item_details.episode_number,
        showtitle=item_details.series_name,
        plot=item_details.plot,
        playcount=item_details.play_count,
        rating=item_details.critic_rating,
        firstaired=item_details.year,
        runtime=item_details.runtime,  # NOTE: This is optional
    ),
    next_episode=dict(
        episodeid=next_item_details.id,
        tvshowid=next_item_details.series_name,
        title=next_item_details.name,
        art={
            'thumb': next_item_details.art.get('thumb', ''),
            'tvshow.clearart': next_item_details.art.get('tvshow.clearart', ''),
            'tvshow.clearlogo': next_item_details.art.get('tvshow.clearlogo', ''),
            'tvshow.fanart': next_item_details.art.get('tvshow.fanart', ''),
            'tvshow.landscape:': next_item_details.art.get('tvshow.landscape', ''),
            'tvshow.poster': next_item_details.art.get('tvshow.poster', ''),
        },
        season=next_item_details.season_number,
        episode=next_item_details.episode_number,
        showtitle=next_item_details.series_name,
        plot=next_item_details.plot,
        playcount=next_item_details.play_count,
        rating=next_item_details.critic_rating,
        firstaired=next_item_details.year,
        runtime=next_item_details.runtime,  # NOTE: This is optional
    ),
    # NOTE: You need to provide either `play_info` or `play_url`
    play_url='plugin://plugin.video.foobar/play_item/' + item_id,
#    play_info=dict(
#        item_id=next_item_details.id,
#    ),
    notification_time=notification_time,  # NOTE: This is optional
#    notification_offset=notification_offset,
)

NOTE: All episode keys are mandatory even if the values are empty!

Episode details

When sending information about the current_episode and next_episode to play the following structure must be provided

current_item = dict(
    episodeid='12345',  # Unique episode id
    tvshowid='67890',   # Unique TV show id
    title='Lorem ipsum dolor sit amet',  # Episode title
    art={
        'thumb': 'https://link.to/episode/thumb',  # Episode thumb
        'tvshow.clearart': 'https://link.to/tvshow/clearart',  # TV show clearart
        'tvshow.clearlogo': 'https://link.to/tvshow/clearlogo',  # TV show clearlogo
        'tvshow.fanart': 'https://link.to/tvshow/fanart',  # TV show fanart
        'tvshow.landscape': 'https://link.to/tvshow/landscape',  # TV show landscape
        'tvshow.poster': 'https://link.to/tvshow/poster',  # TV show poster
    }
    season='1',  # Episode season
    episode='1',  # Episode episode
    showtitle='Foo bar',  # TV show title
    plot='Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',  # Episode plot
    playcount=0,  # Number of times the episode was played
    rating=5,  # Episode rating
    firstaired='2020-02-14',  # Episode aired date
    runtime=2230,  # Total episode length in seconds (optional)
)

play_url vs play_info

There are two ways to make Up Next initiate the next episode.

play_url

This is by far the easiest way to initiate playing the next episode.

The URL provided here will be used to play the next episode. The Up Next add-on will call this URL when the next episode is to be started.

This may be a route into your add-on like this: plugin://plugin.video.foobar/play_item/12345

play_info

The play_info key is what will be sent back to your add-on and can contain any JSON. It should contain information that allows your add-on to playback the next episode

That may be as simple as:

play_info = dict(
    item_id=next_item_details.id,
)

Or more complicated such as:

play_info = dict(
    item_id=next_item_details.id,
    auto_resume=False,
    force_transcode=False,
)

The choice is yours, the play_info data is what gets returned to your add-on when playback is requested.

notification_time vs notification_offset (optional)

Some add-ons may know exactly when the notification should be shown (eg. they are aware of when the credits start) This notification time (in seconds before the end) can be sent across with the data.

notification_time = 30  # NOTE: Popup happens 30 seconds before the end of the current episode

In some cases the add-on has this information as an absolute offset in the video (e.g. Netflix), in that case you can do:

notification_offset = 1643  # NOTE: Popup happens at 1643 seconds into the current episode

Responding to play

When the user selected to watch the next episode, or when the current episode has ended and the default action is to play the next episode, the time has come to initiate that next episode.

When using play_url

The Up Next add-on will call the URL specified as play_url. This typically routes into your add-on again and call the function that is used for playing an episode based on the information provided in the URL.

The add-on can implement how this is taken care of as it pleases.

When using play_info

The Up Next add-on will send a message instructing your add-on to react to the play-info data that was supplied in the required data.

It will append the string play_action to the source_id that was used when sending the Up Next data across. This assures the method name called is unique between add-ons.

So with the example we used earlier we would end up with plugin.video.foobar_play_action

Your add-on should register a listener to this event by doing something along the lines of:

AddonSignals.registerSlot('upnextprovider', 'plugin.video.foobar_play_action', self.play_action)

Where the first parameter must be upnextprovider and the second parameter must be the string identified above.

Your play_action method will have the data sent from the Up Next add-on and be called when it is time to play the episode, eg.

def play_action(self, data):

Once the data is received playback of the next episode can proceed normally by getting the item_id, for example:

play_id = data['item_id']