com.oakesville.mythling.media.PlaybackOptions.java Source code

Java tutorial

Introduction

Here is the source code for com.oakesville.mythling.media.PlaybackOptions.java

Source

/**
 * Copyright 2016 Donald Oakes
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.oakesville.mythling.media;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.json.JSONException;
import org.json.JSONObject;

import com.oakesville.mythling.R;
import com.oakesville.mythling.app.AppResources;
import com.oakesville.mythling.app.AppSettings;
import com.oakesville.mythling.media.MediaSettings.MediaType;

import android.net.Uri;
import android.util.Log;

public class PlaybackOptions {
    private static final String TAG = PlaybackOptions.class.getSimpleName();

    public static final String NETWORK_INTERNAL = "internal";
    public static final String NETWORK_EXTERNAL = "external";
    public static final String NETWORK_DOWNLOAD = "download";
    public static final String PLAYER_LIBVLC = "libvlc";
    public static final String PLAYER_ANDROID = "android";
    public static final String PLAYER_APP = "app";
    public static final String STREAM_FILE = "file";
    public static final String STREAM_HLS = "hls";
    public static final String PROPERTY_ALWAYS = "always";
    public static final String PROPERTY_DEFAULT = "default";

    private AppSettings appSettings;
    private JSONObject defaultOptionsJson;

    public PlaybackOptions(AppSettings appSettings) {
        this.appSettings = appSettings;
    }

    public PlaybackOption getOption(MediaType mediaType, String fileType, String network)
            throws IOException, JSONException {
        return getOption(mediaType, fileType, network, null);
    }

    /**
     * An existing option had better match streamMode.  Example:
     *  "recordings":
     *  {
     *    "mpg":
     *    {
     *      "internal":
     *      {
     *        "file": "libvlc",
     *        "always": true
     *      },
     *      "external":
     *      {
     *        "file": "libvlc",
     *        "hls": "android"
     *      },
     *   ...
     */
    public PlaybackOption getOption(MediaType mediaType, String fileType, String network, String streamMode)
            throws IOException, JSONException {
        JSONObject json = new JSONObject(appSettings.getPlaybackOptionsJson());
        PlaybackOption playbackOption = getOption(mediaType, fileType, network, streamMode, json);
        if (playbackOption == null) {
            Log.d(TAG, "No saved playback option: " + mediaType.name() + "/" + fileType + "/" + network + "/"
                    + streamMode);
            playbackOption = getDefaultOption(mediaType, fileType, network, streamMode);
        }
        return playbackOption;
    }

    public PlaybackOption getDefaultOption(MediaType mediaType, String fileType, String network, String streamMode)
            throws IOException, JSONException {
        if (defaultOptionsJson == null) {
            AppResources appResources = new AppResources(appSettings.getAppContext());
            String jsonString = appResources.readJsonString(R.raw.default_playback_options);
            defaultOptionsJson = new JSONObject(jsonString);
        }
        PlaybackOption defaultOption = getOption(mediaType, fileType, network, streamMode, defaultOptionsJson);
        if (defaultOption == null) {
            throw new JSONException("No match in default_playback_options.json: " + mediaType.name() + "/"
                    + fileType + "/" + network + "/" + streamMode);
        }

        // overrule default playback option where LIBVLC not supported by CPU
        if (PLAYER_LIBVLC.equals(defaultOption.getPlayer()) && !appSettings.isCpuCompatibleWithLibVlcPlayer())
            defaultOption.setPlayer(PLAYER_ANDROID);

        return defaultOption;
    }

    /**
     * Sets the one-and-only player for the stream type in the option parameter.
     */
    public void setOption(MediaType mediaType, String fileType, String network, PlaybackOption option)
            throws JSONException {
        JSONObject json = new JSONObject(appSettings.getPlaybackOptionsJson());
        JSONObject mt = null;
        if (json.has(mediaType.name())) {
            mt = json.getJSONObject(mediaType.name());
        } else {
            mt = new JSONObject();
            json.put(mediaType.name(), mt);
        }
        JSONObject ft = null;
        if (mt.has(fileType)) {
            ft = mt.getJSONObject(fileType);
        } else {
            ft = new JSONObject();
            mt.put(fileType, ft);
        }
        if (option.always) {
            appSettings.setAlwaysPromptForPlaybackOptions(false);
            // obliterate any existing stream type since this itself is a pref
            JSONObject net = new JSONObject();
            net.put(option.stream, option.player);
            net.put(PROPERTY_ALWAYS, true);
            ft.put(network, net);
        } else {
            JSONObject net;
            if (ft.has(network)) {
                net = ft.getJSONObject(network);
                if (net.has(PROPERTY_ALWAYS))
                    net.remove(PROPERTY_ALWAYS);
            } else {
                net = new JSONObject();
                ft.put(network, net);
            }
            net.put(option.stream, option.player);
            // set this stream option as the default
            if (net.has(PROPERTY_DEFAULT))
                net.remove(PROPERTY_DEFAULT);
            JSONObject def = new JSONObject();
            def.put(option.stream, option.player);
            net.put(PROPERTY_DEFAULT, def);
        }
        appSettings.setPlaybackOptionsJson(json.toString());
    }

    public String getDefaultPlayer() {
        return PLAYER_LIBVLC;
    }

    public void clearAlwaysDoThisSettings() throws JSONException {
        JSONObject json = new JSONObject(appSettings.getPlaybackOptionsJson());
        Iterator<String> mtKeys = json.keys();
        while (mtKeys.hasNext()) {
            JSONObject mt = json.getJSONObject(mtKeys.next());
            Iterator<String> ftKeys = mt.keys();
            while (ftKeys.hasNext()) {
                JSONObject ft = mt.getJSONObject(ftKeys.next());
                Iterator<String> netKeys = ft.keys();
                while (netKeys.hasNext()) {
                    JSONObject net = ft.getJSONObject(netKeys.next());
                    if (net.has(PROPERTY_ALWAYS))
                        net.remove(PROPERTY_ALWAYS);
                }
            }
        }
        appSettings.setPlaybackOptionsJson(json.toString());
    }

    public void clearAll() {
        appSettings.setPlaybackOptionsJson("{}");
    }

    /**
     * Passing streamMode of null should return the one-and-only mode, or the default.
     */
    private PlaybackOption getOption(MediaType mediaType, String fileType, String network, String streamMode,
            JSONObject json) throws JSONException {
        PlaybackOption option = null;
        JSONObject mt = null;
        if (json.has(mediaType.name()))
            mt = json.getJSONObject(mediaType.name());
        else if (json.has(PROPERTY_DEFAULT))
            mt = json.getJSONObject(PROPERTY_DEFAULT);
        if (mt != null) {
            JSONObject ft = null;
            if (mt.has(fileType))
                ft = mt.getJSONObject(fileType);
            else if (mt.has(PROPERTY_DEFAULT))
                ft = mt.getJSONObject(PROPERTY_DEFAULT);
            if (ft != null) {
                JSONObject net = null;
                if (ft.has(network))
                    net = ft.getJSONObject(network);
                else if (ft.has(PROPERTY_DEFAULT))
                    net = ft.getJSONObject(PROPERTY_DEFAULT);
                if (net != null) {
                    String player = null;
                    if (streamMode == null) {
                        if (net.has(PROPERTY_DEFAULT)) {
                            JSONObject def = net.getJSONObject(PROPERTY_DEFAULT);
                            streamMode = def.keys().next();
                            player = def.getString(streamMode);
                        } else {
                            // return any match (should be only one -- ie: download in default_playback_options)
                            Iterator<String> keys = net.keys();
                            while (keys.hasNext()) {
                                String key = keys.next();
                                if (!key.equals(PROPERTY_ALWAYS)) {
                                    streamMode = key;
                                    player = net.getString(key);
                                }
                            }
                        }
                    } else if (net.has(streamMode)) {
                        player = net.getString(streamMode);
                    }
                    if (player != null) {
                        option = new PlaybackOption(streamMode, player);
                        if (net.has(PROPERTY_ALWAYS))
                            option.setAlways(net.getBoolean(PROPERTY_ALWAYS));
                    }
                }
            }
        }

        return option;
    }

    public List<String> getMediaOptions(String player) {
        List<String> options = new ArrayList<String>();
        if (player.equals(PLAYER_LIBVLC))
            options = appSettings.getVlcMediaOptions();
        else if (player.equals(PLAYER_ANDROID)) {
            if (appSettings.isProxyAndroicAuthenticatedPlayback())
                options.add(AppSettings.PROXY_ANDROID_AUTHENTICATED_PLAYBACK);
        }
        return options;
    }

    public static boolean isHls(Uri videoUri) {
        String lastPathSeg = videoUri.getLastPathSegment();
        if (lastPathSeg != null) {
            int lastDot = lastPathSeg.lastIndexOf('.');
            if (lastDot > 0)
                return "m3u8".equals(lastPathSeg.substring(lastDot + 1));
        }
        return false;
    }

    public static class PlaybackOption {

        public PlaybackOption(String stream, String player) {
            this(stream, player, false);
        }

        public PlaybackOption(String stream, String player, boolean always) {
            this.stream = stream;
            this.player = player;
            this.always = always;
        }

        private String stream;

        public String getStream() {
            return stream;
        }

        public void setStream(String stream) {
            this.stream = stream;
        }

        public boolean isHls() {
            return STREAM_HLS.equals(stream);
        }

        private String player;

        public String getPlayer() {
            return player;
        }

        public void setPlayer(String player) {
            this.player = player;
        }

        public boolean isAppPlayer() {
            return PLAYER_APP.equals(player);
        }

        private boolean always;

        public boolean isAlways() {
            return always;
        }

        public void setAlways(boolean always) {
            this.always = always;
        }

        public String toString() {
            return stream + ": " + player + (always ? ", always: true" : "");
        }
    }
}