2015-01-14 12:12:47 +01:00
|
|
|
/*
|
|
|
|
* Copyright 2015 Synced Synapse. All rights reserved.
|
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*/
|
2015-03-09 22:35:18 +01:00
|
|
|
package org.xbmc.kore.host;
|
2015-01-14 12:12:47 +01:00
|
|
|
|
|
|
|
import android.content.ContentValues;
|
|
|
|
import android.content.Context;
|
2015-03-11 19:38:59 +01:00
|
|
|
import android.content.SharedPreferences;
|
2015-01-14 12:12:47 +01:00
|
|
|
import android.database.Cursor;
|
|
|
|
import android.net.Uri;
|
2016-11-15 20:09:23 +01:00
|
|
|
import android.os.Handler;
|
2015-03-11 19:38:59 +01:00
|
|
|
import android.preference.PreferenceManager;
|
2016-11-15 20:09:23 +01:00
|
|
|
import android.text.format.DateUtils;
|
2015-04-18 11:52:31 +02:00
|
|
|
|
|
|
|
import com.squareup.okhttp.OkHttpClient;
|
|
|
|
import com.squareup.picasso.OkHttpDownloader;
|
2015-01-14 12:12:47 +01:00
|
|
|
import com.squareup.picasso.Picasso;
|
2015-04-18 11:52:31 +02:00
|
|
|
|
2015-03-09 22:35:18 +01:00
|
|
|
import org.xbmc.kore.Settings;
|
2016-11-15 20:09:23 +01:00
|
|
|
import org.xbmc.kore.jsonrpc.ApiCallback;
|
2015-03-09 22:35:18 +01:00
|
|
|
import org.xbmc.kore.jsonrpc.HostConnection;
|
2016-11-15 20:09:23 +01:00
|
|
|
import org.xbmc.kore.jsonrpc.method.Application;
|
|
|
|
import org.xbmc.kore.jsonrpc.type.ApplicationType;
|
2015-03-09 22:35:18 +01:00
|
|
|
import org.xbmc.kore.provider.MediaContract;
|
|
|
|
import org.xbmc.kore.utils.LogUtils;
|
2015-04-18 11:52:31 +02:00
|
|
|
import org.xbmc.kore.utils.NetUtils;
|
2015-01-14 12:12:47 +01:00
|
|
|
|
2015-04-18 11:52:31 +02:00
|
|
|
import java.io.File;
|
2015-01-14 12:12:47 +01:00
|
|
|
import java.util.ArrayList;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Manages XBMC Hosts
|
|
|
|
* Singleton that loads the list of registered hosts, keeps a
|
|
|
|
* {@link HostConnection} to the active host
|
|
|
|
* and allows for creation and removal of hosts
|
|
|
|
*/
|
|
|
|
public class HostManager {
|
|
|
|
private static final String TAG = LogUtils.makeLogTag(HostManager.class);
|
|
|
|
|
|
|
|
// Singleton instance
|
|
|
|
private static volatile HostManager instance = null;
|
|
|
|
|
|
|
|
private Context context;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Arraylist that will hold all the hosts in the database
|
|
|
|
*/
|
|
|
|
private ArrayList<HostInfo> hosts = new ArrayList<HostInfo>();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Current host
|
|
|
|
*/
|
|
|
|
private HostInfo currentHostInfo = null;
|
|
|
|
/**
|
|
|
|
* Current host connection
|
|
|
|
*/
|
|
|
|
private HostConnection currentHostConnection = null;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Picasso to download images from current XBMC
|
|
|
|
*/
|
|
|
|
private Picasso currentPicasso = null;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Current connection observer
|
|
|
|
*/
|
|
|
|
private HostConnectionObserver currentHostConnectionObserver = null;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Singleton constructor
|
|
|
|
* @param context Context (can pass Activity context, will get App Context)
|
|
|
|
*/
|
|
|
|
protected HostManager(Context context) {
|
|
|
|
this.context = context.getApplicationContext();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Singleton access method
|
|
|
|
* @param context Android app context
|
|
|
|
* @return HostManager singleton
|
|
|
|
*/
|
|
|
|
public static HostManager getInstance(Context context) {
|
|
|
|
if (instance == null) {
|
|
|
|
synchronized (HostManager.class) {
|
|
|
|
if (instance == null) {
|
|
|
|
instance = new HostManager(context);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return instance;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the current host list
|
|
|
|
* @return Host list
|
|
|
|
*/
|
|
|
|
public ArrayList<HostInfo> getHosts() {
|
|
|
|
return getHosts(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the current host list, maybe forcing a reload from the database
|
|
|
|
* @param forcedReload Whether to force a reload from the database
|
|
|
|
* @return Host list
|
|
|
|
*/
|
|
|
|
public ArrayList<HostInfo> getHosts(boolean forcedReload) {
|
2016-06-29 12:04:24 +02:00
|
|
|
if (forcedReload || (hosts.isEmpty())) {
|
2015-01-14 12:12:47 +01:00
|
|
|
hosts.clear();
|
|
|
|
|
|
|
|
Cursor cursor = context.getContentResolver()
|
|
|
|
.query(MediaContract.Hosts.CONTENT_URI,
|
|
|
|
MediaContract.Hosts.ALL_COLUMNS,
|
|
|
|
null, null, null);
|
2015-04-13 23:59:49 +02:00
|
|
|
if (cursor == null) return hosts;
|
2015-01-14 12:12:47 +01:00
|
|
|
|
|
|
|
if (cursor.getCount() > 0) {
|
|
|
|
while (cursor.moveToNext()) {
|
|
|
|
int idx = 0;
|
|
|
|
int id = cursor.getInt(idx++);
|
|
|
|
long updated = cursor.getLong(idx++);
|
|
|
|
String name = cursor.getString(idx++);
|
|
|
|
String address = cursor.getString(idx++);
|
|
|
|
int protocol = cursor.getInt(idx++);
|
|
|
|
int httpPort = cursor.getInt(idx++);
|
|
|
|
int tcpPort = cursor.getInt(idx++);
|
|
|
|
String username = cursor.getString(idx++);
|
|
|
|
String password = cursor.getString(idx++);
|
|
|
|
String macAddress = cursor.getString(idx++);
|
|
|
|
int wolPort = cursor.getInt(idx++);
|
2015-06-21 16:04:54 +02:00
|
|
|
boolean useEventServer = (cursor.getInt(idx++) != 0);
|
|
|
|
int eventServerPort = cursor.getInt(idx++);
|
2015-01-14 12:12:47 +01:00
|
|
|
|
2016-11-15 20:09:23 +01:00
|
|
|
int kodiVersionMajor = cursor.getInt(idx++);
|
|
|
|
int kodiVersionMinor = cursor.getInt(idx++);
|
|
|
|
String kodiVersionRevision = cursor.getString(idx++);
|
|
|
|
String kodiVersionTag = cursor.getString(idx++);
|
2017-01-27 16:17:39 +01:00
|
|
|
boolean isHttps = (cursor.getInt(idx++) != 0);
|
2016-11-15 20:09:23 +01:00
|
|
|
|
|
|
|
hosts.add(new HostInfo(
|
|
|
|
id, name, address, protocol, httpPort, tcpPort,
|
|
|
|
username, password, macAddress, wolPort, useEventServer, eventServerPort,
|
|
|
|
kodiVersionMajor, kodiVersionMinor, kodiVersionRevision, kodiVersionTag,
|
2017-01-27 16:17:39 +01:00
|
|
|
updated, isHttps));
|
2015-01-14 12:12:47 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
cursor.close();
|
|
|
|
}
|
|
|
|
return hosts;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the current active host info
|
|
|
|
* @return Active host info
|
|
|
|
*/
|
|
|
|
public HostInfo getHostInfo() {
|
|
|
|
if (currentHostInfo == null) {
|
2015-03-11 19:38:59 +01:00
|
|
|
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
|
|
|
int currentHostId = prefs.getInt(Settings.KEY_PREF_CURRENT_HOST_ID, Settings.DEFAULT_PREF_CURRENT_HOST_ID);
|
|
|
|
|
2015-01-14 12:12:47 +01:00
|
|
|
ArrayList<HostInfo> hosts = getHosts();
|
|
|
|
|
|
|
|
// No host selected. Check if there are hosts configured and default to the first one
|
2015-03-11 19:38:59 +01:00
|
|
|
if (currentHostId == -1) {
|
2016-06-29 12:04:24 +02:00
|
|
|
if (!hosts.isEmpty()) {
|
2015-01-14 12:12:47 +01:00
|
|
|
currentHostInfo = hosts.get(0);
|
2015-03-11 19:38:59 +01:00
|
|
|
currentHostId = currentHostInfo.getId();
|
|
|
|
prefs.edit()
|
|
|
|
.putInt(Settings.KEY_PREF_CURRENT_HOST_ID, currentHostId)
|
|
|
|
.apply();
|
2015-01-14 12:12:47 +01:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
for (HostInfo host : hosts) {
|
2015-03-11 19:38:59 +01:00
|
|
|
if (host.getId() == currentHostId) {
|
2015-01-14 12:12:47 +01:00
|
|
|
currentHostInfo = host;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return currentHostInfo;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the current active host connection
|
|
|
|
* @return Active host connection
|
|
|
|
*/
|
|
|
|
public HostConnection getConnection() {
|
|
|
|
if (currentHostConnection == null) {
|
Tweak connection threads
This PR fixes some issues with connections and threading. Specifically, the change in #618 introduced threading in `HostConnection`, which had some issues. To fix them, the following changes were made:
- A specific TCP listener thread is used and manually started, instead of using one of the threads in the pool. The TCP listener thread is a long lived thread that should always be running (as long as the connection is through TCP), blocked listening on the TCP socket, so it shouldn't be managed in a pool, where, theoretically, it can be paused and reused.
- Changed the number of threads to 5. We shouldn't need more than this, otherwise we can overwhelm some Kodi hardware.
- Had to sprinkle some `synchronized` to avoid race conditions. For instance, through a TCP connection, as soon as Kore is opened (on the remote screen) it will call at least `GetActivePlayers`, `GetProperties`, `Ping`. If the TCP socket isn't set up yet, each of these calls would create a socket (and a TCP listener thread), so we would open 3 or more sockets when we should just open 1. A `synchronized` in `executeThroughTcp` prevents this. The others prevent similar issues.
Aditionally:
- Tweaked the playlist fetching code, so that it happens exclusively in `HostConnectionObserver` and when PlaylistFragment is notified of changes, it already gets the playlist data. This somewhat simplifies the code, and makes it more consistent with the Player Observer code;
- Change `EventServerConnection` to accept a Handler on which to post the result of the connection, so that the caller can control on which thread the result is called;
- Calls to the various `RegisterObserver` loose the reply immediately parameter, as it was always true.
2019-05-28 20:44:02 +02:00
|
|
|
synchronized (this) {
|
|
|
|
if (currentHostConnection == null) {
|
|
|
|
currentHostInfo = getHostInfo();
|
2015-01-14 12:12:47 +01:00
|
|
|
|
Tweak connection threads
This PR fixes some issues with connections and threading. Specifically, the change in #618 introduced threading in `HostConnection`, which had some issues. To fix them, the following changes were made:
- A specific TCP listener thread is used and manually started, instead of using one of the threads in the pool. The TCP listener thread is a long lived thread that should always be running (as long as the connection is through TCP), blocked listening on the TCP socket, so it shouldn't be managed in a pool, where, theoretically, it can be paused and reused.
- Changed the number of threads to 5. We shouldn't need more than this, otherwise we can overwhelm some Kodi hardware.
- Had to sprinkle some `synchronized` to avoid race conditions. For instance, through a TCP connection, as soon as Kore is opened (on the remote screen) it will call at least `GetActivePlayers`, `GetProperties`, `Ping`. If the TCP socket isn't set up yet, each of these calls would create a socket (and a TCP listener thread), so we would open 3 or more sockets when we should just open 1. A `synchronized` in `executeThroughTcp` prevents this. The others prevent similar issues.
Aditionally:
- Tweaked the playlist fetching code, so that it happens exclusively in `HostConnectionObserver` and when PlaylistFragment is notified of changes, it already gets the playlist data. This somewhat simplifies the code, and makes it more consistent with the Player Observer code;
- Change `EventServerConnection` to accept a Handler on which to post the result of the connection, so that the caller can control on which thread the result is called;
- Calls to the various `RegisterObserver` loose the reply immediately parameter, as it was always true.
2019-05-28 20:44:02 +02:00
|
|
|
if (currentHostInfo != null) {
|
|
|
|
currentHostConnection = new HostConnection(currentHostInfo);
|
|
|
|
}
|
|
|
|
}
|
2015-01-14 12:12:47 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return currentHostConnection;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the current host {@link Picasso} image downloader
|
|
|
|
* @return {@link Picasso} instance suitable to download images from the current xbmc
|
|
|
|
*/
|
|
|
|
public Picasso getPicasso() {
|
|
|
|
if (currentPicasso == null) {
|
|
|
|
currentHostInfo = getHostInfo();
|
|
|
|
if (currentHostInfo != null) {
|
2015-04-18 11:52:31 +02:00
|
|
|
// currentPicasso = new Picasso.Builder(context)
|
|
|
|
// .downloader(new BasicAuthUrlConnectionDownloader(context,
|
|
|
|
// currentHostInfo.getUsername(), currentHostInfo.getPassword()))
|
|
|
|
// .indicatorsEnabled(BuildConfig.DEBUG)
|
|
|
|
// .build();
|
|
|
|
|
|
|
|
// Http client should already handle authentication
|
|
|
|
OkHttpClient picassoClient = getConnection().getOkHttpClient().clone();
|
|
|
|
|
|
|
|
// OkHttpClient picassoClient = new OkHttpClient();
|
|
|
|
// // Set authentication on the client
|
|
|
|
// if (!TextUtils.isEmpty(currentHostInfo.getUsername())) {
|
|
|
|
// picassoClient.interceptors().add(new Interceptor() {
|
|
|
|
// @Override
|
|
|
|
// public Response intercept(Chain chain) throws IOException {
|
|
|
|
//
|
|
|
|
// String creds = currentHostInfo.getUsername() + ":" + currentHostInfo.getPassword();
|
|
|
|
// Request newRequest = chain.request().newBuilder()
|
|
|
|
// .addHeader("Authorization",
|
|
|
|
// "Basic " + Base64.encodeToString(creds.getBytes(), Base64.NO_WRAP))
|
|
|
|
// .build();
|
|
|
|
// return chain.proceed(newRequest);
|
|
|
|
// }
|
|
|
|
// });
|
|
|
|
// }
|
|
|
|
|
|
|
|
// Set cache
|
|
|
|
File cacheDir = NetUtils.createDefaultCacheDir(context);
|
|
|
|
long cacheSize = NetUtils.calculateDiskCacheSize(cacheDir);
|
|
|
|
picassoClient.setCache(new com.squareup.okhttp.Cache(cacheDir,cacheSize));
|
|
|
|
|
2015-01-14 12:12:47 +01:00
|
|
|
currentPicasso = new Picasso.Builder(context)
|
2015-04-18 11:52:31 +02:00
|
|
|
.downloader(new OkHttpDownloader(picassoClient))
|
|
|
|
// .indicatorsEnabled(BuildConfig.DEBUG)
|
2015-01-14 12:12:47 +01:00
|
|
|
.build();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return currentPicasso;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the current {@link HostConnectionObserver} for the current connection
|
|
|
|
* @return The {@link HostConnectionObserver} for the current connection
|
|
|
|
*/
|
|
|
|
public HostConnectionObserver getHostConnectionObserver() {
|
|
|
|
if (currentHostConnectionObserver == null) {
|
|
|
|
currentHostConnection = getConnection();
|
|
|
|
if (currentHostConnection != null) {
|
|
|
|
currentHostConnectionObserver = new HostConnectionObserver(currentHostConnection);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return currentHostConnectionObserver;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Sets the current host.
|
|
|
|
* @param hostInfo Host info
|
|
|
|
*/
|
|
|
|
public void switchHost(HostInfo hostInfo) {
|
|
|
|
releaseCurrentHost();
|
|
|
|
|
|
|
|
currentHostInfo = hostInfo;
|
|
|
|
if (currentHostInfo != null) {
|
2015-03-11 19:38:59 +01:00
|
|
|
PreferenceManager.getDefaultSharedPreferences(context)
|
|
|
|
.edit()
|
|
|
|
.putInt(Settings.KEY_PREF_CURRENT_HOST_ID, currentHostInfo.getId())
|
|
|
|
.apply();
|
2015-01-14 12:12:47 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// /**
|
|
|
|
// * Sets the current host.
|
|
|
|
// * Throws {@link java.lang.IllegalArgumentException} if the host doesn't exist
|
|
|
|
// * @param hostId Host id
|
|
|
|
// */
|
|
|
|
// public void switchHost(int hostId) {
|
|
|
|
// ArrayList<HostInfo> hosts = getHosts();
|
|
|
|
// HostInfo newHostInfo = null;
|
|
|
|
//
|
|
|
|
// for (HostInfo host : hosts) {
|
|
|
|
// if (host.getId() == hostId) {
|
|
|
|
// newHostInfo = host;
|
|
|
|
// break;
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// if (newHostInfo == null) {
|
|
|
|
// throw new IllegalArgumentException("Host doesn't exist!");
|
|
|
|
// }
|
|
|
|
// switchHost(newHostInfo);
|
|
|
|
// }
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Adds a new XBMC host to the database
|
|
|
|
* @param hostInfo Host to add
|
2015-03-09 22:35:18 +01:00
|
|
|
* @return Newly created {@link org.xbmc.kore.host.HostInfo}
|
2015-01-14 12:12:47 +01:00
|
|
|
*/
|
|
|
|
public HostInfo addHost(HostInfo hostInfo) {
|
|
|
|
return addHost(hostInfo.getName(), hostInfo.getAddress(), hostInfo.getProtocol(),
|
2015-06-21 16:04:54 +02:00
|
|
|
hostInfo.getHttpPort(), hostInfo.getTcpPort(),
|
|
|
|
hostInfo.getUsername(), hostInfo.getPassword(),
|
|
|
|
hostInfo.getMacAddress(), hostInfo.getWolPort(),
|
2016-11-15 20:09:23 +01:00
|
|
|
hostInfo.getUseEventServer(), hostInfo.getEventServerPort(),
|
|
|
|
hostInfo.getKodiVersionMajor(), hostInfo.getKodiVersionMinor(),
|
2017-01-27 16:17:39 +01:00
|
|
|
hostInfo.getKodiVersionRevision(), hostInfo.getKodiVersionTag(),
|
|
|
|
hostInfo.isHttps);
|
2015-01-14 12:12:47 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Adds a new XBMC host to the database
|
|
|
|
* @param name Name of this instance
|
|
|
|
* @param address Hostname or IP Address
|
|
|
|
* @param protocol Protocol to use
|
|
|
|
* @param httpPort HTTP port
|
|
|
|
* @param tcpPort TCP port
|
|
|
|
* @param username Username for HTTP
|
|
|
|
* @param password Password for HTTP
|
2015-03-09 22:35:18 +01:00
|
|
|
* @return Newly created {@link org.xbmc.kore.host.HostInfo}
|
2015-01-14 12:12:47 +01:00
|
|
|
*/
|
|
|
|
public HostInfo addHost(String name, String address, int protocol, int httpPort, int tcpPort,
|
2015-06-21 16:04:54 +02:00
|
|
|
String username, String password, String macAddress, int wolPort,
|
2016-11-15 20:09:23 +01:00
|
|
|
boolean useEventServer, int eventServerPort,
|
2017-01-27 16:17:39 +01:00
|
|
|
int kodiVersionMajor, int kodiVersionMinor, String kodiVersionRevision, String kodiVersionTag,
|
|
|
|
boolean isHttps) {
|
2015-01-14 12:12:47 +01:00
|
|
|
|
|
|
|
ContentValues values = new ContentValues();
|
|
|
|
values.put(MediaContract.HostsColumns.NAME, name);
|
|
|
|
values.put(MediaContract.HostsColumns.ADDRESS, address);
|
|
|
|
values.put(MediaContract.HostsColumns.PROTOCOL, protocol);
|
|
|
|
values.put(MediaContract.HostsColumns.HTTP_PORT, httpPort);
|
|
|
|
values.put(MediaContract.HostsColumns.TCP_PORT, tcpPort);
|
|
|
|
values.put(MediaContract.HostsColumns.USERNAME, username);
|
|
|
|
values.put(MediaContract.HostsColumns.PASSWORD, password);
|
|
|
|
values.put(MediaContract.HostsColumns.MAC_ADDRESS, macAddress);
|
|
|
|
values.put(MediaContract.HostsColumns.WOL_PORT, wolPort);
|
2015-06-21 16:04:54 +02:00
|
|
|
values.put(MediaContract.HostsColumns.USE_EVENT_SERVER, useEventServer);
|
|
|
|
values.put(MediaContract.HostsColumns.EVENT_SERVER_PORT, eventServerPort);
|
2016-11-15 20:09:23 +01:00
|
|
|
values.put(MediaContract.HostsColumns.KODI_VERSION_MAJOR, kodiVersionMajor);
|
|
|
|
values.put(MediaContract.HostsColumns.KODI_VERSION_MINOR, kodiVersionMinor);
|
|
|
|
values.put(MediaContract.HostsColumns.KODI_VERSION_REVISION, kodiVersionRevision);
|
|
|
|
values.put(MediaContract.HostsColumns.KODI_VERSION_TAG, kodiVersionTag);
|
2017-01-27 16:17:39 +01:00
|
|
|
values.put(MediaContract.HostsColumns.IS_HTTPS, isHttps);
|
|
|
|
|
2016-11-15 20:09:23 +01:00
|
|
|
|
2015-01-14 12:12:47 +01:00
|
|
|
Uri newUri = context.getContentResolver()
|
|
|
|
.insert(MediaContract.Hosts.CONTENT_URI, values);
|
|
|
|
long newId = Long.valueOf(MediaContract.Hosts.getHostId(newUri));
|
|
|
|
|
|
|
|
// Refresh the list and return the created host
|
|
|
|
hosts = getHosts(true);
|
|
|
|
HostInfo newHost = null;
|
|
|
|
for (HostInfo host : hosts) {
|
|
|
|
if (host.getId() == newId) {
|
|
|
|
newHost = host;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return newHost;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Edits a host on the database
|
|
|
|
* @param hostId Id of the host to edit
|
|
|
|
* @param newHostInfo New values to update
|
|
|
|
* @return New {@link HostInfo} object
|
|
|
|
*/
|
|
|
|
public HostInfo editHost(int hostId, HostInfo newHostInfo) {
|
|
|
|
ContentValues values = new ContentValues();
|
|
|
|
values.put(MediaContract.HostsColumns.NAME, newHostInfo.getName());
|
|
|
|
values.put(MediaContract.HostsColumns.ADDRESS, newHostInfo.getAddress());
|
|
|
|
values.put(MediaContract.HostsColumns.PROTOCOL, newHostInfo.getProtocol());
|
|
|
|
values.put(MediaContract.HostsColumns.HTTP_PORT, newHostInfo.getHttpPort());
|
|
|
|
values.put(MediaContract.HostsColumns.TCP_PORT, newHostInfo.getTcpPort());
|
|
|
|
values.put(MediaContract.HostsColumns.USERNAME, newHostInfo.getUsername());
|
|
|
|
values.put(MediaContract.HostsColumns.PASSWORD, newHostInfo.getPassword());
|
|
|
|
values.put(MediaContract.HostsColumns.MAC_ADDRESS, newHostInfo.getMacAddress());
|
|
|
|
values.put(MediaContract.HostsColumns.WOL_PORT, newHostInfo.getWolPort());
|
2015-06-21 16:04:54 +02:00
|
|
|
values.put(MediaContract.HostsColumns.USE_EVENT_SERVER, newHostInfo.getUseEventServer());
|
|
|
|
values.put(MediaContract.HostsColumns.EVENT_SERVER_PORT, newHostInfo.getEventServerPort());
|
2016-11-15 20:09:23 +01:00
|
|
|
values.put(MediaContract.HostsColumns.KODI_VERSION_MAJOR, newHostInfo.getKodiVersionMajor());
|
|
|
|
values.put(MediaContract.HostsColumns.KODI_VERSION_MINOR, newHostInfo.getKodiVersionMinor());
|
|
|
|
values.put(MediaContract.HostsColumns.KODI_VERSION_REVISION, newHostInfo.getKodiVersionRevision());
|
|
|
|
values.put(MediaContract.HostsColumns.KODI_VERSION_TAG, newHostInfo.getKodiVersionTag());
|
2017-01-27 16:17:39 +01:00
|
|
|
values.put(MediaContract.HostsColumns.IS_HTTPS, newHostInfo.isHttps);
|
2016-11-15 20:09:23 +01:00
|
|
|
|
2015-01-14 12:12:47 +01:00
|
|
|
context.getContentResolver()
|
|
|
|
.update(MediaContract.Hosts.buildHostUri(hostId), values, null, null);
|
|
|
|
|
|
|
|
// Refresh the list and return the created host
|
|
|
|
hosts = getHosts(true);
|
|
|
|
HostInfo newHost = null;
|
|
|
|
for (HostInfo host : hosts) {
|
|
|
|
if (host.getId() == hostId) {
|
|
|
|
newHost = host;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return newHost;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Deletes a host from the database.
|
|
|
|
* If the delete host is the current one, we will try too change the current one to another
|
|
|
|
* or set it to null if there's no other
|
|
|
|
* @param hostId Id of the host to delete
|
|
|
|
*/
|
|
|
|
public void deleteHost(final int hostId) {
|
|
|
|
// Async call delete. The triggers to delete all host information can take some time
|
|
|
|
new Thread(new Runnable() {
|
|
|
|
@Override
|
|
|
|
public void run() {
|
|
|
|
context.getContentResolver()
|
|
|
|
.delete(MediaContract.Hosts.buildHostUri(hostId), null, null);
|
|
|
|
}
|
|
|
|
}).start();
|
|
|
|
|
|
|
|
// Refresh information
|
|
|
|
int index = -1;
|
|
|
|
for (int i = 0; i < hosts.size(); i++) {
|
|
|
|
if (hosts.get(i).getId() == hostId) {
|
|
|
|
index = i;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (index != -1)
|
|
|
|
hosts.remove(index);
|
|
|
|
// If we just deleted the current connection, switch to another
|
|
|
|
if ((currentHostInfo != null) && (currentHostInfo.getId() == hostId)) {
|
|
|
|
releaseCurrentHost();
|
2016-06-29 12:04:24 +02:00
|
|
|
if (!hosts.isEmpty())
|
2015-01-14 12:12:47 +01:00
|
|
|
switchHost(hosts.get(0));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Releases all state related to the current connection
|
|
|
|
*/
|
|
|
|
private void releaseCurrentHost() {
|
|
|
|
if (currentHostConnectionObserver != null) {
|
2015-02-15 20:11:32 +01:00
|
|
|
currentHostConnectionObserver.stopObserving();
|
2015-01-14 12:12:47 +01:00
|
|
|
currentHostConnectionObserver = null;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (currentHostConnection != null) {
|
|
|
|
currentHostConnection.disconnect();
|
|
|
|
currentHostConnection = null;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (currentPicasso != null) {
|
|
|
|
// Calling shutdown here causes a picasso error:
|
|
|
|
// Handler (com.squareup.picasso.Stats$StatsHandler) {41b13d40} sending message to a Handler on a dead thread
|
|
|
|
// Check: https://github.com/square/picasso/issues/445
|
|
|
|
// So, for now, just let it be...
|
|
|
|
// currentPicasso.shutdown();
|
|
|
|
currentPicasso = null;
|
|
|
|
}
|
|
|
|
}
|
2016-11-15 20:09:23 +01:00
|
|
|
|
2019-02-08 18:25:21 +01:00
|
|
|
// Check Kodi's version every 2 hours
|
|
|
|
private final static long KODI_VERSION_CHECK_INTERVAL_MILLIS = 2 * DateUtils.HOUR_IN_MILLIS;
|
2016-11-15 20:09:23 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Periodic checks Kodi's version and updates the DB to reflect that.
|
|
|
|
* This should be called somewhere that gets executed periodically
|
|
|
|
*
|
|
|
|
*/
|
2019-02-08 18:25:21 +01:00
|
|
|
public void checkAndUpdateKodiVersion() {
|
|
|
|
if (currentHostInfo == null) {
|
|
|
|
currentHostInfo = getHostInfo();
|
|
|
|
if (currentHostInfo == null) return;
|
|
|
|
}
|
2016-11-16 13:10:20 +01:00
|
|
|
|
2019-02-08 18:25:21 +01:00
|
|
|
if (currentHostInfo.getUpdated() + KODI_VERSION_CHECK_INTERVAL_MILLIS < java.lang.System.currentTimeMillis()) {
|
2016-11-15 20:09:23 +01:00
|
|
|
LogUtils.LOGD(TAG, "Checking Kodi version...");
|
|
|
|
final Application.GetProperties getProperties = new Application.GetProperties(Application.GetProperties.VERSION);
|
2019-02-08 18:25:21 +01:00
|
|
|
getProperties.execute(getConnection(), new ApiCallback<ApplicationType.PropertyValue>() {
|
2016-11-15 20:09:23 +01:00
|
|
|
@Override
|
|
|
|
public void onSuccess(ApplicationType.PropertyValue result) {
|
|
|
|
LogUtils.LOGD(TAG, "Successfully checked Kodi version.");
|
2019-02-08 18:25:21 +01:00
|
|
|
currentHostInfo.setKodiVersionMajor(result.version.major);
|
|
|
|
currentHostInfo.setKodiVersionMinor(result.version.minor);
|
|
|
|
currentHostInfo.setKodiVersionRevision(result.version.revision);
|
|
|
|
currentHostInfo.setKodiVersionTag(result.version.tag);
|
2016-11-15 20:09:23 +01:00
|
|
|
|
2019-02-08 18:25:21 +01:00
|
|
|
currentHostInfo = editHost(currentHostInfo.getId(), currentHostInfo);
|
2016-11-15 20:09:23 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onError(int errorCode, String description) {
|
|
|
|
// Couldn't get Kodi version... Ignore
|
|
|
|
LogUtils.LOGD(TAG, "Couldn't get Kodi version. Error: " + description);
|
|
|
|
}
|
|
|
|
}, new Handler());
|
|
|
|
}
|
|
|
|
}
|
2015-01-14 12:12:47 +01:00
|
|
|
}
|