Merge branch 'libreelec-11.0' of github.com:LibreELEC/LibreELEC.tv into Lakka-v5.x

This commit is contained in:
Demetris Ierokipides 2023-06-25 20:47:07 +03:00
commit cff38254a6
414 changed files with 69126 additions and 27693 deletions

View file

@ -3,7 +3,7 @@
PKG_NAME="cli"
PKG_VERSION="$(get_pkg_version moby)"
PKG_SHA256="bef4fc68b9f81ab2ae8bb2605e16a0965a3c4a82f0c0cf9d9f5d2cee8e95415d"
PKG_SHA256="b31eb0343e8bb587e921a7630baa659896602072a77ad97720e5f2a8e48005e9"
PKG_LICENSE="ASL"
PKG_SITE="https://github.com/docker/cli"
PKG_URL="https://github.com/docker/cli/archive/v${PKG_VERSION}.tar.gz"
@ -12,7 +12,7 @@ PKG_LONGDESC="The Docker CLI"
PKG_TOOLCHAIN="manual"
# Git commit of the matching release https://github.com/docker/cli/releases
export PKG_GIT_COMMIT="569dd73db13099a7c3104d73aa15117b359045bc"
export PKG_GIT_COMMIT="ef23cbc4315ae76c744e02d687c09548ede461bd"
configure_target() {
go_configure

View file

@ -3,8 +3,8 @@
# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv)
PKG_NAME="containerd"
PKG_VERSION="1.7.0"
PKG_SHA256="c80b1c7f04057108059fdec9c936fc1ec0dccafa45c00a1d54f14dceb6500552"
PKG_VERSION="1.7.1"
PKG_SHA256="fd844af82afda7242d8eba5e0086c5a0d54ddc3041c1bbdd4d3c62bfee844e3a"
PKG_LICENSE="APL"
PKG_SITE="https://containerd.io"
PKG_URL="https://github.com/containerd/containerd/archive/v${PKG_VERSION}.tar.gz"
@ -19,9 +19,9 @@ pre_make_target() {
go_configure
export CONTAINERD_VERSION=${PKG_VERSION}
export CONTAINERD_REVISION=${PKG_GIT_COMMIT}
export CONTAINERD_PKG=github.com/containerd/containerd
export CONTAINERD_VERSION="${PKG_VERSION}"
export CONTAINERD_REVISION="${PKG_GIT_COMMIT}"
export CONTAINERD_PKG="github.com/containerd/containerd"
export LDFLAGS="-w -extldflags -static -X ${CONTAINERD_PKG}/version.Version=${CONTAINERD_VERSION} -X ${CONTAINERD_PKG}/version.Revision=${CONTAINERD_REVISION} -X ${CONTAINERD_PKG}/version.Package=${CONTAINERD_PKG} -extld ${CC}"
export GO111MODULE=off

View file

@ -0,0 +1,32 @@
# SPDX-License-Identifier: GPL-2.0-only
# Copyright (C) 2023-present Team LibreELEC (https://libreelec.tv)
PKG_NAME="ctop"
PKG_VERSION="0.7.7"
PKG_SHA256="0db439f2030af73ad5345884b08a33a762c3b41b30604223dd0ebddde72d2741"
PKG_LICENSE="MIT"
PKG_SITE="https://ctop.sh"
PKG_URL="https://github.com/bcicen/ctop/archive/v${PKG_VERSION}.tar.gz"
PKG_DEPENDS_TARGET="toolchain go:host"
PKG_LONGDESC="Top-like interface for container metrics"
PKG_TOOLCHAIN="manual"
# Git commit of the matching release https://github.com/bcicen/ctop/releases
PKG_GIT_COMMIT="11a1cb10f416b4ca5e36c22c1acc2d11dbb24fb4"
pre_make_target() {
go_configure
export CTOP_VERSION="${PKG_VERSION}"
export CTOP_REVISION="${PKG_GIT_COMMIT}"
export CTOP_PKG="github.com/bcicen/ctop"
export LDFLAGS="-w -extldflags -static -X main.version=${CTOP_VERSION} -X main.build=${CTOP_REVISION} -extld ${CC}"
mkdir -p ${GOPATH}/src/github.com/bcicen
ln -fs ${PKG_BUILD} ${GOPATH}/src/${CTOP_PKG}
}
make_target() {
mkdir -p bin
${GOLANG} build -v -o bin/ctop -a -tags "static_build release" -ldflags "${LDFLAGS}"
}

View file

@ -2,8 +2,8 @@
# Copyright (C) 2022-present Team LibreELEC (https://libreelec.tv)
PKG_NAME="moby"
PKG_VERSION="23.0.2"
PKG_SHA256="4caca59c774445a5aad6114d89c97c88d9705f048704fecdd3f5712cb369dc39"
PKG_VERSION="23.0.6"
PKG_SHA256="3bbd32f401f652cc15084d3c09bd7acd381571802beac9333fd63d803dc66c3e"
PKG_LICENSE="ASL"
PKG_SITE="https://mobyproject.org/"
PKG_URL="https://github.com/moby/moby/archive/v${PKG_VERSION}.tar.gz"
@ -12,7 +12,7 @@ PKG_LONGDESC="Moby is an open-source project created by Docker to enable and acc
PKG_TOOLCHAIN="manual"
# Git commit of the matching release https://github.com/moby/moby
export PKG_GIT_COMMIT="219f21bf07502b447095649b5a2764661737f164"
export PKG_GIT_COMMIT="9dbdbd4b6d7681bd18c897a6ba0376073c2a72ff"
PKG_MOBY_BUILDTAGS="daemon \
autogen \

View file

@ -2,7 +2,7 @@
# Copyright (C) 2022-present Team LibreELEC (https://libreelec.tv)
PKG_NAME="aspnet6-runtime"
PKG_VERSION="6.0.15"
PKG_VERSION="6.0.18"
PKG_LICENSE="MIT"
PKG_SITE="https://dotnet.microsoft.com/"
PKG_DEPENDS_TARGET="toolchain"
@ -11,16 +11,16 @@ PKG_TOOLCHAIN="manual"
case "${ARCH}" in
"aarch64")
PKG_SHA256="b37cf63d5962b2f67288a78b6541151c458bc9e67baaf5d5852b2214e858070b"
PKG_URL="https://download.visualstudio.microsoft.com/download/pr/0d9619a1-af06-40c6-9816-46d08c9e42d6/744ecc09a1058822dc08ae17a3dc9c77/aspnetcore-runtime-6.0.15-linux-arm64.tar.gz"
PKG_SHA256="cae83353c508eb7766be43f6cae4e500569f3bcf8a1139e4e762c5b9f7dabbf1"
PKG_URL="https://download.visualstudio.microsoft.com/download/pr/f60912b4-b50d-4d85-b3aa-3b69504a426b/190ebc4012cd4da240e4d5247b484b15/aspnetcore-runtime-6.0.18-linux-arm64.tar.gz"
;;
"arm")
PKG_SHA256="70afd74a6a070f629fcf44571582eec026442c4530f69afc142b92667542932c"
PKG_URL="https://download.visualstudio.microsoft.com/download/pr/c7eade0f-81ff-4587-a58e-647702814ec4/1b8c56efc82990ee986d8dd52a9a09ab/aspnetcore-runtime-6.0.15-linux-arm.tar.gz"
PKG_SHA256="45d22a5ef4eb687648fdd4bf918e25f2fc9a63a0f84fa68a45a88ee6d44f204d"
PKG_URL="https://download.visualstudio.microsoft.com/download/pr/7b10cc0d-3627-4d1b-8307-630c05fb30be/06e4498eeb854db5a723b46114377fce/aspnetcore-runtime-6.0.18-linux-arm.tar.gz"
;;
"x86_64")
PKG_SHA256="930b6254500e53a4f0d87b5551840a3ac8882e93797cf1e23da40652085d44dd"
PKG_URL="https://download.visualstudio.microsoft.com/download/pr/4518a0d8-9a6b-4836-ada9-096afa24efd0/ad0d8ccefb6b6a36dc108417b74775cb/aspnetcore-runtime-6.0.15-linux-x64.tar.gz"
PKG_SHA256="8b7a6c4fc46887d1281f18558e76e34b1656ca1f487c3c71f63d3453a1f5c63b"
PKG_URL="https://download.visualstudio.microsoft.com/download/pr/503c4325-104f-41e0-8dc6-1a8b55e0651a/3dcd8a5d03d3a04bb4111296b12cd11d/aspnetcore-runtime-6.0.18-linux-x64.tar.gz"
;;
esac
PKG_SOURCE_NAME="aspnetcore-runtime_${PKG_VERSION}_${ARCH}.tar.gz"

View file

@ -3,8 +3,8 @@
# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv)
PKG_NAME="runc"
PKG_VERSION="1.1.5"
PKG_SHA256="76cbf30637cbb828794d72d32fb3fd6ff3139cd9743b8b44790fd110f43d96b2"
PKG_VERSION="1.1.7"
PKG_SHA256="f1885d6dfa188f8112328ac2355e5d67346174a2e2e795ec514a972bcbfcc2fa"
PKG_LICENSE="APL"
PKG_SITE="https://github.com/opencontainers/runc"
PKG_URL="https://github.com/opencontainers/runc/archive/v${PKG_VERSION}.tar.gz"

View file

@ -2,8 +2,8 @@
# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv)
PKG_NAME="asio"
PKG_VERSION="1.27.0"
PKG_SHA256="9bee8e50236ce7752325efde38cae223cbc85759ed49509d9cbc5d55458332d9"
PKG_VERSION="1.28.0"
PKG_SHA256="5c2af07ef73b42a2d48e34c0ecbf41cd40dc823bc681bf5833c129384999c963"
PKG_LICENSE="BSL"
PKG_SITE="http://think-async.com/Asio"
PKG_URL="https://github.com/chriskohlhoff/asio/archive/asio-${PKG_VERSION//./-}.zip"

View file

@ -2,8 +2,8 @@
# Copyright (C) 2022-present Team LibreELEC (https://libreelec.tv)
PKG_NAME="nqptp"
PKG_VERSION="c71b49a3556ba8547ee28482cb31a97fe99298aa"
PKG_SHA256="02ed710ed37269adbede06fcd4e12892cc0f9d14d5c68b7f45d67b8694bff1e4"
PKG_VERSION="1.2.1"
PKG_SHA256="fab700572961ca81addb405e8bd4bd57c47259f91e7e8e0f5f82240c38c63ce5"
PKG_LICENSE="GPL-2.0"
PKG_SITE="https://github.com/mikebrady/nqptp"
PKG_URL="https://github.com/mikebrady/nqptp/archive/${PKG_VERSION}.tar.gz"

View file

@ -2,8 +2,8 @@
# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv)
PKG_NAME="shairport-sync"
PKG_VERSION="4.1.1"
PKG_SHA256="e55caad73dcd36341baf8947cf5e0923997370366d6caf3dd917b345089c4a20"
PKG_VERSION="4.2"
PKG_SHA256="649d95eede8b9284b2e8b9c97d18c1c64cffae0a6c75bc4f03e3ae494a3e25b6"
PKG_LICENSE="OSS"
PKG_SITE="https://github.com/mikebrady/shairport-sync"
PKG_URL="https://github.com/mikebrady/shairport-sync/archive/${PKG_VERSION}.tar.gz"

View file

@ -1 +1,17 @@
initial release
1
- not released for LE11
2
- not released for LE11
3
- fix ctop
- update moby and cli to 23.0.4
- containerd: update to 1.7.0
- runc: build with seccomp
- runc: update to 1.1.5
4
- update moby and cli to 23.0.6
- containerd: update to 1.7.1
- runc: update to 1.1.7

View file

@ -3,11 +3,11 @@
# Copyright (C) 2017-present Team LibreELEC (https://libreelec.tv)
PKG_NAME="docker"
PKG_REV="2"
PKG_REV="4"
PKG_ARCH="any"
PKG_LICENSE="ASL"
PKG_SITE="http://www.docker.com/"
PKG_DEPENDS_TARGET="cli containerd moby runc tini"
PKG_DEPENDS_TARGET="cli containerd ctop moby runc tini"
PKG_SECTION="service/system"
PKG_SHORTDESC="Docker is an open-source engine that automates the deployment of any application as a lightweight, portable, self-sufficient container that will run virtually anywhere."
PKG_LONGDESC="Docker containers can encapsulate any payload, and will run consistently on and between virtually any server. The same container that a developer builds and tests on a laptop will run at scale, in production*, on VMs, bare-metal servers, OpenStack clusters, public instances, or combinations of the above."
@ -32,6 +32,9 @@ addon() {
cp -P $(get_build_dir containerd)/bin/containerd-shim ${ADDON_BUILD}/${PKG_ADDON_ID}/bin/containerd-shim
cp -P $(get_build_dir containerd)/bin/containerd-shim-runc-v2 ${ADDON_BUILD}/${PKG_ADDON_ID}/bin/containerd-shim-runc-v2
# ctop
cp -P $(get_build_dir ctop)/bin/ctop ${ADDON_BUILD}/${PKG_ADDON_ID}/bin/ctop
# runc
cp -P $(get_build_dir runc)/bin/runc ${ADDON_BUILD}/${PKG_ADDON_ID}/bin/runc

File diff suppressed because it is too large Load diff

View file

@ -1 +1,2 @@
initial release
1
- jellyfin: update to 10.8.10

View file

@ -3,8 +3,8 @@
PKG_NAME="jellyfin"
PKG_VERSION="1.0"
PKG_VERSION_NUMBER="10.8.9"
PKG_REV="0"
PKG_VERSION_NUMBER="10.8.10"
PKG_REV="1"
PKG_ARCH="any"
PKG_LICENSE="GPLv2"
PKG_SITE="https://jellyfin.org/"

View file

@ -1 +1,4 @@
initial release
1
- update librespot to githash 03b547d (2023-04-16)
2
- update librespot to githash c964102 (2023-05-14)

View file

@ -3,13 +3,14 @@
# Copyright (C) 2017-present Team LibreELEC (https://libreelec.tv)
PKG_NAME="librespot"
PKG_VERSION="0.3.1"
PKG_SHA256="d360eaf61ad4216ee2c4a4d583d61c8ec7367b5efbe512011d049f73e4f24952"
PKG_REV="0"
PKG_VERSION="c964102a349589d644baef5f43a566d6d1e151f1"
PKG_VERSION_DATE="2023-05-14"
PKG_SHA256="3bc6782d8796253040d995043fba4e6f6c71ff902da110b50398071e082b1930"
PKG_REV="2"
PKG_ARCH="any"
PKG_LICENSE="MIT"
PKG_SITE="https://github.com/librespot-org/librespot/"
PKG_URL="https://github.com/librespot-org/librespot/archive/v${PKG_VERSION}.tar.gz"
PKG_URL="https://github.com/librespot-org/librespot/archive/${PKG_VERSION}.tar.gz"
PKG_DEPENDS_TARGET="toolchain alsa-lib avahi pulseaudio cargo:host"
PKG_SECTION="service"
PKG_SHORTDESC="Librespot: play Spotify through Kodi using a Spotify app as a remote"
@ -19,10 +20,10 @@ PKG_TOOLCHAIN="manual"
PKG_IS_ADDON="yes"
PKG_ADDON_NAME="Librespot"
PKG_ADDON_TYPE="xbmc.service"
PKG_ADDON_REQUIRES="script.module.requests:0.0.0"
PKG_MAINTAINER="Anton Voyl (awiouy)"
make_target() {
export RUSTC_LINKER=${CC}
cargo build \
--target ${TARGET_NAME} \
--release \

View file

@ -1,108 +0,0 @@
commit 10489ef0b9de4241eb8e007596f3d62616120545
Author: awiouy <awiouy@gmail.com>
Date: Fri May 29 07:40:19 2020 +0200
Notify Kodi
diff --git a/core/src/spotify_id.rs b/core/src/spotify_id.rs
index 1a5fcd2..c670977 100644
--- a/core/src/spotify_id.rs
+++ b/core/src/spotify_id.rs
@@ -9,6 +9,12 @@
Podcast,
NonPlayable,
}
+
+impl fmt::Display for SpotifyAudioType {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "{:?}", self)
+ }
+}
impl From<&str> for SpotifyAudioType {
fn from(v: &str) -> Self {
diff --git a/playback/src/config.rs b/playback/src/config.rs
index 9d65042..6d098db 100644
--- a/playback/src/config.rs
+++ b/playback/src/config.rs
@@ -142,6 +142,7 @@
// pass function pointers so they can be lazily instantiated *after* spawning a thread
// (thereby circumventing Send bounds that they might not satisfy)
pub ditherer: Option<DithererBuilder>,
+ pub notify_kodi: bool,
}
impl Default for PlayerConfig {
@@ -159,6 +160,7 @@
normalisation_knee: 1.0,
passthrough: false,
ditherer: Some(mk_ditherer::<TriangularDitherer>),
+ notify_kodi: false,
}
}
}
diff --git a/playback/src/player.rs b/playback/src/player.rs
index 2dd8f3b..67b3b28 100644
--- a/playback/src/player.rs
+++ b/playback/src/player.rs
@@ -1868,6 +1868,10 @@ impl PlayerInternal {
}
}
+ fn notify_kodi(&mut self, event: String) {
+ eprintln!("@{}", event);
+ }
+
fn send_event(&mut self, event: PlayerEvent) {
let mut index = 0;
while index < self.event_senders.len() {
@@ -1878,6 +1882,16 @@ impl PlayerInternal {
}
}
}
+ if self.config.notify_kodi {
+ use PlayerEvent::*;
+ match event {
+ Playing {track_id, .. } => self.notify_kodi(["Playing",
+ &track_id.audio_type.to_string(),
+ &track_id.to_base62()].join(" ")),
+ Stopped { .. } => self.notify_kodi("Stopped".to_string()),
+ _ => ()
+ }
+ }
}
fn load_track(
diff --git a/src/main.rs b/src/main.rs
index 2efd62b..ecee2ff 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -424,6 +424,11 @@
"",
PASSTHROUGH,
"Pass a raw stream to the output. Only works with the pipe and subprocess backends.",
+ )
+ .optflag(
+ "",
+ "notify-kodi",
+ "Notify Kodi",
);
let matches = match opts.parse(&args[1..]) {
@@ -644,6 +649,8 @@ fn setup(args: &[String]) -> Setup {
)
};
+ let notify_kodi = matches.opt_present("notify-kodi");
+
let session_config = {
let device_id = device_id(&name);
@@ -763,6 +763,7 @@
normalisation_release,
normalisation_knee,
ditherer,
+ notify_kodi: notify_kodi,
}
};

View file

@ -0,0 +1,66 @@
#!/usr/bin/python
import json
import os
import socket
ADDRESS = ('127.0.0.1', 36963)
BUFFER_SIZE = 1024
def send_event(event):
data = json.dumps(event).encode()
with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as sock:
sock.sendto(data, ADDRESS)
def receive_event():
with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as sock:
sock.settimeout(None)
sock.bind(ADDRESS)
while True:
data, addr = sock.recvfrom(BUFFER_SIZE)
event = json.loads(data.decode())
if not event:
break
yield event
ARG_ALBUM = 'album'
ARG_ARTIST = 'artist'
ARG_ART = 'art'
ARG_TITLE = 'title'
KEY_ALBUM = 'ALBUM'
KEY_ARTISTS = 'ARTISTS'
KEY_COVERS = 'COVERS'
KEY_ITEM_TYPE = 'ITEM_TYPE'
KEY_NAME = 'NAME'
KEY_PLAYER_EVENT = 'PLAYER_EVENT'
KEY_SHOW_NAME = 'SHOW_NAME'
PLAYER_EVENT_STOPPED = 'stopped'
PLAYER_EVENT_TRACK_CHANGED = 'track_changed'
ITEM_TYPE_EPISODE = 'Episode'
ITEM_TYPE_TRACK = 'Track'
def get_env_value(key):
return os.environ.get(key, '').partition('\n')[0]
if __name__ == '__main__':
player_event = get_env_value(KEY_PLAYER_EVENT)
event = {KEY_PLAYER_EVENT: player_event}
if player_event == PLAYER_EVENT_STOPPED:
send_event(event)
elif player_event == PLAYER_EVENT_TRACK_CHANGED:
event[ARG_ART] = get_env_value(KEY_COVERS)
event[ARG_TITLE] = get_env_value(KEY_NAME)
item_type = get_env_value(KEY_ITEM_TYPE)
if item_type == ITEM_TYPE_EPISODE:
event[ARG_ALBUM] = get_env_value(KEY_SHOW_NAME)
elif item_type == ITEM_TYPE_TRACK:
event[ARG_ALBUM] = get_env_value(KEY_ALBUM)
event[ARG_ARTIST] = get_env_value(KEY_ARTISTS)
send_event(event)

View file

@ -1,8 +1,25 @@
import os
import sys
import xbmcaddon
import xbmcvfs
sys.path.append(os.path.join(os.path.dirname(__file__), 'resources', 'lib'))
from ls_monitor import Monitor as Monitor
def _set_home():
home = xbmcvfs.translatePath(xbmcaddon.Addon().getAddonInfo('profile'))
os.makedirs(home, exist_ok=True)
os.chdir(home)
Monitor().run()
def _set_paths():
path = xbmcaddon.Addon().getAddonInfo('path')
os.environ['PATH'] += os.pathsep + os.path.join(path, 'bin')
os.environ['LD_LIBRARY_PATH'] += os.pathsep + os.path.join(path, 'lib')
sys.path.append(os.path.join(path, 'bin'))
sys.path.append(os.path.join(path, 'resources', 'lib'))
if __name__ == '__main__':
_set_home()
_set_paths()
import service
service.Monitor().run()

View file

@ -1,30 +0,0 @@
# Librespot for ALSA
# Copy this file to '/storage/.config/system.d/service.librespot-alsa.service' and adapt it to your needs
# Enable the service with 'systemctl enable /storage/.config/system.d/service.librespot-alsa.service'
# Start the service with 'systemctl start service.librespot-alsa.service'
# If you update the file, reload units with 'systemctl daemon-reload' and restart the service
[Unit]
Description=librespot alsa backend
After=network-online.target
Wants=network-online.target
[Service]
Environment=LD_LIBRARY_PATH=/storage/.kodi/addons/service.librespot/lib
#Enable Raspberry Pi onboard audio
#ExecStartPre=-dtparam audio=on
#Set Raspberry Pi playback route
#ExecStartPre=-amixer -c 0 cset name="PCM Playback Route" 1
ExecStart=/storage/.kodi/addons/service.librespot/bin/librespot \
--backend alsa \
--bitrate 320 \
--cache "/storage/.config/lsa_cache" \
# Use 'aplay -L' to list available devices
# --device "default:CARD=ALSA" \
--device-type computer \
--disable-audio-cache \
--name "Librespot ALSA" \
Restart=always
[Install]
WantedBy=network-online.target

View file

@ -8,29 +8,21 @@ msgid "Configuration"
msgstr ""
msgctxt "#30101"
msgid "Autoplay"
msgstr ""
msgctxt "#30102"
msgid "Discovery"
msgstr ""
msgctxt "#30103"
msgid "Username"
msgstr ""
msgctxt "#30104"
msgid "Password"
msgstr ""
msgctxt "#30105"
msgid "Name"
msgstr ""
msgctxt "#30106"
msgid "RTP Port"
msgctxt "#30102"
msgid "Do not disturb Kodi"
msgstr ""
msgctxt "#30107"
msgid "Connect Port"
msgctxt "#30103"
msgid "User options"
msgstr ""
msgctxt "#30104"
msgid "Backend"
msgstr ""
msgctxt "#30105"
msgid "ALSA device"
msgstr ""

View file

@ -0,0 +1,8 @@
import player
import service
class Player(player.Player):
def onLibrespotTrackChanged(self, art, artist, title, **kwargs):
service.notification(heading=title, message=artist, icon=art)

View file

@ -0,0 +1,34 @@
import xbmc
import xbmcgui
import player
import service
class Player(player.Player):
def __init__(self, codec='pcm_sb16be', max_fanarts='10', **kwargs):
super().__init__(**kwargs)
self._max_fanarts = int(max_fanarts)
self._list_item = xbmcgui.ListItem(path=self.librespot.file)
self._list_item.getVideoInfoTag().addAudioStream(xbmc.AudioStreamDetail(2, codec))
self._music_info_tag = self._list_item.getMusicInfoTag()
def onLibrespotTrackChanged(self, album='', art='', artist='', title=''):
fanart = service.get_fanart(art, self._max_fanarts) if art else art
self._list_item.setArt({'fanart': fanart, 'thumb': art})
self._music_info_tag.setAlbum(album)
self._music_info_tag.setArtist(artist)
self._music_info_tag.setTitle(title)
if self.isPlaying() and self.getPlayingFile() == self.librespot.file:
self.updateInfoTag(self._list_item)
else:
self.stop() # fixes unepxected behaviour of Player.play()
self.librespot.start_sink()
self.play(self.librespot.file, listitem=self._list_item)
def onLibrespotStopped(self):
self.librespot.stop_sink()
if self.isPlaying() and self.getPlayingFile() == self.librespot.file:
self.last_file = None
self.stop()

View file

@ -0,0 +1,93 @@
import shlex
import socket
import subprocess
import threading
import external_player
import internal_player
import service
class Librespot:
def __init__(self,
bitrate='320',
device_type='tv',
max_retries='5',
name='Librespot@{}',
options='',
**kwargs):
name = name.format(socket.gethostname())
self.command = [
'librespot',
'--bitrate', f'{bitrate}',
'--device-type', f'{device_type}',
'--disable-audio-cache',
'--disable-credential-cache',
'--name', f'{name}',
'--onevent', 'onevent.py',
'--quiet',
] + shlex.split(options)
service.log(self.command)
self.file = ''
self._is_started = threading.Event()
self._is_stopped = threading.Event()
self._librespot = None
self._max_retries = int(max_retries)
self._retries = 0
self._thread = threading.Thread()
def get_player(self, **kwargs):
return (internal_player if self.file else external_player).Player(**kwargs)
def restart(self):
if self._thread.is_alive():
self._librespot.terminate()
else:
self.start()
def start(self):
if not self._thread.is_alive() and self._retries < self._max_retries:
self._thread = threading.Thread(daemon=True, target=self._run)
self._thread.start()
self._is_started.wait(1)
def stop(self):
if self._thread.is_alive():
self._is_stopped.set()
self._librespot.terminate()
self._thread.join()
def start_sink(self):
pass
def stop_sink(self):
pass
def _run(self):
service.log('librespot thread started')
self._is_started.clear()
self._is_stopped.clear()
while not self._is_stopped.is_set():
with subprocess.Popen(self.command, stderr=subprocess.PIPE, text=True) as self._librespot:
self._is_started.set()
for line in self._librespot.stderr:
service.log(line.rstrip())
self.stop_sink()
if self._librespot.returncode <= 0:
self._retries = 0
else:
self._retries += 1
if self._retries < self._max_retries:
service.notification(
f'librespot failed {self._retries}/{self._max_retries}')
else:
service.notification('librespot failed too many times')
break
service.log('librespot thread stopped')
def __enter__(self):
return self
def __exit__(self, *args):
self.stop()

View file

@ -0,0 +1,11 @@
import librespot
class Librespot(librespot.Librespot):
def __init__(self, alsa_device='hw:2,0', **kwargs):
super().__init__(**kwargs)
self.command += [
'--backend', 'alsa',
'--device', f'{alsa_device}',
]

View file

@ -0,0 +1,73 @@
import socket
import subprocess
import librespot
import service
class Librespot(librespot.Librespot):
def __init__(self,
codec='pcm_sb16be',
pa_rtp_address='127.0.0.1',
pa_rtp_device='librespot',
pa_rtp_port='24642',
**kwargs):
service.log('pulseaudio backend started')
sap_cmd = f'nc -l -u -s {pa_rtp_address} -p 9875'.split()
self._sap_server = subprocess.Popen(sap_cmd,
stdout=subprocess.DEVNULL,
stderr=subprocess.STDOUT)
service.log(f'sap server started')
if not pa_rtp_port:
with socket.socket() as s:
s.bind((pa_rtp_address, 0))
pa_rtp_port = s.getsockname()[1]
modules = [
[
f'module-null-sink',
f'sink_name={pa_rtp_device}',
],
[
f'module-rtp-send',
f'destination_ip={pa_rtp_address}',
f'inhibit_auto_suspend=always',
f'port={pa_rtp_port}',
f'source={pa_rtp_device}.monitor',
],
]
self._modules = [self._pactl('load-module', *m) for m in modules]
self._sink_name = f'{pa_rtp_device}'
self.stop_sink()
service.log(f'pulseaudio modules loaded: {self._modules}')
super().__init__(**kwargs)
self.command += [
'--backend', 'pulseaudio',
'--device', f'{pa_rtp_device}',
]
self.file = f'rtp://{pa_rtp_address}:{pa_rtp_port}'
def start_sink(self):
self._pactl('suspend-sink', self._sink_name, '0')
def stop_sink(self):
self._pactl('suspend-sink', self._sink_name, '1')
def _pactl(self, command, *args):
out = subprocess.run(['pactl', command, *args],
stdout=subprocess.PIPE,
text=True
).stdout.rstrip()
service.log(f'pactl {command} {args}: {out}')
return out
def __exit__(self, *args):
super().__exit__(*args)
for module in reversed(self._modules):
if module:
self._pactl('unload-module', module)
service.log('pulseaudio backend stopped')
if self._sap_server.poll() is None:
self._sap_server.terminate()
self._sap_server.wait()
service.log('sap server stopped')

View file

@ -1,49 +0,0 @@
import os
import socket
import xbmc
import xbmcvfs
import xbmcaddon
import xbmcgui
DEFAULTS = dict(
autoplay='true',
bitrate='320',
device='librespot',
discovery='true',
name='Librespot@{}',
password='',
rtp_dest='127.0.0.1',
rtp_port='24642',
connect_port='0',
username='',
)
ADDON = xbmcaddon.Addon()
ADDON_HOME = xbmcvfs.translatePath(ADDON.getAddonInfo('profile'))
ADDON_ICON = ADDON.getAddonInfo('icon')
ADDON_NAME = ADDON.getAddonInfo('name')
ADDON_PATH = ADDON.getAddonInfo('path')
ADDON_ENVT = dict(
LD_LIBRARY_PATH=os.path.join(ADDON_PATH, 'lib'),
PATH=os.path.join(ADDON_PATH, 'bin'))
DIALOG = xbmcgui.Dialog()
def get_settings():
if not os.path.exists(ADDON_HOME):
os.makedirs(ADDON_HOME)
settings = dict()
for id in DEFAULTS.keys():
value = ADDON.getSetting(id)
settings[id] = DEFAULTS[id] if value == '' else value
settings['name'] = settings['name'].format(socket.gethostname())
return settings
def log(message):
xbmc.log('{}: {}'.format(ADDON_NAME, message), xbmc.LOGINFO)
def notification(message):
DIALOG.notification(ADDON_NAME, message, ADDON_ICON)

View file

@ -1,164 +0,0 @@
import shlex
import subprocess
import threading
import xbmc
import xbmcgui
from ls_addon import ADDON_ENVT as ADDON_ENVT
from ls_addon import ADDON_HOME as ADDON_HOME
from ls_addon import get_settings as get_settings
from ls_addon import log as log
from ls_pulseaudio import Pulseaudio as Pulseaudio
from ls_spotify import SPOTIFY as SPOTIFY
LIBRESPOT = 'librespot' \
' --backend pulseaudio' \
' --bitrate {bitrate}' \
' --cache cache' \
' --device {device}' \
' --device-type TV' \
' --disable-audio-cache' \
' --name {name}' \
' --notify-kodi'
LIBRESPOT_AUTOPLAY = ' --autoplay'
LIBRESPOT_AUTHENTICATE = ' --disable-discovery' \
' --password {password}' \
' --username {username}'
CODEC = 'pcm_s16be'
MAX_PANICS = 3
class Librespot(xbmc.Player):
def __init__(self):
super().__init__()
settings = get_settings()
quoted = {k: shlex.quote(v) for (k, v) in settings.items()}
command = LIBRESPOT
if settings['connect_port'] != "0":
command += ' --zeroconf-port %s ' % settings['connect_port']
if settings['autoplay'] == 'true':
command += LIBRESPOT_AUTOPLAY
if (settings['discovery'] == 'false' and
settings['password'] != '' and
settings['username'] != ''):
command += LIBRESPOT_AUTHENTICATE
self.command = shlex.split(command.format(**quoted))
log(shlex.split(command.format(**dict(quoted, password='*obfuscated*'))))
self.is_aborted = False
self.is_dead = False
self.pulseaudio = Pulseaudio(settings)
self.listitem = xbmcgui.ListItem()
self.listitem.addStreamInfo('audio', {'codec': CODEC})
self.listitem.setPath(path=self.pulseaudio.url)
def __enter__(self):
self.pulseaudio.load_modules()
self.panics = 0
self.librespot = None
self.is_playing_librespot = False
if not self.isPlaying():
self.start_librespot()
def __exit__(self, *args):
self.stop_librespot()
self.pulseaudio.unload_modules()
def on_event_panic(self):
self.pulseaudio.suspend_sink(1)
self.panics += 1
log('event panic {}/{}'.format(self.panics, MAX_PANICS))
self.is_dead = self.panics >= MAX_PANICS
self.stop_librespot(True)
def on_event_playing(self, type, id):
log('event playing')
SPOTIFY.update_listitem(self.listitem, type, id, self.country)
if not self.isPlaying():
log('starting librespot playback')
self.pulseaudio.suspend_sink(0)
self.play(self.pulseaudio.url, self.listitem)
elif self.is_playing_librespot:
log('updating librespot playback')
self.updateInfoTag(self.listitem)
def on_event_stopped(self):
self.pulseaudio.suspend_sink(1)
log('event stopped')
self.panics = 0
self.stop()
def onPlayBackEnded(self):
self.onPlayBackStopped()
def onPlayBackError(self):
self.onPlayBackStopped()
def onPlayBackStarted(self):
log('Kodi playback started')
self.is_playing_librespot = self.getPlayingFile() == self.pulseaudio.url
if not self.is_playing_librespot:
self.stop_librespot()
def onPlayBackStopped(self):
if self.is_playing_librespot:
log('librespot playback stopped')
self.is_playing_librespot = False
self.stop_librespot(True)
else:
log('Kodi playback stopped')
self.start_librespot()
def run_librespot(self):
log('librespot thread started')
self.restart = True
while self.restart and not self.is_dead:
self.librespot = subprocess.Popen(
self.command,
cwd=ADDON_HOME,
env=ADDON_ENVT,
stderr=subprocess.STDOUT,
stdout=subprocess.PIPE,
text=True,
encoding='utf-8')
log('librespot started')
with self.librespot.stdout:
for line in self.librespot.stdout:
words = line.split()
if words[0] == '@Playing':
self.on_event_playing(words[1], words[2])
elif words[0] == '@Stopped':
self.on_event_stopped()
elif words[0] == 'stack':
self.on_event_panic()
else:
log(line.rstrip())
if 'Country:' in line:
self.country = words[-1].strip('"')
log('country={}'.format(self.country))
self.pulseaudio.suspend_sink(1)
self.stop()
self.librespot.wait()
log('librespot stopped')
self.librespot = None
log('librespot thread stopped')
def start_librespot(self):
if self.librespot is None:
self.thread = threading.Thread(target=self.run_librespot)
self.thread.start()
def stop(self):
if self.is_playing_librespot and not self.is_aborted:
log('stopping librespot playback')
self.is_playing_librespot = False
super().stop()
def stop_librespot(self, restart=False):
self.restart = restart
if self.librespot is not None:
self.librespot.terminate()
if not restart:
self.thread.join()

View file

@ -1,35 +0,0 @@
import xbmc
from ls_addon import log as log
from ls_addon import notification as notification
from ls_librespot import Librespot as Librespot
class Monitor(xbmc.Monitor):
def onSettingsChanged(self):
self.is_changed = True
def run(self):
log('monitor started')
is_aborted = False
is_dead = False
while not (is_aborted or is_dead):
self.is_changed = False
librespot = Librespot()
with librespot:
while True:
is_aborted = self.waitForAbort(1)
if is_aborted:
log('monitor aborted')
librespot.is_aborted = True
break
is_dead = librespot.is_dead
if is_dead:
log('librespot died')
notification('Too many errors')
break
if self.is_changed:
log('settings changed')
break
log('monitor stopped')

View file

@ -1,46 +0,0 @@
import subprocess
from ls_addon import log as log
def run(command):
return subprocess.check_output(command.split(), text=True)
class Pulseaudio:
def __init__(self, settings):
self.null_sink = dict(
module='module-null-sink',
args='sink_name={device}'.format(**settings)
)
self.rtp_send = dict(
module='module-rtp-send',
args='destination_ip={rtp_dest} port={rtp_port}'
' source={device}.monitor'.format(**settings)
)
self.suspend = 'pactl suspend-sink {device} {{}}'.format(**settings)
self.url = 'rtp://{rtp_dest}:{rtp_port}'.format(**settings)
def list_modules(self):
return [module.split('\t')
for module in run('pactl list modules short').splitlines()[::-1]]
def load_modules(self):
args = [module[2] for module in self.list_modules()]
for module in [self.null_sink, self.rtp_send]:
if module['args'] not in args:
run('pactl load-module {} {}'.format(
module['module'], module['args']))
log('loaded {} {}'.format(module['module'], module['args']))
self.suspend_sink(1)
def suspend_sink(self, bit):
run(self.suspend.format(bit))
log('suspended sink {}'.format(bit))
def unload_modules(self):
for module in self.list_modules():
if module[2] in [self.null_sink['args'], self.rtp_send['args']]:
run('pactl unload-module {}'.format(module[0]))
log('unloaded {} {}'.format(module[1], module[2]))

View file

@ -1,80 +0,0 @@
import requests
import time
from ls_addon import ADDON_ICON as ADDON_ICON
from ls_addon import log as log
SPOTIFY_ENDPOINT_EPISODES = 'https://api.spotify.com/v1/episodes/'
SPOTIFY_ENDPOINT_TRACKS = 'https://api.spotify.com/v1/tracks/'
SPOTIFY_HEADERS = {
'Accept': 'application/json',
'Content-Type': 'application/json',
}
SPOTIFY_REQUEST_TOKEN = {
'url': 'https://accounts.spotify.com/api/token',
'data': {'grant_type': 'client_credentials'},
'headers': {'Authorization': 'Basic MTY5ZGY1NTMyZGVlNDdhNTk5MTNmODUyOGU4M2FlNzE6MWYzZDhiNTA3YmJlNGY2OGJlYjNhNDQ3MmU4YWQ0MTE='}
}
def get(info, indices, default):
try:
for index in indices:
info = info[index]
return info.encode('utf-8')
except LookupError:
return default
class Spotify:
def __init__(self):
self.headers = SPOTIFY_HEADERS
self.expiration = time.time()
def get_headers(self):
if time.time() > self.expiration:
log('token expired')
token = requests.post(**SPOTIFY_REQUEST_TOKEN).json()
log(token)
self.expiration = time.time() + float(token['expires_in']) - 5
self.headers['Authorization'] = 'Bearer {}'.format(
token['access_token'])
def get_endpoint(self, endpoint, id, market):
try:
self.get_headers()
return requests.get(url=endpoint + id,
headers=self.headers,
params=dict(market=market)).json()
except Exception as e:
log('failed to get {} from Spotify {}'.format(endpoint, e))
return {}
def update_listitem(self, listitem, type, id, market='SE'):
if type == 'Podcast':
info = self.get_endpoint(SPOTIFY_ENDPOINT_EPISODES, id, market)
album = get(info, ['show', 'name'], 'unknown show',)
artist = get(info, ['show', 'publisher'], 'unknown publisher')
thumb = get(info, ['images', 0, 'url'], ADDON_ICON)
title = get(info, ['name'], 'unknown episode')
elif type == 'Track':
info = self.get_endpoint(SPOTIFY_ENDPOINT_TRACKS, id, market)
album = get(info, ['album', 'name'], 'unknown album')
artist = get(info, ['artists', 0, 'name'], 'unknown artist')
thumb = get(info, ['album', 'images', 0, 'url'], ADDON_ICON)
title = get(info, ['name'], 'unknown title')
else:
album = ''
artist = 'Unknown Media Type'
thumb = ADDON_ICON
title = ''
listitem.setArt(dict(fanart=thumb, thumb=thumb))
listitem.setInfo('music', dict(
album=album, artist=artist, title=title))
log('{}#{}#{}#{}'.format(title, artist, album, thumb))
SPOTIFY = Spotify()

View file

@ -0,0 +1,71 @@
import threading
import xbmc
import onevent
import service
class Player(xbmc.Player):
def __init__(self, dnd_kodi='false', librespot=None, **kwargs):
super().__init__()
self._dnd_kodi = (dnd_kodi == 'true')
self._thread = threading.Thread(daemon=True, target=self._run)
self._thread.start()
self.last_file = None
self.librespot = librespot
if not (self._dnd_kodi and self.isPlaying()):
self.librespot.start()
def onAVStarted(self):
file = self.getPlayingFile()
if file != self.librespot.file:
if self._dnd_kodi:
self.librespot.stop()
elif self.last_file == self.librespot.file:
self.librespot.restart()
self.last_file = file
def onLibrespotStopped(self):
pass
def onLibrespotTrackChanged(self, album='', art='', artist='', title=''):
pass
def onPlayBackEnded(self):
if self.last_file == self.librespot.file:
self.librespot.restart()
else:
self.librespot.start()
self.last_file = None
def onPlayBackError(self):
self.onPlayBackEnded()
def onPlayBackStopped(self):
self.onPlayBackEnded()
# fixes unexpected behaviour of Player.stop()
def stop(self):
xbmc.executebuiltin('PlayerControl(Stop)')
def _run(self):
service.log('onevent dispatcher started')
for event in onevent.receive_event():
try:
player_event = event.pop(onevent.KEY_PLAYER_EVENT)
if player_event == onevent.PLAYER_EVENT_STOPPED:
self.onLibrespotStopped()
elif player_event == onevent.PLAYER_EVENT_TRACK_CHANGED:
self.onLibrespotTrackChanged(**event)
except Exception as e:
service.log(e, True)
service.log('onevent dispatcher stopped')
def __enter__(self):
return self
def __exit__(self, *args):
onevent.send_event({})
self._thread.join()
self.onLibrespotStopped()

View file

@ -0,0 +1,88 @@
import PIL.Image
import urllib.request
import tempfile
import os
import xbmc
import xbmcaddon
import xbmcgui
_ADDON = xbmcaddon.Addon()
_ICON = _ADDON.getAddonInfo('icon')
_NAME = _ADDON.getAddonInfo('name')
_DIALOG = xbmcgui.Dialog()
def log(message, show=False):
xbmc.log(f'{_NAME}: {message}', xbmc.LOGINFO if show else xbmc.LOGDEBUG)
def notification(message='', sound=False, heading=_NAME, icon=_ICON, time=5000):
_DIALOG.notification(heading, message, icon, time, sound)
_FANART_DIR = os.path.join(tempfile.gettempdir(), 'librespot.fanart')
def get_fanart(url, max_fanarts):
name = os.path.basename(url)
target = os.path.join(_FANART_DIR, f'{name}_16x9')
if not os.path.exists(target):
if not os.path.exists(_FANART_DIR):
os.makedirs(_FANART_DIR)
files = os.listdir(_FANART_DIR)
files = [os.path.join(_FANART_DIR, file) for file in files if os.path.isfile(
os.path.join(_FANART_DIR, file))]
files.sort(key=os.path.getmtime)
for file in files[:-max_fanarts]:
os.remove(file)
source = os.path.join(_FANART_DIR, f'{name}_9x9')
urllib.request.urlretrieve(url, source)
image = PIL.Image.open(source)
width, height = image.size
new_width = int(height * 16 / 9)
delta_w = new_width - width
new_image = PIL.Image.new('RGB', (new_width, height), (0, 0, 0))
new_image.paste(image, (delta_w // 2, 0))
new_image.save(target, 'JPEG', optimize=True)
os.remove(source)
return target
_SETTINGS = {
'alsa_device': 'hw:2,0',
'backend': 'pulseaudio_rtp',
'dnd_kodi': 'false',
'name': f'{_NAME}@{{}}',
'options': '',
}
def _get_setting(setting, default):
value = _ADDON.getSetting(setting)
return value if value else default
def _get_librespot():
while True:
settings = {k: _get_setting(k, v) for k, v in _SETTINGS.items()}
backend = settings.pop('backend')
librespot_class = __import__(f'librespot_{backend}').Librespot
with librespot_class(**settings) as librespot:
with librespot.get_player(librespot=librespot, **settings) as player:
yield
class Monitor(xbmc.Monitor):
def __init__(self):
self._get_librespot = _get_librespot()
self.onSettingsChanged()
def onSettingsChanged(self):
log('settings changed')
next(self._get_librespot)
def run(self):
self.waitForAbort()
log('abort requested')
self._get_librespot.close()

View file

@ -1,12 +1,10 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<settings>
<category label="30100">
<setting label="30101" id="autoplay" type="bool" default="true" />
<setting label="30102" id="discovery" type="bool" default="true" />
<setting label="30103" id="username" type="text" default="" subsetting="true" visible="eq(-1,false)" />
<setting label="30104" id="password" type="text" default="" subsetting="true" visible="eq(-2,false)" option="hidden" />
<setting label="30105" id="name" type="text" default="Librespot@{}" />
<setting label="30106" id="rtp_port" type="number" default="24642" />
<setting label="30107" id="connect_port" type="number" default="0" />
<setting label="30101" id="name" type="text" default="Librespot@{}" />
<setting label="30102" id="dnd_kodi" type="bool" default="false" />
<setting label="30103" id="options" type="text" default="" />
<setting label="30104" id="backend" type="select" values="pulseaudio_rtp|alsa" />
<setting label="30105" id="alsa_device" type="text" default="hw:2,0" subsetting="true" visible="eq(-1,1)" />
</category>
</settings>

View file

@ -3,7 +3,7 @@
PKG_NAME="minisatip"
PKG_VERSION="1.2.84"
PKG_SHA256="b8e58eae2e0502d940b59cf60bf73ffb6af1a4c7d4cd23ddd939f29cd4004d8c"
PKG_SHA256="d5a06b0c371e1f5ccba6fcb3d76abf348e93e14ab4d7317bb701ae023c085e4b"
PKG_REV="0"
PKG_ARCH="any"
PKG_LICENSE="GPL"

View file

@ -1 +1,2 @@
initial release
1
- mpd: update to 0.23.12

View file

@ -1,3 +1,5 @@
3
Update to 6.1.3
2
Fix nextpvr-downloader script

View file

@ -2,8 +2,8 @@
# Copyright (C) 2021-present Team LibreELEC (https://libreelec.tv)
PKG_NAME="nextpvr"
PKG_VERSION="6.1.1~Nexus"
PKG_ADDON_VERSION="6.1.1~2"
PKG_VERSION="6.1.3~Nexus"
PKG_ADDON_VERSION="6.1.3~3"
PKG_REV="0"
PKG_ARCH="any"
PKG_LICENSE="NextPVR"

View file

@ -1 +1,2 @@
initial release
1
- ccid: update to 1.5.2

View file

@ -1 +1,8 @@
initial release
2
- asio: update to 1.28.0
- nqptp: update to 1.2.1
- shairport-sync: update to 4.2
1
- asio: update to 1.27.0
- snapcast: update to 0.27.0

View file

@ -3,7 +3,7 @@
PKG_NAME="snapclient"
PKG_VERSION="0.27.0"
PKG_REV="1"
PKG_REV="2"
PKG_ARCH="any"
PKG_LICENSE="GPLv3"
PKG_DEPENDS_TARGET="toolchain alsa-plugins snapcast"

View file

@ -1 +1,8 @@
initial release
2
- asio: update to 1.28.0
- nqptp: update to 1.2.1
- shairport-sync: update to 4.2
1
- asio: update to 1.27.0
- snapcast: update to 0.27.0

View file

@ -3,7 +3,7 @@
PKG_NAME="snapserver"
PKG_VERSION="0.27.0"
PKG_REV="1"
PKG_REV="2"
PKG_ARCH="any"
PKG_LICENSE="GPLv3"
PKG_DEPENDS_TARGET="toolchain nqptp shairport-sync snapcast"

View file

@ -1 +1,5 @@
initial release
1
- not released for LE11
2
- syncthing: update to 1.23.4

View file

@ -1 +1,2 @@
initial release
1
- fix not working TigerVNC

View file

@ -4,7 +4,7 @@
PKG_NAME="tigervnc"
PKG_VERSION="1.10.1"
PKG_SHA256="19fcc80d7d35dd58115262e53cac87d8903180261d94c2a6b0c19224f50b58c4"
PKG_REV="0"
PKG_REV="1"
PKG_ARCH="x86_64"
PKG_LICENSE="GPLv2"
PKG_SITE="http://www.tigervnc.org"

View file

@ -1 +1,2 @@
initial release
1
- ttyd: update to 1.7.3

View file

@ -1 +1,2 @@
initial release
1
- btrfs-progs: update to 6.2.2

View file

@ -1 +1,8 @@
initial release
3
- aspnet6-runtime: update to 6.0.18
2
- aspnet6-runtime: update to 6.0.16
1
- aspnet6-runtime: update to 6.0.15

View file

@ -2,7 +2,7 @@
# Copyright (C) 2018-present Team LibreELEC (https://libreelec.tv)
PKG_NAME="dotnet-runtime"
PKG_REV="1"
PKG_REV="3"
PKG_ARCH="any"
PKG_LICENSE="MIT"
PKG_SITE="https://dotnet.microsoft.com/"

View file

@ -1 +1,3 @@
initial release
1
- mpg123: update to 1.31.3
- mpv-drmprime: update to 0.35.1

View file

@ -1 +1,5 @@
initial release
1
- iperf: update to 3.13
- libpcap: update to 1.10.3
- rar2fs: update to 1.29.6
- tcpdump: update to 4.99.3

View file

@ -1 +1,9 @@
initial release
1
- bottom: update to 0.8.0
- diffutils: update to 3.9
- htop: update to 3.2.2
- lshw: fix lshw -version display
- mc: update to 4.8.29
- stress-ng: update to 0.15.06
- unrar: update to 6.2.6
- vim: update to 9.0.1417

View file

@ -3,8 +3,8 @@
# Copyright (C) 2017-present Team LibreELEC (https://libreelec.tv)
PKG_NAME="bcm2835-driver"
PKG_VERSION="c4122b8708d2d1e8a123e45b188d0bc2d0105bca"
PKG_SHA256="b4c9701d6e5803a5e42cc55f117feee27f35549c5156d165fe120282f9b98544"
PKG_VERSION="543692d23dff7075915bc9c7e34abb3fe28e1c46"
PKG_SHA256="838aa79b842fc10030c6a8b8d7f8dc6b6b08ed7ac762a5488d3d64f1bc51a4ec"
PKG_LICENSE="nonfree"
PKG_SITE="http://www.broadcom.com"
PKG_URL="${DISTRO_SRC}/${PKG_NAME}-${PKG_VERSION}.tar.xz"

View file

@ -15,14 +15,3 @@ PKG_TOOLCHAIN="manual"
makeinstall_target() {
DESTDIR=${INSTALL}/$(get_kernel_overlay_dir) ./install
}
post_makeinstall_target() {
# Install rpi btuart script to bring up Bluetooth
mkdir -p ${INSTALL}/usr/bin
cp -P ${PKG_DIR}/scripts/rpi-btuart ${INSTALL}/usr/bin
cp -P ${PKG_DIR}/scripts/rpi-udev ${INSTALL}/usr/bin
}
post_install() {
enable_service brcmfmac_sdio-firmware.service
}

View file

@ -1,26 +0,0 @@
#!/bin/sh
HCIATTACH=/usr/bin/hciattach
if grep -q "Pi 4" /proc/device-tree/model; then
BDADDR=
else
SERIAL=$(cat /proc/device-tree/serial-number | cut -c9-)
B1=${SERIAL:2:2}
B2=${SERIAL:4:2}
B3=${SERIAL:6:2}
BDADDR=$(printf b8:27:eb:%02x:%02x:%02x $((0x$B1 ^ 0xaa)) $((0x$B2 ^ 0xaa)) $((0x$B3 ^ 0xaa)))
fi
uart0="$(cat /proc/device-tree/aliases/uart0)"
serial1="$(cat /proc/device-tree/aliases/serial1)"
if [ "$uart0" = "$serial1" ] ; then
uart0_pins="$(wc -c /proc/device-tree/soc/gpio@7e200000/uart0_pins/brcm\,pins | cut -f 1 -d ' ')"
if [ "$uart0_pins" = "16" ] ; then
$HCIATTACH /dev/serial1 bcm43xx 3000000 flow - $BDADDR
else
$HCIATTACH /dev/serial1 bcm43xx 921600 noflow - $BDADDR
fi
else
$HCIATTACH /dev/serial1 bcm43xx 460800 noflow - $BDADDR
fi

View file

@ -1,12 +0,0 @@
#!/bin/sh
ALIASES="/proc/device-tree/aliases"
UARTX="uart${1}"
if [ $(cat ${ALIASES}/${UARTX}) = $(cat ${ALIASES}/serial0) ]; then
echo 0
elif [ $(cat ${ALIASES}/${UARTX}) = $(cat ${ALIASES}/serial1) ]; then
echo 1
else
exit 1
fi

View file

@ -1,13 +0,0 @@
[Unit]
Description=Broadcom sdio firmware update for BCM43430A1
ConditionFileNotEmpty=/proc/device-tree/soc/gpio@7e200000/bt_pins/brcm,pins
Requires=dev-serial1.device
After=dev-serial1.device network.target
[Service]
Type=simple
RemainAfterExit=yes
ExecStart=/usr/bin/rpi-btuart
[Install]
WantedBy=network.target

View file

@ -1,2 +0,0 @@
KERNEL=="ttyAMA[01]", PROGRAM="/usr/bin/rpi-udev 0", SYMLINK+="serial%c"
KERNEL=="ttyS0", PROGRAM="/usr/bin/rpi-udev 1", SYMLINK+="serial%c"

View file

@ -2,8 +2,8 @@
# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv)
PKG_NAME="intel-ucode"
PKG_VERSION="20230214"
PKG_SHA256="3a3cfe2c7642339af9f4c2ad69f5f367dfa4cd1f7f9fd4124dedefb7803591d4"
PKG_VERSION="20230613"
PKG_SHA256="894d822d2347222a2595d4fc47d358e01d35a54780123100c317dfc31b1b0cc9"
PKG_ARCH="x86_64"
[ "${DISTRO}" = "Lakka" ] && PKG_ARCH+=" i386" || true
PKG_LICENSE="other"

View file

@ -16,15 +16,15 @@ PKG_PATCH_DIRS="${LINUX}"
case "${LINUX}" in
amlogic)
PKG_VERSION="7d54cb2c26dad1264ecca85992bfe8984df4b7b5" # 6.1.14
PKG_SHA256="76f039741d61e06c740b846291e5017b97da7d3f91fb2f368230a161d46905a6"
PKG_VERSION="6449a0ba6843fe70523eeb7855984054f36f6d24" # 6.1.19
PKG_SHA256="6a46c7b91028157d56437736cc8601fa46485e6f52bd6983e92ff80f17aa3065"
PKG_URL="https://github.com/torvalds/linux/archive/${PKG_VERSION}.tar.gz"
PKG_SOURCE_NAME="linux-${LINUX}-${PKG_VERSION}.tar.gz"
PKG_PATCH_DIRS="default"
;;
raspberrypi)
PKG_VERSION="cb8d82ae0059dd19f0f24a3c1e1081c87d73b0ea" # 6.1.23
PKG_SHA256="bb447497dddae03d6cf9235e8e8a9613a637c0143ea4ca6cb842d0f5c805c577"
PKG_VERSION="a72a720bfd4d2093ce9e51239cd7067dd060ff81" # 6.1.34
PKG_SHA256="3acaf74f06c04c5727e8d917251b40e5378303b9e2fc62eca81f362857c1db70"
PKG_URL="https://github.com/raspberrypi/linux/archive/${PKG_VERSION}.tar.gz"
PKG_SOURCE_NAME="linux-${LINUX}-${PKG_VERSION}.tar.gz"
;;

View file

@ -0,0 +1,138 @@
From 94d0a9815c99385e57a17fb20448e47a1f229bcf Mon Sep 17 00:00:00 2001
From: Matthias Reichl <hias@horus.com>
Date: Sat, 3 Jun 2023 12:00:28 +0200
Subject: [PATCH 1/2] ALSA: pcm: fix ELD constraints for (E)AC3, DTS(-HD) and
MLP formats
The SADs of compressed formats contain the channel and sample rate
info of the audio data inside the compressed stream, but when
building constraints we must use the rates and channels used to
transport the compressed streams.
eg 48kHz 6ch EAC3 needs to be transmitted as a 2ch 192kHz stream.
This patch fixes the constraints for the common AC3 and DTS formats,
the constraints for the less common MPEG, DSD etc formats are copied
directly from the info in the SADs as before as I don't have the specs
and equipment to test those.
Signed-off-by: Matthias Reichl <hias@horus.com>
---
sound/core/pcm_drm_eld.c | 73 ++++++++++++++++++++++++++++++++++++++--
1 file changed, 70 insertions(+), 3 deletions(-)
diff --git a/sound/core/pcm_drm_eld.c b/sound/core/pcm_drm_eld.c
index 4b5faae5d16e5..07075071972dd 100644
--- a/sound/core/pcm_drm_eld.c
+++ b/sound/core/pcm_drm_eld.c
@@ -2,11 +2,25 @@
/*
* PCM DRM helpers
*/
+#include <linux/bitfield.h>
#include <linux/export.h>
+#include <linux/hdmi.h>
#include <drm/drm_edid.h>
#include <sound/pcm.h>
#include <sound/pcm_drm_eld.h>
+#define SAD0_CHANNELS_MASK GENMASK(2, 0) /* max number of channels - 1 */
+#define SAD0_FORMAT_MASK GENMASK(6, 3) /* audio format */
+
+#define SAD1_RATE_MASK GENMASK(6, 0) /* bitfield of supported rates */
+#define SAD1_RATE_32000_MASK BIT(0)
+#define SAD1_RATE_44100_MASK BIT(1)
+#define SAD1_RATE_48000_MASK BIT(2)
+#define SAD1_RATE_88200_MASK BIT(3)
+#define SAD1_RATE_96000_MASK BIT(4)
+#define SAD1_RATE_176400_MASK BIT(5)
+#define SAD1_RATE_192000_MASK BIT(6)
+
static const unsigned int eld_rates[] = {
32000,
44100,
@@ -17,9 +31,62 @@ static const unsigned int eld_rates[] = {
192000,
};
+static unsigned int map_rate_families(const u8 *sad,
+ unsigned int mask_32000,
+ unsigned int mask_44100,
+ unsigned int mask_48000)
+{
+ unsigned int rate_mask = 0;
+
+ if (sad[1] & SAD1_RATE_32000_MASK)
+ rate_mask |= mask_32000;
+ if (sad[1] & (SAD1_RATE_44100_MASK | SAD1_RATE_88200_MASK | SAD1_RATE_176400_MASK))
+ rate_mask |= mask_44100;
+ if (sad[1] & (SAD1_RATE_48000_MASK | SAD1_RATE_96000_MASK | SAD1_RATE_192000_MASK))
+ rate_mask |= mask_48000;
+ return rate_mask;
+}
+
+static unsigned int sad_rate_mask(const u8 *sad)
+{
+ switch (FIELD_GET(SAD0_FORMAT_MASK, sad[0])) {
+ case HDMI_AUDIO_CODING_TYPE_PCM:
+ return sad[1] & SAD1_RATE_MASK;
+ case HDMI_AUDIO_CODING_TYPE_AC3:
+ case HDMI_AUDIO_CODING_TYPE_DTS:
+ return map_rate_families(sad,
+ SAD1_RATE_32000_MASK,
+ SAD1_RATE_44100_MASK,
+ SAD1_RATE_48000_MASK);
+ case HDMI_AUDIO_CODING_TYPE_EAC3:
+ case HDMI_AUDIO_CODING_TYPE_DTS_HD:
+ case HDMI_AUDIO_CODING_TYPE_MLP:
+ return map_rate_families(sad,
+ 0,
+ SAD1_RATE_176400_MASK,
+ SAD1_RATE_192000_MASK);
+ default:
+ /* TODO adjust for other compressed formats as well */
+ return sad[1] & SAD1_RATE_MASK;
+ }
+}
+
static unsigned int sad_max_channels(const u8 *sad)
{
- return 1 + (sad[0] & 7);
+ switch (FIELD_GET(SAD0_FORMAT_MASK, sad[0])) {
+ case HDMI_AUDIO_CODING_TYPE_PCM:
+ return 1 + FIELD_GET(SAD0_CHANNELS_MASK, sad[0]);
+ case HDMI_AUDIO_CODING_TYPE_AC3:
+ case HDMI_AUDIO_CODING_TYPE_DTS:
+ case HDMI_AUDIO_CODING_TYPE_EAC3:
+ return 2;
+ case HDMI_AUDIO_CODING_TYPE_DTS_HD:
+ case HDMI_AUDIO_CODING_TYPE_MLP:
+ return 8;
+ default:
+ /* TODO adjust for other compressed formats as well */
+ return 1 + FIELD_GET(SAD0_CHANNELS_MASK, sad[0]);
+ }
}
static int eld_limit_rates(struct snd_pcm_hw_params *params,
@@ -42,7 +109,7 @@ static int eld_limit_rates(struct snd_pcm_hw_params *params,
* requested number of channels.
*/
if (c->min <= max_channels)
- rate_mask |= sad[1];
+ rate_mask |= sad_rate_mask(sad);
}
}
@@ -70,7 +137,7 @@ static int eld_limit_channels(struct snd_pcm_hw_params *params,
rate_mask |= BIT(i);
for (i = drm_eld_sad_count(eld); i > 0; i--, sad += 3)
- if (rate_mask & sad[1])
+ if (rate_mask & sad_rate_mask(sad))
t.max = max(t.max, sad_max_channels(sad));
}
--
2.39.2

View file

@ -1,91 +0,0 @@
From a2769637a9b98c6809d4d25a3a20447a3ff7b23a Mon Sep 17 00:00:00 2001
From: Matthias Reichl <hias@horus.com>
Date: Fri, 19 Mar 2021 12:14:17 +0100
Subject: [PATCH] ALSA: pcm: fix ELD constraints for some compressed audio
formats
The SADs of compressed formats like AC3 and DTS contain the channel
and sample rate info of the audio data inside the compressed stream,
but when building constraints we must use the rates and formats used
to pass through the stream. eg 2ch 48kHz for AC3.
Signed-off-by: Matthias Reichl <hias@horus.com>
---
sound/core/pcm_drm_eld.c | 38 +++++++++++++++++++++++++++++++++++---
1 file changed, 35 insertions(+), 3 deletions(-)
diff --git a/sound/core/pcm_drm_eld.c b/sound/core/pcm_drm_eld.c
index 4b5faae5d16e5..e7ec7a8b9d420 100644
--- a/sound/core/pcm_drm_eld.c
+++ b/sound/core/pcm_drm_eld.c
@@ -6,6 +6,7 @@
#include <drm/drm_edid.h>
#include <sound/pcm.h>
#include <sound/pcm_drm_eld.h>
+#include <linux/hdmi.h>
static const unsigned int eld_rates[] = {
32000,
@@ -17,9 +18,40 @@ static const unsigned int eld_rates[] = {
192000,
};
+static unsigned int sad_format(const u8 *sad)
+{
+ return (sad[0] & 0x78) >> 3;
+}
+
static unsigned int sad_max_channels(const u8 *sad)
{
- return 1 + (sad[0] & 7);
+ switch (sad_format(sad)) {
+ case HDMI_AUDIO_CODING_TYPE_AC3:
+ case HDMI_AUDIO_CODING_TYPE_DTS:
+ case HDMI_AUDIO_CODING_TYPE_EAC3:
+ return 2;
+ case HDMI_AUDIO_CODING_TYPE_DTS_HD:
+ case HDMI_AUDIO_CODING_TYPE_MLP:
+ return 8;
+ default:
+ return 1 + (sad[0] & 7);
+ }
+}
+
+static unsigned int sad_rate_mask(const u8 *sad)
+{
+ switch (sad_format(sad)) {
+ case HDMI_AUDIO_CODING_TYPE_AC3:
+ case HDMI_AUDIO_CODING_TYPE_DTS:
+ return 0x07; // 32-48kHz
+ case HDMI_AUDIO_CODING_TYPE_EAC3:
+ return 0x7f; // 32-192kHz
+ case HDMI_AUDIO_CODING_TYPE_DTS_HD:
+ case HDMI_AUDIO_CODING_TYPE_MLP:
+ return 0x60; // 176.4, 192kHz
+ default:
+ return sad[1] & 0x7f;
+ }
}
static int eld_limit_rates(struct snd_pcm_hw_params *params,
@@ -42,7 +74,7 @@ static int eld_limit_rates(struct snd_pcm_hw_params *params,
* requested number of channels.
*/
if (c->min <= max_channels)
- rate_mask |= sad[1];
+ rate_mask |= sad_rate_mask(sad);
}
}
@@ -70,7 +102,7 @@ static int eld_limit_channels(struct snd_pcm_hw_params *params,
rate_mask |= BIT(i);
for (i = drm_eld_sad_count(eld); i > 0; i--, sad += 3)
- if (rate_mask & sad[1])
+ if (rate_mask & sad_rate_mask(sad))
t.max = max(t.max, sad_max_channels(sad));
}
--
2.20.1

View file

@ -0,0 +1,89 @@
From 99586e3f502fcc4fdd21b621f3c87ae7a8f7c170 Mon Sep 17 00:00:00 2001
From: Matthias Reichl <hias@horus.com>
Date: Sat, 3 Jun 2023 12:12:28 +0200
Subject: [PATCH 2/2] ASoC: hdmi-codec: don't set channel and speaker info for
compressed formats
CTA 861 only mandates that the speaker allocation in the audio info frame
is set for multichannel PCM formats. Likewise the number of channels in the
audio infoframe is only relevant for PCM.
Some TVs won't decode compressed formats if the number of channels isn't
set to 0 (refer to stream header) and the speaker allocation is set to the
default 0 (FL and FR).
So fill in this info only for PCM audio and set it to 0 for compressed
audio formats.
This also prevents hdmi_codec_prepare failing with an error when trying to
play back DTS-HD or MLP (which is passed through as 8ch) if the sink only
supports 2ch PCM and announces only FL/FR speaker support in the EDID.
Signed-off-by: Matthias Reichl <hias@horus.com>
---
sound/soc/codecs/hdmi-codec.c | 36 +++++++++++++++++++++++------------
1 file changed, 24 insertions(+), 12 deletions(-)
diff --git a/sound/soc/codecs/hdmi-codec.c b/sound/soc/codecs/hdmi-codec.c
index 0b1cdb2d60498..a192d985c5f18 100644
--- a/sound/soc/codecs/hdmi-codec.c
+++ b/sound/soc/codecs/hdmi-codec.c
@@ -484,31 +484,43 @@ static int hdmi_codec_fill_codec_params(struct snd_soc_dai *dai,
struct hdmi_codec_params *hp)
{
struct hdmi_codec_priv *hcp = snd_soc_dai_get_drvdata(dai);
- int idx;
-
- /* Select a channel allocation that matches with ELD and pcm channels */
- idx = hdmi_codec_get_ch_alloc_table_idx(hcp, channels);
- if (idx < 0) {
- dev_err(dai->dev, "Not able to map channels to speakers (%d)\n",
- idx);
- hcp->chmap_idx = HDMI_CODEC_CHMAP_IDX_UNKNOWN;
- return idx;
+ int idx = HDMI_CODEC_CHMAP_IDX_UNKNOWN;
+ u8 ca_id = 0;
+ bool pcm_audio = !(hcp->iec_status[0] & IEC958_AES0_NONAUDIO);
+
+ if (pcm_audio) {
+ /* Select a channel allocation that matches with ELD and pcm channels */
+ idx = hdmi_codec_get_ch_alloc_table_idx(hcp, channels);
+
+ if (idx < 0) {
+ dev_err(dai->dev, "Not able to map channels to speakers (%d)\n",
+ idx);
+ hcp->chmap_idx = HDMI_CODEC_CHMAP_IDX_UNKNOWN;
+ return idx;
+ }
+
+ ca_id = hdmi_codec_channel_alloc[idx].ca_id;
}
memset(hp, 0, sizeof(*hp));
hdmi_audio_infoframe_init(&hp->cea);
- hp->cea.channels = channels;
+
+ if (pcm_audio)
+ hp->cea.channels = channels;
+ else
+ hp->cea.channels = 0;
+
hp->cea.coding_type = HDMI_AUDIO_CODING_TYPE_STREAM;
hp->cea.sample_size = HDMI_AUDIO_SAMPLE_SIZE_STREAM;
hp->cea.sample_frequency = HDMI_AUDIO_SAMPLE_FREQUENCY_STREAM;
- hp->cea.channel_allocation = hdmi_codec_channel_alloc[idx].ca_id;
+ hp->cea.channel_allocation = ca_id;
hp->sample_width = sample_width;
hp->sample_rate = sample_rate;
hp->channels = channels;
- hcp->chmap_idx = hdmi_codec_channel_alloc[idx].ca_id;
+ hcp->chmap_idx = idx;
return 0;
}
--
2.39.2

View file

@ -0,0 +1,138 @@
From 94d0a9815c99385e57a17fb20448e47a1f229bcf Mon Sep 17 00:00:00 2001
From: Matthias Reichl <hias@horus.com>
Date: Sat, 3 Jun 2023 12:00:28 +0200
Subject: [PATCH 1/2] ALSA: pcm: fix ELD constraints for (E)AC3, DTS(-HD) and
MLP formats
The SADs of compressed formats contain the channel and sample rate
info of the audio data inside the compressed stream, but when
building constraints we must use the rates and channels used to
transport the compressed streams.
eg 48kHz 6ch EAC3 needs to be transmitted as a 2ch 192kHz stream.
This patch fixes the constraints for the common AC3 and DTS formats,
the constraints for the less common MPEG, DSD etc formats are copied
directly from the info in the SADs as before as I don't have the specs
and equipment to test those.
Signed-off-by: Matthias Reichl <hias@horus.com>
---
sound/core/pcm_drm_eld.c | 73 ++++++++++++++++++++++++++++++++++++++--
1 file changed, 70 insertions(+), 3 deletions(-)
diff --git a/sound/core/pcm_drm_eld.c b/sound/core/pcm_drm_eld.c
index 4b5faae5d16e5..07075071972dd 100644
--- a/sound/core/pcm_drm_eld.c
+++ b/sound/core/pcm_drm_eld.c
@@ -2,11 +2,25 @@
/*
* PCM DRM helpers
*/
+#include <linux/bitfield.h>
#include <linux/export.h>
+#include <linux/hdmi.h>
#include <drm/drm_edid.h>
#include <sound/pcm.h>
#include <sound/pcm_drm_eld.h>
+#define SAD0_CHANNELS_MASK GENMASK(2, 0) /* max number of channels - 1 */
+#define SAD0_FORMAT_MASK GENMASK(6, 3) /* audio format */
+
+#define SAD1_RATE_MASK GENMASK(6, 0) /* bitfield of supported rates */
+#define SAD1_RATE_32000_MASK BIT(0)
+#define SAD1_RATE_44100_MASK BIT(1)
+#define SAD1_RATE_48000_MASK BIT(2)
+#define SAD1_RATE_88200_MASK BIT(3)
+#define SAD1_RATE_96000_MASK BIT(4)
+#define SAD1_RATE_176400_MASK BIT(5)
+#define SAD1_RATE_192000_MASK BIT(6)
+
static const unsigned int eld_rates[] = {
32000,
44100,
@@ -17,9 +31,62 @@ static const unsigned int eld_rates[] = {
192000,
};
+static unsigned int map_rate_families(const u8 *sad,
+ unsigned int mask_32000,
+ unsigned int mask_44100,
+ unsigned int mask_48000)
+{
+ unsigned int rate_mask = 0;
+
+ if (sad[1] & SAD1_RATE_32000_MASK)
+ rate_mask |= mask_32000;
+ if (sad[1] & (SAD1_RATE_44100_MASK | SAD1_RATE_88200_MASK | SAD1_RATE_176400_MASK))
+ rate_mask |= mask_44100;
+ if (sad[1] & (SAD1_RATE_48000_MASK | SAD1_RATE_96000_MASK | SAD1_RATE_192000_MASK))
+ rate_mask |= mask_48000;
+ return rate_mask;
+}
+
+static unsigned int sad_rate_mask(const u8 *sad)
+{
+ switch (FIELD_GET(SAD0_FORMAT_MASK, sad[0])) {
+ case HDMI_AUDIO_CODING_TYPE_PCM:
+ return sad[1] & SAD1_RATE_MASK;
+ case HDMI_AUDIO_CODING_TYPE_AC3:
+ case HDMI_AUDIO_CODING_TYPE_DTS:
+ return map_rate_families(sad,
+ SAD1_RATE_32000_MASK,
+ SAD1_RATE_44100_MASK,
+ SAD1_RATE_48000_MASK);
+ case HDMI_AUDIO_CODING_TYPE_EAC3:
+ case HDMI_AUDIO_CODING_TYPE_DTS_HD:
+ case HDMI_AUDIO_CODING_TYPE_MLP:
+ return map_rate_families(sad,
+ 0,
+ SAD1_RATE_176400_MASK,
+ SAD1_RATE_192000_MASK);
+ default:
+ /* TODO adjust for other compressed formats as well */
+ return sad[1] & SAD1_RATE_MASK;
+ }
+}
+
static unsigned int sad_max_channels(const u8 *sad)
{
- return 1 + (sad[0] & 7);
+ switch (FIELD_GET(SAD0_FORMAT_MASK, sad[0])) {
+ case HDMI_AUDIO_CODING_TYPE_PCM:
+ return 1 + FIELD_GET(SAD0_CHANNELS_MASK, sad[0]);
+ case HDMI_AUDIO_CODING_TYPE_AC3:
+ case HDMI_AUDIO_CODING_TYPE_DTS:
+ case HDMI_AUDIO_CODING_TYPE_EAC3:
+ return 2;
+ case HDMI_AUDIO_CODING_TYPE_DTS_HD:
+ case HDMI_AUDIO_CODING_TYPE_MLP:
+ return 8;
+ default:
+ /* TODO adjust for other compressed formats as well */
+ return 1 + FIELD_GET(SAD0_CHANNELS_MASK, sad[0]);
+ }
}
static int eld_limit_rates(struct snd_pcm_hw_params *params,
@@ -42,7 +109,7 @@ static int eld_limit_rates(struct snd_pcm_hw_params *params,
* requested number of channels.
*/
if (c->min <= max_channels)
- rate_mask |= sad[1];
+ rate_mask |= sad_rate_mask(sad);
}
}
@@ -70,7 +137,7 @@ static int eld_limit_channels(struct snd_pcm_hw_params *params,
rate_mask |= BIT(i);
for (i = drm_eld_sad_count(eld); i > 0; i--, sad += 3)
- if (rate_mask & sad[1])
+ if (rate_mask & sad_rate_mask(sad))
t.max = max(t.max, sad_max_channels(sad));
}
--
2.39.2

View file

@ -1,91 +0,0 @@
From a2769637a9b98c6809d4d25a3a20447a3ff7b23a Mon Sep 17 00:00:00 2001
From: Matthias Reichl <hias@horus.com>
Date: Fri, 19 Mar 2021 12:14:17 +0100
Subject: [PATCH] ALSA: pcm: fix ELD constraints for some compressed audio
formats
The SADs of compressed formats like AC3 and DTS contain the channel
and sample rate info of the audio data inside the compressed stream,
but when building constraints we must use the rates and formats used
to pass through the stream. eg 2ch 48kHz for AC3.
Signed-off-by: Matthias Reichl <hias@horus.com>
---
sound/core/pcm_drm_eld.c | 38 +++++++++++++++++++++++++++++++++++---
1 file changed, 35 insertions(+), 3 deletions(-)
diff --git a/sound/core/pcm_drm_eld.c b/sound/core/pcm_drm_eld.c
index 4b5faae5d16e5..e7ec7a8b9d420 100644
--- a/sound/core/pcm_drm_eld.c
+++ b/sound/core/pcm_drm_eld.c
@@ -6,6 +6,7 @@
#include <drm/drm_edid.h>
#include <sound/pcm.h>
#include <sound/pcm_drm_eld.h>
+#include <linux/hdmi.h>
static const unsigned int eld_rates[] = {
32000,
@@ -17,9 +18,40 @@ static const unsigned int eld_rates[] = {
192000,
};
+static unsigned int sad_format(const u8 *sad)
+{
+ return (sad[0] & 0x78) >> 3;
+}
+
static unsigned int sad_max_channels(const u8 *sad)
{
- return 1 + (sad[0] & 7);
+ switch (sad_format(sad)) {
+ case HDMI_AUDIO_CODING_TYPE_AC3:
+ case HDMI_AUDIO_CODING_TYPE_DTS:
+ case HDMI_AUDIO_CODING_TYPE_EAC3:
+ return 2;
+ case HDMI_AUDIO_CODING_TYPE_DTS_HD:
+ case HDMI_AUDIO_CODING_TYPE_MLP:
+ return 8;
+ default:
+ return 1 + (sad[0] & 7);
+ }
+}
+
+static unsigned int sad_rate_mask(const u8 *sad)
+{
+ switch (sad_format(sad)) {
+ case HDMI_AUDIO_CODING_TYPE_AC3:
+ case HDMI_AUDIO_CODING_TYPE_DTS:
+ return 0x07; // 32-48kHz
+ case HDMI_AUDIO_CODING_TYPE_EAC3:
+ return 0x7f; // 32-192kHz
+ case HDMI_AUDIO_CODING_TYPE_DTS_HD:
+ case HDMI_AUDIO_CODING_TYPE_MLP:
+ return 0x60; // 176.4, 192kHz
+ default:
+ return sad[1] & 0x7f;
+ }
}
static int eld_limit_rates(struct snd_pcm_hw_params *params,
@@ -42,7 +74,7 @@ static int eld_limit_rates(struct snd_pcm_hw_params *params,
* requested number of channels.
*/
if (c->min <= max_channels)
- rate_mask |= sad[1];
+ rate_mask |= sad_rate_mask(sad);
}
}
@@ -70,7 +102,7 @@ static int eld_limit_channels(struct snd_pcm_hw_params *params,
rate_mask |= BIT(i);
for (i = drm_eld_sad_count(eld); i > 0; i--, sad += 3)
- if (rate_mask & sad[1])
+ if (rate_mask & sad_rate_mask(sad))
t.max = max(t.max, sad_max_channels(sad));
}
--
2.20.1

View file

@ -0,0 +1,89 @@
From 99586e3f502fcc4fdd21b621f3c87ae7a8f7c170 Mon Sep 17 00:00:00 2001
From: Matthias Reichl <hias@horus.com>
Date: Sat, 3 Jun 2023 12:12:28 +0200
Subject: [PATCH 2/2] ASoC: hdmi-codec: don't set channel and speaker info for
compressed formats
CTA 861 only mandates that the speaker allocation in the audio info frame
is set for multichannel PCM formats. Likewise the number of channels in the
audio infoframe is only relevant for PCM.
Some TVs won't decode compressed formats if the number of channels isn't
set to 0 (refer to stream header) and the speaker allocation is set to the
default 0 (FL and FR).
So fill in this info only for PCM audio and set it to 0 for compressed
audio formats.
This also prevents hdmi_codec_prepare failing with an error when trying to
play back DTS-HD or MLP (which is passed through as 8ch) if the sink only
supports 2ch PCM and announces only FL/FR speaker support in the EDID.
Signed-off-by: Matthias Reichl <hias@horus.com>
---
sound/soc/codecs/hdmi-codec.c | 36 +++++++++++++++++++++++------------
1 file changed, 24 insertions(+), 12 deletions(-)
diff --git a/sound/soc/codecs/hdmi-codec.c b/sound/soc/codecs/hdmi-codec.c
index 0b1cdb2d60498..a192d985c5f18 100644
--- a/sound/soc/codecs/hdmi-codec.c
+++ b/sound/soc/codecs/hdmi-codec.c
@@ -484,31 +484,43 @@ static int hdmi_codec_fill_codec_params(struct snd_soc_dai *dai,
struct hdmi_codec_params *hp)
{
struct hdmi_codec_priv *hcp = snd_soc_dai_get_drvdata(dai);
- int idx;
-
- /* Select a channel allocation that matches with ELD and pcm channels */
- idx = hdmi_codec_get_ch_alloc_table_idx(hcp, channels);
- if (idx < 0) {
- dev_err(dai->dev, "Not able to map channels to speakers (%d)\n",
- idx);
- hcp->chmap_idx = HDMI_CODEC_CHMAP_IDX_UNKNOWN;
- return idx;
+ int idx = HDMI_CODEC_CHMAP_IDX_UNKNOWN;
+ u8 ca_id = 0;
+ bool pcm_audio = !(hcp->iec_status[0] & IEC958_AES0_NONAUDIO);
+
+ if (pcm_audio) {
+ /* Select a channel allocation that matches with ELD and pcm channels */
+ idx = hdmi_codec_get_ch_alloc_table_idx(hcp, channels);
+
+ if (idx < 0) {
+ dev_err(dai->dev, "Not able to map channels to speakers (%d)\n",
+ idx);
+ hcp->chmap_idx = HDMI_CODEC_CHMAP_IDX_UNKNOWN;
+ return idx;
+ }
+
+ ca_id = hdmi_codec_channel_alloc[idx].ca_id;
}
memset(hp, 0, sizeof(*hp));
hdmi_audio_infoframe_init(&hp->cea);
- hp->cea.channels = channels;
+
+ if (pcm_audio)
+ hp->cea.channels = channels;
+ else
+ hp->cea.channels = 0;
+
hp->cea.coding_type = HDMI_AUDIO_CODING_TYPE_STREAM;
hp->cea.sample_size = HDMI_AUDIO_SAMPLE_SIZE_STREAM;
hp->cea.sample_frequency = HDMI_AUDIO_SAMPLE_FREQUENCY_STREAM;
- hp->cea.channel_allocation = hdmi_codec_channel_alloc[idx].ca_id;
+ hp->cea.channel_allocation = ca_id;
hp->sample_width = sample_width;
hp->sample_rate = sample_rate;
hp->channels = channels;
- hcp->chmap_idx = hdmi_codec_channel_alloc[idx].ca_id;
+ hcp->chmap_idx = idx;
return 0;
}
--
2.39.2

View file

@ -5,7 +5,7 @@
PKG_NAME="audiodecoder.2sf"
PKG_VERSION="20.2.1-Nexus"
PKG_SHA256="247ad2d9e1df00304882b40d80bc8fd70a4efd2bf2613163c24177d36649247c"
PKG_REV="6"
PKG_REV="5"
PKG_ARCH="any"
PKG_LICENSE="GPL"
PKG_SITE="https://github.com/xbmc/audiodecoder.2sf"

View file

@ -5,7 +5,7 @@
PKG_NAME="audiodecoder.asap"
PKG_VERSION="20.3.0-Nexus"
PKG_SHA256="9f54285866766b80d0d0c5210561678579d396591ab16cf70c83c4968bfbc8ba"
PKG_REV="6"
PKG_REV="5"
PKG_ARCH="any"
PKG_LICENSE="GPL"
PKG_SITE="https://github.com/xbmc/audiodecoder.asap"

View file

@ -5,7 +5,7 @@
PKG_NAME="audiodecoder.dumb"
PKG_VERSION="20.2.1-Nexus"
PKG_SHA256="d2ef04e80645f0bd1c9d31c9633d2a27d1757198fbcd2d43d00c84889e6ae585"
PKG_REV="6"
PKG_REV="5"
PKG_ARCH="any"
PKG_LICENSE="GPL"
PKG_SITE="https://github.com/xbmc/audiodecoder.dumb"

View file

@ -5,7 +5,7 @@
PKG_NAME="audiodecoder.fluidsynth"
PKG_VERSION="20.2.1-Nexus"
PKG_SHA256="dd8ca6386a3beed360c1d2f989cd81553baf81652007fdfd478a28b44b68db10"
PKG_REV="7"
PKG_REV="6"
PKG_ARCH="any"
PKG_LICENSE="GPL"
PKG_SITE="https://github.com/xbmc/audiodecoder.fluidsynth"

View file

@ -5,7 +5,7 @@
PKG_NAME="audiodecoder.gme"
PKG_VERSION="20.2.1-Nexus"
PKG_SHA256="5aaec959e92f4af2684aa0439576d7f576f28a0a43f50439a6f38d0738792bdc"
PKG_REV="6"
PKG_REV="5"
PKG_ARCH="any"
PKG_LICENSE="GPL"
PKG_SITE="https://github.com/xbmc/audiodecoder.gme"

View file

@ -5,7 +5,7 @@
PKG_NAME="audiodecoder.gsf"
PKG_VERSION="20.2.1-Nexus"
PKG_SHA256="b09dcb379bdc536117a956b10b37cf50c8afaa65337993c44a6847d382d7e2a5"
PKG_REV="6"
PKG_REV="5"
PKG_ARCH="any"
PKG_LICENSE="GPL"
PKG_SITE="https://github.com/xbmc/audiodecoder.gsf"

View file

@ -5,7 +5,7 @@
PKG_NAME="audiodecoder.modplug"
PKG_VERSION="20.2.0-Nexus"
PKG_SHA256="619ba20ea19dd9aea15e7d30aa12a146b412c7fcd9e709528f6758e82a3d85e7"
PKG_REV="6"
PKG_REV="5"
PKG_ARCH="any"
PKG_LICENSE="GPL"
PKG_SITE="https://github.com/xbmc/audiodecoder.modplug"

View file

@ -5,7 +5,7 @@
PKG_NAME="audiodecoder.ncsf"
PKG_VERSION="20.2.0-Nexus"
PKG_SHA256="31b25846a9b8213306456eb6f8ab8fdaeede5cad35627e77aff2c422f370b211"
PKG_REV="6"
PKG_REV="5"
PKG_ARCH="any"
PKG_LICENSE="GPL"
PKG_SITE="https://github.com/xbmc/audiodecoder.ncsf"

View file

@ -5,7 +5,7 @@
PKG_NAME="audiodecoder.nosefart"
PKG_VERSION="20.2.0-Nexus"
PKG_SHA256="2f7a92bfaddcd5aa63e2ea7348ae9eeefd07dee2aba46840ce5376677e2abc19"
PKG_REV="6"
PKG_REV="5"
PKG_ARCH="any"
PKG_LICENSE="GPL"
PKG_SITE="https://github.com/xbmc/audiodecoder.nosefart"

View file

@ -5,7 +5,7 @@
PKG_NAME="audiodecoder.openmpt"
PKG_VERSION="20.2.0-Nexus"
PKG_SHA256="388fb4c9fcb5bd9edc978e3db5f54fa531c7f397393f3e421757e4e0de2d9c54"
PKG_REV="7"
PKG_REV="5"
PKG_ARCH="any"
PKG_LICENSE="GPL"
PKG_SITE="https://github.com/xbmc/audiodecoder.openmpt"

View file

@ -5,7 +5,7 @@
PKG_NAME="audiodecoder.organya"
PKG_VERSION="20.2.0-Nexus"
PKG_SHA256="df5db2c94161c7c578d672a8cc36bdbde6c345142c9bb5212759ad0dc30fd59d"
PKG_REV="6"
PKG_REV="5"
PKG_ARCH="any"
PKG_LICENSE="GPL"
PKG_SITE="https://github.com/xbmc/audiodecoder.organya"

View file

@ -5,7 +5,7 @@
PKG_NAME="audiodecoder.qsf"
PKG_VERSION="20.2.0-Nexus"
PKG_SHA256="3116bb31b3fe53b85675ba664a7a8d5885e157940a4bcf57b96050844b11a377"
PKG_REV="6"
PKG_REV="5"
PKG_ARCH="any"
PKG_LICENSE="GPL"
PKG_SITE="https://github.com/xbmc/audiodecoder.qsf"

View file

@ -4,7 +4,7 @@
PKG_NAME="audiodecoder.sacd"
PKG_VERSION="20.3.0-Nexus"
PKG_SHA256="6d54f6cf81e13aadcec1b43689551feba6e9426453a758d955e96348ba996277"
PKG_REV="4"
PKG_REV="3"
PKG_ARCH="any"
PKG_LICENSE="GPL"
PKG_SITE="https://github.com/xbmc/audiodecoder.sacd"

View file

@ -5,7 +5,7 @@
PKG_NAME="audiodecoder.sidplay"
PKG_VERSION="20.2.0-Nexus"
PKG_SHA256="ab1f89237c91bc7157557f42dadcff50a7191eb7285ee668543defce9f1efcf2"
PKG_REV="6"
PKG_REV="5"
PKG_ARCH="any"
PKG_LICENSE="GPL"
PKG_SITE="https://github.com/xbmc/audiodecoder.sidplay"

View file

@ -5,7 +5,7 @@
PKG_NAME="audiodecoder.snesapu"
PKG_VERSION="20.2.0-Nexus"
PKG_SHA256="f216a7d25c864986618118236c575687ab62d129a16cb1f73c15860948d9ac92"
PKG_REV="6"
PKG_REV="5"
PKG_ARCH="any"
PKG_LICENSE="GPL"
PKG_SITE="https://github.com/xbmc/audiodecoder.snesapu"

View file

@ -5,7 +5,7 @@
PKG_NAME="audiodecoder.ssf"
PKG_VERSION="20.2.0-Nexus"
PKG_SHA256="c2d5fbba35d2d73ed5891567d507f77bc64fa447dfcb4474f5d58594e9a07b2d"
PKG_REV="6"
PKG_REV="5"
PKG_ARCH="any"
PKG_LICENSE="GPL"
PKG_SITE="https://github.com/xbmc/audiodecoder.ssf"

View file

@ -5,7 +5,7 @@
PKG_NAME="audiodecoder.stsound"
PKG_VERSION="20.2.0-Nexus"
PKG_SHA256="a8138fb075a480c59d7041a9408eca6e52dc88f188daed519cd9e684b430f333"
PKG_REV="6"
PKG_REV="5"
PKG_ARCH="any"
PKG_LICENSE="GPL"
PKG_SITE="https://github.com/xbmc/audiodecoder.stsound"

View file

@ -5,7 +5,7 @@
PKG_NAME="audiodecoder.timidity"
PKG_VERSION="20.2.0-Nexus"
PKG_SHA256="ef1b384090df3c2c78d00ed33de1d989ce802702b0a9aa13575946409a5cd0f1"
PKG_REV="6"
PKG_REV="5"
PKG_ARCH="any"
PKG_LICENSE="GPL"
PKG_SITE="https://github.com/xbmc/audiodecoder.timidity"

View file

@ -5,7 +5,7 @@
PKG_NAME="audiodecoder.upse"
PKG_VERSION="20.2.0-Nexus"
PKG_SHA256="d9f75e5cbab3ba5fc391cb40e0585bf22fad0eebfaf002d1d58bc896b6f2a5d6"
PKG_REV="6"
PKG_REV="5"
PKG_ARCH="any"
PKG_LICENSE="GPL"
PKG_SITE="https://github.com/xbmc/audiodecoder.upse"

View file

@ -5,7 +5,7 @@
PKG_NAME="audiodecoder.usf"
PKG_VERSION="20.2.0-Nexus"
PKG_SHA256="3ce9ef8823c773d894fd0018455ea5000e9b5a64f3cd8d66ddb4cf8f6c9ea836"
PKG_REV="6"
PKG_REV="5"
PKG_ARCH="any"
PKG_LICENSE="GPL"
PKG_SITE="https://github.com/xbmc/audiodecoder.usf"

View file

@ -5,7 +5,7 @@
PKG_NAME="audiodecoder.vgmstream"
PKG_VERSION="20.2.0-Nexus"
PKG_SHA256="72367d7196f8049ef1fae426d32d3de1eac56bd4cb5a8fc38a6ba0c3da1b23d8"
PKG_REV="6"
PKG_REV="5"
PKG_ARCH="any"
PKG_LICENSE="GPL"
PKG_SITE="https://github.com/xbmc/audiodecoder.vgmstream"

View file

@ -5,7 +5,7 @@
PKG_NAME="audiodecoder.wsr"
PKG_VERSION="20.2.0-Nexus"
PKG_SHA256="e8f8e06b61fbf612d59d689c38a6acade485aabae2382f3fbbedb0ce0c00048d"
PKG_REV="6"
PKG_REV="5"
PKG_ARCH="any"
PKG_LICENSE="GPL"
PKG_SITE="https://github.com/xbmc/audiodecoder.wsr"

View file

@ -5,7 +5,7 @@
PKG_NAME="audioencoder.flac"
PKG_VERSION="20.2.0-Nexus"
PKG_SHA256="71daf8c35bbf644591600fef93412cd068a6bf6173d2258dc243ee04c8e5b091"
PKG_REV="6"
PKG_REV="5"
PKG_ARCH="any"
PKG_LICENSE="GPL"
PKG_SITE="https://github.com/xbmc/audioencoder.flac"

View file

@ -5,7 +5,7 @@
PKG_NAME="audioencoder.lame"
PKG_VERSION="20.3.0-Nexus"
PKG_SHA256="90f36ee0b4972669ed2876eae2502e58d86287aacdbf4bb25180aca01385e1c1"
PKG_REV="6"
PKG_REV="5"
PKG_ARCH="any"
PKG_LICENSE="GPL"
PKG_SITE="https://github.com/xbmc/audioencoder.lame"

View file

@ -5,7 +5,7 @@
PKG_NAME="audioencoder.vorbis"
PKG_VERSION="20.2.0-Nexus"
PKG_SHA256="359e972ddcc498727620ff224a82f970fa2ae22b71ea6ab30b96898dffe6f1f9"
PKG_REV="6"
PKG_REV="5"
PKG_ARCH="any"
PKG_LICENSE="GPL"
PKG_SITE="https://github.com/xbmc/audioencoder.vorbis"

View file

@ -5,7 +5,7 @@
PKG_NAME="audioencoder.wav"
PKG_VERSION="20.2.0-Nexus"
PKG_SHA256="1baf69cca688ebd389705ea2bef2c5285ba75dcfd0d0b534b6ab1e61c0020979"
PKG_REV="6"
PKG_REV="5"
PKG_ARCH="any"
PKG_LICENSE="GPL"
PKG_SITE="https://github.com/xbmc/audioencoder.wav"

View file

@ -2,8 +2,8 @@
# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv)
PKG_NAME="game.libretro.2048"
PKG_VERSION="1.0.0.134-Nexus"
PKG_SHA256="f07dc1cd34f9e2746ebf3fbf666f5301df49a9aa59760049a66aef953d514f87"
PKG_VERSION="1.0.0.133-Nexus"
PKG_SHA256="64263ff32d22ea0301b26137ce59b1e6e82026b4a6d130dc3fd9699624d36011"
PKG_REV="1"
PKG_ARCH="any"
PKG_LICENSE="GPL"

View file

@ -1,17 +0,0 @@
# SPDX-License-Identifier: GPL-2.0-only
# Copyright (C) 2023-present Team LibreELEC (https://libreelec.tv)
PKG_NAME="game.libretro.81"
PKG_VERSION="1.0.0.21-Nexus"
PKG_SHA256="a66f10511ecc30c2c76f73c018b56a45bab9c6783d180910cc7363ec66748ea7"
PKG_REV="1"
PKG_ARCH="any"
PKG_LICENSE="GPLv3"
PKG_SITE="https://github.com/kodi-game/game.libretro.81"
PKG_URL="https://github.com/kodi-game/game.libretro.81/archive/${PKG_VERSION}.tar.gz"
PKG_DEPENDS_TARGET="toolchain kodi-platform libretro-81"
PKG_SECTION=""
PKG_LONGDESC="game.libretro.81: 81 for Kodi"
PKG_IS_ADDON="yes"
PKG_ADDON_TYPE="kodi.gameclient"

View file

@ -1,17 +0,0 @@
# SPDX-License-Identifier: GPL-2.0-only
# Copyright (C) 2023-present Team LibreELEC (https://libreelec.tv)
PKG_NAME="game.libretro.a5200"
PKG_VERSION="2.0.2.4-Nexus"
PKG_SHA256="a0b1805581f244c2e0300f0821f96b93be017abc10813a9b8eb3c43da570c231"
PKG_REV="1"
PKG_ARCH="any"
PKG_LICENSE="GPLv2"
PKG_SITE="https://github.com/kodi-game/game.libretro.a5200"
PKG_URL="https://github.com/kodi-game/game.libretro.a5200/archive/${PKG_VERSION}.tar.gz"
PKG_DEPENDS_TARGET="toolchain kodi-platform libretro-a5200"
PKG_SECTION=""
PKG_LONGDESC="game.libretro.a5200: a5200 for Kodi"
PKG_IS_ADDON="yes"
PKG_ADDON_TYPE="kodi.gameclient"

View file

@ -2,8 +2,8 @@
# Copyright (C) 2020-present Team LibreELEC (https://libreelec.tv)
PKG_NAME="game.libretro.atari800"
PKG_VERSION="3.1.0.25-Nexus"
PKG_SHA256="dbd6c5719e5cb88841e213d7389d9416e6e623d6d09615f92c53c871045bf70a"
PKG_VERSION="3.1.0.23-Nexus"
PKG_SHA256="4839836a4bf8a461d9554ad4920c0e45e89a384149abc6e82d847f74208f28cc"
PKG_REV="1"
PKG_ARCH="any"
PKG_LICENSE="GPL"

View file

@ -2,10 +2,10 @@
# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv)
PKG_NAME="game.libretro.beetle-bsnes"
PKG_VERSION="0.9.26.24-Nexus"
PKG_SHA256="fc356984fba343651d4c8a77834f2f5e6e86d4fcd78ab967de451abdf3e99816"
PKG_VERSION="0.9.26.23-Nexus"
PKG_SHA256="8f7830c484f5da5726fae1210c5cfe03ac1493c99a27cb9086f5b019052c688d"
PKG_REV="1"
PKG_ARCH="x86_64"
PKG_ARCH="any"
PKG_LICENSE="GPL"
PKG_SITE="https://github.com/kodi-game/game.libretro.beetle-bsnes"
PKG_URL="https://github.com/kodi-game/game.libretro.beetle-bsnes/archive/${PKG_VERSION}.tar.gz"

View file

@ -2,8 +2,8 @@
# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv)
PKG_NAME="game.libretro.beetle-gba"
PKG_VERSION="0.9.36.24-Nexus"
PKG_SHA256="8b55b9936af1b61b66b3e15d512a5d3e701f70caabefd4b442ec40c535e88d4b"
PKG_VERSION="0.9.36.23-Nexus"
PKG_SHA256="f16c4faf9e52c75a20239854d76b678b1b6ab1dad354b34043941e4b0f08bb39"
PKG_REV="1"
PKG_ARCH="any"
PKG_LICENSE="GPL"

View file

@ -2,8 +2,8 @@
# Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv)
PKG_NAME="game.libretro.beetle-lynx"
PKG_VERSION="1.24.0.47-Nexus"
PKG_SHA256="54ce67dc0ac86842918b4e58d58b14f959128a1452dc72104a890bf60289ce2d"
PKG_VERSION="1.24.0.43-Nexus"
PKG_SHA256="63528c7ed0dabf79dc7e67228472d16da589ed49a9ab947966c1fee76c2936cb"
PKG_REV="1"
PKG_ARCH="any"
PKG_LICENSE="GPL"

Some files were not shown because too many files have changed in this diff Show more