### Initialize and Start Medialibrary Scanning Source: https://context7.com/videolan/vlc-android/llms.txt Initialize the Medialibrary singleton and start the media discovery process. Call `construct()` once with a `Context`, then `init()` to open the native database, and finally `discover()` to kick off folder scanning. The `onMedialibraryReady` callback is used to safely query the library after initialization. ```kotlin val ml = Medialibrary.getInstance() ml.addOnMedialibraryReadyListener(object : Medialibrary.OnMedialibraryReadyListener { override fun onMedialibraryReady() { // Safe to query the library val videos: Array = ml.getVideos( Medialibrary.SORT_INSERTIONDATE, /*desc=*/true, /*includeMissing=*/false, /*onlyFavorites=*/false ) Log.d("ML", "Found ${videos.size} videos") } override fun onMedialibraryIdle() = Unit }) val result = ml.init(applicationContext) // returns ML_INIT_SUCCESS etc. if (result != Medialibrary.ML_INIT_ALREADY_INITIALIZED) { ml.start() ml.discover(Environment.getExternalStorageDirectory().absolutePath) } ``` -------------------------------- ### Install Maven on Debian/Ubuntu Source: https://github.com/videolan/vlc-android/blob/master/buildsystem/maven/README.md Installs Apache Maven using the system's package manager. Ensure you have sudo privileges. ```bash sudo apt install maven ``` -------------------------------- ### Install Build Dependencies on Debian/Ubuntu Source: https://github.com/videolan/vlc-android/blob/master/README.md Installs essential packages required for building VLC on Debian/Ubuntu systems. Ensure you have sufficient disk space and a stable internet connection. ```bash sudo apt install automake ant autopoint cmake build-essential libtool-bin \n patch pkg-config protobuf-compiler ragel subversion unzip git \n openjdk-8-jre openjdk-8-jdk flex python wget ``` -------------------------------- ### Take Screenshots for TV Source: https://github.com/videolan/vlc-android/blob/master/buildsystem/automation/README.md Launches the screenshot UI tests for Android TV. Requires three AVDs to be created, VLC installed, and samples added. ```bash bundle exec fastlane screenshots_tv version:"3.3.1-Beta-1" ``` -------------------------------- ### Install fastlane Source: https://github.com/videolan/vlc-android/blob/master/buildsystem/automation/README.md Installs fastlane using RubyGems. Ensure Ruby and its development headers are installed first. ```bash sudo apt install ruby ruby-dev export LC_ALL=en_US.UTF-8 export LANG=en_US.UTF-8 sudo gem install fastlane ``` -------------------------------- ### Take Screenshots for 10-inch Tablets Source: https://github.com/videolan/vlc-android/blob/master/buildsystem/automation/README.md Launches the screenshot UI tests for 10-inch tablets. Requires three AVDs to be created, VLC installed, and samples added. ```bash bundle exec fastlane screenshots_ten version:"3.3.1-Beta-1" ``` -------------------------------- ### Take Screenshots for Mobile Source: https://github.com/videolan/vlc-android/blob/master/buildsystem/automation/README.md Launches the screenshot UI tests for mobile devices. Requires three AVDs to be created, VLC installed, and samples added. ```bash bundle exec fastlane screenshots version:"3.3.1-Beta-1" ``` -------------------------------- ### Take Screenshots for 7-inch Tablets Source: https://github.com/videolan/vlc-android/blob/master/buildsystem/automation/README.md Launches the screenshot UI tests for 7-inch tablets. Requires three AVDs to be created, VLC installed, and samples added. ```bash bundle exec fastlane screenshots_seven version:"3.3.1-Beta-1" ``` -------------------------------- ### Set Android SDK Path Source: https://github.com/videolan/vlc-android/blob/master/buildsystem/automation/README.md Sets the ANDROID_SDK environment variable to the path of your Android SDK installation. ```bash export ANDROID_SDK=/path/to/sdk/ ``` -------------------------------- ### Deploy Beta to Play Store Source: https://github.com/videolan/vlc-android/blob/master/buildsystem/automation/README.md Deploys a beta version to the Play Store in draft mode. Ensure the Play Store certificate is available at './certificates/vlc.json' and necessary API keys are exported. ```bash bundle exec fastlane deploy_beta ``` -------------------------------- ### Deploy via FTP Source: https://github.com/videolan/vlc-android/blob/master/buildsystem/automation/README.md Uploads APKs and SHA256 files to an FTP server. Requires VIDEOLAN_FTP_HOST environment variable to be set. Files are uploaded to '/incoming/[version]' folder. ```bash bundle exec fastlane deploy_ftp version:"3.3.1-Beta-1" ``` -------------------------------- ### Deploy Beta to Play Store Source: https://github.com/videolan/vlc-android/blob/master/buildsystem/automation/README.md Deploys a beta version to the Play Store in draft mode. Requires Play Store API key and Slack webhook URL to be set as environment variables. ```bash bundle exec fastlane deploy_beta version:"3.3.1-Beta-1" ``` -------------------------------- ### Deploy Release to Play Store Source: https://github.com/videolan/vlc-android/blob/master/buildsystem/automation/README.md Deploys a release version to the Play Store in draft mode. Ensure the Play Store certificate is available at './certificates/vlc.json' and necessary API keys are exported. ```bash bundle exec fastlane deploy_release ``` -------------------------------- ### Manage Bookmarks and Playback on MediaWrapper Source: https://context7.com/videolan/vlc-android/llms.txt Add, list, and remove bookmarks with timestamps and descriptions for media files. Track playback progress, set play counts, and request thumbnail generation for `MediaWrapper` objects. ```kotlin val ml = Medialibrary.getInstance() val media: MediaWrapper? = ml.getMedia(Uri.parse("file:///storage/emulated/0/Movies/sample.mp4")) media?.let { mw -> // Add a bookmark at 1m30s val bookmark: Bookmark? = mw.addBookmark(90_000L) // time in ms bookmark?.setNameAndDescription("Intro ends", "Scene change at 1:30") // List bookmarks mw.getBookmarks()?.forEach { bm -> Log.d("Bookmark", "${bm.getTitle()} @ ${bm.getTime()}ms") } // Remove a specific bookmark mw.removeBookmark(90_000L) // Track progress mw.setPlayCount(1L) Log.d("Media", "Played ${mw.getPlayCount()} time(s), width=${mw.width}, height=${mw.height}") // Request thumbnail generation at 25% into the video mw.requestThumbnail(/*width=*/512, /*position=*/0.25f) } ``` -------------------------------- ### Deploy to Huawei AppGallery Source: https://github.com/videolan/vlc-android/blob/master/buildsystem/automation/README.md Sends a release to the Huawei AppGallery in draft mode. Requires HUAWEI_CLIENT_ID, HUAWEI_CLIENT_SECRET, and HUAWEI_APP_ID environment variables to be set. ```bash bundle exec fastlane deploy_huawei version:"3.3.1-Beta-1" ``` -------------------------------- ### Register Medialibrary Discovery and Change Callbacks Source: https://context7.com/videolan/vlc-android/llms.txt Observe scanning lifecycle events using `DevicesDiscoveryCb` and react to library changes (media added, modified, deleted) with `MediaCb`. Remember to clean up callbacks when no longer needed. ```kotlin val ml = Medialibrary.getInstance() val discoveryCb = object : DevicesDiscoveryCb { override fun onDiscoveryStarted() = Log.d("ML", "Scan started") override fun onDiscoveryProgress(root: String) = Log.d("ML", "Scanning: $root") override fun onDiscoveryCompleted() = Log.d("ML", "Scan complete") override fun onDiscoveryFailed(root: String) = Log.e("ML", "Scan failed: $root") override fun onParsingStatsUpdated(done: Int, scheduled: Int) = Log.d("ML", "$done/$scheduled parsed") override fun onReloadStarted(root: String) = Unit override fun onReloadCompleted(root: String) = Unit } ml.addDeviceDiscoveryCb(discoveryCb) val mediaCb = object : Medialibrary.MediaCb { override fun onMediaAdded() = Log.d("ML", "New media added") override fun onMediaModified() = Log.d("ML", "Media modified") override fun onMediaDeleted() = Log.d("ML", "Media deleted") override fun onMediaConvertedToExternal() = Unit } ml.addMediaCb(mediaCb) // Force a full rescan ml.forceRescan() // Cleanup ml.removeDeviceDiscoveryCb(discoveryCb) ml.removeMediaCb(mediaCb) ``` -------------------------------- ### Deploy Artifacts using Script Source: https://github.com/videolan/vlc-android/blob/master/buildsystem/maven/README.md Executes a deployment script to sign and upload artifacts to Maven Central. Requires a path to the artifact zip file. The script handles unzipping, configuration, signing, and deployment, including temporary credential file management. ```bash ./deploy-to-mavencentral.sh [FILE_PATH] ``` -------------------------------- ### Access MediaDatabase DAOs for Browser Favourites and Equalizer Presets Source: https://context7.com/videolan/vlc-android/llms.txt Interact with the MediaDatabase singleton to access Data Access Objects (DAOs) for managing browser favorites, external subtitles, equalizer presets, and widgets. This includes inserting, observing, and deleting favorites, as well as inserting equalizer bands. ```kotlin val db = MediaDatabase.getInstance(applicationContext) // --- Browser Favourites --- val favDao = db.browserFavDao() // Insert a network favourite favDao.insert(BrowserFav(uri = Uri.parse("smb://nas/Movies"), type = 0, title = "NAS Movies")) // Observe all favourites as a Flow lifecycleScope.launch { favDao.getAll().collect { favs -> favs.forEach { Log.d("Fav", "${it.title}: ${it.uri}") } } } // Delete a favourite favDao.delete(Uri.parse("smb://nas/Movies")) // --- Equalizer --- val eqDao = db.equalizerDao() // Insert a preset band eqDao.insertBand(EqualizerBand(eqId = 1L, index = 0, value = 3.5f)) ``` -------------------------------- ### Compile Medialibrary Source: https://github.com/videolan/vlc-android/blob/master/README.md Builds the Medialibrary component of the VLC for Android project. Use the '-ml' flag instead of '-l' to compile Medialibrary. ```bash buildsystem/compile.sh -ml ``` -------------------------------- ### Implement PlaybackService Callback for Real-time Updates Source: https://context7.com/videolan/vlc-android/llms.txt Implement the PlaybackService.Callback interface to receive real-time notifications about playback state changes, media events, and player events. Register and unregister the callback with the PlaybackService to monitor updates like state changes, meta changes, and media player events. ```kotlin val callback = object : PlaybackService.Callback { override fun update() { // Called on any state change (play/pause/seek/track change) playbackService?.let { svc -> Log.d("CB", "State update — playing=${svc.isPlaying}, pos=${svc.currentMediaPosition}/${svc.mediaListSize}") } } override fun onMediaEvent(event: IMedia.Event) { when (event.type) { IMedia.Event.MetaChanged -> Log.d("CB", "Meta changed") IMedia.Event.ParsedChanged -> Log.d("CB", "Parsed changed") } } override fun onMediaPlayerEvent(event: MediaPlayer.Event) { when (event.type) { MediaPlayer.Event.Playing -> Log.d("CB", "Playing") MediaPlayer.Event.Paused -> Log.d("CB", "Paused") MediaPlayer.Event.EndReached -> Log.d("CB", "End of media") MediaPlayer.Event.EncounteredError -> Log.e("CB", "Playback error") MediaPlayer.Event.PositionChanged -> Log.v("CB", "Position: ${event.positionChanged}") } } } // Register / unregister playbackService?.addCallback(callback) // ... playbackService?.removeCallback(callback) ``` -------------------------------- ### Video Groups and Folders Source: https://context7.com/videolan/vlc-android/llms.txt Organize videos into logical groups or browse media within filesystem folders. Supports pagination and custom group creation. ```APIDOC ## Medialibrary — Video Groups and Folders `VideoGroup` aggregates related video files under a shared name prefix. `Folder` represents a filesystem directory containing media. ```kotlin val ml = Medialibrary.getInstance() // List video groups (paginated) val groups: Array = ml.getVideoGroups( Medialibrary.SORT_ALPHA, false, false, false, /*nbItems=*/20, /*offset=*/0 ) groups.forEach { val videos: Array = group.media( Medialibrary.SORT_DEFAULT, false, false, false, 50, 0 ) Log.d("Group", "${group.getName()}: ${group.mediaCount()} videos (${group.duration()}ms)") } // Create a custom video group from media IDs val customGroup: VideoGroup = ml.createVideoGroup(longArrayOf(10L, 11L, 12L)) customGroup.rename("Holiday 2024") // Browse a video folder val folders: Array = ml.getFolders( Folder.TYPE_FOLDER_VIDEO, Medialibrary.SORT_ALPHA, false, false, false, 20, 0 ) folders.firstOrNull()?.let { val folderMedia: Array = folder.media( Folder.TYPE_FOLDER_VIDEO, Medialibrary.SORT_ALPHA, false, false, false, 50, 0 ) val subFolders: Array = folder.subfolders(Medialibrary.SORT_ALPHA, false, false, false, 20, 0) } ``` ``` -------------------------------- ### PlaybackService - Callback Interface Source: https://context7.com/videolan/vlc-android/llms.txt Implement PlaybackService.Callback to receive real-time updates on playback state and media events. ```APIDOC ## PlaybackService - Callback Interface Implement `PlaybackService.Callback` to receive real-time updates about playback state, media events, and player events. ```kotlin val callback = object : PlaybackService.Callback { override fun update() { // Called on any state change (play/pause/seek/track change) playbackService?.let { svc -> Log.d("CB", "State update — playing=${svc.isPlaying}, pos=${svc.currentMediaPosition}/${svc.mediaListSize}") } } override fun onMediaEvent(event: IMedia.Event) { when (event.type) { IMedia.Event.MetaChanged -> Log.d("CB", "Meta changed") IMedia.Event.ParsedChanged -> Log.d("CB", "Parsed changed") } } override fun onMediaPlayerEvent(event: MediaPlayer.Event) { when (event.type) { MediaPlayer.Event.Playing -> Log.d("CB", "Playing") MediaPlayer.Event.Paused -> Log.d("CB", "Paused") MediaPlayer.Event.EndReached -> Log.d("CB", "End of media") MediaPlayer.Event.EncounteredError -> Log.e("CB", "Playback error") MediaPlayer.Event.PositionChanged -> Log.v("CB", "Position: ${event.positionChanged}") } } } // Register / unregister playbackService?.addCallback(callback) // ... playbackService?.removeCallback(callback) ``` ``` -------------------------------- ### Manage Video Groups and Folders Source: https://context7.com/videolan/vlc-android/llms.txt Aggregate related video files using `VideoGroup` or represent filesystem directories with `Folder`. You can list video groups and their media, create custom groups, and browse folder contents and subfolders. ```kotlin val ml = Medialibrary.getInstance() // List video groups (paginated) val groups: Array = ml.getVideoGroups( Medialibrary.SORT_ALPHA, false, false, false, /*nbItems=*/20, /*offset=*/0 ) groups.forEach { group -> val videos: Array = group.media( Medialibrary.SORT_DEFAULT, false, false, false, 50, 0 ) Log.d("Group", "${group.getName()}: ${group.mediaCount()} videos (${group.duration()}ms)") } // Create a custom video group from media IDs val customGroup: VideoGroup = ml.createVideoGroup(longArrayOf(10L, 11L, 12L)) customGroup.rename("Holiday 2024") // Browse a video folder val folders: Array = ml.getFolders( Folder.TYPE_FOLDER_VIDEO, Medialibrary.SORT_ALPHA, false, false, false, 20, 0 ) folders.firstOrNull()?.let { folder -> val folderMedia: Array = folder.media( Folder.TYPE_FOLDER_VIDEO, Medialibrary.SORT_ALPHA, false, false, false, 50, 0 ) val subFolders: Array = folder.subfolders(Medialibrary.SORT_ALPHA, false, false, false, 20, 0) } ``` -------------------------------- ### Compile LibVLC Library Source: https://github.com/videolan/vlc-android/blob/master/README.md Compiles the LibVLC library for Android. Specify the target ABI (Application Binary Interface) or 'all' for multiple ABIs. Use the '-r' flag for a release build. ```bash buildsystem/compile.sh -l -a ``` -------------------------------- ### Discovery and Library Change Callbacks Source: https://context7.com/videolan/vlc-android/llms.txt Register callbacks to monitor device discovery events and changes within the media library, such as added, modified, or deleted media. Allows for library rescanning. ```APIDOC ## Medialibrary — Discovery Callbacks Register `DevicesDiscoveryCb` to observe scanning lifecycle events, or `MediaCb` / `AlbumsCb` / `ArtistsCb` etc. to react to library changes. ```kotlin val ml = Medialibrary.getInstance() val discoveryCb = object : DevicesDiscoveryCb { override fun onDiscoveryStarted() = Log.d("ML", "Scan started") override fun onDiscoveryProgress(root: String) = Log.d("ML", "Scanning: $root") override fun onDiscoveryCompleted() = Log.d("ML", "Scan complete") override fun onDiscoveryFailed(root: String) = Log.e("ML", "Scan failed: $root") override fun onParsingStatsUpdated(done: Int, scheduled: Int) = Log.d("ML", "$done/$scheduled parsed") override fun onReloadStarted(root: String) = Unit override fun onReloadCompleted(root: String) = Unit } ml.addDeviceDiscoveryCb(discoveryCb) val mediaCb = object : Medialibrary.MediaCb { override fun onMediaAdded() = Log.d("ML", "New media added") override fun onMediaModified() = Log.d("ML", "Media modified") override fun onMediaDeleted() = Log.d("ML", "Media deleted") override fun onMediaConvertedToExternal() = Unit } ml.addMediaCb(mediaCb) // Force a full rescan ml.forceRescan() // Cleanup ml.removeDeviceDiscoveryCb(discoveryCb) ml.removeMediaCb(mediaCb) ``` ``` -------------------------------- ### Search Medialibrary for Media Source: https://context7.com/videolan/vlc-android/llms.txt Use `search()` to find albums, artists, genres, videos, audio tracks, and playlists. The `searchAudio()` method can be used to specifically search for audio tracks with sorting and pagination options. You can also search for albums within a specific artist. ```kotlin val ml = Medialibrary.getInstance() val results: SearchAggregate = ml.search("Beatles", /*includeMissing=*/false, /*onlyFavorites=*/false) if (!results.isEmpty()) { results.artists?.forEach { artist -> Log.d("Search", "Artist: ${artist.title}") } results.albums?.forEach { album -> Log.d("Search", "Album: ${album.title} (${album.releaseYear})") } results.tracks?.forEach { track -> Log.d("Search", "Track: ${track.title}") } results.playlists?.forEach { pl -> Log.d("Search", "Playlist: ${pl.title}") } } // Narrow search to audio tracks only (paginated) val audioHits: Array = ml.searchAudio( "Beatles", Medialibrary.SORT_ALPHA, false, false, false, 20, 0 ) // Search within an artist's albums val artist = ml.getArtist(artistId) val matchingAlbums: Array? = artist?.searchAlbums( "abbey", Medialibrary.SORT_ALPHA, false, false, false, 10, 0 ) ``` -------------------------------- ### Work with MediaWrapper Metadata Source: https://context7.com/videolan/vlc-android/llms.txt MediaWrapper wraps media URIs with parsed metadata, playback state, and type information. Construct from URI, access metadata, and retrieve from Medialibrary. ```kotlin val mw = MediaWrapper(Uri.parse("file:///storage/emulated/0/Music/track.flac")) Log.d("MW", "Title: ${mw.title}") Log.d("MW", "Artist: ${mw.artist}, Album: ${mw.albumName}") Log.d("MW", "Duration: ${mw.length}ms, Type: ${mw.type}") // TYPE_AUDIO / TYPE_VIDEO / etc. Log.d("MW", "Width: ${mw.width}, Height: ${mw.height}") Log.d("MW", "Artwork: ${mw.artworkMrl}") ``` ```kotlin val ml = Medialibrary.getInstance() val libMedia: MediaWrapper? = ml.getMedia(Uri.parse("file:///storage/emulated/0/Music/track.flac")) libMedia?.let { it.setStringMeta(MediaWrapper.META_TITLE, "Custom Title") it.setLongMeta(MediaWrapper.META_PLAYED_COUNT, 10L) it.markAsPlayed() val resumeTime = it.time // last position in ms val resumePos = it.position // last position as 0.0–1.0 float val album: Album? = it.getAlbum() val artist: Artist? = it.getArtist() } ``` -------------------------------- ### Set Android Build Environment Variables Source: https://github.com/videolan/vlc-android/blob/master/README.md Configures the build environment by setting the ANDROID_SDK and ANDROID_NDK paths. These variables are crucial for the build scripts to locate the necessary Android development tools. ```bash export ANDROID_SDK=/path/to/android-sdk export ANDROID_NDK=/path/to/android-ndk ``` -------------------------------- ### Discover and Cast Renderers Source: https://context7.com/videolan/vlc-android/llms.txt Use RendererDelegate to discover remote renderers like Chromecast and UPnP. Observe discovered renderers and assign them to PlaybackService for casting. ```kotlin RendererDelegate.renderers.observe(viewLifecycleOwner) { renderers -> renderers.forEach { item -> Log.d("Renderer", "Found: ${item.displayName} (${item.type})") } } ``` ```kotlin lifecycleScope.launch { RendererDelegate.start() } RendererDelegate.stop() ``` ```kotlin val targetRenderer: RendererItem? = RendererDelegate.renderers.value?.firstOrNull() PlaybackService.renderer.value = targetRenderer ``` ```kotlin PlaybackService.renderer.value = null ``` -------------------------------- ### Query Audio Tracks, Albums, Artists, and Genres Source: https://context7.com/videolan/vlc-android/llms.txt Retrieve paginated or full-result queries for audio tracks, albums, artists, and genres from the Medialibrary. Supports sorting and filtering options. Use `getPagedAudio` for tracks, `getArtist` and `getAlbums` for artist-specific albums, and `getGenres` to list genres. ```kotlin val ml = Medialibrary.getInstance() // --- Audio tracks (first 50, sorted alphabetically) --- val audioPage: Array = ml.getPagedAudio( Medialibrary.SORT_ALPHA, /*desc=*/false, /*includeMissing=*/false, /*onlyFavorites=*/false, /*nbItems=*/50, /*offset=*/0 ) // --- Albums for a given artist ID --- val artist: Artist? = ml.getArtist(artistId) val albums: Array? = artist?.getAlbums( Medialibrary.SORT_RELEASEDATE, /*desc=*/true, /*includeMissing=*/false, /*onlyFavorites=*/false ) // --- Tracks in an album (paginated) --- val album: Album? = ml.getAlbum(albumId) val tracks: Array? = album?.getPagedTracks( Medialibrary.SORT_DEFAULT, /*desc=*/false, /*includeMissing=*/false, /*onlyFavorites=*/false, /*nbItems=*/100, /*offset=*/0 ) // --- Genres and their tracks --- val genres: Array = ml.getGenres(Medialibrary.SORT_ALPHA, false, false, false) genres.firstOrNull()?.let { val genreTracks: Array = genre.getPagedTracks( /*withThumbnail=*/false, Medialibrary.SORT_ALBUM, false, false, false, 20, 0 ) } ``` -------------------------------- ### Playlist Operations: Create, Append, Move, Remove, Rename, Delete Source: https://context7.com/videolan/vlc-android/llms.txt Manage playlists by creating, appending tracks, inserting at specific positions, moving tracks, removing tracks, renaming, and deleting playlists. Tracks can be paginated and filtered. Query playlists by type using `getPlaylists`. ```kotlin val ml = Medialibrary.getInstance() // Create a playlist val playlist: Playlist? = ml.createPlaylist("My Favourites", false, false) // Append media by ID val mediaIds = longArrayOf(42L, 77L, 103L) playlist?.append(mediaIds) // Insert a track at a specific position playlist?.add(mediaId = 55L, position = 1) // Move track from position 2 to position 0 playlist?.move(oldPosition = 2, newPosition = 0) // Remove track at position 1 playlist?.remove(position = 1) // Paginate tracks val tracks: Array? = playlist?.getPagedTracks( /*nbItems=*/20, /*offset=*/0, /*includeMissing=*/false, /*onlyFavorites=*/false ) Log.d("Playlist", "${playlist?.title}: ${tracks?.size} tracks, duration=${playlist?.duration}ms") // Rename or delete playlist?.setName("Best Of") playlist?.delete() // Query playlists by type val audioPlaylists: Array = ml.getPlaylists( Playlist.Type.AudioOnly, /*onlyFavorites=*/false ) ``` -------------------------------- ### MediaDatabase - Room DAOs Source: https://context7.com/videolan/vlc-android/llms.txt Access Room DAOs for browser favorites, external subtitles, equalizer presets, and widgets. ```APIDOC ## MediaDatabase - Room DAOs `MediaDatabase` is the Room database exposing DAO interfaces for browser favourites, external subtitles, equalizer presets, and widgets. Access it via the singleton companion. ```kotlin val db = MediaDatabase.getInstance(applicationContext) // --- Browser Favourites --- val favDao = db.browserFavDao() // Insert a network favourite favDao.insert(BrowserFav(uri = Uri.parse("smb://nas/Movies"), type = 0, title = "NAS Movies")) // Observe all favourites as a Flow lifecycleScope.launch { favDao.getAll().collect { favs -> favs.forEach { Log.d("Fav", "${it.title}: ${it.uri}") } } } // Delete a favourite favDao.delete(Uri.parse("smb://nas/Movies")) // --- Equalizer --- val eqDao = db.equalizerDao() // Insert a preset band eqDao.insertBand(EqualizerBand(eqId = 1L, index = 0, value = 3.5f)) ``` ``` -------------------------------- ### Bind to PlaybackService for Playback Control Source: https://context7.com/videolan/vlc-android/llms.txt Bind to the PlaybackService, a MediaBrowserServiceCompat, from an Activity or Fragment to control media playback. This allows for basic transport controls, seeking, inspecting playback status, navigating the queue, and managing playback speed, repeat, shuffle, and track selection. ```kotlin // Bind from an Activity or Fragment var playbackService: PlaybackService? = null val connection = object : ServiceConnection { override fun onServiceConnected(name: ComponentName, binder: IBinder) { playbackService = (binder as? PlaybackService.LocalBinder)?.service } override fun onServiceDisconnected(name: ComponentName) { playbackService = null } } val intent = Intent(this, PlaybackService::class.java) bindService(intent, connection, Context.BIND_AUTO_CREATE) // --- After binding --- playbackService?.let { svc -> // Basic transport svc.play() svc.pause() svc.stop() // Seek to 30 seconds svc.setTime(30_000L) val currentMs = svc.getTime() // Inspect now-playing Log.d("PS", "Title: ${svc.title}") Log.d("PS", "Artist: ${svc.artist}, Album: ${svc.album}") Log.d("PS", "Length: ${svc.length}ms, Playing: ${svc.isPlaying}") // Queue navigation svc.next() svc.previous(false) // Speed and repeat // svc.speed (read via playlistManager.player.speed.value) svc.repeatType = PlaybackStateCompat.REPEAT_MODE_ALL svc.shuffleType = PlaybackStateCompat.SHUFFLE_MODE_ALL // Track selection val audioTracks = svc.audioTracks val subtitleTracks = svc.spuTracks Log.d("PS", "Audio delay: ${svc.audioDelay}µs, SPU delay: ${svc.spuDelay}µs") } ``` -------------------------------- ### Bookmarks on MediaWrapper Source: https://context7.com/videolan/vlc-android/llms.txt Manage bookmarks, track play counts, and retrieve media metadata for individual media files. Supports thumbnail generation. ```APIDOC ## Medialibrary — Bookmarks on MediaWrapper `MediaWrapper` supports per-file bookmarks with timestamps, play counts, last-played position, and thumbnail generation. ```kotlin val ml = Medialibrary.getInstance() val media: MediaWrapper? = ml.getMedia(Uri.parse("file:///storage/emulated/0/Movies/sample.mp4")) media?.let { // Add a bookmark at 1m30s val bookmark: Bookmark? = mw.addBookmark(90_000L) // time in ms bookmark?.setNameAndDescription("Intro ends", "Scene change at 1:30") // List bookmarks mw.getBookmarks()?.forEach { bm -> Log.d("Bookmark", "${bm.getTitle()} @ ${bm.getTime()}ms") } // Remove a specific bookmark mw.removeBookmark(90_000L) // Track progress mw.setPlayCount(1L) Log.d("Media", "Played ${mw.getPlayCount()} time(s), width=${mw.width}, height=${mw.height}") // Request thumbnail generation at 25% into the video mw.requestThumbnail(/*width=*/512, /*position=*/0.25f) } ``` ``` -------------------------------- ### PlaybackService - Binding and Playback Control Source: https://context7.com/videolan/vlc-android/llms.txt Bind to PlaybackService to control playback, manage the queue, and inspect media status. ```APIDOC ## PlaybackService - Binding and Playback Control `PlaybackService` is the central `MediaBrowserServiceCompat` that manages queue, transport controls, audio focus, and MediaSession. Bind to it to drive playback from any component. ```kotlin // Bind from an Activity or Fragment var playbackService: PlaybackService? = null val connection = object : ServiceConnection { override fun onServiceConnected(name: ComponentName, binder: IBinder) { playbackService = (binder as? PlaybackService.LocalBinder)?.service } override fun onServiceDisconnected(name: ComponentName) { playbackService = null } } val intent = Intent(this, PlaybackService::class.java) bindService(intent, connection, Context.BIND_AUTO_CREATE) // --- After binding --- playbackService?.let { svc -> // Basic transport svc.play() svc.pause() svc.stop() // Seek to 30 seconds svc.setTime(30_000L) val currentMs = svc.getTime() // Inspect now-playing Log.d("PS", "Title: ${svc.title}") Log.d("PS", "Artist: ${svc.artist}, Album: ${svc.album}") Log.d("PS", "Length: ${svc.length}ms, Playing: ${svc.isPlaying}") // Queue navigation svc.next() svc.previous(false) // Speed and repeat // svc.speed (read via playlistManager.player.speed.value) svc.repeatType = PlaybackStateCompat.REPEAT_MODE_ALL svc.shuffleType = PlaybackStateCompat.SHUFFLE_MODE_ALL // Track selection val audioTracks = svc.audioTracks val subtitleTracks = svc.spuTracks Log.d("PS", "Audio delay: ${svc.audioDelay}µs, SPU delay: ${svc.spuDelay}µs") } ``` ``` -------------------------------- ### Upload Screenshots Source: https://github.com/videolan/vlc-android/blob/master/buildsystem/automation/README.md Uploads the generated screenshots. This lane is used after the screenshot generation lanes have been executed. ```bash bundle exec fastlane deploy_screenshots ``` -------------------------------- ### Medialibrary - Folder and Device Management Source: https://context7.com/videolan/vlc-android/llms.txt Manage banned folders and external devices within the media library. ```APIDOC ## Medialibrary - Folder and Device Management Block directories from being scanned using ban/unban, and manage removable storage devices explicitly. ```kotlin val ml = Medialibrary.getInstance() // Prevent a folder from appearing in the library ml.banFolder("/storage/emulated/0/Android/data") // List all banned folders val banned: Array = ml.bannedFolders() banned.forEach { Log.d("ML", "Banned: $it") } // Unban ml.unbanFolder("/storage/emulated/0/Android/data") // Register an external SD card (UUID from StorageManager) ml.addDevice(uuid = "1234-ABCD", path = "/storage/1234-ABCD", removable = true) // Remove it when ejected val success = ml.removeDevice("1234-ABCD", "/storage/1234-ABCD") // Clear history ml.clearHistory(Medialibrary.HISTORY_TYPE_LOCAL) // Pause/resume background parsing (e.g., when battery is low) ml.pauseBackgroundOperations() ml.resumeBackgroundOperations() ``` ``` -------------------------------- ### Manage Banned Folders and Devices with Medialibrary Source: https://context7.com/videolan/vlc-android/llms.txt Use Medialibrary to prevent specific folders from being scanned, manage banned folders, and explicitly register or remove external storage devices. It also supports clearing history and pausing/resuming background operations. ```kotlin val ml = Medialibrary.getInstance() // Prevent a folder from appearing in the library ml.banFolder("/storage/emulated/0/Android/data") // List all banned folders val banned: Array = ml.bannedFolders() banned.forEach { Log.d("ML", "Banned: $it") } // Unban ml.unbanFolder("/storage/emulated/0/Android/data") // Register an external SD card (UUID from StorageManager) ml.addDevice(uuid = "1234-ABCD", path = "/storage/1234-ABCD", removable = true) // Remove it when ejected val success = ml.removeDevice("1234-ABCD", "/storage/1234-ABCD") // Clear history ml.clearHistory(Medialibrary.HISTORY_TYPE_LOCAL) // Pause/resume background parsing (e.g., when battery is low) ml.pauseBackgroundOperations() ml.resumeBackgroundOperations() ``` -------------------------------- ### Search Across the Library Source: https://context7.com/videolan/vlc-android/llms.txt Perform searches across the entire media library, including albums, artists, genres, videos, audio tracks, and playlists. Results can be filtered and paginated. ```APIDOC ## Medialibrary — Search Across the Library `search()` returns a `SearchAggregate` containing matched albums, artists, genres, videos, audio tracks, and playlists in a single call. ```kotlin val ml = Medialibrary.getInstance() val results: SearchAggregate = ml.search("Beatles", /*includeMissing=*/false, /*onlyFavorites=*/false) if (!results.isEmpty()) { results.artists?.forEach { artist -> Log.d("Search", "Artist: ${artist.title}") } results.albums?.forEach { album -> Log.d("Search", "Album: ${album.title} (${album.releaseYear})") } results.tracks?.forEach { track -> Log.d("Search", "Track: ${track.title}") } results.playlists?.forEach { pl -> Log.d("Search", "Playlist: ${pl.title}") } } // Narrow search to audio tracks only (paginated) val audioHits: Array = ml.searchAudio( "Beatles", Medialibrary.SORT_ALPHA, false, false, false, 20, 0 ) // Search within an artist's albums val artist = ml.getArtist(artistId) val matchingAlbums: Array? = artist?.searchAlbums( "abbey", Medialibrary.SORT_ALPHA, false, false, false, 10, 0 ) ``` ``` -------------------------------- ### Monitor USB OTG and Storage Events Source: https://context7.com/videolan/vlc-android/llms.txt ExternalMonitor is a lifecycle-aware BroadcastReceiver for tracking USB devices and storage events. Observe device lists and raw mount/unmount events. ```kotlin ExternalMonitor.devices.observe(this) { usbDevices -> usbDevices.forEach { device -> Log.d("USB", "Device attached: ${device.deviceName} (${device.manufacturerName})") } } ``` ```kotlin lifecycleScope.launch { ExternalMonitor.storageEvents.collect { action -> when (action) { is MediaMounted -> Log.d("Storage", "Mounted ${action.path} (uuid=${action.uuid})") is MediaUnmounted -> Log.d("Storage", "Unmounted ${action.path}") } } } ``` ```kotlin ExternalMonitor.subscribeStorageCb(this) ExternalMonitor.unsubscribeStorageCb(this) ``` -------------------------------- ### Control PlaybackService Remotely Source: https://context7.com/videolan/vlc-android/llms.txt Send broadcast intents to control PlaybackService for widgets and notifications. These actions do not require binding to the service. ```kotlin context.sendBroadcast(Intent(ACTION_REMOTE_PLAYPAUSE)) ``` ```kotlin context.sendBroadcast(Intent(ACTION_REMOTE_FORWARD)) ``` ```kotlin context.sendBroadcast(Intent(ACTION_REMOTE_BACKWARD)) ``` ```kotlin context.sendBroadcast(Intent(ACTION_REMOTE_STOP)) ``` ```kotlin context.sendBroadcast( Intent(ACTION_REMOTE_SEEK_FORWARD).putExtra(EXTRA_SEEK_DELAY, 30L) ) ``` ```kotlin val searchBundle = Bundle().apply { putString(SearchManager.QUERY, "Abbey Road") putString(MediaStore.EXTRA_MEDIA_FOCUS, MediaStore.Audio.Albums.ENTRY_CONTENT_TYPE) } context.startService( Intent(ACTION_PLAY_FROM_SEARCH, null, context, PlaybackService::class.java) .putExtra(EXTRA_SEARCH_BUNDLE, searchBundle) ) ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.