@roitium/expo-orpheus 0.2.2 → 0.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/android/src/main/java/expo/modules/orpheus/DownloadCache.kt +25 -0
- package/android/src/main/java/expo/modules/orpheus/ExpoOrpheusModule.kt +4 -7
- package/android/src/main/java/expo/modules/orpheus/OrpheusService.kt +8 -1
- package/build/ExpoOrpheusModule.d.ts +3 -1
- package/build/ExpoOrpheusModule.d.ts.map +1 -1
- package/build/ExpoOrpheusModule.js.map +1 -1
- package/package.json +1 -1
- package/src/ExpoOrpheusModule.ts +3 -1
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
package expo.modules.orpheus
|
|
2
|
+
|
|
3
|
+
import android.content.Context
|
|
4
|
+
import androidx.media3.common.util.UnstableApi
|
|
5
|
+
import androidx.media3.database.StandaloneDatabaseProvider
|
|
6
|
+
import androidx.media3.datasource.cache.LeastRecentlyUsedCacheEvictor
|
|
7
|
+
import androidx.media3.datasource.cache.SimpleCache
|
|
8
|
+
import java.io.File
|
|
9
|
+
|
|
10
|
+
@UnstableApi
|
|
11
|
+
object DownloadCache {
|
|
12
|
+
private var cache: SimpleCache? = null
|
|
13
|
+
|
|
14
|
+
@UnstableApi
|
|
15
|
+
fun get(context: Context): SimpleCache {
|
|
16
|
+
if (cache == null) {
|
|
17
|
+
val cacheDir = File(context.cacheDir, "media_cache")
|
|
18
|
+
val evictor = LeastRecentlyUsedCacheEvictor(256 * 1024 * 1024)
|
|
19
|
+
val databaseProvider = StandaloneDatabaseProvider(context)
|
|
20
|
+
|
|
21
|
+
cache = SimpleCache(cacheDir, evictor, databaseProvider)
|
|
22
|
+
}
|
|
23
|
+
return cache!!
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -20,10 +20,6 @@ import expo.modules.kotlin.modules.Module
|
|
|
20
20
|
import expo.modules.kotlin.modules.ModuleDefinition
|
|
21
21
|
|
|
22
22
|
class ExpoOrpheusModule : Module() {
|
|
23
|
-
companion object {
|
|
24
|
-
val TAG = "Orpheus"
|
|
25
|
-
}
|
|
26
|
-
|
|
27
23
|
private var controllerFuture: ListenableFuture<MediaController>? = null
|
|
28
24
|
|
|
29
25
|
private var controller: MediaController? = null
|
|
@@ -201,7 +197,7 @@ class ExpoOrpheusModule : Module() {
|
|
|
201
197
|
return@AsyncFunction queue
|
|
202
198
|
}.runOnQueue(Queues.MAIN)
|
|
203
199
|
|
|
204
|
-
AsyncFunction("addToEnd") { tracks: List<TrackRecord>, startFromId: String? ->
|
|
200
|
+
AsyncFunction("addToEnd") { tracks: List<TrackRecord>, startFromId: String?, clearQueue: Boolean? ->
|
|
205
201
|
val mediaItems = tracks.mapNotNull { track ->
|
|
206
202
|
try {
|
|
207
203
|
val trackJson = gson.toJson(track)
|
|
@@ -229,6 +225,9 @@ class ExpoOrpheusModule : Module() {
|
|
|
229
225
|
}
|
|
230
226
|
}
|
|
231
227
|
val player = controller ?: return@AsyncFunction
|
|
228
|
+
if (clearQueue == true) {
|
|
229
|
+
player.clearMediaItems()
|
|
230
|
+
}
|
|
232
231
|
val initialSize = player.mediaItemCount
|
|
233
232
|
player.addMediaItems(mediaItems)
|
|
234
233
|
|
|
@@ -271,8 +270,6 @@ class ExpoOrpheusModule : Module() {
|
|
|
271
270
|
.setUri(track.url)
|
|
272
271
|
.setMediaMetadata(metadata)
|
|
273
272
|
.build()
|
|
274
|
-
|
|
275
|
-
val currentId = player.currentMediaItem?.mediaId
|
|
276
273
|
val targetIndex = player.currentMediaItemIndex + 1
|
|
277
274
|
|
|
278
275
|
var existingIndex = -1
|
|
@@ -8,6 +8,7 @@ import androidx.media3.common.util.UnstableApi
|
|
|
8
8
|
import androidx.media3.datasource.DataSpec
|
|
9
9
|
import androidx.media3.datasource.DefaultHttpDataSource
|
|
10
10
|
import androidx.media3.datasource.ResolvingDataSource
|
|
11
|
+
import androidx.media3.datasource.cache.CacheDataSource
|
|
11
12
|
import androidx.media3.exoplayer.ExoPlayer
|
|
12
13
|
import androidx.media3.exoplayer.source.DefaultMediaSourceFactory
|
|
13
14
|
import androidx.media3.session.MediaLibraryService
|
|
@@ -29,8 +30,13 @@ class OrpheusService : MediaLibraryService() {
|
|
|
29
30
|
.setUserAgent("Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36")
|
|
30
31
|
.setAllowCrossProtocolRedirects(true)
|
|
31
32
|
|
|
33
|
+
val cacheDataSourceFactory = CacheDataSource.Factory()
|
|
34
|
+
.setCache(DownloadCache.get(this))
|
|
35
|
+
.setUpstreamDataSourceFactory(httpDataSourceFactory)
|
|
36
|
+
.setFlags(CacheDataSource.FLAG_IGNORE_CACHE_ON_ERROR)
|
|
37
|
+
|
|
32
38
|
val resolvingDataSourceFactory = ResolvingDataSource.Factory(
|
|
33
|
-
|
|
39
|
+
cacheDataSourceFactory,
|
|
34
40
|
object : ResolvingDataSource.Resolver {
|
|
35
41
|
// TODO: maybe we need to add a cache?
|
|
36
42
|
override fun resolveDataSpec(dataSpec: DataSpec): DataSpec {
|
|
@@ -64,6 +70,7 @@ class OrpheusService : MediaLibraryService() {
|
|
|
64
70
|
return dataSpec.buildUpon()
|
|
65
71
|
.setUri(realUrl.toUri())
|
|
66
72
|
.setHttpRequestHeaders(headers)
|
|
73
|
+
.setKey(uri.toString())
|
|
67
74
|
.build()
|
|
68
75
|
} catch (e: Exception) {
|
|
69
76
|
throw IOException("Resolve Url Failed: ${e.message}", e)
|
|
@@ -99,8 +99,10 @@ declare class OrpheusModule extends NativeModule<OrpheusEvents> {
|
|
|
99
99
|
/**
|
|
100
100
|
* 添加到队列末尾,且不去重。
|
|
101
101
|
* @param tracks
|
|
102
|
+
* @param startFromId 可选,添加后立即播放该 ID 的曲目
|
|
103
|
+
* @param clearQueue 可选,是否清空当前队列
|
|
102
104
|
*/
|
|
103
|
-
addToEnd(tracks: Track[], startFromId?: string): Promise<void>;
|
|
105
|
+
addToEnd(tracks: Track[], startFromId?: string, clearQueue?: boolean): Promise<void>;
|
|
104
106
|
/**
|
|
105
107
|
* 播放下一首
|
|
106
108
|
* @param track
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ExpoOrpheusModule.d.ts","sourceRoot":"","sources":["../src/ExpoOrpheusModule.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"ExpoOrpheusModule.d.ts","sourceRoot":"","sources":["../src/ExpoOrpheusModule.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ExpoOrpheusModule.js","sourceRoot":"","sources":["../src/ExpoOrpheusModule.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAgB,MAAM,mBAAmB,CAAC;AAEtE,MAAM,CAAN,IAAY,aAKX;AALD,WAAY,aAAa;IACvB,iDAAQ,CAAA;IACR,2DAAa,CAAA;IACb,mDAAS,CAAA;IACT,mDAAS,CAAA;AACX,CAAC,EALW,aAAa,KAAb,aAAa,QAKxB;AAED,MAAM,CAAN,IAAY,UAIX;AAJD,WAAY,UAAU;IACpB,yCAAO,CAAA;IACP,6CAAS,CAAA;IACT,6CAAS,CAAA;AACX,CAAC,EAJW,UAAU,KAAV,UAAU,QAIrB;AAED,MAAM,CAAN,IAAY,gBAKX;AALD,WAAY,gBAAgB;IAC1B,2DAAU,CAAA;IACV,uDAAQ,CAAA;IACR,uDAAQ,CAAA;IACR,+EAAoB,CAAA;AACtB,CAAC,EALW,gBAAgB,KAAhB,gBAAgB,QAK3B;
|
|
1
|
+
{"version":3,"file":"ExpoOrpheusModule.js","sourceRoot":"","sources":["../src/ExpoOrpheusModule.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAgB,MAAM,mBAAmB,CAAC;AAEtE,MAAM,CAAN,IAAY,aAKX;AALD,WAAY,aAAa;IACvB,iDAAQ,CAAA;IACR,2DAAa,CAAA;IACb,mDAAS,CAAA;IACT,mDAAS,CAAA;AACX,CAAC,EALW,aAAa,KAAb,aAAa,QAKxB;AAED,MAAM,CAAN,IAAY,UAIX;AAJD,WAAY,UAAU;IACpB,yCAAO,CAAA;IACP,6CAAS,CAAA;IACT,6CAAS,CAAA;AACX,CAAC,EAJW,UAAU,KAAV,UAAU,QAIrB;AAED,MAAM,CAAN,IAAY,gBAKX;AALD,WAAY,gBAAgB;IAC1B,2DAAU,CAAA;IACV,uDAAQ,CAAA;IACR,uDAAQ,CAAA;IACR,+EAAoB,CAAA;AACtB,CAAC,EALW,gBAAgB,KAAhB,gBAAgB,QAK3B;AAkHD,MAAM,CAAC,MAAM,OAAO,GAAG,mBAAmB,CAAgB,SAAS,CAAC,CAAC","sourcesContent":["import { requireNativeModule, NativeModule } from \"expo-modules-core\";\n\nexport enum PlaybackState {\n IDLE = 1,\n BUFFERING = 2,\n READY = 3,\n ENDED = 4,\n}\n\nexport enum RepeatMode {\n OFF = 0,\n TRACK = 1,\n QUEUE = 2,\n}\n\nexport enum TransitionReason {\n REPEAT = 0,\n AUTO = 1,\n SEEK = 2,\n PLAYLIST_CHANGED = 3,\n}\n\nexport interface Track {\n id: string;\n url: string;\n title?: string;\n artist?: string;\n artwork?: string;\n duration?: number;\n [key: string]: any;\n}\n\nexport type OrpheusEvents = {\n onPlaybackStateChanged(event: { state: PlaybackState }): void;\n onTrackTransition(event: {\n currentTrackId: string;\n previousTrackId?: string;\n reason: TransitionReason;\n }): void;\n onPlayerError(event: { code: string; message: string }): void;\n onPositionUpdate(event: {\n position: number;\n duration: number;\n buffered: number;\n }): void;\n onIsPlayingChanged(event: { status: boolean }): void;\n};\n\ndeclare class OrpheusModule extends NativeModule<OrpheusEvents> {\n /**\n * 获取当前进度(秒)\n */\n getPosition(): Promise<number>;\n\n /**\n * 获取总时长(秒)\n */\n getDuration(): Promise<number>;\n\n /**\n * 获取缓冲进度(秒)\n */\n getBuffered(): Promise<number>;\n\n /**\n * 获取是否正在播放\n */\n getIsPlaying(): Promise<boolean>;\n\n /**\n * 获取当前播放索引\n */\n getCurrentIndex(): Promise<number>;\n\n /**\n * 获取当前播放的 Track 对象\n */\n getCurrentTrack(): Promise<Track | null>;\n\n /**\n * 获取随机模式状态\n */\n getShuffleMode(): Promise<boolean>;\n\n /**\n * 获取指定索引的 Track\n */\n getIndexTrack(index: number): Promise<Track | null>;\n\n getRepeatMode(): Promise<RepeatMode>;\n\n setBilibiliCookie(cookie: string): void;\n\n play(): Promise<void>;\n\n pause(): Promise<void>;\n\n clear(): Promise<void>;\n\n skipTo(index: number): Promise<void>;\n\n skipToNext(): Promise<void>;\n\n skipToPrevious(): Promise<void>;\n\n /**\n * 跳转进度\n * @param seconds 秒数\n */\n seekTo(seconds: number): Promise<void>;\n\n setRepeatMode(mode: RepeatMode): Promise<void>;\n\n setShuffleMode(enabled: boolean): Promise<void>;\n\n getQueue(): Promise<Track[]>;\n\n /**\n * 添加到队列末尾,且不去重。\n * @param tracks\n * @param startFromId 可选,添加后立即播放该 ID 的曲目\n * @param clearQueue 可选,是否清空当前队列\n */\n addToEnd(tracks: Track[], startFromId?: string, clearQueue?: boolean): Promise<void>;\n\n /**\n * 播放下一首\n * @param track\n */\n playNext(track: Track): Promise<void>;\n\n removeTrack(index: number): Promise<void>;\n}\n\nexport const Orpheus = requireNativeModule<OrpheusModule>(\"Orpheus\");\n"]}
|
package/package.json
CHANGED
package/src/ExpoOrpheusModule.ts
CHANGED
|
@@ -118,8 +118,10 @@ declare class OrpheusModule extends NativeModule<OrpheusEvents> {
|
|
|
118
118
|
/**
|
|
119
119
|
* 添加到队列末尾,且不去重。
|
|
120
120
|
* @param tracks
|
|
121
|
+
* @param startFromId 可选,添加后立即播放该 ID 的曲目
|
|
122
|
+
* @param clearQueue 可选,是否清空当前队列
|
|
121
123
|
*/
|
|
122
|
-
addToEnd(tracks: Track[], startFromId?: string): Promise<void>;
|
|
124
|
+
addToEnd(tracks: Track[], startFromId?: string, clearQueue?: boolean): Promise<void>;
|
|
123
125
|
|
|
124
126
|
/**
|
|
125
127
|
* 播放下一首
|