Version 2 moods.
[paraslash.git] / web / manual.md
index c31e1d3..904ac18 100644 (file)
@@ -301,12 +301,6 @@ Requirements
 
 In any case you will need
 
-- [libosl](http://people.tuebingen.mpg.de/maan/osl/). The _object
-storage layer_ library is used by para_server. To clone the source
-code repository, execute
-
-               git clone git://git.tuebingen.mpg.de/osl
-
 - [lopsub](http://people.tuebingen.mpg.de/maan/lopsub/). The long
 option parser for subcommands generates the command line and config
 file parsers for all paraslash executables. Clone the source code
@@ -330,6 +324,12 @@ from templates by the m4 macro processor.
 
 Optional:
 
+- [libosl](http://people.tuebingen.mpg.de/maan/osl/). The _object
+storage layer_ library is used by para_server. To clone the source
+code repository, execute
+
+               git clone git://git.tuebingen.mpg.de/osl
+
 - [openssl](http://www.openssl.org/) or
 [libgcrypt](ftp://ftp.gnupg.org/gcrypt/libgcrypt/).  At least one
 of these two libraries is needed as the backend for cryptographic
@@ -338,6 +338,11 @@ libgcrypt are usually shipped with the distro, but you might have
 to install the development package (`libssl-dev` or `libgcrypt-dev`
 on debian systems) as well.
 
+- [flex](https://github.com/westes/flex) and
+[bison](https://www.gnu.org/software/bison) are needed to build the
+mood parser of para_server. The build system will skip para_server
+if these tools are not installed.
+
 - [libmad](http://www.underbit.com/products/mad/). To compile in MP3
 support for paraslash, the development package must be installed. It
 is called `libmad0-dev` on debian-based systems. Note that libmad is
@@ -976,124 +981,140 @@ the score table (but not from the playlist).
 
 <h3> Moods </h3>
 
-A mood consists of a unique name and its *mood definition*, which is
-a set of *mood lines* containing expressions in terms of attributes
-and other data contained in the database.
-
-At any time at most one mood can be *active* which means that
-para_server is going to select only files from that subset of
-admissible files.
-
-So in order to create a mood definition one has to write a set of
-mood lines. Mood lines come in three flavours: Accept lines, deny
-lines and score lines.
-
-The general syntax of the three types of mood lines is
-
-
-       accept [with score <score>] [if] [not] <mood_method> [options]
-       deny [with score <score>] [if] [not] <mood_method> [options]
-       score <score>  [if] [not] <mood_method> [options]
-
-
-Here <score> is either an integer or the string "random" which assigns
-a random score to all matching files. The score value changes the
-order in which admissible files are going to be selected, but is of
-minor importance for this introduction.
-
-So we concentrate on the first two forms, i.e. accept and deny
-lines. As usual, everything in square brackets is optional, i.e.
-accept/deny lines take the following form when ignoring scores:
-
-       accept [if] [not] <mood_method> [options]
-
-and analogously for the deny case. The "if" keyword is only syntactic
-sugar and has no function. The "not" keyword just inverts the result,
-so the essence of a mood line is the mood method part and the options
-following thereafter.
-
-A *mood method* is realized as a function which takes an audio file
-and computes a number from the data contained in the database.
-If this number is non-negative, we say the file *matches* the mood
-method. The file matches the full mood line if it either
-
-       - matches the mood method and the "not" keyword is not given,
-or
-       - does not match the mood method, but the "not" keyword is given.
-
-The set of admissible files for the whole mood is now defined as those
-files which match at least one accept mood line, but no deny mood line.
-More formally, an audio file F is admissible if and only if
-
-       (F ~ AL1 or F ~ AL2...) and not (F ~ DL1 or F ~ DN2 ...)
-
-where AL1, AL2... are the accept lines, DL1, DL2... are the deny
-lines and "~" means "matches".
-
-The cases where no mood lines of accept/deny type are defined need
-special treatment:
-
-       - Neither accept nor deny lines: This treats all files as
-       admissible (in fact, that is the definition of the dummy mood
-       which is activated automatically if no moods are available).
-
-       - Only accept lines: A file is admissible iff it matches at
-       least one accept line:
-
-               F ~ AL1 or F ~ AL2 or ...
-
-       - Only deny lines: A file is admissible iff it matches no
-       deny line:
-
-               not (F ~ DL1 or F ~ DN2 ...)
-
-
-
-<h3> List of mood_methods </h3>
-
-       no_attributes_set
-
-Takes no arguments and matches an audio file if and only if no
-attributes are set.
-
-       is_set <attribute_name>
-
-Takes the name of an attribute and matches iff that attribute is set.
-
-       path_matches <pattern>
-
-Takes a filename pattern and matches iff the path of the audio file
-matches the pattern.
-
-       artist_matches <pattern>
-       album_matches <pattern>
-       title_matches <pattern>
-       comment_matches <pattern>
-
-Takes an extended regular expression and matches iff the text of the
-corresponding tag of the audio file matches the pattern. If the tag
-is not set, the empty string is matched against the pattern.
-
-       year ~ <num>
-       bitrate ~ <num>
-       frequency ~ <num>
-       channels ~ <num>
-       num_played ~ <num>
-       image_id ~ <num>
-       lyrics_id ~ <num>
-
-Takes a comparator ~ of the set {<, =, <=, >, >=, !=} and a number
-<num>. Matches an audio file iff the condition <val> ~ <num> is
-satisfied where val is the corresponding value of the audio file
-(value of the year tag, bitrate in kbit/s, etc.).
-
-The year tag is special as its value is undefined if the audio file
-has no year tag or the content of the year tag is not a number. Such
-audio files never match. Another difference is the special treatment
-if the year tag is a two-digit number. In this case either 1900 or
-2000 is added to the tag value, depending on whether the number is
-greater than 2000 plus the current year.
-
+A mood consists of a unique name and a definition. The definition
+is an expression which describes which audio files are considered
+admissible. At any time at most one mood can be active, meaning
+that para_server will only stream files which are admissible for the
+active mood.
+
+The expression may refer to attributes and other metadata stored in
+the database. Expressions may be combined by means of logical and
+arithmetical operators in a natural way. Moreover, string matching
+based on regular expression or wildcard patterns is supported.
+
+The set of admissible files is determined by applying the expression
+to each audio file in turn. For a mood definition to be valid, its
+expression must evaluate to a number, a string or a boolean value
+("true" or "false"). For numbers, any value other than zero means the
+file is admissible. For strings, any non-empty string indicates an
+admissible file. For boolean values, true means admissible and false
+means not admissible.  As a special case, the empty expression treats
+all files as admissible.
+
+<h3> Mood grammar </h3>
+
+Expressions are based on a context-free grammar which distinguishes
+between several types for syntactic units or groupings. The grammar
+defines a set of keywords which have a type and a corresponding
+semantic value, as shown in the following table.
+
+Keyword              |    Type | Semantic value
+:--------------------|--------:|:----------------------------------
+`path`               |  string | Full path of the current audio file
+`artist`             |  string | Content of the artist meta tag
+`title`              |  string | Content of the title meta tag
+`album`              |  string | Content of the album meta tag
+`comment`            |  string | Content of the somment meta tag
+`num_attributes_set` | integer | Number of attributes which are set
+`year`               | integer | Content of the year meta tag [\*]
+`num_played`         | integer | How many times the file has been streamed
+`image_id`           | integer | The identifier of the (cover art) image
+`lyrics_id`          | integer | The identifier of the lyrics blob
+`bitrate`            | integer | The average bitrate
+`frequency`          | integer | The output sample rate
+`channels`           | integer | The number of channels
+`is_set("foo")`      | boolean | True if attribute "foo" is set.
+
+[\*] For most audio formats, the year tag is stored as a string. It
+is converted to an integer by the mood parser. If the audio file
+has no year tag or the content of the year tag is not a number, the
+semantic value is zero. A special convention applies if the year tag
+is a one-digit or a two-digit number. In this case 1900 is added to
+the tag value.
+
+Expressions may be grouped using parentheses, logical and
+arithmetical operators or string matching operators. The following
+table lists the available operators.
+
+Token  | Meaning
+:------|:-------
+`\|\|` | Logical Or
+`&&`   | Logical And
+`!`    | Logical Not
+`==`   | Equal (can be applied to all types)
+`!=`   | Not equal. Likewise
+`<`    | Less than
+`<=`   | Less or equal
+`>=`   | Greater or equal
+`+`    | Arithmetical minus
+`-`    | Binary/unary minus
+`*`    | Multiplication
+`/`    | Division
+`=~`   | Regular expression match
+`=\|`  | Filename match
+
+Besides integers, strings and booleans there is an additional type
+which describes regular expression or wildcard patterns. Patterns
+are not just strings because they also include a list of flags which
+modify matching behaviour.
+
+Regular expression patterns are of the form `/pattern/[flags]`. That
+is, the pattern is delimited by slashes, and is followed by zero or
+more characters, each specifying a flag according to the following
+table
+
+Flag |    POSIX name | Meaning
+:----|--------------:|--------
+`i`  |   `REG_ICASE` | Ignore case in match
+`n`  | `REG_NEWLINE` | Treat newline as an ordinary character
+
+Note that only extended regular expression patterns are supported. See
+regex(3) for details.
+
+Wildcard patterns are similar, but the pattern must be delimited by
+`'|'` characters rather than slashes. For wildcard patterns different
+flags exist, as shown below.
+
+Flag |             POSIX name | Meaning
+:----|-----------------------:|--------
+`n`  | `FNM_NOESCAPE`         | Treat backslash as an ordinary character
+`p`  | `FNM_PATHNAME`         | Match a slash only with a slash in pattern
+`P`  | `FNM_PERIOD`           | Leading period has to be matched exactly
+`l`  | `FNM_LEADING_DIR` [\*] | Ignore "/\*" rest after successful matching
+`i`  | `FNM_CASEFOLD` [\*]    | Ignore case in match
+`e`  | `FNM_EXTMATCH` [\*\*]  | Enable extended pattern matching
+
+[\*] Not in POSIX, but both FreeBSD and NetBSD have it.
+
+[\*\*] GNU extension, silently ignored on non GNU systems.
+
+See fnmatch(3) for details.
+
+Mood definitions may contain arbitrary whitespace and comments.
+A comment is a word beginning with #. This word and all remaining
+characters of the line are ignored.
+
+<h3> Example moods </h3>
+
+* Files with no/invalid year tag: `year == 0`
+
+* Only oldies: `year != 0 && year < 1980`
+
+* Only 80's Rock or Metal: `(year >= 1980 && year < 1990) &&
+  (is_set("rock") || is_set("metal"))`
+
+* Files with incomplete tags: `artist == "" || title == "" || album =
+"" || comment == "" || year == 0`
+
+* Files with no attributes defined so far: `num_attributes_set == 0`
+
+* Only newly added files: `num_played == 0`
+
+* Only poor quality files: `bitrate < 96`
+
+* Cope with different spellings of Motörhead: `artist =~ /mot(ö|oe{0,1})rhead/i`
+
+* The same with extended wildcard patterns: `artist =| |mot+(o\|oe\|ö)rhead|ie`
 
 <h3> Mood usage </h3>
 
@@ -1122,27 +1143,6 @@ if the "-a" switch is given:
 
        para ls -a
 
-
-<h3> Example mood definition </h3>
-
-Suppose you have defined attributes "punk" and "rock" and want to define
-a mood containing only Punk-Rock songs. That is, an audio file should be
-admissible if and only if both attributes are set. Since
-
-       punk and rock
-
-is obviously the same as
-
-       not (not punk or not rock)
-
-(de Morgan's rule), a mood definition that selects only Punk-Rock
-songs is
-
-       deny if not is_set punk
-       deny if not is_set rock
-
-
-
 File renames and content changes
 --------------------------------
 
@@ -1981,12 +1981,14 @@ welcome. Here's a list of things you can do to help the project:
 - Compile and test on your favorite architecture or operating
   system. The code is tested only on a limited set of systems, so you
   will probably encounter problems when building on different systems.
-- Post about about paraslash on your blog or on social networks.
+- Post about paraslash on your blog or on social networks.
 - Build and maintain Debian/RPM packages for your favorite distribution.
 
 Note that there is no mailing list, no bug tracker and no discussion
 forum for paraslash. If you'd like to contribute, or have questions
 about contributing, send email to Andre Noll <maan@tuebingen.mpg.de>.
+New releases are announced by email. If you would like to receive
+these announcements, contact the author through the above address.
 
 Tools
 -----