| Newsgroups |
gmane.emacs.emms.user |
| Message-ID |
<[email protected]> |
Igor Sosa Mayor <[email protected]> writes:
Hello Igor.
I think there is a problem with that factory in that it doesn't
take an argument.
Factories take arguments and return functions that use them. Which
are in
fact the actual filters.
I think the best never played would be to use a really large
number.
Here is how to create filters in code.
I pasted the first two out of emms-filters, Added some examples
on how to write a never played filter. and then add some of
the more interesting filters from my Emacs config.
There is also emms-filters-make-filter if you just want to create
one.
As you create filters, remember they are composable later, So you
don't have to go crazy with them. Make building blocks.
Filter factories are used with their registered name. Filters are
also registerd when they are created, and have their human
readable
name.
A filter is: factory name, filter name, and factory arguments.
A Multi-filter uses the multi-filter factory which expects lists
of filter names arranged with and, or and not.
(emms-filters-make-filters
'(
("Played since" "Played in the last month" 30)
("Not played since" "Not played since a year" 365)
("Not played since" "Never" 7300) ;; 20 years.
("Played since" "Played since forever" 7300)
("Multi-filter"
"Not played in the last month"
((:not "Played in the last month")))
("Multi-filter"
"Never played"
((:not "Played since forever")))
;; Here are more examples
;; Notice that Year range takes two arguments.
("Year range" "1900-1929" 1900 1929)
("Year range" "1929-1937" 1929 1937)
("Year range" "1937-1942" 1937 1942)
("Year range" "1940-1946" 1940 1946)
("Year range" "1946-1958" 1946 1958)
("Year range" "1958-" 1958 3000)
("Directory" "tangotunes" "tangotunesflac")
("Genre" "Vals" "vals")
("Genre" "Tango" "tango")
("Genre" "Milonga" "milonga")
("Genre" "Condombe" "condombe")
("Genre" "Foxtrot" "foxtrot")
;; In tango, we often dance Milonga, Condombe and Foxtrot the same
way.
("Multi-filter"
"Milonga+"
(("Milonga" "Condombe")))
("Multi-filter"
"Milonga++"
(("Milonga+" "Foxtrot")))
("Album-artist" "OTV" "Orquesta Tipica Victor")
("Album-artist" "Carabelli" "Carabelli")
;; Carabelli was directing OTV and his own
;; orchestra at the same time. They sound very similar.
("Multi-filter"
"OTV+"
(("OTV" "Carabelli")))
("Multi-filter"
"1900-1937"
(("1900-1929" "1929-1937")))
("Multi-filter"
"1937-1946"
(("1937-1942" "1940-1946")))
("Multi-filter"
"Vals | milonga"
(("Vals" "Milonga")))
("Multi-filter"
"Vals 1900-1929"
(("Vals") ("1900-1929")))
("Multi-filter"
"Not vals"
((:not "Vals")))
("Multi-filter"
"Vals or milonga 1900-1937"
(("Vals" "Milonga")
("1900-1929" "1929-1937")))
))
I hope that helps. All of the default filters are defined it
emms-filters.el.
I have some in my config, but the most interesting ones are above.
I kept the default filters to a minimum, Everyone has their own
music, and
their own way of looking through it. Filters are so easy to make
and also
so personal.
I hope this helps.
Erica
> Hi Erica,
>
> thanks for your reply and for the interesting hydras (and emacs
> config).
>
> And now the last question if you have time: what do you
> recommend for
> filter all never-played tracks? For instance using "not played
> since"
> and a very high number for the days?
>
> Best,
>
> PS: there is a small error in this line:
>
> https://codeberg.org/ZeniesQis/Zenies-Emacs/src/commit/842b2690736f1d97e120524ff090aaa229e2fcfe/config/emms-conf.el#L95
>
> "mms-volume-change-amount" and not
> "emms-volume-change-amount"...
>
> On 11/29/25 00:55, Erica Qi wrote:
>> 1. I don't see any reason to get rid of them.
>> But they do primarily exist simply because that was what was
>> there
>> before. The filters factories that I created later on took into
>> consideration that they could be combined with logic and other
>> filters. Initially I made one for versions of all the filters
>> that the
>> browser had so I could preserve it's API.
>> 2. I did not build an autoload system for the filters that are
>> kept.
>> Their names are generated and rather verbose.
>> And just because you kept a filter doesn't mean you want to
>> load it
>> automatically next time. I didn't make assumptions about what
>> people
>> might want to do. I personally found that I rarely used kept
>> filters
>> directly.
>> What I do is I look through my kept filters and copy the ones I
>> want
>> into my config. I fix their names and sometimes modify them.
>> They are
>> good way to understand how filters work as well.
>> I don't really keep that many anymore. I can write them
>> directly
>> without much effort.
>> 3. Yes of course.
>> Https://codeberg.org/ZeniesQis/zis-hydras.git
>> I just pushed them as part of my emacs configuration cleanup. I
>> mostly
>> only use a couple of the EMMS ones.
>> Have fun!
>> Goodnight!
>> Erica (Zenie)
>> Sent from Proton Mail for Android.
>> -------- Original Message --------
>> On Friday, 11/28/25 at 22:40 Igor Sosa Mayor
>> <[email protected]> wrote:
>> Hi Erica,
>> thanks for your reply and your elaborate explanation.
>> I have at least three questions:
>> 1. when you say
>> > The filter system was just beginning to take shape and
>> > backward
>> compatible was a big concern.
>> > Now, there is no longer a good reason to have both.
>> what are you exactly proposing? Just to have the since-filter
>> and
>> remove
>> the not-filter?
>> 2. when you say
>> > Also the filters you build on the filter stack can be
>> > saved,
>> > and you can copy them into your config, give them a name
>> > and just
>> have them as choices in the system. They are human readable
>> data.
>> How does the save mechanism really work? If a) I make a filter,
>> b)
>> execute emms-filters-keep, the filter is saved to the file I
>> have
>> configured with emms-filters-multi-filter-save-file. But: If I
>> restart
>> emacs, this file is never read again (I do not see any code for
>> this in
>> emms-filters.el). How is this supposed to work?
>> Could you maybe give us an example?
>> 3. could you share your hydra please?
>> Many thanks in advance.
>> On 11/28/25 18:54, Erica Qi wrote:
>>> Hello everyone,
>>>
>>> I thought I should show the fix and explain a little bit about
>>> the filter system. These were two of the first filters I
>>> replaced from the old browser filters.
>>>
>>> I replaced them purely to be backwards compatible in the same
>>> choices. But really, the not filter is unnecessary.
>>> So much so that I forget to put the 'not'.
>>>
>>> A 'push-not' of the played-within filter does the same thing.
>>>
>>> So here is the fix, and a short explanation of using the
>>> Interactive filter stack.
>>>
>>> ---
>>>
>>> The fix is the 'not' in front of the (funcall ....
>>>
>>> Filters are simple tests which take an Emms track. They get
>>> the values they care about and test them how they want.
>>> And return true or false.
>>>
>>> To get a filter that is the not of another filter we can use
>>> the original filter and put a 'not' around it.
>>>
>>> (defun emms-filters-make-filter-not-played-within (days)
>>> "Make a not played since DAYS filter."
>>> (lambda (track)
>>> (not (funcall (emms-filters-make-filter-played-within
>>> days)
>>> track))))
>>>
>>> (emms-filters-register-filter-factory "Not played since"
>>> 'emms-filters-make-filter-not-played-within
>>> '(("Days: " (:number . nil))))
>>>
>>> Historically, the within and not-within were 2 of the first
>>> filters I created because the browser originally had them.
>>> The filter system was just beginning to take shape and
>>> backward compatible was a big concern.
>>> Now, there is no longer a good reason to have both.
>>>
>>> Another way to filter 'not within is with the interactive
>>> filter stack. Push a 'Not' filter of 'played-since' onto the
>>> filter stack with 'push-not'. That's a not played within
>>> filter.
>>> You can save it, and put the definition in your config.
>>> It's just data.
>>>
>>> The filter stack is the way to filter your tracks.
>>>
>>> Pushes can be 'regular', 'and', 'or' and 'not'.
>>>
>>> The filter stack is a stack of filter lists.
>>> Each list is a list of 'or' filters.
>>> Between the lists you can think of them as 'and'
>>>
>>> So think of an 'and list' of 'or's.
>>>
>>> A 'not' is a special way to start a new 'and' that indicates
>>> that it is 'not' this or this or this.
>>>
>>> There are actually 4 ways to push a filter onto the filter
>>> stack. There is the regular push, push-and, push-or,
>>> push-not.
>>>
>>> The 'regular' push starts a new list of lists. You can have
>>> more than one on the stack. That means you can be searching
>>> and decide to 'start over' with some quick search. When you
>>> are done with that you can 'pop' back down to where you were
>>> and resume where you left off.
>>>
>>> push-and adds a new list with a filter in it to whatever is
>>> going on. Push-and is the same as push if it's the first one.
>>>
>>> push-or adds a new filter to the current 'and' list.
>>> push-not starts a new 'and' list flagged as 'not'.
>>>
>>> Popping goes back to the previous way things were.
>>> Smashing will clear the stack to a new choice.
>>> Squashing reduces the stack to have only the top thing.
>>> Swap will swap the top thing with the one below it.
>>>
>>> You can also swap and pop, so swap the last thing with the
>>> thing before it and pop it off. If you swap-pop enough you
>>> have a squash.
>>>
>>> If you happen to make a 'new' filter as you go, that filter
>>> will show up in its factory's menu so you don't need to create
>>> it again until the next session.
>>>
>>> Also the filters you build on the filter stack can be saved,
>>> and you can copy them into your config, give them a name and
>>> just have them as choices in the system. They are human
>>> readable data.
>>>
>>> Don't forget you can also push and pop your results on the
>>> cache-stack. If you have a huge library this can speed things
>>> up quite a bit. The cache is the data, the filter is a 'view'
>>> of the data. You can push to the cache stack and keep going or
>>> smash your filter and continue like that.
>>>
>>> Caches can also be stashed for later in the session. Once
>>> stashed you can push them back on your cache stack whenever
>>> you want. They are like a snaposhot database of your results.
>>>
>>> I hope that all makes sense.
>>> I don't know why I didn't think to just say do a 'push-not'.
>>>
>>> Also, I do have a nice hydra that allows all this to be done
>>> interactively so you can see the two stacks change as you push
>>> and pop filters.
>>>
>>> I'm not sure transient is capable of the same thing. I haven't
>>> seen one that shows much in the way of formatted and changing
>>> data. I'm working on a filter-view-mode for it. But it's not
>>> ready yet. I'll post a link to my hydra.
>>>
>>> Have a nice day or evening. It's evening here.
>>>
>>> Erica
>>>
>>> Sent from Proton Mail for Android.
>>>
>>> -------- Original Message --------
>>> On Tuesday, 11/25/25 at 08:53 Igor Sosa Mayor
>>> <[email protected]> wrote:
>>> Hi emms-users,
>>>
>>> I have already a small problem. In this case with the filter
>>> factory
>>> defined as "Not played since". If I filter my tracks with
>>> "Played since"
>>> and "Not played since" 30 days, I get exactly the same
>>> results... Either
>>> it is a problem with the way my tracks are storing the time or
>>> a problem
>>> with the code.
>>>
>>> More precisely my question is: is this code working at
>>> expected?
>>>
>>> (defun emms-filters-make-filter-not-played-within (days)
>>> "Make a not played since DAYS filter."
>>> (lambda (track)
>>> (funcall (emms-filters-make-filter-played-within days)
>>> track)))
>>>
>>> Thanks in advance!
>>>
>>> Best,
>>>
>>>
>>>
>>