musikr: remove di

This commit is contained in:
Alexander Capehart 2024-12-13 18:02:39 -07:00
parent a2498db6e5
commit e16b23f34e
No known key found for this signature in database
GPG key ID: 37DBE3621FE9AD47
23 changed files with 80 additions and 268 deletions

View file

@ -26,6 +26,7 @@ import dagger.hilt.InstallIn
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import javax.inject.Singleton
import org.oxycblt.musikr.Musikr
import org.oxycblt.musikr.cache.CacheDatabase
@Module
@ -42,4 +43,6 @@ class MusikrShimModule {
@Singleton
@Provides
fun tagDatabase(@ApplicationContext context: Context) = CacheDatabase.from(context)
@Provides fun musikr(@ApplicationContext context: Context) = Musikr.new(context)
}

View file

@ -18,7 +18,7 @@
package org.oxycblt.musikr
import javax.inject.Inject
import android.content.Context
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.flow.buffer
@ -37,6 +37,11 @@ interface Musikr {
interpretation: Interpretation,
onProgress: suspend (IndexingProgress) -> Unit = {}
): MutableLibrary
companion object {
fun new(context: Context): Musikr =
MusikrImpl(ExploreStep.from(context), ExtractStep.from(context), EvaluateStep.new())
}
}
/**
@ -50,9 +55,7 @@ sealed interface IndexingProgress {
data object Indeterminate : IndexingProgress
}
class MusikrImpl
@Inject
constructor(
class MusikrImpl(
private val exploreStep: ExploreStep,
private val extractStep: ExtractStep,
private val evaluateStep: EvaluateStep

View file

@ -1,30 +0,0 @@
/*
* Copyright (c) 2024 Auxio Project
* MusikrModule.kt is part of Auxio.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.oxycblt.musikr
import dagger.Binds
import dagger.Module
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
@Module
@InstallIn(SingletonComponent::class)
interface MusikrModule {
@Binds fun musikr(impl: MusikrImpl): Musikr
}

View file

@ -19,8 +19,6 @@
package org.oxycblt.musikr.metadata
import android.content.Context
import dagger.hilt.android.qualifiers.ApplicationContext
import javax.inject.Inject
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import org.oxycblt.auxio.util.unlikelyToBeNull
@ -31,10 +29,13 @@ import org.oxycblt.musikr.fs.query.DeviceFile
interface MetadataExtractor {
suspend fun extract(file: DeviceFile): Metadata?
companion object {
fun from(context: Context): MetadataExtractor = MetadataExtractorImpl(context)
}
}
class MetadataExtractorImpl @Inject constructor(@ApplicationContext private val context: Context) :
MetadataExtractor {
private class MetadataExtractorImpl(private val context: Context) : MetadataExtractor {
override suspend fun extract(file: DeviceFile) =
withContext(Dispatchers.IO) {
KTagLib.open(context, FileRef(unlikelyToBeNull(file.path.name), file.uri))

View file

@ -28,6 +28,4 @@ import dagger.hilt.components.SingletonComponent
interface MetadataModule {
@Binds
fun audioPropertiesFactory(interpreter: AudioPropertiesFactoryImpl): AudioProperties.Factory
@Binds fun metadataExtractor(extractor: MetadataExtractorImpl): MetadataExtractor
}

View file

@ -18,7 +18,6 @@
package org.oxycblt.musikr.model
import javax.inject.Inject
import org.oxycblt.musikr.Album
import org.oxycblt.musikr.Artist
import org.oxycblt.musikr.Genre
@ -32,9 +31,13 @@ import org.oxycblt.musikr.graph.SongVertex
interface LibraryFactory {
fun create(graph: MusicGraph): MutableLibrary
companion object {
fun new(): LibraryFactory = LibraryFactoryImpl()
}
}
class LibraryFactoryImpl @Inject constructor() : LibraryFactory {
private class LibraryFactoryImpl() : LibraryFactory {
override fun create(graph: MusicGraph): MutableLibrary {
val songs =
graph.songVertex.mapTo(mutableSetOf()) { vertex ->

View file

@ -1,30 +0,0 @@
/*
* Copyright (c) 2024 Auxio Project
* ModelModule.kt is part of Auxio.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.oxycblt.musikr.model
import dagger.Binds
import dagger.Module
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
@Module
@InstallIn(SingletonComponent::class)
interface ModelModule {
@Binds fun libraryFactory(factory: LibraryFactoryImpl): LibraryFactory
}

View file

@ -18,7 +18,6 @@
package org.oxycblt.musikr.pipeline
import javax.inject.Inject
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.Flow
@ -37,11 +36,13 @@ interface EvaluateStep {
interpretation: Interpretation,
extractedMusic: Flow<ExtractedMusic>
): MutableLibrary
companion object {
fun new(): EvaluateStep = EvaluateStepImpl(TagInterpreter.new(), LibraryFactory.new())
}
}
class EvaluateStepImpl
@Inject
constructor(
private class EvaluateStepImpl(
private val tagInterpreter: TagInterpreter,
private val libraryFactory: LibraryFactory
) : EvaluateStep {

View file

@ -19,8 +19,6 @@
package org.oxycblt.musikr.pipeline
import android.content.Context
import dagger.hilt.android.qualifiers.ApplicationContext
import javax.inject.Inject
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.asFlow
@ -33,12 +31,15 @@ import org.oxycblt.musikr.playlist.m3u.M3U
interface ExploreStep {
fun explore(locations: List<MusicLocation>): Flow<ExploreNode>
companion object {
fun from(context: Context): ExploreStep = ExploreStepImpl(DeviceFiles.from(context))
}
}
class ExploreStepImpl @Inject constructor(@ApplicationContext private val context: Context) :
ExploreStep {
private class ExploreStepImpl(private val deviceFiles: DeviceFiles) : ExploreStep {
override fun explore(locations: List<MusicLocation>) =
DeviceFiles.from(context)
deviceFiles
.explore(locations.asFlow())
.mapNotNull {
when {

View file

@ -18,7 +18,7 @@
package org.oxycblt.musikr.pipeline
import javax.inject.Inject
import android.content.Context
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.Flow
@ -39,12 +39,17 @@ import timber.log.Timber as L
interface ExtractStep {
fun extract(storage: Storage, nodes: Flow<ExploreNode>): Flow<ExtractedMusic>
companion object {
fun from(context: Context): ExtractStep =
ExtractStepImpl(MetadataExtractor.from(context), TagParser.new())
}
}
class ExtractStepImpl
@Inject
constructor(private val metadataExtractor: MetadataExtractor, private val tagParser: TagParser) :
ExtractStep {
private class ExtractStepImpl(
private val metadataExtractor: MetadataExtractor,
private val tagParser: TagParser
) : ExtractStep {
override fun extract(storage: Storage, nodes: Flow<ExploreNode>): Flow<ExtractedMusic> {
val cacheResults =
nodes

View file

@ -1,34 +0,0 @@
/*
* Copyright (c) 2024 Auxio Project
* PipelineModule.kt is part of Auxio.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.oxycblt.musikr.pipeline
import dagger.Binds
import dagger.Module
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
@Module
@InstallIn(SingletonComponent::class)
interface InterpretModule {
@Binds fun exploreStep(step: ExploreStepImpl): ExploreStep
@Binds fun extractStep(step: ExtractStepImpl): ExtractStep
@Binds fun evaluateStep(step: EvaluateStepImpl): EvaluateStep
}

View file

@ -1,19 +0,0 @@
/*
* Copyright (c) 2023 Auxio Project
* PlaylistModule.kt is part of Auxio.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.oxycblt.musikr.playlist

View file

@ -18,11 +18,13 @@
package org.oxycblt.musikr.playlist.db
import android.content.Context
import androidx.room.Dao
import androidx.room.Database
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import androidx.room.Room
import androidx.room.RoomDatabase
import androidx.room.Transaction
import androidx.room.TypeConverters
@ -39,7 +41,15 @@ import org.oxycblt.musikr.Music
exportSchema = false)
@TypeConverters(Music.UID.TypeConverters::class)
abstract class PlaylistDatabase : RoomDatabase() {
abstract fun playlistDao(): PlaylistDao
internal abstract fun playlistDao(): PlaylistDao
companion object {
fun from(context: Context) =
Room.databaseBuilder(
context.applicationContext, PlaylistDatabase::class.java, "user_music.db")
.fallbackToDestructiveMigration()
.build()
}
}
// TODO: Handle playlist defragmentation? I really don't want dead songs to accumulate in this
@ -51,7 +61,7 @@ abstract class PlaylistDatabase : RoomDatabase() {
* @author Alexander Capehart (OxygenCobalt)
*/
@Dao
abstract class PlaylistDao {
internal abstract class PlaylistDao {
/**
* Read out all playlists stored in the database.
*

View file

@ -31,7 +31,7 @@ import org.oxycblt.musikr.Music
*
* @author Alexander Capehart (OxygenCobalt)
*/
data class RawPlaylist(
internal data class RawPlaylist(
@Embedded val playlistInfo: PlaylistInfo,
@Relation(
parentColumn = "playlistUid",
@ -45,14 +45,14 @@ data class RawPlaylist(
*
* @author Alexander Capehart (OxygenCobalt)
*/
@Entity data class PlaylistInfo(@PrimaryKey val playlistUid: Music.UID, val name: String)
@Entity internal data class PlaylistInfo(@PrimaryKey val playlistUid: Music.UID, val name: String)
/**
* Song information corresponding to a [RawPlaylist] entry.
*
* @author Alexander Capehart (OxygenCobalt)
*/
@Entity data class PlaylistSong(@PrimaryKey val songUid: Music.UID)
@Entity internal data class PlaylistSong(@PrimaryKey val songUid: Music.UID)
/**
* Links individual songs to a playlist entry.
@ -60,7 +60,7 @@ data class RawPlaylist(
* @author Alexander Capehart (OxygenCobalt)
*/
@Entity
data class PlaylistSongCrossRef(
internal data class PlaylistSongCrossRef(
@PrimaryKey(autoGenerate = true) val id: Long = 0,
@ColumnInfo(index = true) val playlistUid: Music.UID,
@ColumnInfo(index = true) val songUid: Music.UID

View file

@ -18,7 +18,6 @@
package org.oxycblt.musikr.playlist.db
import javax.inject.Inject
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.asFlow
import kotlinx.coroutines.flow.emitAll
@ -28,9 +27,13 @@ import org.oxycblt.musikr.playlist.PlaylistFile
interface StoredPlaylists {
fun read(): Flow<PlaylistFile>
companion object {
fun from(database: PlaylistDatabase): StoredPlaylists =
StoredPlaylistsImpl(database.playlistDao())
}
}
class StoredPlaylistsImpl @Inject constructor(private val playlistDao: PlaylistDao) :
StoredPlaylists {
private class StoredPlaylistsImpl(private val playlistDao: PlaylistDao) : StoredPlaylists {
override fun read() = flow { emitAll(playlistDao.readRawPlaylists().asFlow().map { TODO() }) }
}

View file

@ -1,47 +0,0 @@
/*
* Copyright (c) 2023 Auxio Project
* UserModule.kt is part of Auxio.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.oxycblt.musikr.playlist.db
import android.content.Context
import androidx.room.Room
import dagger.Binds
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
@Module
@InstallIn(SingletonComponent::class)
interface PlaylistModule {
@Binds fun storedPlaylists(impl: StoredPlaylistsImpl): StoredPlaylists
}
@Module
@InstallIn(SingletonComponent::class)
class PlaylistRoomModule {
@Provides fun playlistDao(database: PlaylistDatabase) = database.playlistDao()
@Provides
fun playlistDatabase(@ApplicationContext context: Context) =
Room.databaseBuilder(
context.applicationContext, PlaylistDatabase::class.java, "user_music.db")
.fallbackToDestructiveMigration()
.build()
}

View file

@ -25,7 +25,6 @@ import java.io.BufferedWriter
import java.io.InputStream
import java.io.InputStreamReader
import java.io.OutputStream
import javax.inject.Inject
import org.oxycblt.auxio.util.unlikelyToBeNull
import org.oxycblt.musikr.Playlist
import org.oxycblt.musikr.fs.Components
@ -80,9 +79,7 @@ interface M3U {
}
}
class M3UImpl
@Inject
constructor(
private class M3UImpl(
@ApplicationContext private val context: Context,
private val volumeManager: VolumeManager
) : M3U {

View file

@ -1,30 +0,0 @@
/*
* Copyright (c) 2024 Auxio Project
* InterpretModule.kt is part of Auxio.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.oxycblt.musikr.tag.interpret
import dagger.Binds
import dagger.Module
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
@Module
@InstallIn(SingletonComponent::class)
interface InterpretModule {
@Binds fun tagInterpreter(factory: TagInterpreterImpl): TagInterpreter
}

View file

@ -18,7 +18,6 @@
package org.oxycblt.musikr.tag.interpret
import javax.inject.Inject
import org.oxycblt.auxio.R
import org.oxycblt.auxio.playback.replaygain.ReplayGainAdjustment
import org.oxycblt.auxio.util.toUuidOrNull
@ -39,9 +38,13 @@ interface TagInterpreter {
cover: Cover.Single?,
interpretation: Interpretation
): PreSong
companion object {
fun new(): TagInterpreter = TagInterpreterImpl
}
}
class TagInterpreterImpl @Inject constructor() : TagInterpreter {
private data object TagInterpreterImpl : TagInterpreter {
override fun interpret(
file: DeviceFile,
parsedTags: ParsedTags,

View file

@ -1,30 +0,0 @@
/*
* Copyright (c) 2024 Auxio Project
* ParseModule.kt is part of Auxio.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.oxycblt.musikr.tag.parse
import dagger.Binds
import dagger.Module
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
@Module
@InstallIn(SingletonComponent::class)
interface ParseModule {
@Binds fun tagParser(factory: TagParserImpl): TagParser
}

View file

@ -18,17 +18,20 @@
package org.oxycblt.musikr.tag.parse
import javax.inject.Inject
import org.oxycblt.ktaglib.Metadata
import org.oxycblt.musikr.fs.query.DeviceFile
interface TagParser {
fun parse(file: DeviceFile, metadata: Metadata): ParsedTags
companion object {
fun new(): TagParser = TagParserImpl
}
}
class MissingTagError(what: String) : Error("missing tag: $what")
class TagParserImpl @Inject constructor() : TagParser {
private data object TagParserImpl : TagParser {
override fun parse(file: DeviceFile, metadata: Metadata): ParsedTags {
return ParsedTags(
durationMs = metadata.properties.durationMs,

View file

@ -10,8 +10,8 @@
JVMMetadataBuilder::JVMMetadataBuilder(JNIEnv *env) : env(env), id3v2(env), xiph(env), mp4(env),
cover(), properties(nullptr) {}
void JVMMetadataBuilder::setMimeType(const std::string_view mimeType) {
this->mimeType = mimeType;
void JVMMetadataBuilder::setMimeType(const std::string_view type) {
this->mimeType = type;
}
void JVMMetadataBuilder::setId3v2(const TagLib::ID3v2::Tag &tag) {
@ -124,8 +124,9 @@ jobject JVMMetadataBuilder::build() {
jobject mp4Map = mp4.getObject();
jbyteArray coverArray = nullptr;
if (cover.has_value()) {
coverArray = env->NewByteArray(static_cast<jsize>(cover->size());
env->SetByteArrayRegion(coverArray, 0, cover->size(), reinterpret_cast<const jbyte *>(cover->data()));
auto coverSize = static_cast<jsize>(cover->size());
coverArray = env->NewByteArray(coverSize);
env->SetByteArrayRegion(coverArray, 0, coverSize, reinterpret_cast<const jbyte *>(cover->data()));
}
jobject metadataObj = env->NewObject(metadataClass, metadataInit, id3v2Map, xiphMap, mp4Map, coverArray, propertiesObj);
env->DeleteLocalRef(metadataClass);

View file

@ -20,7 +20,7 @@ class JVMMetadataBuilder {
public:
JVMMetadataBuilder(JNIEnv *env);
void setMimeType(const std::string_view mimeType);
void setMimeType(const std::string_view type);
void setId3v2(const TagLib::ID3v2::Tag &tag);
void setXiph(const TagLib::Ogg::XiphComment &tag);
void setMp4(const TagLib::MP4::Tag &tag);