Skip to main content


Please note that most of the software linked on this forum is likely to be safe to use. If you are unsure, feel free to ask in the relevant topics, or send a private message to an administrator or moderator. To help curb the problems of false positives, or in the event that you do find actual malware, you can contribute through the article linked here.
Topic: Architectural thoughts about fb2k macro-scripting (Read 863 times) previous topic - next topic
0 Members and 1 Guest are viewing this topic.

Architectural thoughts about fb2k macro-scripting

Since at least 0.9 it is becoming apparent, that foobar2000 in general lacks macro-level frameworks. What i mean with this is that in many cases, we had (and now to some extend still have) lots of small parts, but no higher level relations between those parts. Individual components and features which act and store data invidually and seperately on their own, without relations between those.

One old example which in DUI has now been solved, was colors. Every component used and stored its own colors, making global colorschemes impossible, and changes of colorsettings a complicated hunt for colorsettings. New DUI fixed that by introducing global colors.

Another example which until now has only been addressed provisorily (though, for most tasks "good enough") is file operations. Until not long ago, converting, replaygaining, DSPing, moving and naming had only been loosely connected.

A more recent phenomenon is an explosion of individual "patterns". We have patterns for sorting, for grouping, for album list, for facets, for playlist display, for naming, for moving, and so on. All those patterns do something very similiar and could be reduced to at max two global kinds (formatting strings and prioritized criteria lists. A synthesis of both may also even be possible) - yet, they are nothing like that. They are right now individual, seperate and without implemented relations. Beneath the surface lurks another pattern-kind which is starting to get similiar redundant behaviour: Queries. While overly complex "strings" are now done away, we are again amassing complexity - this time by the sheer quantity of pattern/string-systems.

In this thread, i will address mostly the second aspect (file ops), though the third aspect (patterns) is strongly related to it, but will not be my focus. I will also not focus on proposing a GUI for doing it. My interest in this thread is restricted only to a basic architecture/system how macro-level taskscripting could work. The topic is the concept, not the implementation.

First lets address the hierachy of how such macro-level taskscripting could work:

1. Tasklist
2. Tasks inside the tasklist (this is just a labeled group of actions, nothing more)
3. Highlevel structure of the Task: Actions which the task performs.
4. Lowlevel detailed instructions (code, parameters) of an action

A few examples should visualize this better.

Task: "Convert to LAME v2"
Action: Converter preset
Detailed instructions: convert with lame via -V2

Task: "Tag files as lossy"
Action: Masstagger script
Detailed instructions: add field "encoding-type" with value "lossy"

Task: "Move files to lossy-folder"
Action: fileops move preset
Detailed instructions: move files to D:\music\lossy\%genre%\%album artist%\%album%\

Those are very simple examples with each task consisting of just one action and each action of just one instruction, but you get the idea.

Now, what is often overlooked when thinking about a topic like this, is the TARGET of such tasks. Users assume for granted, that the app just magically knows WHICH files it should operate on. This is because they do not take into account, that as the tasklist is processed, the files worked on may no longer be the files originally selected. At the point in the above example where the masstagger is tagging the converted files, it is supposed to tag the converted files - not the files originally selected for conversion!

Okay, easy you may think - each task just "sends" the results to the next task? Okay, but what if you do not want that? What if for example you want to build and save a tasklist which operates always on the same "kind" of files, so that you dont need to define the target each time yourself?

I propose that in a tasklist, each task has a "target"-parameter, which may be "result of previous task", "query" or "selected files".

For such a system to work, each relevant component would need to expose its "actions" as services to the tasklist-manager component.

edit: slight changes to the wording of the example
I am arrogant and I can afford it because I deliver.