Initial libvlc implementation, Makefiles, dev log detailing libvlc testing.
This commit is contained in:
parent
e429d2656e
commit
5493fd4143
17
Makefile
Normal file
17
Makefile
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
SOURCES := $(shell find src/main/nim -name "*.nim")
|
||||||
|
|
||||||
|
wdiwtlt.exe: $(SOURCES)
|
||||||
|
nimble build -d:mingw --cpu:amd64
|
||||||
|
|
||||||
|
.PHONY: run-win
|
||||||
|
run-win: wdiwtlt.exe
|
||||||
|
cp wdiwtlt.exe /home/jdb/winhome/programs/vlc-3.0.18
|
||||||
|
/home/jdb/winhome/programs/vlc-3.0.18/wdiwtlt.exe
|
||||||
|
|
||||||
|
.PHONY: update-version
|
||||||
|
update-version:
|
||||||
|
update_nim_package_version wdiwtlt src/main/private/version.nim
|
||||||
|
|
||||||
|
.PHONY: test
|
||||||
|
test:
|
||||||
|
nim c -r src/test/nim/runner
|
60
devlog.yaml
Normal file
60
devlog.yaml
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
---
|
||||||
|
Log of things tried:
|
||||||
|
|
||||||
|
- c2nim on vlc/src/include/vlc/vlc.h
|
||||||
|
Failed to generate any meaningful.
|
||||||
|
|
||||||
|
- c2n on vlc/src/include/vlc/libvlc.h
|
||||||
|
Memory usage exploded (24+ GB)
|
||||||
|
|
||||||
|
- Next will be to write a libvlc.nim by hand.
|
||||||
|
|
||||||
|
This worked. However, ran into a problem running. Link to VLC library was
|
||||||
|
working with libvlc.dll and libvlccore.dll in the same directory as
|
||||||
|
wdiwtlt.exe, but libvlc_new always returned NULL (unable to initialize VLC
|
||||||
|
instance).
|
||||||
|
|
||||||
|
This led me down a rabbit-hole of compiling VLC from source to be able to
|
||||||
|
add debug statements to the initialization logic. Follwed this guide
|
||||||
|
"https://wiki.videolan.org/Win32Compile/" to cross-compile for Windows from
|
||||||
|
Ubuntu (WSL2).
|
||||||
|
|
||||||
|
Notably, the chromecast plugin fails to compile. Initially it was because
|
||||||
|
the code present in the VLC contrib folder was missing .inc files
|
||||||
|
(specifically port_def.inc). Ubuntu has these libraries (need to install
|
||||||
|
protobuf dev package) underneath /usr/include/google, but after symlinking
|
||||||
|
that into the include path for g++, there were still compilation errors. As
|
||||||
|
best I can tell, the version of Mingw64 present doesn't support the win32
|
||||||
|
threading primitives required by the chromecast plugin. Rather than debug,
|
||||||
|
I disabled the chromecast plugin when building the contrib packages using
|
||||||
|
"../extras/package/win32/configure.sh \
|
||||||
|
--host=$VLC_HOST_TRIPLET \
|
||||||
|
--enable-chromecast=false \
|
||||||
|
--build=x86_64-pc-linux-gnu"
|
||||||
|
|
||||||
|
After disabling chromecast I was able to build VLC. To get the DLLs I
|
||||||
|
needed, I used the `package-win-common` build target.
|
||||||
|
|
||||||
|
Ultimately, the cause of libvlc failing to initialize an instance was the
|
||||||
|
lack of plugins. VLC needs more than just the libvlc and libvlccore DLLs.
|
||||||
|
It needs to know the location of its plugins. Ultimately I decided it was
|
||||||
|
easier to relocate the wdiwtlt.exe binary to the same folder as the vlc.exe
|
||||||
|
binary (with plugin subfolders, DLLs besides, etc.) and run from there.
|
||||||
|
After doing this, wdiwtlt was able to initialize and use the libvlc
|
||||||
|
instance, playing audio.
|
||||||
|
|
||||||
|
Where Am I:
|
||||||
|
- Implementing WdiwtltLibrary (core media management):
|
||||||
|
- Implemented the clean function
|
||||||
|
- TODO: implement media scanning using vlc to parse tags
|
||||||
|
|
||||||
|
- Implementing WdiwtltDb based on JSON-formatted persistence of the in-memory
|
||||||
|
object graph. Still corresponds highly to the original WDIWTLT database
|
||||||
|
schema. Eventually I may want to migrate to SQLite for the persistence and
|
||||||
|
in-memory acccess, but I would want to add support for SQLite to fiber_orm
|
||||||
|
|
||||||
|
TOOD:
|
||||||
|
- Implement media scanning in WdiwtltLibrary usng libvlc to parse tags.
|
||||||
|
- Implement a simple version of the TUI, prompt-based, writing responses to
|
||||||
|
stdout. No fancy redraws yet, just typical shell back and forth.
|
||||||
|
- Implement a more robust TUI using illwill directly or using nimwave
|
BIN
lib/win64/pcre64.dll
Executable file
BIN
lib/win64/pcre64.dll
Executable file
Binary file not shown.
141
src/main/nim/private/libvlc.nim
Normal file
141
src/main/nim/private/libvlc.nim
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
when defined(Windows):
|
||||||
|
const libName* = "libvlc.dll"
|
||||||
|
when defined(Linux):
|
||||||
|
const libName* = "libvlc.so"
|
||||||
|
when defined(MacOsX):
|
||||||
|
const libName* = "libvlc.dylib"
|
||||||
|
|
||||||
|
type
|
||||||
|
LibVlcInstance* = ptr object
|
||||||
|
VlcMediaPlayer* = ptr object
|
||||||
|
VlcMedia* = ptr object
|
||||||
|
|
||||||
|
VlcMetaType* = enum
|
||||||
|
vmTitle,
|
||||||
|
vmArtist,
|
||||||
|
vmGenre,
|
||||||
|
vmCopyright,
|
||||||
|
vmAlbum,
|
||||||
|
vmTrackNumber,
|
||||||
|
vmDescription,
|
||||||
|
vmRating,
|
||||||
|
vmDate,
|
||||||
|
vmSetting,
|
||||||
|
vmURL,
|
||||||
|
vmLanguage,
|
||||||
|
vmNowPlaying,
|
||||||
|
vmPublisher,
|
||||||
|
vmEncodedBy,
|
||||||
|
vmArtworkURL,
|
||||||
|
vmTrackID,
|
||||||
|
vmTrackTotal,
|
||||||
|
vmDirector,
|
||||||
|
vmSeason,
|
||||||
|
vmEpisode,
|
||||||
|
vmShowName,
|
||||||
|
vmActors,
|
||||||
|
vmAlbumArtist,
|
||||||
|
vmDiscNumber,
|
||||||
|
vmDiscTotal
|
||||||
|
|
||||||
|
VlcMediaState* = enum
|
||||||
|
vmsNothingSpecial,
|
||||||
|
vmsOpening,
|
||||||
|
vmsBuffering,
|
||||||
|
vmsPlaying,
|
||||||
|
vmsPaused,
|
||||||
|
vmsStopped,
|
||||||
|
vmsEnded,
|
||||||
|
vmsError
|
||||||
|
|
||||||
|
{.push dynlib: libName.}
|
||||||
|
|
||||||
|
# LibVlcCore
|
||||||
|
# https://videolan.videolan.me/vlc/group__libvlc__core.html
|
||||||
|
|
||||||
|
proc libvlc_new(argc: cint, argv: cstringArray):
|
||||||
|
LibVlcInstance {.importc: "libvlc_new".}
|
||||||
|
|
||||||
|
proc release*(inst: LibVlcInstance) {.importc: "libvlc_release".}
|
||||||
|
|
||||||
|
proc retain*(inst: LibVlcInstance) {.importc: "libvlc_retain".}
|
||||||
|
|
||||||
|
proc version*(inst: LibVlcInstance): cstring {.importc: "libvlc_get_version".}
|
||||||
|
|
||||||
|
# Media Player
|
||||||
|
# https://videolan.videolan.me/vlc/group__libvlc__media__player.html
|
||||||
|
proc newMediaPlayer*(inst: LibVlcInstance):
|
||||||
|
VlcMediaPlayer {.importc: "libvlc_media_player_new".}
|
||||||
|
|
||||||
|
proc release*(mp: VlcMediaPlayer) {.importc: "libvlc_media_player_release".}
|
||||||
|
|
||||||
|
proc retain*(mp: VlcMediaPlayer) {.importc: "libvlc_media_player_retain".}
|
||||||
|
|
||||||
|
proc setMedia*(mp: VlcMediaPlayer, m: VlcMedia):
|
||||||
|
void {.importc: "libvlc_media_player_set_media" }
|
||||||
|
|
||||||
|
proc getMedia*(mp: VlcMediaPlayer):
|
||||||
|
VlcMedia {.importc: "libvlc_media_player_get_media" }
|
||||||
|
|
||||||
|
proc libvlc_media_player_is_playing(mp: VlcMediaPlayer):
|
||||||
|
cint {.importc: "libvlc_media_player_is_playing".}
|
||||||
|
|
||||||
|
proc isPlaying*(mp: VlcMediaPlayer): bool =
|
||||||
|
libvlc_media_player_is_playing(mp) > 0
|
||||||
|
|
||||||
|
proc libvlc_media_player_play(mp: VlcMediaPlayer):
|
||||||
|
cint {.importc: "libvlc_media_player_play".}
|
||||||
|
|
||||||
|
proc play*(mp: VlcMediaPlayer): bool =
|
||||||
|
libvlc_media_player_play(mp) >= 0
|
||||||
|
|
||||||
|
proc libvlc_media_player_set_pause(mp: VlcMediaPlayer, pause: cint):
|
||||||
|
void {.importc: "libvlc_media_player_set_pause"}
|
||||||
|
|
||||||
|
proc setPause*(mp: VlcMediaPlayer, pause = true) =
|
||||||
|
if pause: mp.libvlc_media_player_set_pause(1)
|
||||||
|
else: mp.libvlc_media_player_set_pause(0)
|
||||||
|
|
||||||
|
proc togglePause*(mp: VlcMediaPlayer):
|
||||||
|
void {.importc: "libvlc_media_player_pause"}
|
||||||
|
|
||||||
|
proc stop*(mp: VlcMediaPlayer): void {.importc: "libvlc_media_player_stop"}
|
||||||
|
|
||||||
|
# Media
|
||||||
|
# https://videolan.videolan.me/vlc/group__libvlc__media.html
|
||||||
|
proc mediaFromUrl*(inst: LibVlcInstance, url: cstring):
|
||||||
|
VlcMedia {.importc: "libvlc_media_new_location".}
|
||||||
|
|
||||||
|
proc mediaFromPath*(inst: LibVlcInstance, path: cstring):
|
||||||
|
VlcMedia {.importc: "libvlc_media_new_location".}
|
||||||
|
|
||||||
|
proc retain*(media: VlcMedia) {.importc: "libvlc_media_retain".}
|
||||||
|
proc release*(media: VlcMedia) {.importc: "libvlc_media_release".}
|
||||||
|
|
||||||
|
proc duplicate*(media: VlcMedia): VlcMedia {.importc: "libvlc_media_duplicate".}
|
||||||
|
|
||||||
|
proc parse*(media: VlcMedia) {.importc: "libvlc_media_parse".}
|
||||||
|
proc isParsed*(media: VlcMedia) {.importc: "libvlc_media_is_parsed".}
|
||||||
|
|
||||||
|
proc getMeta*(media: VlcMedia, key: VlcMetaType):
|
||||||
|
cstring {.importc: "libvlc_media_get_meta".}
|
||||||
|
|
||||||
|
proc setMeta*(media: VlcMedia, key: VlcMetaType, value: cstring)
|
||||||
|
{.importc: "libvlc_media_set_meta".}
|
||||||
|
|
||||||
|
proc saveMeta*(media: VlcMedia): bool {.importc: "libvlc_media_save_meta".}
|
||||||
|
|
||||||
|
# Error
|
||||||
|
# https://videolan.videolan.me/vlc/group__libvlc__error.html
|
||||||
|
proc libvlc_errmsg*(): cstring {.importc: "libvlc_errmsg" .}
|
||||||
|
proc libvlc_clearerr*(): cstring {.importc: "libvlc_clearerr" .}
|
||||||
|
proc libvlc_printerr*(fmt: cstring): cstring {.importc: "libvlc_printerr" .}
|
||||||
|
|
||||||
|
# Nim-native wrappers
|
||||||
|
proc newVlc*(args: openarray[string] = []): LibVlcInstance =
|
||||||
|
let argc = args.len
|
||||||
|
let argv = allocCstringArray(args)
|
||||||
|
result = libvlc_new(cast[cint](argc), argv)
|
||||||
|
if result.isNil:
|
||||||
|
raise newException(Exception,
|
||||||
|
"Failed to initialize VLC instance: " & $libvlc_errmsg())
|
25
wdiwtlt.nimble
Normal file
25
wdiwtlt.nimble
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
# Package
|
||||||
|
|
||||||
|
version = "1.0.0-alpha"
|
||||||
|
author = "Jonathan Bernard"
|
||||||
|
description = "What Do I Want To Listen To: Personal music library, server, and player."
|
||||||
|
license = "GPL-3.0-or-later"
|
||||||
|
srcDir = "src/main/nim"
|
||||||
|
installExt = @["nim"]
|
||||||
|
bin = @["wdiwtlt"]
|
||||||
|
|
||||||
|
|
||||||
|
# Dependencies
|
||||||
|
|
||||||
|
requires "nim >= 1.4.8"
|
||||||
|
requires @["docopt", "jester", "uuids", "zero_functional"]
|
||||||
|
|
||||||
|
requires "https://git.jdb-software.com/jdb/nim-cli-utils.git >= 0.6.3"
|
||||||
|
requires "https://git.jdb-software.com/jdb/nim-time-utils.git"
|
||||||
|
requires "https://git.jdb-software.com/jdb/update-nim-package-version"
|
||||||
|
|
||||||
|
task updateVersion, "Update the WDIWTLT version.":
|
||||||
|
exec "update_nim_package_version wdiwtlt 'src/main/nim/private/version.nim'"
|
||||||
|
|
||||||
|
task test, "Runs the test suite.":
|
||||||
|
exec "nim c -r src/test/nim/runner"
|
Loading…
x
Reference in New Issue
Block a user