Skip to content

Commit

Permalink
6.13.0 commit
Browse files Browse the repository at this point in the history
  • Loading branch information
XilinJia committed Oct 29, 2024
1 parent 38a2708 commit 69de20f
Show file tree
Hide file tree
Showing 22 changed files with 373 additions and 217 deletions.
8 changes: 4 additions & 4 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,11 @@ android {
vectorDrawables.useSupportLibrary false
vectorDrawables.generatedDensities = []

testApplicationId "ac.mdiq.podcini.tests"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
// testApplicationId "ac.mdiq.podcini.tests"
// testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"

versionCode 3020286
versionName "6.12.8"
versionCode 3020287
versionName "6.13.0"

applicationId "ac.mdiq.podcini.R"
def commit = ""
Expand Down
12 changes: 4 additions & 8 deletions app/src/main/kotlin/ac/mdiq/podcini/playback/base/InTheatre.kt
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,14 @@ object InTheatre {
value != null -> {
field = unmanaged(value)
if (field?.media != null && curMedia?.getIdentifier() != field?.media?.getIdentifier()) curMedia = unmanaged(field!!.media!!)
// field = value
// if (field?.media != null && curMedia?.getIdentifier() != field?.media?.getIdentifier()) curMedia = field!!.media!!
}
else -> {
field = null
if (curMedia != null) curMedia = null
}
}
// field = if (value != null) unmanaged(value) else null
// if (field?.media != null && curMedia?.getIdentifier() != field?.media?.getIdentifier()) curMedia = unmanaged(field!!.media!!)
}

var curMedia: Playable? = null // unmanged if EpisodeMedia
Expand All @@ -45,19 +45,15 @@ object InTheatre {
value is EpisodeMedia -> {
field = unmanaged(value)
if (value.episode != null && curEpisode?.id != value.episode?.id) curEpisode = unmanaged(value.episode!!)
// field = value
// if (value.episode != null && curEpisode?.id != value.episode?.id) curEpisode = value.episode!!
}
value == null -> {
field = null
if (curEpisode != null) curEpisode = null
}
else -> field = value
}
// if (value is EpisodeMedia) {
// field = unmanaged(value)
// if (value.episode != null && curEpisode?.id != value.episode?.id) curEpisode = unmanaged(value.episode!!)
// } else {
// field = value
// }
}

var curState: CurrentState // managed
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,7 @@ import ac.mdiq.podcini.preferences.UserPreferences.isSkipSilence
import ac.mdiq.podcini.preferences.UserPreferences.prefLowQualityMedia
import ac.mdiq.podcini.preferences.UserPreferences.rewindSecs
import ac.mdiq.podcini.storage.database.RealmDB.runOnIOScope
import ac.mdiq.podcini.storage.model.EpisodeMedia
import ac.mdiq.podcini.storage.model.Feed
import ac.mdiq.podcini.storage.model.MediaType
import ac.mdiq.podcini.storage.model.Playable
import ac.mdiq.podcini.storage.model.*
import ac.mdiq.podcini.storage.utils.EpisodeUtil
import ac.mdiq.podcini.util.EventFlow
import ac.mdiq.podcini.util.FlowEvent
Expand Down Expand Up @@ -518,10 +515,16 @@ class LocalMediaPlayer(context: Context, callback: MediaPlayerCallback) : MediaP
Logd(TAG, "setVolume: $volumeLeft $volumeRight")
val playable = curMedia
if (playable is EpisodeMedia) {
val preferences = playable.episodeOrFetch()?.feed?.preferences
if (preferences != null) {
val volumeAdaptionSetting = preferences.volumeAdaptionSetting
val adaptionFactor = volumeAdaptionSetting.adaptionFactor
var adaptionFactor = 1f
if (playable.volumeAdaptionSetting != VolumeAdaptionSetting.OFF) adaptionFactor = playable.volumeAdaptionSetting.adaptionFactor
else {
val preferences = playable.episodeOrFetch()?.feed?.preferences
if (preferences != null) {
val volumeAdaptionSetting = preferences.volumeAdaptionSetting
adaptionFactor = volumeAdaptionSetting.adaptionFactor
}
}
if (adaptionFactor != 1f) {
volumeLeft *= adaptionFactor
volumeRight *= adaptionFactor
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import ac.mdiq.podcini.playback.base.MediaPlayerBase.Companion.getCurrentPlaybac
import ac.mdiq.podcini.playback.base.MediaPlayerBase.MediaPlayerInfo
import ac.mdiq.podcini.playback.cast.CastMediaPlayer
import ac.mdiq.podcini.playback.cast.CastStateListener
import ac.mdiq.podcini.playback.service.PlaybackService.TaskManager.Companion.positionUpdateInterval
import ac.mdiq.podcini.preferences.SleepTimerPreferences
import ac.mdiq.podcini.preferences.SleepTimerPreferences.autoEnable
import ac.mdiq.podcini.preferences.SleepTimerPreferences.autoEnableFrom
Expand All @@ -28,6 +29,7 @@ import ac.mdiq.podcini.preferences.UserPreferences
import ac.mdiq.podcini.preferences.UserPreferences.appPrefs
import ac.mdiq.podcini.preferences.UserPreferences.fastForwardSecs
import ac.mdiq.podcini.preferences.UserPreferences.isSkipSilence
import ac.mdiq.podcini.preferences.UserPreferences.prefAdaptiveProgressUpdate
import ac.mdiq.podcini.preferences.UserPreferences.rewindSecs
import ac.mdiq.podcini.receiver.MediaButtonReceiver
import ac.mdiq.podcini.storage.database.Episodes.deleteMediaSync
Expand Down Expand Up @@ -369,7 +371,7 @@ class PlaybackService : MediaLibraryService() {
val shouldAutoDelete = (action == AutoDeleteAction.ALWAYS ||
(action == AutoDeleteAction.GLOBAL && item?.feed != null && shouldAutoDeleteItem(item!!.feed!!)))
if (playable is EpisodeMedia && shouldAutoDelete && (item?.isSUPER != true || !shouldFavoriteKeepEpisode)) {
item = deleteMediaSync(this@PlaybackService, item!!)
if (playable.localFileAvailable()) item = deleteMediaSync(this@PlaybackService, item!!)
if (shouldDeleteRemoveFromQueue()) removeFromQueueSync(null, item!!)
}
}
Expand All @@ -380,11 +382,12 @@ class PlaybackService : MediaLibraryService() {

override fun onPlaybackStart(playable: Playable, position: Int) {
Logd(TAG, "onPlaybackStart position: $position")
taskManager.startWidgetUpdater()
if (position != Playable.INVALID_TIME) playable.setPosition(position)
val delayInterval = positionUpdateInterval(playable.getDuration())
taskManager.startWidgetUpdater(delayInterval)
if (position != Playable.INVALID_TIME) playable.setPosition(position + (delayInterval/2).toInt())
else skipIntro(playable)
playable.onPlaybackStart()
taskManager.startPositionSaver()
taskManager.startPositionSaver(delayInterval)
}

override fun onPlaybackPause(playable: Playable?, position: Int) {
Expand Down Expand Up @@ -1310,12 +1313,14 @@ class PlaybackService : MediaLibraryService() {
get() = positionSaverFuture != null && !positionSaverFuture!!.isCancelled && !positionSaverFuture!!.isDone

@Synchronized
fun startPositionSaver() {
fun startPositionSaver(delayInterval: Long) {
if (!isPositionSaverActive) {
var positionSaver = Runnable { callback.positionSaverTick() }
positionSaver = useMainThreadIfNecessary(positionSaver)
positionSaverFuture = schedExecutor.scheduleWithFixedDelay(
positionSaver, POSITION_SAVER_WAITING_INTERVAL.toLong(), POSITION_SAVER_WAITING_INTERVAL.toLong(), TimeUnit.MILLISECONDS)
// val delayInterval = positionUpdateInterval(duration)
// positionSaverFuture = schedExecutor.scheduleWithFixedDelay(
// positionSaver, POSITION_SAVER_WAITING_INTERVAL.toLong(), POSITION_SAVER_WAITING_INTERVAL.toLong(), TimeUnit.MILLISECONDS)
positionSaverFuture = schedExecutor.scheduleWithFixedDelay(positionSaver, delayInterval, delayInterval, TimeUnit.MILLISECONDS)
Logd(TAG, "Started PositionSaver")
} else Logd(TAG, "Call to startPositionSaver was ignored.")
}
Expand All @@ -1329,12 +1334,14 @@ class PlaybackService : MediaLibraryService() {
}

@Synchronized
fun startWidgetUpdater() {
fun startWidgetUpdater(delayInterval: Long) {
if (!isWidgetUpdaterActive && !schedExecutor.isShutdown) {
var widgetUpdater = Runnable { this.requestWidgetUpdate() }
widgetUpdater = useMainThreadIfNecessary(widgetUpdater)
widgetUpdaterFuture = schedExecutor.scheduleWithFixedDelay(
widgetUpdater, WIDGET_UPDATER_NOTIFICATION_INTERVAL.toLong(), WIDGET_UPDATER_NOTIFICATION_INTERVAL.toLong(), TimeUnit.MILLISECONDS)
// val delayInterval = positionUpdateInterval(duration)
// widgetUpdaterFuture = schedExecutor.scheduleWithFixedDelay(
// widgetUpdater, WIDGET_UPDATER_NOTIFICATION_INTERVAL.toLong(), WIDGET_UPDATER_NOTIFICATION_INTERVAL.toLong(), TimeUnit.MILLISECONDS)
widgetUpdaterFuture = schedExecutor.scheduleWithFixedDelay(widgetUpdater, delayInterval, delayInterval, TimeUnit.MILLISECONDS)
Logd(TAG, "Started WidgetUpdater")
}
}
Expand Down Expand Up @@ -1401,7 +1408,6 @@ class PlaybackService : MediaLibraryService() {
fun startChapterLoader(media: Playable) {
// chapterLoaderFuture?.dispose()
// chapterLoaderFuture = null

if (!media.chaptersLoaded()) {
val scope = CoroutineScope(Dispatchers.Main)
scope.launch(Dispatchers.IO) {
Expand All @@ -1423,7 +1429,6 @@ class PlaybackService : MediaLibraryService() {
cancelPositionSaver()
cancelWidgetUpdater()
disableSleepTimer()

// chapterLoaderFuture?.dispose()
// chapterLoaderFuture = null
}
Expand Down Expand Up @@ -1557,8 +1562,13 @@ class PlaybackService : MediaLibraryService() {

private const val SLEEP_TIMER_UPDATE_INTERVAL = 10000L // in millisoconds
const val POSITION_SAVER_WAITING_INTERVAL: Int = 5000 // in millisoconds
const val WIDGET_UPDATER_NOTIFICATION_INTERVAL: Int = 5000 // in millisoconds
// const val WIDGET_UPDATER_NOTIFICATION_INTERVAL: Int = 5000 // in millisoconds
const val NOTIFICATION_THRESHOLD: Long = 10000 // in millisoconds

fun positionUpdateInterval(duration: Int): Long {
return if (prefAdaptiveProgressUpdate) max(POSITION_SAVER_WAITING_INTERVAL, duration/50).toLong()
else POSITION_SAVER_WAITING_INTERVAL.toLong()
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,12 @@ object UserPreferences {
appPrefs.edit().putBoolean(Prefs.prefLowQualityOnMobile.name, stream).apply()
}

var prefAdaptiveProgressUpdate: Boolean
get() = appPrefs.getBoolean(Prefs.prefUseAdaptiveProgressUpdate.name, false)
set(value) {
appPrefs.edit().putBoolean(Prefs.prefUseAdaptiveProgressUpdate.name, value).apply()
}

/**
* Sets up the UserPreferences class.
* @throws IllegalArgumentException if context is null
Expand Down Expand Up @@ -313,6 +319,7 @@ object UserPreferences {
prefStreamOverDownload,
prefLowQualityOnMobile,
prefSpeedforwardSpeed,
prefUseAdaptiveProgressUpdate,

// Network
prefEnqueueDownloaded,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,10 @@ object AutoDownloads {
queryString += " AND playState <= ${PlayState.SOON.code} SORT(pubDate DESC) LIMIT(${3*allowedDLCount})"
episodes = realm.query(Episode::class).query(queryString).find().toMutableList()
}
FeedPreferences.AutoDownloadPolicy.SOON -> {
queryString += " AND playState == ${PlayState.SOON.code} SORT(pubDate DESC) LIMIT(${3*allowedDLCount})"
episodes = realm.query(Episode::class).query(queryString).find().toMutableList()
}
FeedPreferences.AutoDownloadPolicy.OLDER -> {
queryString += " AND playState <= ${PlayState.SOON.code} SORT(pubDate ASC) LIMIT(${3*allowedDLCount})"
episodes = realm.query(Episode::class).query(queryString).find().toMutableList()
Expand All @@ -136,7 +140,7 @@ object AutoDownloads {
var count = 0
for (e in episodes) {
if (isCurMedia(e.media)) continue
if (f.preferences?.autoDownloadFilter?.shouldAutoDownload(e) == true) {
if (f.preferences?.autoDownloadFilter?.meetsAutoDLCriteria(e) == true) {
Logd(TAG, "autoDownloadEpisodeMedia add to cadidates: ${e.title} ${e.isDownloaded}")
candidates.add(e)
if (++count >= allowedDLCount) break
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ object Episodes {
episode = upsertBlk(episode) {
it.media?.setfileUrlOrNull(null)
if (media.downloadUrl.isNullOrEmpty()) it.media = null
it.playState = PlayState.SKIPPED.code
if (it.playState < PlayState.SKIPPED.code) it.playState = PlayState.SKIPPED.code
}
EventFlow.postEvent(FlowEvent.EpisodePlayedEvent(episode))
localDelete = true
Expand All @@ -139,15 +139,15 @@ object Episodes {
val mediaFile = File(url)
if (!mediaFile.delete()) {
Log.e(TAG, "delete media file failed: $url")
val evt = FlowEvent.MessageEvent(context.getString(R.string.delete_failed))
val evt = FlowEvent.MessageEvent(context.getString(R.string.delete_failed_simple) + ": $url")
EventFlow.postEvent(evt)
return episode
}
episode = upsertBlk(episode) {
it.media?.downloaded = false
it.media?.setfileUrlOrNull(null)
it.media?.hasEmbeddedPicture = false
it.playState = PlayState.SKIPPED.code
if (it.playState < PlayState.SKIPPED.code) it.playState = PlayState.SKIPPED.code
if (media.downloadUrl.isNullOrEmpty()) it.media = null
}
EventFlow.postEvent(FlowEvent.EpisodePlayedEvent(episode))
Expand Down
11 changes: 11 additions & 0 deletions app/src/main/kotlin/ac/mdiq/podcini/storage/model/EpisodeMedia.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package ac.mdiq.podcini.storage.model
import ac.mdiq.podcini.storage.database.RealmDB.realm
import ac.mdiq.podcini.storage.database.RealmDB.unmanaged
import ac.mdiq.podcini.storage.database.RealmDB.upsertBlk
import ac.mdiq.podcini.storage.model.VolumeAdaptionSetting.Companion.fromInteger
import ac.mdiq.podcini.storage.utils.MediaMetadataRetrieverCompat
import ac.mdiq.podcini.util.Logd
import ac.mdiq.podcini.util.showStackTrace
Expand Down Expand Up @@ -68,6 +69,16 @@ class EpisodeMedia: EmbeddedRealmObject, Playable {
var playedDurationWhenStarted: Int = 0
private set

@Ignore
var volumeAdaptionSetting: VolumeAdaptionSetting = VolumeAdaptionSetting.OFF
get() = fromInteger(volumeAdaption)
set(value) {
field = value
volumeAdaption = field.toInteger()
}
@Ignore
var volumeAdaption: Int = 0

// if null: unknown, will be checked
// TODO: what to do with this? can be expensive
@Ignore
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class FeedAutoDownloadFilter(val includeFilterRaw: String? = "", val excludeFilt
* @param item
* @return true if the item should be downloaded
*/
fun shouldAutoDownload(item: Episode): Boolean {
fun meetsAutoDLCriteria(item: Episode): Boolean {
// if (includeTerms == null) includeTerms = parseTerms(includeFilterRaw)
// if (excludeTerms == null) excludeTerms = parseTerms(excludeFilterRaw)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,8 @@ class FeedPreferences : EmbeddedRealmObject {
enum class AutoDownloadPolicy(val code: Int, val resId: Int) {
ONLY_NEW(0, R.string.feed_auto_download_new),
NEWER(1, R.string.feed_auto_download_newer),
OLDER(2, R.string.feed_auto_download_older);
OLDER(2, R.string.feed_auto_download_older),
SOON(3, R.string.feed_auto_download_soon);

companion object {
fun fromCode(code: Int): AutoDownloadPolicy {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,6 @@ enum class VolumeAdaptionSetting(private val value: Int, @JvmField val adaptionF
LIGHT_REDUCTION(1, 0.5f, R.string.feed_volume_reduction_light),
HEAVY_REDUCTION(2, 0.2f, R.string.feed_volume_reduction_heavy),
LIGHT_BOOST(3, 1.6f, R.string.feed_volume_boost_light),
// MEDIUM_BOOST(4, 2f, R.string.feed_volume_boost_medium),
// HEAVY_BOOST(5, 2.5f, R.string.feed_volume_boost_heavy);
// LIGHT_BOOST(3, 2f, R.string.feed_volume_boost_light),
MEDIUM_BOOST(4, 2.4f, R.string.feed_volume_boost_medium),
HEAVY_BOOST(5, 3.6f, R.string.feed_volume_boost_heavy);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,8 @@ abstract class EpisodeActionButton internal constructor(@JvmField var item: Epis

abstract fun onClick(context: Context)

fun forItem(): EpisodeActionButton {
open fun forItem(item_: Episode): EpisodeActionButton {
item = item_
val media = item.media ?: return TTSActionButton(item)
val isDownloadingMedia = when (media.downloadUrl) {
null -> false
Expand Down Expand Up @@ -189,6 +190,11 @@ class VisitWebsiteActionButton(item: Episode) : EpisodeActionButton(item) {
if (!item.link.isNullOrEmpty()) IntentUtils.openInBrowser(context, item.link!!)
actionState.value = getLabel()
}

override fun forItem(item_: Episode): EpisodeActionButton {
item = item_
return this
}
}

class CancelDownloadActionButton(item: Episode) : EpisodeActionButton(item) {
Expand Down Expand Up @@ -358,6 +364,21 @@ class DownloadActionButton(item: Episode) : EpisodeActionButton(item) {
val isDownloading = DownloadServiceInterface.get()?.isDownloadingEpisode(media.downloadUrl!!)?:false
return isDownloading || media.downloaded
}

// override fun forItem(item_: Episode): EpisodeActionButton {
// item = item_
// val media = item.media ?: return TTSActionButton(item)
// val isDownloadingMedia = when (media.downloadUrl) {
// null -> false
// else -> DownloadServiceInterface.get()?.isDownloadingEpisode(media.downloadUrl!!)?:false
// }
// Logd("DownloadActionButton", "forItem: local feed: ${item.feed?.isLocalFeed} downloaded: ${media.downloaded} playing: ${isCurrentlyPlaying(media)} ${item.title} ")
// return when {
// media.downloaded -> PlayActionButton(item)
// isDownloadingMedia -> CancelDownloadActionButton(item)
// else -> DownloadActionButton(item)
// }
// }
}

class StreamActionButton(item: Episode) : EpisodeActionButton(item) {
Expand Down
8 changes: 6 additions & 2 deletions app/src/main/kotlin/ac/mdiq/podcini/ui/actions/SwipeAction.kt
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,20 @@ interface SwipeAction {

fun performAction(item: Episode, fragment: Fragment, filter: EpisodeFilter)

fun willRemove(filter: EpisodeFilter, item: Episode): Boolean
fun willRemove(filter: EpisodeFilter, item: Episode): Boolean {
return false
}

enum class ActionTypes {
NO_ACTION,
COMBO,
ADD_TO_QUEUE,
PUT_TO_QUEUE,
START_DOWNLOAD,
MARK_FAV,
TOGGLE_PLAYED,
SET_PLAY_STATE,
SHELVE,
ERASE,
REMOVE_FROM_QUEUE,
DELETE,
REMOVE_FROM_HISTORY
Expand Down
Loading

0 comments on commit 69de20f

Please sign in to comment.