From f9ea80bb3d69426d128087600530e1736a29d543 Mon Sep 17 00:00:00 2001 From: Schoumi Date: Tue, 27 Jul 2021 20:20:08 +0200 Subject: [PATCH] Manage instance live configuration: live enabled and allow replay fixes #11 --- .../activity/CreateLiveActivity.kt | 55 ++++++++++++---- .../peertubelive/activity/StreamActivity.kt | 1 - .../peertubelive/manager/InstanceManager.kt | 66 +++++++++++++++++-- .../mobdev/peertubelive/objects/ConfigData.kt | 31 +++++++++ .../peertubelive/objects/StreamSettings.kt | 5 +- .../{channel_list.xml => create_live.xml} | 12 ++++ app/src/main/res/values-fr/strings.xml | 1 + app/src/main/res/values/strings.xml | 1 + 8 files changed, 149 insertions(+), 23 deletions(-) create mode 100644 app/src/main/java/fr/mobdev/peertubelive/objects/ConfigData.kt rename app/src/main/res/layout/{channel_list.xml => create_live.xml} (96%) diff --git a/app/src/main/java/fr/mobdev/peertubelive/activity/CreateLiveActivity.kt b/app/src/main/java/fr/mobdev/peertubelive/activity/CreateLiveActivity.kt index af9eb89..7e5f3aa 100644 --- a/app/src/main/java/fr/mobdev/peertubelive/activity/CreateLiveActivity.kt +++ b/app/src/main/java/fr/mobdev/peertubelive/activity/CreateLiveActivity.kt @@ -5,21 +5,16 @@ import android.os.Bundle import android.view.View import android.widget.ArrayAdapter import android.widget.ProgressBar -import androidx.activity.result.ActivityResult -import androidx.activity.result.ActivityResultCallback import androidx.activity.result.ActivityResultLauncher import androidx.activity.result.contract.ActivityResultContracts import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AppCompatActivity import androidx.databinding.DataBindingUtil import fr.mobdev.peertubelive.R -import fr.mobdev.peertubelive.databinding.ChannelListBinding +import fr.mobdev.peertubelive.databinding.CreateLiveBinding import fr.mobdev.peertubelive.manager.DatabaseManager import fr.mobdev.peertubelive.manager.InstanceManager -import fr.mobdev.peertubelive.objects.ChannelData -import fr.mobdev.peertubelive.objects.OAuthData -import fr.mobdev.peertubelive.objects.StreamData -import fr.mobdev.peertubelive.objects.StreamSettings +import fr.mobdev.peertubelive.objects.* import fr.mobdev.peertubelive.utils.TranslationUtils import java.util.ArrayList @@ -35,9 +30,10 @@ class CreateLiveActivity : AppCompatActivity() { private lateinit var privacies: MutableMap private lateinit var languages: MutableMap private lateinit var oAuthData: OAuthData + private lateinit var configData: ConfigData private var inError: Boolean = false private var showAdvancedSettings = true - private lateinit var binding: ChannelListBinding + private lateinit var binding: CreateLiveBinding private lateinit var startLive: ActivityResultLauncher override fun onCreate(savedInstanceState: Bundle?) { @@ -45,7 +41,7 @@ class CreateLiveActivity : AppCompatActivity() { oAuthData = intent.getParcelableExtra(OAUTH_DATA)!! - binding = DataBindingUtil.setContentView(this,R.layout.channel_list) + binding = DataBindingUtil.setContentView(this,R.layout.create_live) binding.error.visibility = View.GONE binding.channelList.visibility = View.GONE @@ -60,6 +56,7 @@ class CreateLiveActivity : AppCompatActivity() { binding.saveReplayInfo.visibility = View.GONE binding.resolution.visibility = View.GONE binding.resolutionList.visibility = View.GONE + binding.liveDisabled.visibility = View.GONE startLive = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { setResult(it.resultCode) @@ -93,7 +90,9 @@ class CreateLiveActivity : AppCompatActivity() { val comments = binding.commentsEnabled.isChecked val download = binding.downloadEnabled.isChecked val nsfw = binding.nsfw.isChecked - val replay = binding.saveReplay.isChecked + var replay: Boolean? = null + if (configData.saveReplayEnabled) + replay = binding.saveReplay.isChecked val resolution = StreamData.STREAM_RESOLUTION.values()[binding.resolutionList.selectedItemPosition] @@ -108,6 +107,22 @@ class CreateLiveActivity : AppCompatActivity() { } } + InstanceManager.getLiveConfig(this,oAuthData.baseUrl!!,object : InstanceManager.InstanceListener { + override fun onSuccess(args: Bundle?) { + configData = args?.getParcelable(InstanceManager.EXTRA_DATA)!! + updateView(null) + } + + override fun onError(error: String?) { + inError = true + updateView(error) + } + + override fun onUpdateOAuthData(oauthData: OAuthData) { + this@CreateLiveActivity.oAuthData.updateData(oauthData) + } + }) + InstanceManager.getCategoryList(this,oAuthData.baseUrl!!,object : InstanceManager.InstanceListener { override fun onSuccess(args: Bundle?) { val map = args?.getSerializable(InstanceManager.EXTRA_DATA)!! as Map @@ -223,7 +238,16 @@ class CreateLiveActivity : AppCompatActivity() { private fun updateView(error: String?) { if(!inError) { - if(this::channels.isInitialized && this::categories.isInitialized && this::privacies.isInitialized && this::languages.isInitialized && this::licences.isInitialized) { + if (this::configData.isInitialized && !configData.liveEnabled) { + runOnUiThread { + binding.loadingProgress.visibility = View.GONE + binding.loadingChannels.visibility = View.GONE + binding.liveDisabled.visibility = View.VISIBLE + } + return + } + if(this::configData.isInitialized && configData.liveEnabled && this::channels.isInitialized && this::categories.isInitialized + && this::privacies.isInitialized && this::languages.isInitialized && this::licences.isInitialized) { val channelAdapter = ArrayAdapter(this, android.R.layout.simple_spinner_dropdown_item) for (channel in channels) { channelAdapter.add(channel.name) @@ -264,8 +288,10 @@ class CreateLiveActivity : AppCompatActivity() { binding.advanceSettings.visibility = View.VISIBLE binding.privacy.visibility = View.VISIBLE binding.privacyList.visibility = View.VISIBLE - binding.saveReplayLayout.visibility = View.VISIBLE - binding.saveReplayInfo.visibility = View.VISIBLE + if (configData.saveReplayEnabled) { + binding.saveReplayLayout.visibility = View.VISIBLE + binding.saveReplayInfo.visibility = View.VISIBLE + } binding.resolution.visibility = View.VISIBLE binding.resolutionList.visibility = View.VISIBLE restoreSettings() @@ -346,7 +372,8 @@ class CreateLiveActivity : AppCompatActivity() { binding.commentsEnabled.isChecked = settings.comments binding.downloadEnabled.isChecked = settings.download binding.nsfw.isChecked = settings.nsfw - binding.saveReplay.isChecked = settings.saveReplay + if (settings.saveReplay != null) + binding.saveReplay.isChecked = settings.saveReplay binding.liveTitle.setText(settings.title) if (settings.privacy != 0) { diff --git a/app/src/main/java/fr/mobdev/peertubelive/activity/StreamActivity.kt b/app/src/main/java/fr/mobdev/peertubelive/activity/StreamActivity.kt index 330aba1..64bb32d 100644 --- a/app/src/main/java/fr/mobdev/peertubelive/activity/StreamActivity.kt +++ b/app/src/main/java/fr/mobdev/peertubelive/activity/StreamActivity.kt @@ -330,7 +330,6 @@ class StreamActivity : AppCompatActivity() { if (rtmpCamera2.prepareAudio() && rtmpCamera2.prepareVideo(width,height,30, (width*height*30*0.076).toInt(),false,CameraHelper.getCameraOrientation(this))) { rtmpCamera2.startStream(streamData.url+"/"+streamData.key) } else { - println("error") /**This device cant init encoders, this could be for 2 reasons: The encoder selected doesnt support any configuration setted or your device hasnt a H264 or AAC encoder (in this case you can see log error valid encoder not found) */ } } diff --git a/app/src/main/java/fr/mobdev/peertubelive/manager/InstanceManager.kt b/app/src/main/java/fr/mobdev/peertubelive/manager/InstanceManager.kt index 9cce226..aba84e3 100644 --- a/app/src/main/java/fr/mobdev/peertubelive/manager/InstanceManager.kt +++ b/app/src/main/java/fr/mobdev/peertubelive/manager/InstanceManager.kt @@ -3,10 +3,7 @@ package fr.mobdev.peertubelive.manager import android.content.Context import android.os.Bundle import fr.mobdev.peertubelive.R -import fr.mobdev.peertubelive.objects.ChannelData -import fr.mobdev.peertubelive.objects.OAuthData -import fr.mobdev.peertubelive.objects.StreamData -import fr.mobdev.peertubelive.objects.StreamSettings +import fr.mobdev.peertubelive.objects.* import org.json.JSONObject import java.lang.Exception import java.util.* @@ -25,6 +22,7 @@ object InstanceManager { private const val GET_PRIVACY_ENDPOINT: String = "/videos/privacies" private const val GET_LICENCE_ENDPOINT: String = "/videos/licences" private const val GET_LANGUAGES_ENDPOINT: String = "/videos/languages" + private const val GET_CONFIG_ENDPOINT: String = "/config" private const val GET_VIDEOS: String = "/users/me/videos" internal const val EXTRA_DATA: String = "EXTRA_DATA" @@ -38,6 +36,9 @@ object InstanceManager { private const val UUID: String = "uuid" private const val RTMP_URL: String = "rtmpUrl" private const val STREAM_KEY: String = "streamKey" + private const val CONFIG_LIVE: String = "live" + private const val CONFIG_LIVE_ENABLED: String = "enabled" + private const val CONFIG_LIVE_SAVE_REPLAY: String = "allowReplay" fun registerAccount(context: Context, url: String, username: String, password: String, listener: InstanceListener) { val registerUrl = url + BASE_API_ENDPOINT+ REGISTER_CLIENT_ENDPOINT @@ -148,8 +149,9 @@ object InstanceManager { formData += prepareFormData(boundary,"licence",streamSettings.licence.toString(),false) formData += prepareFormData(boundary,"commentsEnabled",streamSettings.comments.toString(),false) formData += prepareFormData(boundary,"nsfw",streamSettings.nsfw.toString(),false) - formData += prepareFormData(boundary,"downloadEnabled",streamSettings.download.toString(),false) - formData += prepareFormData(boundary,"saveReplay",streamSettings.saveReplay.toString(),true) + formData += prepareFormData(boundary,"downloadEnabled",streamSettings.download.toString(),streamSettings.saveReplay == null) + if (streamSettings.saveReplay != null) + formData += prepareFormData(boundary,"saveReplay",streamSettings.saveReplay.toString(),true) data.putString(CONTENT_TYPE,"multipart/form-data; boundary=$boundary") data.putString(CONTENT_DATA,formData) val internalListener = object: InstanceListener { @@ -365,6 +367,36 @@ object InstanceManager { oauthManager.get(context,userInfoUrl,null,internalListener) } + fun getLiveConfig(context: Context, url: String, listener: InstanceListener) { + val userInfoUrl: String = url + BASE_API_ENDPOINT + GET_CONFIG_ENDPOINT + val internalListener : InstanceListener = object : InstanceListener { + override fun onSuccess(args: Bundle?) { + val response = args?.getString(EXTRA_DATA, null) + if (response == null) { + listener.onError(context.getString(R.string.unknwon_error)) + return + } + val configData = extractConfigData(response) + if (configData == null) { + listener.onError(context.getString(R.string.json_error)) + return + } + args.putParcelable(EXTRA_DATA, configData) + listener.onSuccess(args) + } + + override fun onError(error: String?) { + listener.onError(error) + } + + override fun onUpdateOAuthData(oauthData: OAuthData) { + listener.onUpdateOAuthData(oauthData) + } + } + + oauthManager.get(context,userInfoUrl,null,internalListener) + } + private fun extractChannelData(response: String): ArrayList? { try { val json = JSONObject(response) @@ -433,6 +465,28 @@ object InstanceManager { } } + private fun extractConfigData(response: String): ConfigData? { + try { + val json = JSONObject(response) + + return if (json.has(CONFIG_LIVE)) { + val live = json.getJSONObject(CONFIG_LIVE) + return if(live.has(CONFIG_LIVE_ENABLED) && live.has(CONFIG_LIVE_SAVE_REPLAY)) { + val liveEnabled = live.getBoolean(CONFIG_LIVE_ENABLED) + val saveReplayEnabled = live.getBoolean(CONFIG_LIVE_SAVE_REPLAY) + ConfigData(liveEnabled,saveReplayEnabled) + } else { + null + } + } else { + null + } + } catch (e: Exception) { + e.printStackTrace() + return null + } + } + private fun extractMapData(response: String, type: T): HashMap? { return try { val json = JSONObject(response) diff --git a/app/src/main/java/fr/mobdev/peertubelive/objects/ConfigData.kt b/app/src/main/java/fr/mobdev/peertubelive/objects/ConfigData.kt new file mode 100644 index 0000000..7efa3f3 --- /dev/null +++ b/app/src/main/java/fr/mobdev/peertubelive/objects/ConfigData.kt @@ -0,0 +1,31 @@ +package fr.mobdev.peertubelive.objects; + +import android.os.Parcel +import android.os.Parcelable + +class ConfigData(val liveEnabled: Boolean, val saveReplayEnabled: Boolean) : Parcelable { + constructor(parcel: Parcel) : this( + parcel.readByte() != 0.toByte(), + parcel.readByte() != 0.toByte() + ) { + } + + override fun describeContents(): Int { + return 0 + } + + override fun writeToParcel(dest: Parcel, flags: Int) { + dest.writeByte(if (liveEnabled) 1 else 0) + dest.writeByte(if (saveReplayEnabled) 1 else 0) + } + + companion object CREATOR : Parcelable.Creator { + override fun createFromParcel(parcel: Parcel): StreamData { + return StreamData(parcel) + } + + override fun newArray(size: Int): Array { + return arrayOfNulls(size) + } + } +} diff --git a/app/src/main/java/fr/mobdev/peertubelive/objects/StreamSettings.kt b/app/src/main/java/fr/mobdev/peertubelive/objects/StreamSettings.kt index 3deb38c..5be7a92 100644 --- a/app/src/main/java/fr/mobdev/peertubelive/objects/StreamSettings.kt +++ b/app/src/main/java/fr/mobdev/peertubelive/objects/StreamSettings.kt @@ -5,7 +5,7 @@ import android.os.Parcelable class StreamSettings( val title: String, val channel: Long, val privacy: Int, val category: Int?, val language: String?, val licence: Int?, val description: String?, - val comments: Boolean, val download: Boolean, val nsfw: Boolean, val saveReplay: Boolean, val resolution: StreamData.STREAM_RESOLUTION) : Parcelable { + val comments: Boolean, val download: Boolean, val nsfw: Boolean, val saveReplay: Boolean?, val resolution: StreamData.STREAM_RESOLUTION) : Parcelable { constructor(parcel: Parcel) : this( parcel.readString()!!, parcel.readLong(), @@ -37,7 +37,8 @@ class StreamSettings( parcel.writeByte(if (comments) 1 else 0) parcel.writeByte(if (download) 1 else 0) parcel.writeByte(if (nsfw) 1 else 0) - parcel.writeByte(if (saveReplay) 1 else 0) + if (saveReplay!= null) + parcel.writeByte(if (saveReplay) 1 else 0) parcel.writeInt(resolution?.ordinal!!) } diff --git a/app/src/main/res/layout/channel_list.xml b/app/src/main/res/layout/create_live.xml similarity index 96% rename from app/src/main/res/layout/channel_list.xml rename to app/src/main/res/layout/create_live.xml index 8e2aa83..85e9593 100644 --- a/app/src/main/res/layout/channel_list.xml +++ b/app/src/main/res/layout/create_live.xml @@ -50,6 +50,18 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent" /> + Votre direct est terminé Voulez-vous arrêter le direct \? Votre direct s\'est terminé à cause d\'un problème réseau + Cette instance a désactivé les directs. Chaîne Démarrer le direct ! diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 7c7f043..047b2ec 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -26,6 +26,7 @@ Your livestream ended Do you want to stop the live? Your livestream ended because of a network problem + This instance has disabled livestream. Channel Start livestream