Skip to content

Commit

Permalink
Don't crash because of deleted files when using media extractor / met…
Browse files Browse the repository at this point in the history
…adata retriever
  • Loading branch information
alashow committed Aug 21, 2021
1 parent 89c2b63 commit 59050f5
Show file tree
Hide file tree
Showing 2 changed files with 120 additions and 112 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -56,30 +56,37 @@ fun Audio.documentFile(parent: DocumentFile, songsGrouping: DownloadsSongsGroupi
}

fun Audio.artworkFromFile(context: Context): Bitmap? {
val downloadInfo = audioDownloadItem?.downloadInfo ?: return null
val metadataRetriever = MediaMetadataRetriever()
metadataRetriever.setDataSource(context, downloadInfo.fileUri)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
try {
return metadataRetriever.primaryImage
} catch (e: Exception) {
Timber.e(e)
try {
val downloadInfo = audioDownloadItem?.downloadInfo ?: return null

val metadataRetriever = MediaMetadataRetriever()
metadataRetriever.setDataSource(context, downloadInfo.fileUri)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
try {
return metadataRetriever.primaryImage
} catch (e: Exception) {
Timber.e(e)
}
}
}

try {
val data = metadataRetriever.embeddedPicture
if (data != null) {
return BitmapFactory.decodeByteArray(data, 0, data.size)
}
return null
} catch (e: Exception) {
Timber.e(e)
}
return null
}

fun AudioDownloadItem.audioHeader(context: Context): AudioHeader {
val mediaExtractor = MediaExtractor()
mediaExtractor.setDataSource(context, downloadInfo.fileUri, null)
return AudioHeader.from(this, mediaExtractor.getTrackFormat(0))
try {
val mediaExtractor = MediaExtractor()
mediaExtractor.setDataSource(context, downloadInfo.fileUri, null)
return AudioHeader.from(this, mediaExtractor.getTrackFormat(0))
} catch (e: Exception) {
Timber.e(e)
}
return AudioHeader()
}
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ import tm.alashow.common.compose.LocalPlaybackConnection
import tm.alashow.common.compose.LocalScaffoldState
import tm.alashow.common.compose.rememberFlowWithLifecycle
import tm.alashow.datmusic.data.repos.search.DatmusicSearchParams
import tm.alashow.datmusic.domain.entities.Audio
import tm.alashow.datmusic.domain.entities.CoverImageSize
import tm.alashow.datmusic.downloader.audioHeader
import tm.alashow.datmusic.playback.NONE_PLAYBACK_STATE
Expand Down Expand Up @@ -249,7 +250,7 @@ fun PlaybackSheetContent(

if (playbackQueue.isValid)
item {
PlaybackNowPlayingAudioInfo(playbackQueue = playbackQueue)
PlaybackAudioInfo(audio = playbackQueue.currentAudio)
}

playbackQueue(
Expand All @@ -264,53 +265,63 @@ fun PlaybackSheetContent(
}
}

@OptIn(ExperimentalAnimationApi::class)
private fun LazyListScope.playbackQueue(
@Composable
private fun PlaybackSheetTopBar(
playbackQueue: PlaybackQueue,
scrollToTop: Callback,
playbackConnection: PlaybackConnection,
) {
val lastIndex = playbackQueue.audiosList.size
val firstIndex = (playbackQueue.currentIndex + 1).coerceAtMost(lastIndex)
val queue = playbackQueue.audiosList.subList(firstIndex, lastIndex)
itemsIndexed(queue, key = { index, _ -> index }) { index, audio ->
val realPosition = firstIndex + index
AudioRow(
audio = audio,
imageSize = 40.dp,
onPlayAudio = {
playbackConnection.transportControls?.skipToQueueItem(realPosition.toLong())
scrollToTop()
}
)
}
}

private fun LazyListScope.playbackNowPlayingWithControls(
nowPlaying: MediaMetadataCompat,
playbackState: PlaybackStateCompat,
contentColor: Color,
onClose: Callback,
iconSize: Dp = 36.dp,
actionHandler: AudioActionHandler = LocalAudioActionHandler.current,
) {
item {
Column(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier
.padding(AppTheme.specs.paddingLarge)
) {
PlaybackNowPlaying(nowPlaying = nowPlaying, onClose = onClose)

PlaybackProgress(
playbackState = playbackState,
contentColor = contentColor
)
val (expanded, setExpanded) = remember { mutableStateOf(false) }

PlaybackControls(
playbackState = playbackState,
contentColor = contentColor,
)
TopAppBar(
elevation = 0.dp,
backgroundColor = Color.Transparent,
contentPadding = rememberInsetsPaddingValues(LocalWindowInsets.current.statusBars),
title = {
Column(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier
.fillMaxWidth()
.offset(x = -8.dp) // idk why this is needed for centering
) {
val context = LocalContext.current
val queueTitle = QueueTitle.from(playbackQueue.title ?: "")
Text(
queueTitle.localizeType(context).uppercase(),
style = MaterialTheme.typography.overline.copy(fontWeight = FontWeight.Light),
maxLines = 1,
)
Text(
queueTitle.localizeValue(context), style = MaterialTheme.typography.body1,
textAlign = TextAlign.Center,
overflow = TextOverflow.Ellipsis,
maxLines = 2,
)
}
},
navigationIcon = {
IconButton(onClick = onClose) {
Icon(
rememberVectorPainter(Icons.Default.KeyboardArrowDown),
modifier = Modifier.size(iconSize),
contentDescription = null,
)
}
},
actions = {
CompositionLocalProvider(LocalContentAlpha provides ContentAlpha.high) {
AudioDropdownMenu(
expanded = expanded,
onExpandedChange = setExpanded,
actionLabels = currentPlayingMenuActionLabels,
) {
if (playbackQueue.isValid)
actionHandler(AudioItemAction.from(it, playbackQueue.currentAudio))
}
}
}
}
)
}

@Composable
Expand Down Expand Up @@ -348,6 +359,33 @@ private fun PlaybackArtwork(
}
}

private fun LazyListScope.playbackNowPlayingWithControls(
nowPlaying: MediaMetadataCompat,
playbackState: PlaybackStateCompat,
contentColor: Color,
onClose: Callback,
) {
item {
Column(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier
.padding(AppTheme.specs.paddingLarge)
) {
PlaybackNowPlaying(nowPlaying = nowPlaying, onClose = onClose)

PlaybackProgress(
playbackState = playbackState,
contentColor = contentColor
)

PlaybackControls(
playbackState = playbackState,
contentColor = contentColor,
)
}
}
}

@Composable
private fun PlaybackNowPlaying(
nowPlaying: MediaMetadataCompat,
Expand Down Expand Up @@ -610,9 +648,9 @@ private fun PlaybackControls(
}

@Composable
private fun PlaybackNowPlayingAudioInfo(playbackQueue: PlaybackQueue) {
private fun PlaybackAudioInfo(audio: Audio) {
val context = LocalContext.current
val dlItem = playbackQueue.currentAudio.audioDownloadItem
val dlItem = audio.audioDownloadItem
if (dlItem != null) {
val audiHeader = dlItem.audioHeader(context)
Column(
Expand All @@ -636,61 +674,24 @@ private fun PlaybackNowPlayingAudioInfo(playbackQueue: PlaybackQueue) {
}
}

@Composable
private fun PlaybackSheetTopBar(
@OptIn(ExperimentalAnimationApi::class)
private fun LazyListScope.playbackQueue(
playbackQueue: PlaybackQueue,
onClose: Callback,
iconSize: Dp = 36.dp,
actionHandler: AudioActionHandler = LocalAudioActionHandler.current,
scrollToTop: Callback,
playbackConnection: PlaybackConnection,
) {
val (expanded, setExpanded) = remember { mutableStateOf(false) }

TopAppBar(
elevation = 0.dp,
backgroundColor = Color.Transparent,
contentPadding = rememberInsetsPaddingValues(LocalWindowInsets.current.statusBars),
title = {
Column(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier
.fillMaxWidth()
.offset(x = -8.dp) // idk why this is needed for centering
) {
val context = LocalContext.current
val queueTitle = QueueTitle.from(playbackQueue.title ?: "")
Text(
queueTitle.localizeType(context).uppercase(),
style = MaterialTheme.typography.overline.copy(fontWeight = FontWeight.Light),
maxLines = 1,
)
Text(
queueTitle.localizeValue(context), style = MaterialTheme.typography.body1,
textAlign = TextAlign.Center,
overflow = TextOverflow.Ellipsis,
maxLines = 2,
)
}
},
navigationIcon = {
IconButton(onClick = onClose) {
Icon(
rememberVectorPainter(Icons.Default.KeyboardArrowDown),
modifier = Modifier.size(iconSize),
contentDescription = null,
)
}
},
actions = {
CompositionLocalProvider(LocalContentAlpha provides ContentAlpha.high) {
AudioDropdownMenu(
expanded = expanded,
onExpandedChange = setExpanded,
actionLabels = currentPlayingMenuActionLabels,
) {
if (playbackQueue.isValid)
actionHandler(AudioItemAction.from(it, playbackQueue.currentAudio))
}
val lastIndex = playbackQueue.audiosList.size
val firstIndex = (playbackQueue.currentIndex + 1).coerceAtMost(lastIndex)
val queue = playbackQueue.audiosList.subList(firstIndex, lastIndex)
itemsIndexed(queue, key = { index, _ -> index }) { index, audio ->
val realPosition = firstIndex + index
AudioRow(
audio = audio,
imageSize = 40.dp,
onPlayAudio = {
playbackConnection.transportControls?.skipToQueueItem(realPosition.toLong())
scrollToTop()
}
}
)
)
}
}

0 comments on commit 59050f5

Please sign in to comment.