Compare commits

..

4 commits

8 changed files with 106 additions and 157 deletions

View file

@ -90,25 +90,50 @@ namespace Jellyfin.Plugin.SmartPlaylist.Lisp {
(lambda (lambda
(list0) (list0)
(car list0))) (car list0)))
;(split
; (lambda
; (list0 pivot fc h0 h1)
; (cond
; ((null list0) (list list0 pivot fc h0 h1))
; ((fc (car list0) pivot) (split (cdr list0) pivot fc h0 (cons (car list0) h1)))
; (t (split (cdr list0) pivot fc (cons (car list0) h0) h1)))))
(split (split
(lambda (lambda
(list0 pivot fc h0 h1) (list0 pivot fc h0 h1 heq)
(cond (cond
((null list0) (list list0 pivot fc h0 h1)) ((null list0) (list list0 pivot fc h0 h1 heq))
((fc (car list0) pivot) (split (cdr list0) pivot fc h0 (cons (car list0) h1))) ((and
(t (split (cdr list0) pivot fc (cons (car list0) h0) h1))))) (fc (car list0) pivot)
(fc pivot (car list0))) (split (cdr list0) pivot fc h0 h1 (cons (car list0) heq)))
((fc (car list0) pivot) (split (cdr list0) pivot fc h0 (cons (car list0) h1) heq))
((fc pivot (car list0)) (split (cdr list0) pivot fc (cons (car list0) h0) h1 heq))
((= (car list0) pivot) (split (cdr list0) pivot fc h0 h1 (cons (car list0) heq)))
(t (split (cdr list0) pivot fc h0 h1 heq)))))
;(sort
; (lambda
; (fc list0)
; (cond
; ((null list0) nil)
; ((null (cdr list0)) list0)
; (t
; (let*
; (halves (split list0 (getpivot list0) fc nil nil))
; (h0 (car (cdr (cdr (cdr halves)))))
; (h1 (car (cdr (cdr (cdr (cdr halves))))))
; (append (sort fc h0) (sort fc h1)))))))
(sort (sort
(lambda (lambda
(fc list0) (fc list0)
(cond (begin t (cond
((null list0) nil) ((null list0) nil)
((null (cdr list0)) list0) ((null (cdr list0)) list0)
(t (t
(let* (let*
(halves (split list0 (getpivot list0) fc nil nil)) (halves (split list0 (getpivot list0) fc nil nil nil))
(h0 (car (cdr (cdr (cdr halves))))) (h0 (car (cdr (cdr (cdr halves)))))
(h1 (car (cdr (cdr (cdr (cdr halves)))))) (h1 (car (cdr (cdr (cdr (cdr halves))))))
(append (sort fc h0) (sort fc h1))))))) (heq (car (cdr (cdr (cdr (cdr (cdr halves)))))))
(append (append (sort fc h0) heq) (sort fc h1))))))))
(sort fc list00))) (sort fc list00)))
""" """
); );

View file

@ -21,10 +21,12 @@ function initial_load() {
Dashboard.hideLoadingMsg(); Dashboard.hideLoadingMsg();
} }
document.querySelector('#LispPlaygroundConfigPage') export default function (view, params) {
.addEventListener('viewshow', function() { view.addEventListener('viewshow', function() {
initial_load(); initial_load(null);
}); });
view.addEventListener('viewhide', function (_e) {});
view.addEventListener('viewdestroy', function (_e) {});
document.querySelector('#LispPlaygroundConfigPage') document.querySelector('#LispPlaygroundConfigPage')
.addEventListener('pageshow', function() { .addEventListener('pageshow', function() {
@ -41,3 +43,4 @@ document.querySelector('#LispPlaygroundConfigForm')
Dashboard.hideLoadingMsg(); Dashboard.hideLoadingMsg();
}); });
}); });
}

View file

@ -88,15 +88,13 @@ function initial_load(selectedId) {
Dashboard.hideLoadingMsg(); Dashboard.hideLoadingMsg();
}); });
} }
document.querySelector('#SmartCollectionConfigPage')
.addEventListener('viewshow', function() {
initial_load(null);
});
document.querySelector('#SmartCollectionConfigPage') export default function (view, params) {
.addEventListener('pageshow', function() { view.addEventListener('viewshow', function() {
initial_load(null); initial_load(null);
}); });
view.addEventListener('viewhide', function (_e) {});
view.addEventListener('viewdestroy', function (_e) {});
document.querySelector('#SmartcollectionSelection') document.querySelector('#SmartcollectionSelection')
.addEventListener('change', function() { .addEventListener('change', function() {
@ -114,3 +112,4 @@ document.querySelector('#SmartCollectionConfigForm')
}); });
e.preventDefault(); e.preventDefault();
}); });
}

View file

@ -116,14 +116,12 @@ function initial_load(selectedId) {
}); });
} }
document.querySelector('#SmartPlaylistConfigPage') export default function (view, params) {
.addEventListener('viewshow', function() { view.addEventListener('viewshow', function() {
initial_load(null);
});
document.querySelector('#SmartPlaylistConfigPage')
.addEventListener('pageshow', function() {
initial_load(null); initial_load(null);
}); });
view.addEventListener('viewhide', function (_e) {});
view.addEventListener('viewdestroy', function (_e) {});
document.querySelector('#SmartplaylistSelection') document.querySelector('#SmartplaylistSelection')
.addEventListener('change', function() { .addEventListener('change', function() {
@ -141,3 +139,4 @@ document.querySelector('#SmartPlaylistConfigForm')
}); });
e.preventDefault(); e.preventDefault();
}); });
}

View file

@ -1,7 +1,7 @@
name: Smart Playlist name: Smart Playlist
guid: dd2326e3-4d3e-4bfc-80e6-28502c1131df guid: dd2326e3-4d3e-4bfc-80e6-28502c1131df
version: 0.5.1.0 version: 0.5.2.0
targetAbi: 10.10.3.0 targetAbi: 10.10.5.0
framework: net8.0 framework: net8.0
owner: redxef owner: redxef
overview: Smart playlists with Lisp filter engine. overview: Smart playlists with Lisp filter engine.
@ -14,89 +14,8 @@ artifacts:
- jellyfin-smart-playlist.dll - jellyfin-smart-playlist.dll
- YamlDotNet.dll - YamlDotNet.dll
changelog: | changelog: |
## v0.5.1.0 ## v0.5.2.0
- Add multiple new functions: - bump Jellyfin ABI version to 10.10.5
- `length` computes the length of a list
- `split` splits off n elements of the given list `(split '(1 2 3 4 5) 3) -> ((1 2 3) 4 5)`
- `reverse` reverses a list
**Fixes**: **Fixes**:
- The configuration can now be updated again. - the config pages will always load, not only the first time
The relevant code got lost during the smart collection restructuring.
## v0.5.0.0
- Add support for collections
- Add a playground to test lisp code, the playground has
two additional functions available: `print` and `println`
to fill the output window
- Separate the config pages
- Enable nearly all item types
## v0.4.1.0
- improve defaults for new playlists
**Fixes**:
- finally get the percentage indicator of the scheduled task right
## v0.4.0.0
- Add a basic UI to configure the playlists.
- It's now possible to print log messages to the jellyfin log by calling `logd`, `logi`, `logw` or `loge`
for the respective levels `debug`, `info`, `warning` or `error`.
- Allow calling generic methods via `(invoke-generic object methodname args list-of-types)`.
- Add quoting via single quote: `'`.
- Add special case for `(quote <form>)` to be rendered as `'<form>`.
- It is now possible to include comments in the source via a semicolon (`;`).
- Respect the `Enabled` flag and only process the playlists that are enabled.
- New methods have been added: `rand`, `shuf`.
- Add `find-artist`, `get-name` and `find-parent` default definitions.
- Update YamlDotNet to v16.2.1.
**Breaking changes**:
- Rename global environment variables to be enclosed by `*`.
**Fixes**:
- The initialization of the executor now contains the same default definitions for the SortProgram and the normal Program.
- The progress report now considers the SmartPlaylists and not the individual playlists per user.
- It is now possible to pass builtins as arguments. Previously to get `(qsort > (list 1 2 3))` one had to write
something like this: `(qsort (lambda (a b) (> a b)) (list 1 2 3))`.
- A program no longer has to be a list, `t` is a valid program.
- Fix list parsing in cases where a space was before the closing parenthesis.
## v0.3.0.0
- Add a second program (`SortProgram`) which is run after the filtering, this
program should return the list of items, but in the order in which they should appear in
the playlist. The default is `(begin items)` which returns the list as is.
- Extend builtin lisp definitions: add `qsort` and string comparison methods
- Extend default program definitions: add `all-genres` and `any-genres` to quickly specify a list of genres which to include (or excluding when negating)
- Update Jellyfin to v 10.10.3
**Fixes**:
- The progress report now correctly gives a percentage in the range [0, 100].
## v0.2.2.0
- Update Jellyfin to v 10.10.2
## v0.2.1.0
- Make default program configuration a textarea in the settings page
- Add convinience definitions: `is-type`, `name-contains`
- Update YamlDotNet to v 16.2.0
**Fixes**:
- The default program was malformed, a closing bracket was at the wrong position
- The `haskeys` function could only be called on Objects
## v0.2.0.0
- Switch to yaml loading, old json files are still accepted
- Rework lisp interpreter to be more conventional
- Use arbitrary strings as ids for playlists
- Add configuration page with some default definitions for
the filter expressions.
**Breaking Changes**:
- The lisp interpreter will now only detect strings in double quotes (`"`).
- The interpreter will also not allow specifying lists without quoting them.
`(1 2 3)` ... used to work but will no longer, replace by either specifying
the list as `(list 1 2 3)` or `(quote (1 2 3))`.
## v0.1.1.0
- Initial Alpha release.

View file

@ -5,12 +5,12 @@
<RootNamespace>Jellyfin.Plugin.SmartPlaylist</RootNamespace> <RootNamespace>Jellyfin.Plugin.SmartPlaylist</RootNamespace>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<Version>0.5.1.0</Version> <Version>0.5.2.0</Version>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Jellyfin.Controller" Version="10.10.3" /> <PackageReference Include="Jellyfin.Controller" Version="10.10.5" />
<PackageReference Include="Jellyfin.Model" Version="10.10.3" /> <PackageReference Include="Jellyfin.Model" Version="10.10.5" />
<PackageReference Include="YamlDotNet" Version="16.2.1" /> <PackageReference Include="YamlDotNet" Version="16.2.1" />
</ItemGroup> </ItemGroup>

View file

@ -5,7 +5,7 @@ Smart playlists with Lisp filter engine.
This readme contains instructions for the most recent changes in This readme contains instructions for the most recent changes in
the development branch (`main`). To view the file appropriate the development branch (`main`). To view the file appropriate
for your version select the tag corresponding to your version. for your version select the tag corresponding to your version.
The latest version is [v0.5.1.0](https://gitea.redxef.at/redxef/jellyfin-smart-playlist/src/tag/v0.5.1.0). The latest version is [v0.5.2.0](https://gitea.redxef.at/redxef/jellyfin-smart-playlist/src/tag/v0.5.2.0).
![configuration page](config.png) ![configuration page](config.png)

View file

@ -267,6 +267,10 @@ namespace Tests
//Assert.Equal("", e.eval("(shuf (list 0 1 2 3 4 5 6))").ToString()); //Assert.Equal("", e.eval("(shuf (list 0 1 2 3 4 5 6))").ToString());
Assert.Equal("(1 2 3 4 5 6 7)", e.eval("(qsort (lambda (a b) (> a b)) '(5 4 7 3 2 6 1))").ToString()); Assert.Equal("(1 2 3 4 5 6 7)", e.eval("(qsort (lambda (a b) (> a b)) '(5 4 7 3 2 6 1))").ToString());
Assert.Equal("(1 2 3 4 5 6 7)", e.eval("(qsort > (list 5 4 7 3 2 6 1))").ToString()); Assert.Equal("(1 2 3 4 5 6 7)", e.eval("(qsort > (list 5 4 7 3 2 6 1))").ToString());
Assert.Equal("(0 1 2 4 5 5)", e.eval("(qsort > '(2 4 1 5 5 0))").ToString());
Assert.Equal("(5 5 4 2 1 0)", e.eval("(qsort < '(2 4 1 5 5 0))").ToString());
Assert.Equal("(5 5 4 2 1 0)", e.eval("(qsort <= '(2 4 1 5 5 0))").ToString());
Assert.Equal("(0 1 2 4 5 5)", e.eval("(qsort >= '(2 4 1 5 5 0))").ToString());
} }
} }
} }