Difference between revisions of "Expression Language"
(→RemoveCharacters(...) addition completed.) |
m (→Delimit(...): Outputs a value with head/tail strings when value is non-empty) |
||
(39 intermediate revisions by 2 users not shown) | |||
Line 8: | Line 8: | ||
As you progress with your expression building, you will begin nesting multiple functions into a single expression; always remember that a completed expression must contain a matching number of opening and closing parenthesis in order to work reliably. | As you progress with your expression building, you will begin nesting multiple functions into a single expression; always remember that a completed expression must contain a matching number of opening and closing parenthesis in order to work reliably. | ||
− | The functions available to us range from highly functional, with a broad range of applicable uses, through specialised, limited use functions that only appeal to a select group of users, to seemingly redundant functions and obscure functions that | + | The functions available to us range from highly functional, with a broad range of applicable uses, through specialised, limited use functions that only appeal to a select group of users, to seemingly redundant functions and obscure functions that Media Center uses internally. The functions below are listed with those with the broadest appeal at the top, and the more obscure at the bottom. |
<ins>'''Any given expression can only work on any given single file. It is not possible to compare a field in one file with a field in another file.'''</ins><br> | <ins>'''Any given expression can only work on any given single file. It is not possible to compare a field in one file with a field in another file.'''</ins><br> | ||
Batch file operations are possible, and when used in a list, even a grouped list, an expression will be applied to each individual file in turn, not as a group. | Batch file operations are possible, and when used in a list, even a grouped list, an expression will be applied to each individual file in turn, not as a group. | ||
− | A slightly extended overview is also available elsewhere in this wiki, titled [http://wiki.jriver.com/index.php/Database_Expressions Database Expressions], and another page attempts to demonstrate | + | A slightly extended overview is also available elsewhere in this wiki, titled [http://wiki.jriver.com/index.php/Database_Expressions Database Expressions], and another page attempts to demonstrate Media Center mimicking the [http://wiki.jriver.com/index.php/Database_Expressions_AND_OR_And_XOR "AND", "OR" and "XOR"] database searches. |
<div style="text-align:right;">([[#top|Back to top)]]</div> | <div style="text-align:right;">([[#top|Back to top)]]</div> | ||
− | == | + | ==Using expressions== |
− | + | Expressions are ubiquitous in Media Center, and are useful in a variety of locations such as the following: | |
− | * | + | * Player Display (right-click the Player Display , choose "Customize") |
− | * | + | * Captions & Thumbnail text |
− | * | + | * Panes (''aka Categories'') |
+ | * Expression columns (right-click a column header and choose "Add expression column") | ||
+ | * The library field manager (''Create expression-based library fields'') | ||
+ | * Theater View | ||
+ | * Link manager (''Use expressions to format link URLs'') | ||
+ | * Rename, Move, & Copy Files tool | ||
− | The | + | The syntax of the expression language is generally consistent throughout Media Center. An expression is evaluated, [[#Formatting output|formatting output]] that is used in the context where the expression was evaluated. To perform [[#Tag assignment|Tag assignment]] or [[#Search rule filtering|Search rule filtering]], an expression is modified slightly to work in these contexts. |
<div style="text-align:right;">([[#top|Back to top)]]</div> | <div style="text-align:right;">([[#top|Back to top)]]</div> | ||
− | === | + | |
− | Expressions can be used to | + | ===Formatting output=== |
− | + | To give usage examples for all of these locations is beyond the scope of this page, so a few tips should suffice to get those interested up and running. | |
− | + | ||
+ | * Using expressions to produce custom Thumbnail text makes it possible to display only relevant or useful data. | ||
+ | * Expressions can be used to reduce link bar clutter by conditionally displaying links based on, for example, Media Type. | ||
+ | * File and directory paths may be based on expressions; this is especially useful in Options > File Locations, and in the "Rename, Move, & Copy Files" tool. | ||
+ | * User-specified library fields may be calculated, based on the output of expressions. | ||
+ | <div style="text-align:right;">([[#top|Back to top)]]</div> | ||
+ | |||
+ | ===Tag assignment=== | ||
+ | The output of an expression can be used to assign a value to a tag. This is accomplished by preceding the expression with an "=" character. The "=" character causes the tagging engine to invoke the expression evaluator first, and then to use its output as the value to assign to the tag. Without the prepended "=" character, the expression itself (and not its evaluated value) would be stored in the tag. | ||
+ | |||
+ | An assignment expression can be entered into the Tag Action Window, or by using inline editing in the file list or a pane entry. | ||
+ | |||
+ | Note: Undo is supported, reverting each tag to its value prior to the assignment. Redo is also supported, reapplying the most recent Undo. | ||
+ | |||
+ | The following screenshots illustrates using an expression for tag assignment:<br> | ||
{| align=center | {| align=center | ||
|- | |- | ||
Line 36: | Line 55: | ||
[[image:Inline2.png|frame|Just like that!]] | [[image:Inline2.png|frame|Just like that!]] | ||
|} | |} | ||
+ | <div style="text-align:right;">([[#top|Back to top)]]</div> | ||
− | + | ===Search rule filtering=== | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | = | ||
Expressions can be used as search filters, and in order to do so, the expression must be entered into the search field using the following format:<br> | Expressions can be used as search filters, and in order to do so, the expression must be entered into the search field using the following format:<br> | ||
'''[=EXPRESSION]=1''' or '''[=EXPRESSION]=0''' | '''[=EXPRESSION]=1''' or '''[=EXPRESSION]=0''' | ||
Line 53: | Line 63: | ||
All files that match the expression will return "1" and all that don't match, return "0". Decide which is required and use "1" or "0" accordingly. | All files that match the expression will return "1" and all that don't match, return "0". Decide which is required and use "1" or "0" accordingly. | ||
− | Remember that the search field appears in many places throughout | + | Remember that the search field appears in many places throughout Media Center, places that include: |
* The search field itself (in the top right corner of the program) | * The search field itself (in the top right corner of the program) | ||
* A view scheme search list | * A view scheme search list | ||
Line 66: | Line 76: | ||
Which will list all files that have been imported this month. | Which will list all files that have been imported this month. | ||
<div style="text-align:right;">([[#top|Back to top)]]</div> | <div style="text-align:right;">([[#top|Back to top)]]</div> | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
==Specify data types for expression based fields== | ==Specify data types for expression based fields== | ||
− | + | It is often useful to force Media Center to operate on data of one type as if it were another type. This is useful for changing sort order, or handling list data as a simple string. For example, month names are sorted alphabetically by default, but by setting the data type, sorting can be chronological instead. Data types are forced by appending to an expression the string: '''&datatype=[<span style="color:blue">''DATA TYPE''</span>]''', where <span style="color:blue">''DATA TYPE''</span> is one of the following values: | |
* '''List''': ''A list of strings, separated by semicolons'' | * '''List''': ''A list of strings, separated by semicolons'' | ||
* '''String''': ''Sorts as strings (with smart number handling)'' | * '''String''': ''Sorts as strings (with smart number handling)'' | ||
* '''Number''': ''Sorts values as numbers (decimal or integer)'' | * '''Number''': ''Sorts values as numbers (decimal or integer)'' | ||
+ | * '''Integer''': ''Sorts values as integers'' | ||
* '''Path''': ''Sorts using a smart filename compare style'' | * '''Path''': ''Sorts using a smart filename compare style'' | ||
* '''Month''': ''Sorts string month names (i.e. January, February, etc.)'' | * '''Month''': ''Sorts string month names (i.e. January, February, etc.)'' | ||
Line 114: | Line 106: | ||
|} | |} | ||
<div style="text-align:right;">([[#top|Back to top)]]</div> | <div style="text-align:right;">([[#top|Back to top)]]</div> | ||
+ | |||
==Fields== | ==Fields== | ||
Line 123: | Line 116: | ||
==Functions== | ==Functions== | ||
− | ===If(...): | + | ===Conditional Functions=== |
+ | The functions in this section evaluate one or more of their arguments to determine if their result is true or false, and execute specific actions depending upon that result. | ||
+ | |||
+ | Although the expression language does not directly support AND, OR, and XOR, these can be easily emulated. See: [[Database_Expressions_AND_OR_And_XOR]]. | ||
+ | |||
+ | Beginning with version 17.0.40, Media Center supports the NOT operator (a '''!''' character) in a conditional. This can be used to invert the sense of an '''If()''' statement for easier reading, or in an '''IfElse()''' to better support if-then-else chains. | ||
+ | |||
+ | ====If(...): Conditional If/Then/Else evaluator.==== | ||
{| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3" | {| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3" | ||
Line 134: | Line 134: | ||
|- valign="top" | |- valign="top" | ||
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples | ! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples | ||
− | |style="background: #ecfeea; color: black; border: 1px solid black" | '''if(isequal([artist],bob dylan,1),Genius,Mediocre)'''<br>''Wherever this expression is applied, be it as an expression column or category, as part of a renaming rule, thumbnail text, if the artist tag is Bob Dylan, | + | |style="background: #ecfeea; color: black; border: 1px solid black" | '''if(isequal([artist],bob dylan,1),Genius,Mediocre)'''<br>''Wherever this expression is applied, be it as an expression column or category, as part of a renaming rule, thumbnail text, if the artist tag is Bob Dylan, Media Center will produce Genius, and for all other artists, it will produce Mediocre.'' The "IsEqual()" function is described in the first table below. |
<br> | <br> | ||
'''if(isequal([artist],bob dylan,1),Genius,if(isequal([album],Joshua Tree,8),Great Album,Mediocre))''' | '''if(isequal([artist],bob dylan,1),Genius,if(isequal([album],Joshua Tree,8),Great Album,Mediocre))''' | ||
<br>''Here, we have two nested "If" functions. First we ask if the artist is Bob Dylan, if the result is positive, write "Genius". If the artist is not Dylan, we then ask if the album is "Joshua Tree", if yes, write "Great Album", and if no, write mediocre'' | <br>''Here, we have two nested "If" functions. First we ask if the artist is Bob Dylan, if the result is positive, write "Genius". If the artist is not Dylan, we then ask if the album is "Joshua Tree", if yes, write "Great Album", and if no, write mediocre'' | ||
− | <br> | + | <br> |
+ | '''if(!isempty([comment]), Regex([comment], /#^(\S+\s+\S+\s+\S+)#/, 1), *No Comment)''' | ||
+ | <br />''Output's the first three words of the comment field; otherwise, outputs "*No Comment". By inverting the sense of the conditional, the more interesting case is moved ahead of the more mundane case. | ||
+ | |||
+ | <br>Take care to provide all three arguments to the If() statement, and for nested statements, to ensure the proper number of closing parenthesis. This can become less-than-obvious with nested sequences. The built-in expression editor can lessen the burden by allowing line breaks or whitespace after commas (argument separators). For example, the previous example is easier to read and maintain as: | ||
+ | |||
+ | : if(!isempty([comment]), | ||
+ | :: Regex([comment], /#^(\S+\s+\S+\s+\S+)#/, 1), | ||
+ | :: *No Comment)''' | ||
+ | |||
+ | |} | ||
+ | <div style="text-align:right;">([[#top|Back to top)]]</div> | ||
+ | |||
+ | ====IfElse(...): If/Then/Else sequence of conditional tests and actions.==== | ||
+ | |||
+ | {| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3" | ||
+ | |- valign="top" | ||
+ | ! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" width=100 | IfElse() | ||
+ | | style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | The IfElse() conditional (available since build 17.0.7) provides a convenient mechanism for shortening and more clearly expressing nested conditionals into an alternating sequence of tests and actions. For example, consider a nested sequence of If() tests such as If(test1, action1, If(test2, action2, If(test3, action3))), shown below in a sequence of if/then/else pseudo-code statements: | ||
+ | |||
+ | : if (test1) | ||
+ | :: action1 | ||
+ | : else if (test2) | ||
+ | :: action2 | ||
+ | : else if (test3) | ||
+ | :: action3 | ||
+ | |||
+ | The IfElse() statement may be used to more cleanly express the flow of expression by removing the superfluous internal If() statements: | ||
+ | |||
+ | '''IfElse(test1, action1, test2, action2, test3, action3)''' | ||
+ | |||
+ | |- valign="top" | ||
+ | ! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction | ||
+ | | style="background: #ecfeea; color: black; border: 1px solid black" | '''ifelse(''test expression 1'',instructions 1,''test expression 2'',instructions 2, ...)''' | ||
+ | |- valign="top" | ||
+ | ! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples | ||
+ | |style="background: #ecfeea; color: black; border: 1px solid black" | '''ifelse(isequal([media type], Audio), Le Tunes, isequal([media type], Video]), Flix)''' | ||
+ | |||
+ | ''If media type is audio, outputs "Le Tunes", else if media type is video, outputs "Flix"'' | ||
+ | <br> | ||
+ | |||
+ | |||
+ | '''ifelse(isequal([artist], Bob Dylan), Genius, isequal([album], Joshua Tree, 8), Great Album, 1, Mediocre)''' | ||
+ | |||
+ | ''This example, implements the nested if statements from the If() section above, first testing if the artist is Bob Dylan, and if true, outputs "Genius", otherwise evaluates the second test to determine if the album is "Joshua Tree", and if true, outputs "Great Album", otherwise, performs a final test, in this case a degenerate test of 1 (and 1 is always true), thus outputting the value "Mediocre".'' | ||
|} | |} | ||
<div style="text-align:right;">([[#top|Back to top)]]</div> | <div style="text-align:right;">([[#top|Back to top)]]</div> | ||
− | ===Query, Test and | + | ===Query, Test and Comparison Functions=== |
All of the functions in this section, when used on their own, will only ever return one of two values, 1 (true) or 0 (false). There is a "[[#FormatBoolean(...): Formats a boolean (true / false) value in a specified manner|FormatBoolean()]]" function that can be wrapped around these and allows us to specify the output for each case and is discussed in more depth in the Format section. The real power and versatility of these "Is" functions is released when they are wrapped inside the If() function discussed above. | All of the functions in this section, when used on their own, will only ever return one of two values, 1 (true) or 0 (false). There is a "[[#FormatBoolean(...): Formats a boolean (true / false) value in a specified manner|FormatBoolean()]]" function that can be wrapped around these and allows us to specify the output for each case and is discussed in more depth in the Format section. The real power and versatility of these "Is" functions is released when they are wrapped inside the If() function discussed above. | ||
+ | |||
+ | ====Compare(...): Compares two numbers==== | ||
+ | {| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3" | ||
+ | |- valign="top" | ||
+ | ! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | Compare() | ||
+ | | style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | Compares two numbers, using the operators less than (<), greater than (>), or equal to (=). Outputs 1 if the comparison is true, and 0 otherwise. Available starting with MC17. | ||
+ | |- valign="top" | ||
+ | ! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction | ||
+ | | style="background: #ecfeea; color: black; border: 1px solid black" | '''compare(''1st number'', ''operator'', ''2nd number'')''' | ||
+ | |||
+ | ''Available Operators:'' | ||
+ | * =: ''numeric equivalence'' | ||
+ | * <: ''numeric less than'' | ||
+ | * <=: ''numeric less than or equal to'' | ||
+ | * >: ''numeric greater than'' | ||
+ | * >=: ''numeric greater than or equal to'' | ||
+ | |||
+ | |- valign="top" | ||
+ | ! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples | ||
+ | |style="background: #ecfeea; color: black; border: 1px solid black" | '''compare([bitrate], <, 320)'''<br>''If the 'bitrate' is less than 320 (Kbps), the output will be 1, otherwise, the output will be 0.'' | ||
+ | |||
+ | <br>'''If(Compare(Math(Now() - [Date Modified, 0]), >, 21), Expired, FormatDate([Date Modified, 0], Elapsed))''' | ||
+ | |||
+ | ''Shows the age of files under 21 days old, or shows 'Expired' for older files.'' | ||
+ | |} | ||
+ | <div style="text-align:right;">([[#top|Back to top)]]</div> | ||
====IsEqual(...): Compares two values in one of nine specified modes==== | ====IsEqual(...): Compares two values in one of nine specified modes==== | ||
Line 186: | Line 256: | ||
|- valign="top" | |- valign="top" | ||
! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | IsEmpty() | ! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | IsEmpty() | ||
− | | style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | Tests any given field for data. If the field is empty, the function returns 1, and if populated, the function returns 0. There are two different test modes available, a "string" test, and a "number" test. This is because as far as | + | | style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | Tests any given field for data. If the field is empty, the function returns 1, and if populated, the function returns 0. There are two different test modes available, a "string" test, and a "number" test. This is because as far as Media Center is concerned, fields designated as containing numerical values that are populated with the number zero, are empty. If no test mode is specified, the function will default to 0. |
Pay particular attention to the third example offered below, as it covers a caveat that comes with this particular function. | Pay particular attention to the third example offered below, as it covers a caveat that comes with this particular function. | ||
|- valign="top" | |- valign="top" | ||
Line 202: | Line 272: | ||
<br>'''if(isempty([disc #]),,[disc #])''' | <br>'''if(isempty([disc #]),,[disc #])''' | ||
− | <br>''Here, by not entering any instructions to carry out for a positive result, the expression will do just that, and output nothing, but if the [disc #] field does contain data, the expression will write that out. Upon first look, you would think that this could work really well in the "Rename, Move | + | <br>''Here, by not entering any instructions to carry out for a positive result, the expression will do just that, and output nothing, but if the [disc #] field does contain data, the expression will write that out. Upon first look, you would think that this could work really well in the "Rename, Move, & Copy Files" tool for only creating a \Disc #\ directory if needed. This will not work. When asking the rename tool to create directories from field data, it is smart enough to know that directories with no name are illegal in Windows, so when it encounters an empty field, it automatically converts it to "Unknown [Field Name]". It does this before the expression engine gets to see it, which means that the IsEmpty function will always return a negative result when used in the rename tool, even when the specified field is indeed empty. As we now know that empty fields are passed through the rename tool as "Unknown [field name]" we can use '''if([[#IsEqual(...): Compares two values in one of nine specified modes|isequal]]([disc #],unknown,8),,[disc #])''' to achieve the desired result. Note that this only applies when using the rename files tool.'' |
|} | |} | ||
<div style="text-align:right;">([[#top|Back to top)]]</div> | <div style="text-align:right;">([[#top|Back to top)]]</div> | ||
Line 225: | Line 295: | ||
<br>''This expression will output "Poor Quality" for any file where the bitrate falls between 96 and 191, and "High Quality" for all others. Note that expressions are only as good as the instructions given, and that the above expression would label files with bitrates less than 96kbps as "High Quality". If this expression were used to add a category to a view, there would be two selectable choices in the category, Low Quality, and High Quality. Selecting either one would then filter the file list accordingly.'' | <br>''This expression will output "Poor Quality" for any file where the bitrate falls between 96 and 191, and "High Quality" for all others. Note that expressions are only as good as the instructions given, and that the above expression would label files with bitrates less than 96kbps as "High Quality". If this expression were used to add a category to a view, there would be two selectable choices in the category, Low Quality, and High Quality. Selecting either one would then filter the file list accordingly.'' | ||
− | <br>'''[http://yabb.jriver.com/interact/index.php?topic=38566.msg262229#msg262229 This post]''' ''on Interact shows the use of IsRange in a Search List. (right click the link, open in new tab to keep this page open). The expression format in that post shows how to form expressions for use in standard | + | <br>'''[http://yabb.jriver.com/interact/index.php?topic=38566.msg262229#msg262229 This post]''' ''on Interact shows the use of IsRange in a Search List. (right click the link, open in new tab to keep this page open). The expression format in that post shows how to form expressions for use in standard Media Center searches, something that was covered earlier'' [[#When, Where and How to use expressions|on this page.]] |
|} | |} | ||
<div style="text-align:right;">([[#top|Back to top)]]</div> | <div style="text-align:right;">([[#top|Back to top)]]</div> | ||
Line 232: | Line 302: | ||
|- valign="top" | |- valign="top" | ||
! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | IsMissing() | ! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | IsMissing() | ||
− | | style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | This function | + | | style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | This function tests the existence of a file in the file system. If the file is missing, the function returns 1 (positive), and if the file is found, the function returns 0 (negative). This function is useful for checking the integrity of your Media Center library as you can use it to produce a list of any files in your library that Media Center cannot find. Beginning with version 17, IsMissing() treats special entries such as ripped Blu-ray or DVDs as single files, even though they physically exist in the file system as several files and directories. |
+ | |||
+ | '''Note''': IsMissing() works directly on the file system and will cause performance to suffer: the larger the library, the longer it will take to produce results. | ||
|- valign="top" | |- valign="top" | ||
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction | ! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction | ||
| style="background: #ecfeea; color: black; border: 1px solid black" | '''IsMissing(Full Path To File)''' | | style="background: #ecfeea; color: black; border: 1px solid black" | '''IsMissing(Full Path To File)''' | ||
− | '' | + | ''Checks for existence of the file "Full Path To File", or the current file if unspecified.'' |
|- valign="top" | |- valign="top" | ||
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples | ! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples | ||
Line 245: | Line 317: | ||
<br>'''[=ismissing([filename])]=1''' | <br>'''[=ismissing([filename])]=1''' | ||
− | <br>''This example also demonstrates how to construct an expression for use as a | + | <br>''This example also demonstrates how to construct an expression for use as a Media Center search string. If you place this in the search field in the top right corner of the program while viewing all of your library, it will filter the list, leaving only the missing files on view. If your library is in good order, this list should be empty. You could also create a view scheme and use this string in the "Set rules for file display" search to give you a view that you can visit periodically to check that your library is intact |
<br>'''if(ismissing(),File is missing,File exists)''' | <br>'''if(ismissing(),File is missing,File exists)''' | ||
Line 251: | Line 323: | ||
|} | |} | ||
<div style="text-align:right;">([[#top|Back to top)]]</div> | <div style="text-align:right;">([[#top|Back to top)]]</div> | ||
+ | |||
====IsRemovable(...): Tests to see if a file is stored on removable media==== | ====IsRemovable(...): Tests to see if a file is stored on removable media==== | ||
{| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3" | {| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3" | ||
|- valign="top" | |- valign="top" | ||
! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | IsRemovable() | ! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | IsRemovable() | ||
− | | style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | Checks to see if a file resides on removable media and if so, returns 1 (positive), and if not, returns 0 (negative). There is not a lot to say about this function, especially since | + | | style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | Checks to see if a file resides on removable media and if so, returns 1 (positive), and if not, returns 0 (negative). There is not a lot to say about this function, especially since Media Center comes equipped with a [Removable] field by default that is automatically populated with 1 for all files in the library that are on removable storage. The function works in exactly the same way as the IsMissing function described above, returning 1 (positive) if the file is on removable storage, and 0 (negative) if not. |
|- valign="top" | |- valign="top" | ||
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction | ! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction | ||
Line 289: | Line 362: | ||
<div style="text-align:right;">([[#top|Back to top)]]</div> | <div style="text-align:right;">([[#top|Back to top)]]</div> | ||
<br><br> | <br><br> | ||
− | === | + | |
− | All of these functions (with the exception of FormatBoolean) take raw data from the library and allow us to present that data in a way that we choose. What does "raw data" mean? | + | ===Formatting Functions=== |
− | ==== | + | All of these functions (with the exception of FormatBoolean) take raw data from the library and allow us to present that data in a way that we choose. What does "raw data" mean? Media Center stores duration information in seconds and converts that information into hours (if needed), minutes and seconds for display in the Duration column in a file list. Likewise, file size information is stored in bytes and is converted into Mb for display in the file list. So there you have it, raw data. The following section gives some idea of what is possible using the raw data and the Format functions. '''''To instruct the expression evaluator to use raw data, a zero is added to the library field, inside the square brackets, like so: [Date Imported,0]''''' |
+ | |||
+ | ====Delimit(...): Outputs a value with head/tail strings when value is non-empty==== | ||
{| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3" | {| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3" | ||
|- valign="top" | |- valign="top" | ||
− | ! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | | + | ! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | Delimit() |
− | | style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | | + | | style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | '''Delimit()''' outputs a value if the value is non-empty, including head and/or tail strings. Nothing is output when the value is empty. |
|- valign="top" | |- valign="top" | ||
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction | ! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction | ||
− | | style="background: #ecfeea; color: black; border: 1px solid black" | ''' | + | | style="background: #ecfeea; color: black; border: 1px solid black" | '''Delimit(Value,Tail string,Head string)''' |
− | '' | + | * "Value" ''The value to be output if it is not empty.'' |
+ | * "Tail string" ''Optional, defaults to space. The string to append at the end of a non-empty Value.'' | ||
+ | * "Head string" ''Optional, defaults to empty. The string to append to the beginning of a non-empty Value.'' | ||
+ | |- valign="top" | ||
+ | ! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples | ||
+ | |style="background: #ecfeea; color: black; border: 1px solid black" | '''delimit([Track #], .)'''<br> | ||
+ | ''Appends a period (.) after a track number if [Track #] is not empty, e.g. "12.".'' | ||
+ | |||
+ | <br /> | ||
+ | '''delimit([Date (year)], {, })'''<br /> | ||
+ | |||
+ | Outputs the year surrounded by curly braces, e.g. "{2012}". | ||
+ | |} | ||
+ | <div style="text-align:right;">([[#top|Back to top)]]</div> | ||
+ | |||
+ | ====FormatBoolean(...): Formats a boolean (true / false) value in a specified manner==== | ||
+ | {| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3" | ||
+ | |- valign="top" | ||
+ | ! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | FormatBoolean() | ||
+ | | style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | This function is wrapped around another function and will return specified strings for true and false values returned by that other function. | ||
+ | |- valign="top" | ||
+ | ! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction | ||
+ | | style="background: #ecfeea; color: black; border: 1px solid black" | '''FormatBoolean(True/False Test,String to use if true,String to use if false)''' | ||
+ | * '''True/False Test''' ''Other functions perform their respective tests and return 1 to indicate a true result, and 0 to indicate a false result'' | ||
+ | * '''String to use if true,String to use if false''' ''If these are not specified, the function will default to using "True" and "False"'' | ||
− | + | |- valign="top" | |
− | + | ! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples | |
− | + | |style="background: #ecfeea; color: black; border: 1px solid black" | '''formatboolean(isempty([number plays]),Never Played,Has Been Played)'''<br>''On it's own, the function'' isempty([number plays]) ''will return either 1 or 0. When wrapped inside a'' formatboolean ''function as shown here, the output for a true result will be "Never Played", and for a false result, the output will be "Has Been Played". | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | '' | + | <br>'''formatboolean(isempty([number plays]))'''<br>''Here, there are no strings specified for the true/false results, therefore the function will default to using "True" and "False"'' |
+ | |} | ||
+ | <div style="text-align:right;">([[#top|Back to top)]]</div> | ||
− | + | ====FormatDuration(...): Presents a duration of seconds in a reader friendly format==== | |
− | + | {| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3" | |
− | + | |- valign="top" | |
− | + | ! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | FormatDuration() | |
− | + | | style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | Media Center stores duration data in seconds, at up to sixteen decimal places. The value shown in the default "Duration" column in a file list is an internally formatted interpretation of this raw "Duration" data. As Media Center automatically applies this formatting for us, there is not a lot of call for this particular function. | |
− | + | |- valign="top" | |
− | + | ! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction | |
− | + | | style="background: #ecfeea; color: black; border: 1px solid black" | '''FormatDuration(Value to format)''' | |
− | + | ''"Value to format" can be either the raw duration data, or a given number of seconds'' | |
|- valign="top" | |- valign="top" | ||
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples | ! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples | ||
− | |style="background: #ecfeea; color: black; border: 1px solid black" | ''' | + | |style="background: #ecfeea; color: black; border: 1px solid black" | '''formatduration([duration,0])'''<br>''This expression will duplicate the contents of the default [duration] field as shown in a file list'' |
− | <br>''' | + | <br>'''formatduration(600)''' |
− | <br>''This will | + | <br>''This will output ten minutes in the format 10:00'' |
+ | |} | ||
+ | <div style="text-align:right;">([[#top|Back to top)]]</div> | ||
− | + | ====FormatFileSize(...): Presents a number of bytes in a reader friendly format==== | |
− | <br>'' | + | {| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3" |
+ | |- valign="top" | ||
+ | ! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | FormatFilesize() | ||
+ | | style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | Media Center stores file size data internally in bytes. This function will convert those byte values into reader-friendly values, 3.2 Kb or 10.4 Mb, for example. The function will also accept a byte value directly. | ||
+ | |- valign="top" | ||
+ | ! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction | ||
+ | | style="background: #ecfeea; color: black; border: 1px solid black" | '''FormatFileSize(Value to format)''' | ||
+ | |||
+ | ''"Value to format" can be either the raw [File Size] data or a given number of bytes. | ||
+ | |- valign="top" | ||
+ | ! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples | ||
+ | |style="background: #ecfeea; color: black; border: 1px solid black" | '''formatfilesize([file size,0])'''<br>''This expression will duplicate the contents of the default [file size] field as shown in a file list'' | ||
+ | |||
+ | <br>'''formatfilesize(56123456)''' | ||
+ | <br>''This expression will convert 56,123,456 bytes and the output will be 53.5 MB'' | ||
|} | |} | ||
<div style="text-align:right;">([[#top|Back to top)]]</div> | <div style="text-align:right;">([[#top|Back to top)]]</div> | ||
+ | |||
====FormatNumber(...): Formats a number to a specified number of decimal places==== | ====FormatNumber(...): Formats a number to a specified number of decimal places==== | ||
{| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3" | {| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3" | ||
Line 372: | Line 484: | ||
|} | |} | ||
<div style="text-align:right;">([[#top|Back to top)]]</div> | <div style="text-align:right;">([[#top|Back to top)]]</div> | ||
− | ==== | + | |
+ | ====FormatRange(...): Formats a value as a range==== | ||
{| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3" | {| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3" | ||
|- valign="top" | |- valign="top" | ||
− | ! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | | + | ! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | FormatRange() |
− | | style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | This function | + | | style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | This function places any given value into its place in any given range. |
|- valign="top" | |- valign="top" | ||
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction | ! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction | ||
− | | style="background: #ecfeea; color: black; border: 1px solid black" | ''' | + | | style="background: #ecfeea; color: black; border: 1px solid black" | '''FormatRange(Value to format,Range size,Mode)''' |
+ | '''Value to format:''' ''This could be a specific word or number, or any library field'' | ||
+ | <br>'''Range Size:''' ''A numerical value dependent on how you wish to set up your range. If not specified, this will default to 1'' | ||
+ | <br>'''Mode:''' ''There are three possible modes, detailed below. If not specified, this will default to zero.'' | ||
+ | * '''0:''' ''Automatically choose between number / letter grouping'' | ||
+ | * '''1:''' ''Specifies that letter grouping should be used'' | ||
+ | * '''2:''' ''Specifies that number grouping should be used'' | ||
|- valign="top" | |- valign="top" | ||
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples | ! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples | ||
− | |style="background: #ecfeea; color: black; border: 1px solid black" | ''' | + | |style="background: #ecfeea; color: black; border: 1px solid black" | '''formatrange([artist])'''<br>''This will return the first letter from the [artist] field. Note that as '''range size''' and '''mode''' values were not specified, the function defaulted to one and automatic respectively.'' |
+ | |||
+ | <br>'''formatrange([artist],3,1)'''<br>''This will take the first letter from the artist field and place it in the appropriate letter range. In this case, a range size of three has been specified, therefore the output will be in the form of "a-c", "d-f", "g-i" etc. etc.'' | ||
+ | |||
+ | <br>'''formatrange([bitrate],100,2)'''<br>''This will take the bitrate and place it in the appropriate number range. In this case a range of 100 has been specified, therefore the output will be in the form of "0-99", "100-199", "200-299" etc. etc.'' | ||
− | + | Note that this function always starts number ranges from zero, 0-9, 10-19, etc, etc.. If you really need a number grouping that starts from 1, 1-10, 11-20, 21-30,etc. etc., you can use expressions to create a pseudo range. Full details, with a helpful explanation, of "1 based grouping" can be found [[CD_Reference_Number|on this page]]. | |
− | |||
|} | |} | ||
<div style="text-align:right;">([[#top|Back to top)]]</div> | <div style="text-align:right;">([[#top|Back to top)]]</div> | ||
− | ==== | + | |
+ | ====Orientation(...): Outputs the orientation of an image==== | ||
{| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3" | {| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3" | ||
|- valign="top" | |- valign="top" | ||
− | ! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | | + | ! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | Orientation() |
− | | style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | | + | | style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | Outputs a word indicating the orientation of an image file. |
|- valign="top" | |- valign="top" | ||
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction | ! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction | ||
− | | style="background: #ecfeea; color: black; border: 1px solid black" | ''' | + | | style="background: #ecfeea; color: black; border: 1px solid black" | '''Orientation()''' |
− | '' | + | * '''Portrait''': ''Output when an image's height is greater than its width.'' |
+ | * '''Landscape''': ''Output when an image's width is greater than its height.'' | ||
+ | * '''Portrait''': ''Output when an image's height is equal to its width.'' | ||
|- valign="top" | |- valign="top" | ||
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples | ! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples | ||
− | |style="background: #ecfeea; color: black; border: 1px solid black" | ''' | + | |style="background: #ecfeea; color: black; border: 1px solid black" | '''if(isequal(orientation(), Square), Square, Rectangle)''' |
− | + | Outputs "Square" for square images or "Rectangle" for portrait and landscape images.'' | |
− | |||
− | |||
|} | |} | ||
<div style="text-align:right;">([[#top|Back to top)]]</div> | <div style="text-align:right;">([[#top|Back to top)]]</div> | ||
− | ==== | + | |
+ | ====PadNumber(...): Adds leading zeros to any given number==== | ||
{| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3" | {| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3" | ||
|- valign="top" | |- valign="top" | ||
− | ! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | | + | ! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | PadNumber() |
− | | style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | | + | | style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | This function is not a 'Format' function by name, but is by nature, hence its inclusion in this section. PadNumber is a nice, simple function that is used to add leading zeros to any given number value. |
|- valign="top" | |- valign="top" | ||
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction | ! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction | ||
− | | style="background: #ecfeea; color: black; border: 1px solid black" | ''' | + | | style="background: #ecfeea; color: black; border: 1px solid black" | '''PadNumber(Field to pad,Total number of digits required)''' |
− | |||
− | |||
|- valign="top" | |- valign="top" | ||
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples | ! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples | ||
− | |style="background: #ecfeea; color: black; border: 1px solid black" | ''' | + | |style="background: #ecfeea; color: black; border: 1px solid black" | '''padnumber([track #],2)'''<br>''This will add a leading zero to all track numbers between one and nine.'' |
− | <br>''' | + | <br>'''padnumber([[#Counter(...): Counts upwards in specified increments|counter()]],4)''' |
− | <br>'' | + | <br>''here, the output from the counter() function will be 'padded' to 4 characters: 0001, 0002, 0003, etc. etc.'' |
|} | |} | ||
<div style="text-align:right;">([[#top|Back to top)]]</div> | <div style="text-align:right;">([[#top|Back to top)]]</div> | ||
− | ==== | + | |
+ | ====RatingStars(...): Outputs Rating as star characters==== | ||
{| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3" | {| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3" | ||
|- valign="top" | |- valign="top" | ||
− | ! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | | + | ! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | RatingStars() |
− | | style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | This function | + | | style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | This function outputs the Rating field's value as the equivalent number of black star characters. |
|- valign="top" | |- valign="top" | ||
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction | ! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction | ||
− | | style="background: #ecfeea; color: black; border: 1px solid black" | ''' | + | | style="background: #ecfeea; color: black; border: 1px solid black" | '''RatingStars()''' |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
|- valign="top" | |- valign="top" | ||
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples | ! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples | ||
− | |style="background: #ecfeea; color: black; border: 1px solid black" | ''' | + | |style="background: #ecfeea; color: black; border: 1px solid black" | '''ratingstars()'''<br>''For a file that has a Rating of 4, outputs "★★★★".'' |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
|} | |} | ||
<div style="text-align:right;">([[#top|Back to top)]]</div> | <div style="text-align:right;">([[#top|Back to top)]]</div> | ||
− | ==== | + | ====Watched(...): Outputs a formatted bookmark position within a video==== |
{| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3" | {| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3" | ||
|- valign="top" | |- valign="top" | ||
− | ! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | | + | ! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | Watched() |
− | | style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | | + | | style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | Outputs a video's bookmark position in a human-readable format. |
|- valign="top" | |- valign="top" | ||
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction | ! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction | ||
− | | style="background: #ecfeea; color: black; border: 1px solid black" | ''' | + | | style="background: #ecfeea; color: black; border: 1px solid black" | '''Watched()''' |
− | |||
− | |||
+ | * '''0''': ''Output a human-readable watched status.'' | ||
+ | * '''1''': ''Output a numeric watched value, 0 if not watched, 1 if partially watched, 2 if entirely watched.'' | ||
+ | * '''2''': ''Output a watched checkmark (√) if watched'' | ||
|- valign="top" | |- valign="top" | ||
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples | ! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples | ||
− | |style="background: #ecfeea; color: black; border: 1px solid black" | ''' | + | |style="background: #ecfeea; color: black; border: 1px solid black" | '''Watched()''' |
− | + | Outputs formatted watched status, such as, ''57% on Sep 25'', or ''Aug 21'', or nothing when the video has not been watched.'' | |
− | |||
|} | |} | ||
<div style="text-align:right;">([[#top|Back to top)]]</div> | <div style="text-align:right;">([[#top|Back to top)]]</div> | ||
<br><br> | <br><br> | ||
− | === | + | |
+ | ===String Manipulation=== | ||
The primary use of the functions in this section is to manipulate the data associated with any given file or files. When used with direct editing in the file list, or in the action window, as decribed [[#When, Where and How to use expressions|here]], they offer extremely fast and efficient methods for batch editing the actual tag data associated with multiple files.<br>Note that when used indirectly, in expression based columns, categories or library fields, the referred fields are not altered in any way, the data is merely presented in the expression field formatted as requested. | The primary use of the functions in this section is to manipulate the data associated with any given file or files. When used with direct editing in the file list, or in the action window, as decribed [[#When, Where and How to use expressions|here]], they offer extremely fast and efficient methods for batch editing the actual tag data associated with multiple files.<br>Note that when used indirectly, in expression based columns, categories or library fields, the referred fields are not altered in any way, the data is merely presented in the expression field formatted as requested. | ||
====Clean(...): Returns a cleaned up version of a filled in template==== | ====Clean(...): Returns a cleaned up version of a filled in template==== | ||
Line 475: | Line 587: | ||
|- valign="top" | |- valign="top" | ||
! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | Clean() | ! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | Clean() | ||
− | | style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | The | + | | style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | The Clean() function is used to generally strip empty bracketing, superfluous dash characters, leading or trailing articles, or replace filesystem-illegal characters. It is typically employed to clean the joining of several fields, some of which may be empty, or to produce filesystem-safe filenames. |
|- valign="top" | |- valign="top" | ||
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction | ! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction | ||
− | | style="background: #ecfeea; color: black; border: 1px solid black" | '''Clean( | + | | style="background: #ecfeea; color: black; border: 1px solid black" | '''Clean(Value to clean, Mode)''' |
− | '' | + | ''Value to clean'': a string that will be cleaned |
''Mode'' (optional, defaults to 0): | ''Mode'' (optional, defaults to 0): | ||
− | * 0: clean | + | * 0: default clean, removes empty () and [], superfluous dash (-) characters and sometimes comma (be careful) |
− | * 1: | + | * 1: removes the article 'the' from the beginning and ', the' from the end |
− | * 2: | + | * 2: removes any article (a, an, the, etc.) from the beginning and end |
− | * 3: | + | * 3: replaces each filesystem-illegal character --- '''\ / : * ? " < > |''' --- with an underscore (_) |
|- valign="top" | |- valign="top" | ||
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples | ! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples | ||
− | |style="background: #ecfeea; color: black; border: 1px solid black" | '''Clean([ | + | |style="background: #ecfeea; color: black; border: 1px solid black" | '''Clean([Album] - [Date])''' |
− | + | Consider the simple expression ''[Album] - [Date]''. When the [Date] value is empty, the result will contain the undesirable dangling separator string " - " following the album name (e.g. "Greatest Hits - "). Using Clean() in the default mode removes this dangling string, and in this example produces "Greatest Hits". | |
− | + | <br />'''Clean(The Beatles, 1)'''<br /> | |
+ | For sorting or grouping purposes, it is often desirable to remove the leading article "The" from a string. Clean() in mode 1 provides a convenient solution, and in this example produces "Beatles". | ||
+ | |||
+ | <br />'''Clean(AC//DC: Back In Black, 3)<br /> | ||
+ | When an expression is to be used to produce a filename, filesystem-illegal characters must be removed or converted to legal characters. Clean() in mode 3 will convert such characters into safe underscores. This example yields the filesystem-safe "AC_DC_ Back In Black". Note: the double forward slash is required above to produce a single double forward slash, since forward slash is the Media Center expression language escape character. | ||
+ | |||
+ | <br />'''Clean(\//:*?"<>|, 3)'''<br /> | ||
+ | This trivial example demonstrates how all filesystem-illegal characters are converted to underscores, producing the nine-character string consisting entirely of underscores "_________". | ||
|} | |} | ||
<div style="text-align:right;">([[#top|Back to top)]]</div> | <div style="text-align:right;">([[#top|Back to top)]]</div> | ||
Line 522: | Line 641: | ||
|} | |} | ||
<div style="text-align:right;">([[#top|Back to top)]]</div> | <div style="text-align:right;">([[#top|Back to top)]]</div> | ||
− | ==== | + | |
+ | ====FixSpacing(...): Intelligently splits adjacent camel-cased words==== | ||
{| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3" | {| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3" | ||
|- valign="top" | |- valign="top" | ||
− | ! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | | + | ! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | FixSpacing() |
− | | style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | This function | + | | style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | This FixSpacing() function inserts spaces between adjacent camel-cased words. For example, ''OneWorld'' becomes ''One World''. This function is useful for helping to clean and convert metadata that favors compactness over standard sentence structure. |
|- valign="top" | |- valign="top" | ||
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction | ! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction | ||
− | | style="background: #ecfeea; color: black; border: 1px solid black" | ''' | + | | style="background: #ecfeea; color: black; border: 1px solid black" | '''FixSpacing(''String to convert'', ''Mode'')'''<br>''The "String to convert" is any string of text.'' |
+ | |||
+ | The available modes are: | ||
+ | * '''0:''' ''Disables conversion'' | ||
+ | * '''1:''' ''Enables camel-case conversion'' | ||
+ | |||
|- valign="top" | |- valign="top" | ||
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples | ! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples | ||
− | |style="background: #ecfeea; color: black; border: 1px solid black" | ''' | + | |style="background: #ecfeea; color: black; border: 1px solid black" | '''fixspacing([name], 1)'''<br>Takes the contents of the [name] field and expands any camel-case into standard sentence structure. E.g. MiracleOn34thStreet becomes Miracle On 34th Street. |
− | <br>''' | + | <br>'''fixspacing(Another [name], 1)'''<br>Assuming the same [name] as above, this would return "Another Miracle On 34th Street". |
|} | |} | ||
<div style="text-align:right;">([[#top|Back to top)]]</div> | <div style="text-align:right;">([[#top|Back to top)]]</div> | ||
− | ==== | + | |
+ | ====Hexify(...): Hexifies a string to make it suitable for website usage==== | ||
{| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3" | {| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3" | ||
|- valign="top" | |- valign="top" | ||
− | ! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | | + | ! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | Hexify() |
− | | style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | | + | | style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | ''The only place this function is likely to be used is in the "Link Manager". Websites often don't like spaces in their addresses, and punctuation could confuse a site's search engine. Hexify attempts to take care of this by replacing spaces and punctuation with web friendly alternatives. For example, Bob Dylan would become Bob%20Dylan.'' |
|- valign="top" | |- valign="top" | ||
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction | ! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction | ||
− | | style="background: #ecfeea; color: black; border: 1px solid black" | ''' | + | | style="background: #ecfeea; color: black; border: 1px solid black" | '''Hexify(Value to hexify)''' |
|- valign="top" | |- valign="top" | ||
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples | ! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples | ||
− | |style="background: #ecfeea; color: black; border: 1px solid black" | ''' | + | |style="background: #ecfeea; color: black; border: 1px solid black" | '''hexify([artist] - [album])'''<br>Oasis - (What's The Story) Morning Glory? becomes: ''Oasis%20-%20%28What%27s%20The%20Story%29%20Morning%20Glory%3F'' |
|} | |} | ||
<div style="text-align:right;">([[#top|Back to top)]]</div> | <div style="text-align:right;">([[#top|Back to top)]]</div> | ||
− | ==== | + | |
+ | ====Left(...): Retrieves a specified number of characters from the left of a value==== | ||
{| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3" | {| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3" | ||
|- valign="top" | |- valign="top" | ||
− | ! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | | + | ! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | Left() |
− | | style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | This function retrieves a specified number of characters from the | + | | style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | This function retrieves a specified number of characters from the left of any given value. |
|- valign="top" | |- valign="top" | ||
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction | ! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction | ||
− | | style="background: #ecfeea; color: black; border: 1px solid black" | ''' | + | | style="background: #ecfeea; color: black; border: 1px solid black" | '''Left(Value to get characters from,Number of characters to get)'''<br>''"Value to get characters from" can be plain text, a library field, or combination of both. If more characters than exist are requested, all available characters are returned.'' |
|- valign="top" | |- valign="top" | ||
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples | ! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples | ||
− | |style="background: #ecfeea; color: black; border: 1px solid black" | ''' | + | |style="background: #ecfeea; color: black; border: 1px solid black" | '''left([filename],3)'''<br>''This will return the drive letter, colon and first back-slash from the filename. If asked to show more characters than actually exist, the expression will return the entire value, also, remember that spaces count as characters too.'' |
|} | |} | ||
<div style="text-align:right;">([[#top|Back to top)]]</div> | <div style="text-align:right;">([[#top|Back to top)]]</div> | ||
− | ==== | + | ====Length(...): Returns the number of characters in a string==== |
{| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3" | {| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3" | ||
|- valign="top" | |- valign="top" | ||
− | ! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | | + | ! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | Length() |
− | | style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | | + | | style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | This function returns the number of characters in any given string. |
|- valign="top" | |- valign="top" | ||
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction | ! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction | ||
− | | style="background: #ecfeea; color: black; border: 1px solid black" | ''' | + | | style="background: #ecfeea; color: black; border: 1px solid black" | '''Length(String to count characters from)'''<br>''The ''"String to count characters from"'' can be plain text, a library field, or a combination of the two.'' |
|- valign="top" | |- valign="top" | ||
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples | ! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples | ||
− | |style="background: #ecfeea; color: black; border: 1px solid black" | ''' | + | |style="background: #ecfeea; color: black; border: 1px solid black" | '''length([filename])'''<br>''This will count the characters in the [filename] field and return the result. Spaces count as characters, so, C:\My File.mp3 would return 14. |
− | + | ||
− | < | + | <br>'''if(isequal(length([filename]),68,6),68 Characters or more,Less than 68 Characters)'''<br>''Here, Length() has been combined with another two functions, "If()" and "IsEqual()". The expression compares the length of the filename against the number 68. If there are 68 or more characters in the filename, the expression will return "68 Characters or more", otherwise, it will return "Less than 68 Characters". If you are working with a device with filename length limitations, these functions can be used to create extremely useful expressions that could help with your device management.'' |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
|} | |} | ||
<div style="text-align:right;">([[#top|Back to top)]]</div> | <div style="text-align:right;">([[#top|Back to top)]]</div> | ||
Line 610: | Line 726: | ||
|} | |} | ||
<div style="text-align:right;">([[#top|Back to top)]]</div> | <div style="text-align:right;">([[#top|Back to top)]]</div> | ||
− | ==== | + | |
+ | ====Regex(...): Regular expression pattern matching and capture==== | ||
{| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3" | {| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3" | ||
|- valign="top" | |- valign="top" | ||
− | ! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | | + | ! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | Regex() |
− | | style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | | + | | style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | This function performs regular expression (RE) pattern matching on its input. It can be used in one of three different modes: a test mode to test for a match, a capture output mode to output the specified captured pattern, and a silent, capture-only mode. All match captures are placed into special variables referenced as [R1], [R2], ... [R9], which can be used in subsequent expressions. The contents of the captures [R1] ... [R9] are available until the entire expression completes, or Regex() is run again, whereby they are replaced. The regular expression implementation used is the [http://msdn.microsoft.com/en-us/library/bb982727.aspx Microsoft 2010 TR1 engine]. (Available since build 16.0.155.) |
|- valign="top" | |- valign="top" | ||
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction | ! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction | ||
− | | style="background: #ecfeea; color: black; border: 1px solid black" | ''' | + | | style="background: #ecfeea; color: black; border: 1px solid black" | '''Regex(String to test, Regular expression, Mode, Case sensitivity)''' |
− | * ''' | + | |
− | * '''String to | + | * '''String to test''': ''One or more library fields, plain text, or a combination of both, which is used as the string evaluated for a match.'' |
− | * ''' | + | * '''Regular expression''': ''This is the regular expression pattern used to perform matches and captures on the '''String to test'''.<br />The regular expression language assigns special meaning to many characters. A few of these meta-characters, such as forward slash "/", comma "," and parenthesis "(" and ")", are also used by the Media Center expression language. To force the Media Center expression engine to ignore the meta-characters in regular expressions, surround the entire regular expression with '''/#''' and '''#/'''. This is Media Center's form of escapement, which tells the expression engine to ignore everything inside, so that the entire, uninterpreted regular expression can be provided to the Regex() regular expression evaluator. Although '''/#''' and '''#/''' is not necessary when no conflicting characters are in use, and you may manually escape such characters with a forward slash "/", it is best practice to always encase a regular expression in '''/#''' and '''#/'''.'' |
+ | * '''Mode''': ''Sets the mode in which Regex() will run. Optional, defaults to 0.'' | ||
+ | ** '''0''': ''Runs in test mode, returning 1 or 0, indicating whether the string matched (1) or did not match (0) the pattern. This mode is useful within an '''if()''' test, so that different true (1) or false (0) actions may be taken. Output will be a 0 or 1. This mode is the default.'' | ||
+ | ** '''1''' to '''9''': ''Outputs the specified N<sup>th</sup> capture group's contents, where N ranges from 1 to 9. Currently, only a single capture is output in this mode, but all captures are available in the [R1] ... [R9] capture variables. This mode is used to easily output a single matching sub-string.'' | ||
+ | ** '''-1''': ''Runs in silent mode, with no output. This mode is useful as a means to capture portions of the string, and later use those captures in subsequent portions of an expression.'' | ||
+ | * '''Case sensitivity''': ''Toggles the case-sensitivity of regular expressions. Optional, defaults to 0, ignoring case. To use this option, a value or comma-placeholder must also be set for the'' '''Mode''' ''option.''<br />'''Note:''' Case insensitivity does not apply to characters inside a character class [ ]. Use both uppercase and lowercase characters when necessary to match either case (e.g. [aAbB] to match either uppercase or lowercase A or B). | ||
+ | ** 0: ''Ignore case when matching (e.g. the letters '''E''' and '''e''' are identical). This is the default.'' | ||
+ | ** 1: ''Consider case when matching (e.g. the letters '''E''' and '''e''' are considered different).'' | ||
+ | |||
|- valign="top" | |- valign="top" | ||
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples | ! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples | ||
− | |style="background: #ecfeea; color: black; border: 1px solid black" | ''' | + | |style="background: #ecfeea; color: black; border: 1px solid black" | '''Example: Modes 1 through 9''' |
+ | |||
+ | The examples in this section use one of the modes from 1 through 9, to output the specified capture. | ||
+ | |||
+ | '''<span style="font-family: Consolas, monospace;"><nowiki> | ||
+ | Regex([Name], /#(Big.*Man)#/, 1) | ||
+ | </nowiki></span>''' | ||
+ | |||
+ | ''Matches track names that contain'' '''Big''' ''followed by'' '''Man''''', with anything (including nothing) in between, and outputs the matched tracks.'' | ||
+ | Sample output: | ||
+ | :Big Butter and Egg Man | ||
+ | :Big Man | ||
+ | :Big Manager | ||
+ | :It's a Bigman Thing | ||
+ | |||
+ | ‾‾‾‾ | ||
+ | |||
+ | '''<span style="font-family: Consolas, monospace;"><nowiki> | ||
+ | Regex([Artist], /#([(].+)$#/, 1) | ||
+ | </nowiki></span>''' | ||
+ | |||
+ | ''Matches against the Artist field and returns items that contain an opening (left) parenthesis followed by additional characters until the end of the artist string. Only the sub-string from any opening parenthesis until the end of the string will be returned, since this is the only captured portion.'' | ||
+ | |||
+ | Sample output: | ||
+ | :(Brian Eno/U2) | ||
+ | :(feat. DJ Cam) | ||
+ | :(Otis Day & The Knights) | ||
+ | :(w/Emmylou Harris) | ||
+ | |||
+ | ‾‾‾‾ | ||
+ | |||
+ | '''<span style="font-family: Consolas, monospace;"><nowiki> | ||
+ | Regex([Name], /#([(][^)]+)$#/, 1) | ||
+ | </nowiki></span>''' | ||
+ | |||
+ | ''Similar to the previous example, but matches track names that contain a opening (left) parenthesis, but are missing the closing (right) parentheses through the end of the track name. This might be useful to help detect tagging inconsistencies'' | ||
+ | |||
+ | Sample output: | ||
+ | :(feat. David Bowie | ||
+ | |||
+ | ---- | ||
+ | '''Examples: Mode 0''' | ||
+ | |||
+ | The examples in this section use mode 0, to test if a string does or does not match the pattern. The result of the test may be used to drive a conditional statement such as an if() statement. | ||
+ | |||
+ | '''<span style="font-family: Consolas, monospace;"><nowiki> | ||
+ | if(Regex([Artist],/#([[:punct:]])#/, 0),[R1] --> [Artist], No Punctuation) | ||
+ | </nowiki></span>''' | ||
+ | |||
+ | ''Matches against the Artist field looking for any punctuation character. The results of the Regex() expression will be a 0 (false) or 1 (true) since the mode is set to 0, The true side of the if() test is set to output the first (and only) capture, which is expressed as [R1], and is followed by the string " --> " and then the artist name. In the false case, the string "No Punctuation" is output.'' | ||
+ | |||
+ | Sample output: | ||
+ | : " --> Clarence "Frogman" Henry | ||
+ | : & --> Al Cohn & Zoot Sims | ||
+ | : . --> Dr. John | ||
+ | : / --> Bootsy Collins/Fatboy Slim | ||
+ | |||
+ | ‾‾‾‾ | ||
+ | |||
+ | '''<div style="font-family: Consolas, monospace;"><nowiki> | ||
+ | if(Regex([Artist], /#([[:punct:]])#/, 0), | ||
+ | </nowiki><br /> | ||
+ | : '''<nowiki> Contains Punctuation\replace(replace([R1], ;,Semicolon), \, Backslash), | ||
+ | </nowiki><br /> | ||
+ | : '''<nowiki> No Punctuation)\replace(replace([Artist], ;, / and/ ), \, //)&DataType=[list] | ||
+ | </nowiki></div>''' | ||
+ | |||
+ | ''A more complex example, similar to the previous one. When used inside an expression column, builds an expandable tree with headings Contains Punctuation and No Punctuation that group artists based on whether or not their names contain any punctuation characters. Because semicolon and backslash are list separator characters for the expression language, for the example expression to work properly, these must be replaced (otherwise the list will not build as desired). In the list of punctuation, both backslash and semicolon characters have been replaced with their English equivalent words. In artist names, a semicolon is often used as a separator between the main artist and featured artists, so the expression replaces semicolons within an artist name with the word "and". Likewise, backslashes have been replaced with forward slashes.'' | ||
+ | |||
+ | Sample output: | ||
+ | : ↓ Contains Punctuation | ||
+ | :: ↓ $ | ||
+ | ::: Payola$ | ||
+ | :: ↓ * | ||
+ | ::: D*Note | ||
+ | :: → + | ||
+ | :: → : | ||
+ | :: → Backslash | ||
+ | :: ↓ Semicolon | ||
+ | ::: Lita Ford and Ozzy Osbourne | ||
+ | ::: Seal and Jeff Beck | ||
+ | : → No Punctuation | ||
+ | |||
+ | ‾‾‾‾ | ||
+ | |||
+ | '''<span style="font-family: Consolas, monospace;"><nowiki> | ||
+ | if(Regex([Album], /#^([^-]+[^\s])- (.*)$#/, 0), [R1]: [R2], / No Change Necessary) | ||
+ | </nowiki></span>''' | ||
+ | |||
+ | ''Some album names contain characters that are not legal in Windows, and after pulling properties from the file name, such characters will be translated into a dash "-" character (e.g. "Staring at the Sea: The Singles" becomes "Staring at the Sea- The Singles"). If you'd like to identify such possibly re-named album, an expression such the one above might help. The expression matches characters from the beginning of the line that do not contain a dash, followed by a non-space character, followed by a dash, space and everything else. Wrapped in an if() statement, these file names become apparent in an expression column. | ||
+ | |||
+ | ---- | ||
+ | '''Examples: Mode -1''' | ||
+ | |||
+ | The examples in this section use mode -1, which cause Regex() to suppress output. This mode is only useful with captures, where the captures are utilized in subsequent portions of an expression. | ||
+ | |||
+ | The previous example (which helped to identify album titles that may have been changed after tags were updated from file properties) used mode 0 to guide an if() evaluation. By using that expression column and selecting only the files whose album name should be changed, the identical Regex() statement can be used to easily fix the album property by changing the mode from 0 to -1: | ||
+ | |||
+ | '''<span style="font-family: Consolas, monospace;"><nowiki> | ||
+ | =Regex([Album], /#^([^-]+[^\s])- (.*)$#/, -1)[R1]: [R2] | ||
+ | </nowiki></span>''' | ||
+ | |||
+ | ''Editing the Album tag and pasting the expression above into the edit field will set the munged album name to use a colon rather than dash. Note: take care to select the correct files, and ensure the tags were changed as desired. Use Undo if not.'' | ||
+ | |||
+ | ''A safety mechanism can be installed into the tag assignment. By using the same Regex() statement from the last mode 0 example, and setting the false side of the if() statement to [Album], the expression would effectively only change those files whose album names matched the pattern. Non-matched album names would be assigned to themselves, essentially acting as a no-op. For completeness, that statement would be:'' | ||
+ | |||
+ | '''<span style="font-family: Consolas, monospace;"><nowiki> | ||
+ | =if(Regex([Album], /#^([^-]+[^\s])- (.*)$#/, 0), [R1]: [R2], [Album]) | ||
+ | </nowiki></span>''' | ||
+ | |||
+ | ‾‾‾‾<br /> | ||
+ | '''<span style="font-family: Consolas, monospace;"><nowiki> | ||
+ | Regex([Name], /#(\d{1,2})\.(\d{1,2}).(\d{4})#/, -1)[R3]//[R1]//[R2] | ||
+ | </nowiki></span>''' | ||
+ | |||
+ | ''Matches and captures a date formatted as dd.mm.yyyy anywhere within a filename, and rearranges it in a standard format of yyyy/mm/dd. Since '''Mode''' is set to -1, no output occurs. However, captured match segments are made available for subsequent use. The three captures, [R1], [R2] and [R3] are arranged in the textual output such that the year, month and day ordering are as desired. | ||
+ | |||
+ | Sample output: | ||
+ | : 2011/08/19 | ||
+ | : 2009/01/22 | ||
+ | |||
+ | ‾‾‾‾ | ||
+ | |||
+ | '''<span style="font-family: Consolas, monospace;"><nowiki> | ||
+ | Regex([Name], /#^(.+?) \(([^(]+)\)$#/, -1)[R2]: [R1] | ||
+ | </nowiki></span>''' | ||
− | + | ''This example shows how rearranging segments of track titles can help call out naming inconsistencies. The expression captures parenthetical information at the end of a track, and moves it to the beginning. In an expression column, inconsistencies become clearer.'' | |
− | + | Sample output: | |
− | + | : Ext. Version: Blinded by the Light | |
− | + | : Extended Version: Peter Gunn | |
− | + | : extended version: the saftey dance | |
− | + | : feat. Crystal Lake: You Might Need Somebody | |
− | + | : Feat. Billy Godfrey: Look Around | |
− | + | : feat Amel Larrieux: Gaze | |
− | |||
− | |||
− | |||
− | |||
− | + | ‾‾‾‾ | |
− | |||
− | |||
− | |||
− | |||
− | + | '''<span style="font-family: Consolas, monospace;"><nowiki> | |
+ | listbuild(1, \, Regex([Name], /#^(.+?) \(([^(]+)\)$#/, -1)[R2],[R1])&datatype=[list] | ||
+ | </nowiki></span>''' | ||
− | + | ''Wrapping the previous expression in a listbuild() to create an expandable list provides quick grouping for even easier spotting of naming irregularities, especially when combined with Search to reduce the list size.'' | |
|} | |} | ||
<div style="text-align:right;">([[#top|Back to top)]]</div> | <div style="text-align:right;">([[#top|Back to top)]]</div> | ||
Line 678: | Line 922: | ||
'''RemoveCharacters([artist],/(/),)'''<br>This will remove any opening or closing brackets from anywhere within the [artist] field. Note how the brackets are 'escaped' as discussed in the [[#Overview|'Overview']] section earlier. | '''RemoveCharacters([artist],/(/),)'''<br>This will remove any opening or closing brackets from anywhere within the [artist] field. Note how the brackets are 'escaped' as discussed in the [[#Overview|'Overview']] section earlier. | ||
+ | |} | ||
+ | <div style="text-align:right;">([[#top|Back to top)]]</div> | ||
+ | ====RemoveLeft(...): Trims characters from the start of a value==== | ||
+ | {| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3" | ||
+ | |- valign="top" | ||
+ | ! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | RemoveLeft() | ||
+ | | style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | The output from this function will remove a specified number of characters from the start of any given value. | ||
+ | |- valign="top" | ||
+ | ! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction | ||
+ | | style="background: #ecfeea; color: black; border: 1px solid black" | '''RemoveLeft(Value to remove characters from,Number of characters to remove)''' | ||
+ | |- valign="top" | ||
+ | ! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples | ||
+ | |style="background: #ecfeea; color: black; border: 1px solid black" | '''removeleft([name],5)'''<br>''This would show the name field, with the first five characters removed. If asked to remove more characters than actually exist, the output will be blank, also, remember that spaces count as characters too.''. | ||
+ | |} | ||
+ | <div style="text-align:right;">([[#top|Back to top)]]</div> | ||
+ | ====RemoveRight(...): Trims characters from the end of a value==== | ||
+ | {| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3" | ||
+ | |- valign="top" | ||
+ | ! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | RemoveRight() | ||
+ | | style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | The output from this function will remove a specified number of characters from the end of any given value. | ||
+ | |- valign="top" | ||
+ | ! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction | ||
+ | | style="background: #ecfeea; color: black; border: 1px solid black" | '''RemoveRight(Value to remove characters from,Number of characters to remove)''' | ||
+ | |- valign="top" | ||
+ | ! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples | ||
+ | |style="background: #ecfeea; color: black; border: 1px solid black" | '''removeright([name],5)'''<br>''This would show the name field, with the last five characters removed. If asked to remove more characters than actually exist, the output will be blank, also, remember that spaces count as characters too.''. | ||
+ | |} | ||
+ | <div style="text-align:right;">([[#top|Back to top)]]</div> | ||
+ | ====Replace(...): Replace or remove strings from a value.==== | ||
+ | {| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3" | ||
+ | |- valign="top" | ||
+ | ! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | Replace() | ||
+ | | style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | Quite simply, this function allows to search for a specified string in a specified value, and if found, remove the specified string, or replace it with another. | ||
+ | |- valign="top" | ||
+ | ! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction | ||
+ | | style="background: #ecfeea; color: black; border: 1px solid black" | '''Replace(Value to check,String to check for,String to replace with)''' | ||
+ | * '''Value to check''': ''This can be plain text, a library field, or combination of both.'' | ||
+ | * '''String to check for''': ''Note that this check is <ins>case-sensitive</ins>'' | ||
+ | * '''String to replace with''': ''Any instance of the "String to check for" will be replaced by this string. If not specified, any instance of the "String to check for" will be removed.'' | ||
+ | |- valign="top" | ||
+ | ! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples | ||
+ | |style="background: #ecfeea; color: black; border: 1px solid black" | '''replace(My Sample String,S,Replaced )'''<br>''All instances of upper-case "S" will be replaced by the text "Replaced ", (note the trailing space), resulting in'' "My Replaced ample Replaced tring" | ||
+ | |||
+ | <br>'''replace(My Sample String,s,Replaced )'''<br>''The "Value to check" does not contain any lower-case "s", resulting in unchanged output'' "My Sample String" | ||
+ | |||
+ | <br>'''replace(My Sample String,/ Sample,stic)'''<br>''In this example, the space preceding the word Sample is to be included in the "String to check for". Remembering that, as discussed in the [[#Overview|Overview]], spaces that follow a comma are ignored unless escaped, an escaping forward slash is used to force the inclusion of the space in the check. The result here will be'' "Mystic String". | ||
+ | |} | ||
+ | <div style="text-align:right;">([[#top|Back to top)]]</div> | ||
+ | ====Right(...): Retrieves a specified number of characters from the right of a value==== | ||
+ | {| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3" | ||
+ | |- valign="top" | ||
+ | ! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | Right() | ||
+ | | style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | This function retrieves a specified number of characters from the right of any given value. | ||
+ | |- valign="top" | ||
+ | ! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction | ||
+ | | style="background: #ecfeea; color: black; border: 1px solid black" | '''Right(Value to get characters from,Number of characters to get)'''<br>''"Value to get characters from" can be plain text, a library field, or combination of both. If more characters than exist are requested, all available characters are returned.'' | ||
+ | |- valign="top" | ||
+ | ! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples | ||
+ | |style="background: #ecfeea; color: black; border: 1px solid black" | '''right([filename],3)'''<br>''This will return the last three characters from the filename. If asked to show more characters than actually exist, the expression will return the entire value, also, remember that spaces count as characters too.'' | ||
|} | |} | ||
<div style="text-align:right;">([[#top|Back to top)]]</div> | <div style="text-align:right;">([[#top|Back to top)]]</div> | ||
<br><br> | <br><br> | ||
− | === | + | ===List Manipulation=== |
− | The default | + | The default Media Center library contains many fields that are referred to as "list type" fields. Users are also able to add their own "list type" fields to their libraries. A list type field contains one or more text items seperated by semi-colons. The semi-colons are referred to as the 'delimiter' and when displayed in a view category, text items seperated by semi-colons are displayed in a list of seprately selectable items. The "Keywords" field is a classic example of a list type field, which demonstrates how list type fields allow a single file to be tagged with many different keywords, as opposed to a 'standard' field, such as 'Genre', where a single file can only be tagged with a single genre. The following functions provide the ability to combine or build custom list type fields using the default semi-colon delimiter, or a specified delimiter, count the number of items contained in a given list, or extract a numbered entry from within a list. Two of the functions listed in this section are used to create "list type" data from two or more existing sources and could reasonably be considered to be functions more suited to those who are very familiar with Media Center and how it gets its job done. If these functions are used to create a new 'calculated data' library field, they will not function as 'list type' fields unless the field is first created as a "User Data" field, with "List Type" specified. After creating the field in this way, it is possible to go back and edit the field, changing it to "calculated data" and entering an expression to be used. The [http://yabb.jriver.com/interact/index.php?topic=54226.msg374211#msg374211 "Eureka moment"] occurred in November 2009. |
====ListBuild(...): Build a list from a series of values==== | ====ListBuild(...): Build a list from a series of values==== | ||
{| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3" | {| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3" | ||
Line 702: | Line 1,005: | ||
|style="background: #ecfeea; color: black; border: 1px solid black" | '''listbuild(1,;,[keywords],[genre])&datatype=[list]'''<br>''This will return a semi-colon delimited list containing all keywords and genres. If either keyords or genre is empty, they will be ignored, so, the data returned for a file with no keywords, and a genre of "Rock" would be simply "Rock".'' | |style="background: #ecfeea; color: black; border: 1px solid black" | '''listbuild(1,;,[keywords],[genre])&datatype=[list]'''<br>''This will return a semi-colon delimited list containing all keywords and genres. If either keyords or genre is empty, they will be ignored, so, the data returned for a file with no keywords, and a genre of "Rock" would be simply "Rock".'' | ||
− | <br>'''listbuild(1,\,[genre],[album artist (auto)],[album])&datatype=[list]'''<br>''When | + | <br>'''listbuild(1,\,[genre],[album artist (auto)],[album])&datatype=[list]'''<br>''When Media Center encounters a back slash character in a list type field, it 'nests' the data in the list. Think of this in exactly the same way as Windows reads file paths, each back slash is another folder along the file path, and in a Media Center list type view category, each back slash creates a virtual folder, and each semi-colon starts a new list entry, which means that effective browsing trees can be created using this knowledge. In the example shown here, a list of genres would be created, and each genre is able to be expanded to reveal a list of artists, which in turn can be expanded to reveal albums by that particular artist in that genre. So, now that this is getting interesting, there's an issue with this example. If a file has no specified [genre], the value is ignored, and the [album artist (auto)] value is placed on the root of the virtual tree, which means that the completely collapsed list contains a mixture of [genre] and [album artist (auto)]. The next example demonstrates how to clean that up.'' |
<br>'''listbuild(1,\,if([[#IsEmpty(...): Tests to see if a field is empty|isempty]]([genre]),!No Genre Applied,[genre]),[album artist (auto)],[album])&datatype=[list]'''<br>''Here, the previous example has been improved by nesting an [[#IsEmpty(...): Tests to see if a field is empty|IsEmpty()]] function into the listbuild function. The result is that all files without a specified genre are placed in a group at the top of the virtual tree called "!No Genre Applied", and the rest of the root consists of existing genre values, which is much tidier. | <br>'''listbuild(1,\,if([[#IsEmpty(...): Tests to see if a field is empty|isempty]]([genre]),!No Genre Applied,[genre]),[album artist (auto)],[album])&datatype=[list]'''<br>''Here, the previous example has been improved by nesting an [[#IsEmpty(...): Tests to see if a field is empty|IsEmpty()]] function into the listbuild function. The result is that all files without a specified genre are placed in a group at the top of the virtual tree called "!No Genre Applied", and the rest of the root consists of existing genre values, which is much tidier. | ||
Line 728: | Line 1,031: | ||
* The output list from the above expression would be: ''Family\Mum;Family\Dad;Family\Gran'''<ins>;</ins>'''United Kingdom\Scotland\Edinburgh;United Kingdom\Scotland\Edinburgh\Edinburgh Castle'' (the specified "listcombine delimiter" shown in bold and underlined) | * The output list from the above expression would be: ''Family\Mum;Family\Dad;Family\Gran'''<ins>;</ins>'''United Kingdom\Scotland\Edinburgh;United Kingdom\Scotland\Edinburgh\Edinburgh Castle'' (the specified "listcombine delimiter" shown in bold and underlined) | ||
− | <br>'''listcombine([people],[places],\)&datatype=[list]'''<br>''Here, the resulting list will be the [people] and [places] lists joined using a back slash. Remember that | + | <br>'''listcombine([people],[places],\)&datatype=[list]'''<br>''Here, the resulting list will be the [people] and [places] lists joined using a back slash. Remember that Media Center interprets back slashes as a folder hierarchy when displaying list type fields in a view category pane.'' |
* [people] contains ''Family\Mum;Family\Dad;Family\Gran'' | * [people] contains ''Family\Mum;Family\Dad;Family\Gran'' | ||
Line 786: | Line 1,089: | ||
<div style="text-align:right;">([[#top|Back to top)]]</div> | <div style="text-align:right;">([[#top|Back to top)]]</div> | ||
<br><br> | <br><br> | ||
− | ===Functions that | + | ===Date & Time Functions=== |
− | The | + | Media Center provides several functions for date and time conversion, formatting and generation. Internally, date and time for date fields is stored as a floating point number, where the integer portion represents the number of days since the Epoch, and the decimal portion represents the fraction of a day. |
+ | |||
+ | The Windows locale setting will affect the interpretation and formatting of date and time information. | ||
+ | ====ConvertDate(...): Converts a human-readable date to the internal format required for use in date fields==== | ||
+ | {| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3" | ||
+ | |- valign="top" | ||
+ | ! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | ConvertDate() | ||
+ | | style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | | ||
+ | |||
+ | Converts human-readable date / time strings into the floating point representation used internally by Media Center to represent date and time. | ||
+ | |||
+ | |- valign="top" | ||
+ | ! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction | ||
+ | | style="background: #ecfeea; color: black; border: 1px solid black" | '''convertdate(Date string)''' | ||
+ | |||
+ | *'''Date string''' ''A human-readable date string to be converted.'' | ||
+ | |- valign="top" | ||
+ | ! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples | ||
+ | |style="background: #ecfeea; color: black; border: 1px solid black" | '''convertdate(3/6/2012)'''<br>''Converts the date March 6th, 2012 into a floating point number that can be assigned to a date field.'' | ||
+ | |||
+ | <br>'''formatdate(convertdate(12/2/1985), decade))''' | ||
+ | <br>''Converts the date string December 2nd, 1985 into internal date/time form, and then formats the result as a decades grouping of "1980's". This might be used for grouping tracks by decades. | ||
+ | |} | ||
+ | <div style="text-align:right;">([[#top|Back to top)]]</div> | ||
+ | |||
+ | ====FormatDate(...): Formats a date value in a specified manner==== | ||
+ | {| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3" | ||
+ | |- valign="top" | ||
+ | ! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | FormatDate() | ||
+ | | style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | FormatDate provides custom formatting of date / time fields through the use of special format specifiers. Select from the available format specifiers, and arrange them to produce the desired date and time components. | ||
+ | |- valign="top" | ||
+ | ! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction | ||
+ | | style="background: #ecfeea; color: black; border: 1px solid black" | '''formatdate(Date value, Format string, Output if date is empty)''' | ||
+ | |||
+ | *'''Date value''' ''The date to be formatted, in Media Center internal format (i.e. a floating point value). This field is optional, and will default to [Date,0]. To use any date field, use the raw (unformatted) field specification (e.g. [Date Imported,0]).'' | ||
+ | |||
+ | *'''Format string''' ''The format specifier string to format the date or time components. Media Center supports Windows style, strftime() style, and Media Center-specific specifiers. Select from any of the format specifiers in the following table. See also: '''[http://yabb.jriver.com/interact/index.php?topic=71000.msg479314#msg479314]'' | ||
+ | |||
+ | *'''Output if date is empty''' ''If the provided date is empty, anything placed here will be output instead. This could be plain text, such as "No Date", or a library field. This value is optional, and if not given, the expression will default to return nothing if the date is empty.'' | ||
+ | |||
+ | <blockquote> | ||
+ | {| style="background: #ecfeea;" border="1" cellpadding="1" cellspacing="0" | ||
+ | | || colspan="3" align="center" | '''Specifier''' || '''Description''' | ||
+ | |- | ||
+ | | rowspan="7" width="100" | '''Day''' | ||
+ | | align="center" width="65" | d || || Day || Day of the month as digits without leading zeros for single-digit days. | ||
+ | |- | ||
+ | | align="center" | dd || %d || || Day of the month as digits with leading zeros for single-digit days. | ||
+ | |- | ||
+ | | align="center" | ddd || %a || || Day of the week, abbreviated to three letters. | ||
+ | |- | ||
+ | | align="center" | dddd || %A || Dayname || Day of the week. | ||
+ | |- | ||
+ | | align="center" | || %w || || Day of the week as a decimal number, Sunday as 0 (0-6). | ||
+ | |- | ||
+ | | align="center" | || %j || || Day of the year (001-366) | ||
+ | |- | ||
+ | | align="center" | || %j ||Dayordinal|| Ordinal day of the month (e.g. 1st, 2nd, etc.). | ||
+ | |- | ||
+ | | rowspan="4" | '''Month''' | ||
+ | | align="center" | M || || || Month as digits without leading zeros for single-digit months. | ||
+ | |- | ||
+ | | align="center" | MM || %m || || Month as digits with leading zeros for single-digit months. | ||
+ | |- | ||
+ | | align="center" | MMM || %b || || Abbreviated month name, three letters (e.g. Apr, Nov). | ||
+ | |- | ||
+ | | align="center" | MMMM || %B || Month || Full Month name (e.g. April, November). | ||
+ | |- | ||
+ | | rowspan="4" | '''Year''' | ||
+ | | align="center" | y || || || Year represented only by the last digit. | ||
+ | |- | ||
+ | | align="center" | yy || %y || || Year represented only by the last two digits. A leading zero is added for single-digit years. | ||
+ | |- | ||
+ | | align="center" | yyyy || %Y || Year || Year represented by a full four or five digits. | ||
+ | |- | ||
+ | | align="center" | || || Decade || Year expressed as a decade (e.g. 1970's, 2010's) | ||
+ | |- | ||
+ | | rowspan="4" | '''Hour''' | ||
+ | | align="center" | h || || Hour || Hours with no leading zero for single-digit hours; 12-hour clock. | ||
+ | |- | ||
+ | | align="center" | hh || %I || || Hours with leading zero for single-digit hours; 12-hour clock. | ||
+ | |- | ||
+ | | align="center" | H || || || Hours with no leading zero for single-digit hours; 24-hour clock. | ||
+ | |- | ||
+ | | align="center" | HH || %H || || Hours with leading zero for single-digit hours; 24-hour clock. | ||
+ | |- | ||
+ | | rowspan="2" | '''Minute''' | ||
+ | | align="center" | m || || Minute || Minutes with no leading zero for single-digit minutes. | ||
+ | |- | ||
+ | | align="center" | mm || %M || || Minutes with leading zero for single-digit minutes. | ||
+ | |- | ||
+ | | rowspan="2" | '''Second''' | ||
+ | | align="center" | s || || Second || Seconds with no leading zero for single-digit seconds. | ||
+ | |- | ||
+ | | align="center" | ss || %S || || Seconds with leading zero for single-digit seconds. | ||
+ | |- | ||
+ | | rowspan="2" | '''AM/PM''' | ||
+ | | align="center" | t || || || One character time marker string, such as A or P. | ||
+ | |- | ||
+ | | align="center" | tt || %p || || Multi-character time marker string, such as AM or PM. | ||
+ | |- | ||
+ | | rowspan="5" | '''Combined''' | ||
+ | | align="center" | || %x || Date || Date expressed in the system's format. | ||
+ | |- | ||
+ | | align="center" | || %X || Time || Time expressed in the system's format. | ||
+ | |- | ||
+ | | align="center" | || %c || DateTime|| Date and time expressed in the system's format. | ||
+ | |- | ||
+ | | align="center" | || || ShortDate|| Age-conditional date formatted as one of "Year", "MMM d", or "MMM d Year". | ||
+ | |- | ||
+ | | align="center" | || || ShortDateTime || Date in ShortDate format plus Time. | ||
+ | |- | ||
+ | | rowspan="2" | '''Week Number''' | ||
+ | | align="center" | || %U || || Week number with the first Sunday as the first day of week one (00-53). | ||
+ | |- | ||
+ | | align="center" | || %W || || Week number with the first Monday as the first day of week one (00-53). | ||
+ | |- | ||
+ | | rowspan="4" | '''Miscellaneous''' | ||
+ | | align="center" | || || Elapsed || Time expressed as elapsed time (e.g. 2.5 hours). | ||
+ | |- | ||
+ | | align="center" | || ||ElapsedAgo|| Time expressed as elapsed time ago (e.g. 2.5 hours ago). | ||
+ | |- | ||
+ | | align="center" | || || Filename|| Date and time expressed in filename-friendly format, includes seconds to avoid filename collisions (e.g. 20040521-032221). | ||
+ | |- | ||
+ | | align="center" | || %% || || A percent (%) character. | ||
+ | |- | ||
+ | |} | ||
+ | </blockquote> | ||
+ | |||
+ | |- valign="top" | ||
+ | ! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples | ||
+ | |style="background: #ecfeea; color: black; border: 1px solid black" | '''formatdate(year-month)'''<br />''Returns the file's date formatted as Year-Month. This uses the default [Date,0] field. Example: 2012-April.'' | ||
+ | |||
+ | <br>'''formatdate([last played,0],yyyy//MM//dd,Not Yet)'''<br>''This will return the last played date as year/month/day without the time, and regardless of the system locale setting. If a file has no last played info, the expression will output "Not Yet" instead.'' | ||
+ | |||
+ | <br>'''formatdate([date modified,0], month %Y)''' | ||
+ | <br>''This will return the month and 4-digit year a file was modified. Example: December 2010.'' | ||
+ | |||
+ | <br>'''formatdate([date imported,0],month)&datatype=[month]''' | ||
+ | <br>''If you were to use the previous expression to create a view category that contained the months your files were imported, it would list the months alphabetically, with April first and September last. Thankfully, we can specify "data types" for expressions which further fine tune how Media Center displays the results. In this case, a data type of month has been specified, therefore Media Center will list the months in the correct chronological order. Data types were discussed [[#Specify data types for expression based fields|earlier on this page]]. | ||
+ | |} | ||
+ | <div style="text-align:right;">([[#top|Back to top)]]</div> | ||
+ | |||
====Now(...): Retrieve and display the system date==== | ====Now(...): Retrieve and display the system date==== | ||
{| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3" | {| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3" | ||
|- valign="top" | |- valign="top" | ||
! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | Now() | ! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | Now() | ||
− | | style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | Now() will return the raw system date. "raw" data is discussed in the [[#Field|Field]] description, and also in the introduction to the [[# | + | | style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | Now() will return the raw system date. "raw" data is discussed in the [[#Field|Field]] description, and also in the introduction to the [[#Formatting Functions|"Format"]] functions. As Media Center's raw date data is illegible, this function needs to be used with the "[[#FormatDate(...): Formats a date value in a specified manner|FormatDate()]]" function, which allows the current date, and time, if desired, to be presented in many different styles. |
|- valign="top" | |- valign="top" | ||
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction | ! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction | ||
Line 804: | Line 1,249: | ||
<br>'''[=isequal(formatdate([date imported,0],MM//yyyy),formatdate(now(),MM//yyyy)]=1 ~sort=[Date Imported]-d'''<br> | <br>'''[=isequal(formatdate([date imported,0],MM//yyyy),formatdate(now(),MM//yyyy)]=1 ~sort=[Date Imported]-d'''<br> | ||
− | '' | + | ''Media Center comes with a stock smartlist titled "Imported This Month". On the face of it, this could be a handy list of files, but is actually rather misleading. Closer inspection of this stock smartlist reveals that it is not actually listing files "Imported This Month", but instead, listing those files that have been imported in the past 31 days by using the following rule: [Date Imported]=<31d ~sort=[Date Imported]-d<br> |
This would mean that if you were to view that list on the second of March, you could potentially be looking at a list of files imported during three different months. The example in bold above corrects this anomaly by comparing the month/year imported with the current month/year, and only lists the file if the two match.<br> | This would mean that if you were to view that list on the second of March, you could potentially be looking at a list of files imported during three different months. The example in bold above corrects this anomaly by comparing the month/year imported with the current month/year, and only lists the file if the two match.<br> | ||
This is also an example of how to use an expression in a search rule, as detailed in "[[#When, Where and How to use expressions|When, Where and How to use expressions]]" | This is also an example of how to use an expression in a search rule, as detailed in "[[#When, Where and How to use expressions|When, Where and How to use expressions]]" | ||
<br>''<ins>[http://yabb.jriver.com/interact/index.php?topic=56487.0 This topic]</ins> expands on the example above a little by showing how to construct rules that return files that have been played or imported today or yesterday.'' | <br>''<ins>[http://yabb.jriver.com/interact/index.php?topic=56487.0 This topic]</ins> expands on the example above a little by showing how to construct rules that return files that have been played or imported today or yesterday.'' | ||
+ | |} | ||
+ | ===Other Functions=== | ||
+ | The functions in this group are varied, and do not readily fit into the other groups of functions. | ||
+ | |||
+ | <div style="text-align:right;">([[#top|Back to top)]]</div> | ||
+ | |||
+ | ====Counter(...): Counts upwards in specified increments==== | ||
+ | {| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3" | ||
+ | |- valign="top" | ||
+ | ! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | Counter() | ||
+ | | style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | This function can be used to number objects sequentially, from a specified starting point, in specified increments. The counter resets itself to zero after five seconds of inactivity.<br>Counter() can exhibit a touch of wierdness when used in certain situations, which will be covered in the examples, that demonstrate why this one is not really a 'fits all' function. | ||
+ | |- valign="top" | ||
+ | ! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction | ||
+ | | style="background: #ecfeea; color: black; border: 1px solid black" | '''Counter(Number to start counting from,Increments to count up in)''' | ||
+ | |||
+ | * '''Number to start counting from''': ''This is optional. If not specified, the counter will start from one. If specified, the start value is inclusive, meaning that if a start value of five is specified, the first value the function returns will be five.'' | ||
+ | * '''Increments to count up in''': ''This optional. If not specified, the counter will count up in increments of 1'' | ||
+ | |- valign="top" | ||
+ | ! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples | ||
+ | |style="background: #ecfeea; color: black; border: 1px solid black" | '''counter()'''<br>This shows the function in its simplest form. The counter will start at one and count upwards in increments of 1. | ||
+ | |||
+ | <br>'''[[#PadNumber(...): Adds leading zeros to any given number|padnumber]](counter(370,2),4)'''<br>This expression shows a combined use of functions. Counter() will count up, in two's, starting from 370, and the padnumber function will pad the results to four figures, giving output values of 0370, 0372, 0374, etc. etc.. | ||
+ | |||
+ | <br>'''Weirdness'''<br>Counter() works really really well, and really really efficiently when used to sequentially number static data fields. It is not designed to be used in a dynamically changing expression column in a file list. To demonstrate this, right click on a list column header and choose the option to "Add expression column". Use the first, simple expression above, and press OK. The column is presented and all the items in the list are now numbered in this column, but, see what happens when you run the cursor up and down the list? The counter function just keeps on going and going. Right click on the expression column header, and it will appear at the top of the selectable columns list with a tick beside it, click on it to remove the column. This same anomally appears when counter() is used in the "Rename, Move, & Copy Files" tool. There may be a possible solution to this effect as seen in the renaming tool by using the CustomData(#) function, but only if the count is to start from 1.<br>Some interesting reading regarding the use of Counter() can be found in answer to "[http://yabb.jriver.com/interact/index.php?topic=48659.0 how to fill the NAME field with incrementing numbers?]" and "[http://yabb.jriver.com/interact/index.php?topic=50622.0 Prepending a consecutive number to titles as I copy them from MC13 to mp3 player]". | ||
+ | |} | ||
+ | <div style="text-align:right;">([[#top|Back to top)]]</div> | ||
+ | |||
+ | ====CustomData(...): Sequence numbering when renaming files==== | ||
+ | {| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3" | ||
+ | |- valign="top" | ||
+ | ! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | CustomData() | ||
+ | | style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | The official description for this function goes as follows: ''"Returns custom data stored in a file array (used primarily for internal uses)."'' There is no recorded practical use for this function, with the exception of using it with a hash symbol in the library tool called "Rename, Move, & Copy Files". When used in the directory or filename rules of this tool, this function will number the files in the list from first to last, starting at number one. As long as any desired numbering is to begin at one, this function is a reasonable alternative to combat the wierdness demonstrated by the [[#Counter(...): Counts upwards in specified increments|Counter()]] function, and could be particularly useful when renaming image files. If the numbering is required to start counting from anywhere other than one, then [[#Counter(...): Counts upwards in specified increments|Counter()]] will need to be used, taking the wierdness and its work arounds into account. | ||
+ | |- valign="top" | ||
+ | ! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction | ||
+ | | style="background: #ecfeea; color: black; border: 1px solid black" | '''CustomData(#)''' | ||
+ | |- valign="top" | ||
+ | ! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples | ||
+ | |style="background: #ecfeea; color: black; border: 1px solid black" | '''[[#PadNumber(...): Adds leading zeros to any given number|padnumber]](customdata(#),4)_Christmas Party 2007'''<br>''It's important to remember that this function will only work when used as part of the renaming rule for either filename or directory (or both) within the "Rename, Move, & Copy Files" tool. In this example, imagine 324 photos from the Christmas party of 2007 were selected for renaming, and this expression was entered into the filename field. The resulting filenames would be 0001_Christmas Party 2007.jpg through to 0324_Christmas Party 2007.jpg. Note how the "[[#PadNumber(...): Adds leading zeros to any given number|padnumber()]]" function has been used to add the leading zeros. | ||
+ | |} | ||
+ | <div style="text-align:right;">([[#top|Back to top)]]</div> | ||
+ | |||
+ | ====FileName(...): Returns the name from a specified file name==== | ||
+ | {| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3" | ||
+ | |- valign="top" | ||
+ | ! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | FileName() | ||
+ | | style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | This function returns the file name for the files in a list, or for the specified file. A second parameter set to 0 will cause the suffix to be suppressed from the file name. The library field [Filename (Name)] already contains the value that would be returned by FileName(); it generally should be used rather than this function. | ||
+ | |- valign="top" | ||
+ | ! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction | ||
+ | | style="background: #ecfeea; color: black; border: 1px solid black" | '''FileName(Filename to check, Suppress suffix)''' | ||
+ | |||
+ | * Filename to check ''This is optional. If not specified, the function defaults to the current file.'' | ||
+ | * Suppress suffix ''This is optional. If set to 0, the file name's suffix will be suppressed from output.'' | ||
+ | |- valign="top" | ||
+ | ! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples | ||
+ | |style="background: #ecfeea; color: black; border: 1px solid black" | '''filename(C:\Music\File.mp3)'''<br>''The result here would be... "File.mp3"'' | ||
+ | |||
+ | <br />'''filename(C:\Music\File 2.wav, 0)'''<br>''The result here would be... "File 2"'' | ||
+ | |||
+ | <br>'''filename()'''<br>''Returns the file name for each file in the list. The [filename (Name)] field returns the same information. | ||
+ | |} | ||
+ | <div style="text-align:right;">([[#top|Back to top)]]</div> | ||
+ | |||
+ | ====FileFolder(...): Returns the name of a parent sub-folder from a specified file path ==== | ||
+ | {| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3" | ||
+ | |- valign="top" | ||
+ | ! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | FileFolder() | ||
+ | | style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | This function returns a parent sub-folder name from a file path. A value of Unassigned will be returned when the specified level exceeds the root of the path. | ||
+ | |- valign="top" | ||
+ | ! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction | ||
+ | | style="background: #ecfeea; color: black; border: 1px solid black" | '''FileFolder(Filepath, Level)''' | ||
+ | |||
+ | * Filepath ''This is optional. If not specified, the function defaults to the path of the current file. Otherwise, the specified path will be used.'' | ||
+ | * Level ''This is optional. Specifies the parent sub-folder name to return, working the path from right-to-left (i.e. bottom of the folder tree upwards to the top). A value of 0 (the default) specifies a file's immediate parent, 1 its grandparent, etc., up to the root of the path.'' | ||
+ | |- valign="top" | ||
+ | ! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples | ||
+ | |style="background: #ecfeea; color: black; border: 1px solid black" | '''filefolder()<br>filefolder([Filename,0], 0)'''<br>''Returns the name of the file's parent folder.'' | ||
+ | |||
+ | <br />'''filefolder(c:\some\path\to\a\file.ape, 2)<br />filefolder(c:\some\path\to\a\, 2)'''<br />''Returns the great grandparent sub-folder name "path".'' Notice above that the file name is not required in the path. FileFolder() works by looking from the end of the file path until it finds a backslash (\). | ||
+ | |} | ||
+ | <div style="text-align:right;">([[#top|Back to top)]]</div> | ||
+ | |||
+ | ====Load(...): Outputs the value of a global variable==== | ||
+ | {| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3" | ||
+ | |- valign="top" | ||
+ | ! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | Load() | ||
+ | | style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | Loads and outputs the value of the specified global variable that has been previously stored with the [[#Save(...): Saves a value to a global variable|Save()]] function. | ||
+ | |- valign="top" | ||
+ | ! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction | ||
+ | | style="background: #ecfeea; color: black; border: 1px solid black" | '''Load(Variable)''' | ||
+ | |||
+ | * Variable ''The global variable to load and output.'' | ||
+ | |||
+ | |- valign="top" | ||
+ | ! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples | ||
+ | |style="background: #ecfeea; color: black; border: 1px solid black" | '''load(var1)'''<br /> | ||
+ | ''Loads and outputs the previous stored value of the global variable "var1". If "var1" has not been previously stored, the output will be empty.'' | ||
+ | |||
+ | <br />'''save(math(1 + 2), sum)load(sum)''' | ||
+ | <br />''Saves the output of the math() function into "sum", and then loads and outputs the value of "sum", which is 3.'' | ||
|} | |} | ||
<div style="text-align:right;">([[#top|Back to top)]]</div> | <div style="text-align:right;">([[#top|Back to top)]]</div> | ||
+ | |||
====Math(...): Evaluates a given mathematical formula==== | ====Math(...): Evaluates a given mathematical formula==== | ||
− | {| style="width: 100%; border: 1px solid black" align="top" | + | {| style="width: 100%; border: 1px solid black" align="top" cellpadding="3" |
|- valign="top" | |- valign="top" | ||
! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | Math() | ! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | Math() | ||
− | | style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | Math() | + | | style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | The Math() function provides the ability to perform mathematical calculations. In addition to the standard arithmetic operators, it also supports various numerical, trigonometric, and comparative functions. Simple variables are supported, as are multiple statements. |
+ | |||
+ | <blockquote> | ||
+ | {| style="background: #ecfeea;" border="1" cellpadding="1" cellspacing="0" | ||
+ | | rowspan="6" width="100" valign="top" | '''Arithmetic Operators''' | ||
+ | | align="center" width="65" | + || Addition | ||
+ | |- | ||
+ | | align="center" | - || Subtraction | ||
+ | |- | ||
+ | | align="center" | * || Multiplication | ||
+ | |- | ||
+ | | align="center" | / || Division | ||
+ | |- | ||
+ | | align="center" | ^ || Power | ||
+ | |- | ||
+ | | align="center" | % || Modulo | ||
+ | |- | ||
+ | | rowspan="3" | '''Boolean Operators''' | ||
+ | | align="center" | ! || NOT | ||
+ | |- | ||
+ | | align="center" | & || AND | ||
+ | |- | ||
+ | | align="center" | <nowiki>|</nowiki> || OR | ||
+ | |- | ||
+ | | rowspan="1" | '''Grouping Operators''' | ||
+ | | align="center" | ( ) || Precedence grouping | ||
+ | |- | ||
+ | | rowspan="4" | '''Comparison Operators''' | ||
+ | | align="center" | } || Absolute value maximum (i.e. x or y that is maximum distance from 0). | ||
+ | |- | ||
+ | | align="center" | { || Absolute value minimum (i.e. x or y that is minimum distance from 0). | ||
+ | |- | ||
+ | | align="center" | > || Distance between x and y, positive when x greater than y, negative otherwise. | ||
+ | |- | ||
+ | | align="center" | < || Distance between x and y, positive when x less than y, negative otherwise. | ||
+ | |- | ||
+ | | rowspan="7" | '''Functions''' | ||
+ | | align="center" | abs(x) || Returns the absolute value of x. | ||
+ | |- | ||
+ | | align="center" | sign(x) || Returns the sign of x (1 when x >= 0, -1 when x < 0). | ||
+ | |- | ||
+ | | align="center" | log(x) || Returns the natural logarithm (base e) of x. | ||
+ | |- | ||
+ | | align="center" | log10(x) || Returns the common logarithm (base 10) of x. | ||
+ | |- | ||
+ | | align="center" | pow(x,y) || Returns x raised to the y-th power. | ||
+ | |- | ||
+ | | align="center" | rand(x) || Returns a random value ranging between 0 to x. | ||
+ | |- | ||
+ | | align="center" | randn(x) || Returns a random value ranging between -x and x. | ||
+ | |- | ||
+ | | rowspan="5" | '''Comparison Functions''' | ||
+ | | align="center" | min(x,y) || Returns the minimum value of x and y. | ||
+ | |- | ||
+ | | align="center" | max(x,y) || Returns the maximum value of x and y. | ||
+ | |- | ||
+ | | align="center" | equal(x,y) || Returns 1 when x = y, 0 otherwise. | ||
+ | |- | ||
+ | | align="center" | below(x,y) || Returns 1 when x < y, 0 otherwise. | ||
+ | |- | ||
+ | | align="center" | above(x,y) || Returns 1 when x > y, 0 otherwise. | ||
+ | |- | ||
+ | | rowspan="6" | '''Trigonometric Functions''' | ||
+ | | align="center" | atan(x) || Returns the arctangent of x. | ||
+ | |- | ||
+ | | align="center" | cos(x) || Returns the cosine of x. | ||
+ | |- | ||
+ | | align="center" | sin(x) || Returns the sine of x. | ||
+ | |- | ||
+ | | align="center" | tan(x) || Returns the tangent of x. | ||
+ | |- | ||
+ | | align="center" | abscos(x) || Returns the absolute value of cosine(x). | ||
+ | |- | ||
+ | | align="center" | abssin(x) || Returns the absolute value of sin(x). | ||
+ | |} | ||
+ | </blockquote> | ||
+ | |||
+ | <br /> | ||
+ | The order or precedence of the operators is summarized as follows, from top to bottom: | ||
+ | {| style="background: #ecfeea; color: black; border: none" cellpadding="0" cellspacing="0" | ||
+ | | align="center" width="100" | <tt>( )</tt> | ||
+ | |- | ||
+ | | align="center" | <tt>!</tt> | ||
+ | |- | ||
+ | | align="center" | <tt>^</tt> | ||
+ | |- | ||
+ | | align="center" | <tt>* /</tt> || Left to right | ||
+ | |- | ||
+ | | align="center" | <tt>+ -</tt> || Left to right | ||
+ | |- | ||
+ | | align="center" | <tt><nowiki>|</nowiki> &</tt> || Left to right | ||
+ | |} | ||
+ | |||
+ | Variables may be assigned and used by specifying a simple string of letters. Examples: <tt>math(val=2)</tt> or <tt>math(x=pow(2,3))</tt> | ||
+ | |||
+ | Multiple equations may be specified, each separated by a semicolon. Expressions are evaluated left to right. The final value of the Math() function will be the result of the right-most equation. Example: <tt>math(x=4; pow(2^x))</tt> | ||
+ | |||
+ | <br /> | ||
+ | '''Note''': Fields used inside of Math() are expanded directly. Those that have no value (eg. empty fields) may produce incomplete Math() statements. For example, if the field [Number Plays] is empty, an expression such as <tt>math([Number Plays] + 2)</tt> would be seen by Math() as " + 2". This incomplete expression would by an error. See <ins>[http://yabb.jriver.com/interact/index.php?topic=58110.0 this topic]</ins> for additional explanations and workarounds. | ||
+ | |||
+ | <br /> | ||
+ | '''Please also note''': The Math() function uses dot (.) as the decimal point, so Math(1,5+1,5) will not work but Math(1.5+1.5) will. If you run MC on a system that uses comma (,) as the decimal point, all date related fields - [Date,0], [Last Played,0], [Date Modified,0], [Date Imported,0] etc. - with time information will in their raw format use comma as the decimal point. This is also the case with the Now() function. In these cases you must replace the commas with dots for the Math() function to work, like this: Math(Replace(Now(),/,,.) - Replace([Last Played,0],/,,.)). The escape character / must be used to have the commas recognised as commas. | ||
+ | |||
|- valign="top" | |- valign="top" | ||
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction | ! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction | ||
− | | style="background: #ecfeea; color: black; border: 1px solid black" | '''Math( | + | | style="background: #ecfeea; color: black; border: 1px solid black" | '''Math(Expression to evaluate)''' |
|- valign="top" | |- valign="top" | ||
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples | ! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples | ||
− | |style="background: #ecfeea; color: black; border: 1px solid black" | '''math(10+4)'''<br>'' | + | |style="background: #ecfeea; color: black; border: 1px solid black" | '''math(10 + 4)'''<br>''Returns 14.'' |
− | <br>'''math(10+2 | + | <br />'''math(10 + 2 * 25)'''<br /> |
+ | ''Returns 60, demonstrating that multiplication has higher precedence than addition.'' | ||
− | <br>' | + | <br />'''math((10 + 2) * 25)'''<br /> |
+ | ''Returns 300, demonstrating that parenthesis grouping has higher precedence than multiplication.'' | ||
− | <br>''' | + | <br>'''listitem([filename (path)], math(listcount([filename (path)], \) - 1), \)'''<br>'' |
+ | Evaluates the [[#ListCount(...): Returns the number of items in a delimited list|ListCount()]] function to determine the number of path components in the field [filename (path)], and uses Math() to subtract one. The result is then used in the [[#ListItem(...): Returns a specified value from a delimited list|ListItem()]] function which yields the parent folder name of the specified file.'' | ||
|} | |} | ||
+ | |||
<div style="text-align:right;">([[#top|Back to top)]]</div> | <div style="text-align:right;">([[#top|Back to top)]]</div> | ||
− | ==== | + | |
+ | ====Note(...): Retrieve information from a note==== | ||
{| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3" | {| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3" | ||
|- valign="top" | |- valign="top" | ||
− | ! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | | + | ! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | Note() |
− | | style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | | + | | style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | Since build 14.0.111, [http://yabb.jriver.com/interact/index.php?topic=54548.0 Media Center has shipped with a "Notes" feature.] One of the many uses available via notes is the ability to store contact information, and that information can be labelled. Labels are typical contact information labels such as "Home phone", "Work phone", "Email" etc. etc.. This function can retrieve and display the contents of specified labels from a note. |
|- valign="top" | |- valign="top" | ||
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction | ! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction | ||
− | | style="background: #ecfeea; color: black; border: 1px solid black" | ''' | + | | style="background: #ecfeea; color: black; border: 1px solid black" | '''Note(Field Label,Field Type,Occurrance)''' |
+ | |||
+ | * '''Field Label''': ''There are too many labels to list here. To see the available labels, select some text in a note and right click that selected text, then hover the cursor over "Set Field" to see the list of available labels.'' | ||
+ | * '''Field Type''': ''If the specified label was, for example, "Phone", then the "Type" could be "Home" or "Business" or any of the other available "Phone" types. This value is optional, and if not specified, the function will default to the first type encountered.'' | ||
+ | * '''Occurrance''': ''If a note contained two home phone numbers, they would be "occurrance 0" and "occurrance 1". If "occurrance 1" was required, the function requires this to be specified. This value is optional, and if not specified, the function will default to using zero.'' | ||
|- valign="top" | |- valign="top" | ||
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples | ! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples | ||
− | |style="background: #ecfeea; color: black; border: 1px solid black" | ''' | + | |style="background: #ecfeea; color: black; border: 1px solid black" | '''note(phone)'''<br>'''note(phone,home)'''<br>'''note(phone,home,1)'''<br>''Here are three sample notes expressions. In the image below, they have been used to create expression list columns, with each expression used shown in the column header. The note, with labels on show, is visible on the right hand end of the image. When comparing the note with the data returned by each expression, it should become apparent how each expression is working.'' |
+ | [[image:Notes.png|thumb|left|500px|alt=note image|A note + expression columns (''click to enlarge)'']] | ||
|} | |} | ||
<div style="text-align:right;">([[#top|Back to top)]]</div> | <div style="text-align:right;">([[#top|Back to top)]]</div> | ||
− | ==== | + | |
+ | ====Save(...): Saves a value to a global variable==== | ||
{| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3" | {| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3" | ||
|- valign="top" | |- valign="top" | ||
− | ! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | | + | ! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | Save() |
− | | style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | | + | | style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | Saves a value into the specified global variable, and optionally outputs the value. |
|- valign="top" | |- valign="top" | ||
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction | ! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction | ||
− | | style="background: #ecfeea; color: black; border: 1px solid black" | ''' | + | | style="background: #ecfeea; color: black; border: 1px solid black" | '''Save(Value,Variable,Output value)''' |
+ | |||
+ | * Value ''The value to store into the variable.'' | ||
+ | * Variable ''The global variable in which to save a value.'' | ||
+ | * Output value ''Optional, outputs Value after the save.'' | ||
+ | |||
|- valign="top" | |- valign="top" | ||
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples | ! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples | ||
− | |style="background: #ecfeea; color: black; border: 1px solid black" | ''' | + | |style="background: #ecfeea; color: black; border: 1px solid black" | '''save(Much Money, local_bank)'''<br /> |
+ | ''Saves the value "Much Money" into the global variable "local_bank".'' | ||
+ | |||
+ | <br />'''save(More Money, My Bank, 1)''' | ||
+ | <br />''Saves "More Money" into "My Bank" and outputs "More Money".'' | ||
+ | |||
+ | |||
+ | The following links demonstrate usage of global variables: | ||
+ | * [http://yabb.jriver.com/interact/index.php?topic=76581.msg518902#msg518902 Generating album track count] | ||
+ | * [http://yabb.jriver.com/interact/index.php?topic=72049.0 Generating album ratings] | ||
+ | * [http://yabb.jriver.com/interact/index.php?topic=74116.0 Highlighting playing album] | ||
+ | |||
|} | |} | ||
<div style="text-align:right;">([[#top|Back to top)]]</div> | <div style="text-align:right;">([[#top|Back to top)]]</div> | ||
+ | |||
====Tag(...): Returns a physical file tag (rather than looking in the database)==== | ====Tag(...): Returns a physical file tag (rather than looking in the database)==== | ||
{| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3" | {| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3" | ||
|- valign="top" | |- valign="top" | ||
! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | Tag() | ! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | Tag() | ||
− | | style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | This function originally came into being as a need arose for there to be a way to re-import the exif date information from image files without affecting any other tags. To that end, the function works well, but that's really where it's functionality ends. Success with any other fields has been extremely limited indeed. The main reason for this is because, when using this function to query specific tag data blocks in an image file, the fields referenced by the tag() function must be spelled ''exactly'' as they appear in the tag block within the file, and yes, they ''are'' case sensitive. It is also extremely important to know that when building a file list that contains a "Tag()" derived column, | + | | style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | This function originally came into being as a need arose for there to be a way to re-import the exif date information from image files without affecting any other tags. To that end, the function works well, but that's really where it's functionality ends. Success with any other fields has been extremely limited indeed. The main reason for this is because, when using this function to query specific tag data blocks in an image file, the fields referenced by the tag() function must be spelled ''exactly'' as they appear in the tag block within the file, and yes, they ''are'' case sensitive. It is also extremely important to know that when building a file list that contains a "Tag()" derived column, Media Center will be inordinately slower, <ins>1000's of times slower</ins>, in building that list than it would be without the "Tag()" column. This is because each and every file in the list must be queried individually for the contents of the specified tag. This particular function is best used using the "inline editing" method outlined in the "[[#When, Where and How to use expressions|When, Where and How to use expressions]]" section of this page, to pull the desired data into the main library database and then reference the information from the database. |
|- valign="top" | |- valign="top" | ||
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction | ! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction | ||
| style="background: #ecfeea; color: black; border: 1px solid black" | '''Tag(Field to read from the file)'''<br>Specific tag data blocks from jpg files can also be referenced:<br>'''Tag(Tag Block To Query: Field to read from the tag block)''' | | style="background: #ecfeea; color: black; border: 1px solid black" | '''Tag(Field to read from the file)'''<br>Specific tag data blocks from jpg files can also be referenced:<br>'''Tag(Tag Block To Query: Field to read from the tag block)''' | ||
− | * Field to read from the file: Not case sensitive in all scenarios, but always case sensitive when | + | * Field to read from the file: Not case sensitive in all scenarios, but always case sensitive when targeting specific tag data blocks within jpg files. |
* Tag blocks that can be queried from within jpg files are: | * Tag blocks that can be queried from within jpg files are: | ||
** EXIF | ** EXIF | ||
Line 877: | Line 1,552: | ||
<br>'''tag(Gapless Header)''' or '''tag(Gapless Footer)'''<br>''These two expressions allow gapless information to be queried from mp3 files.'' | <br>'''tag(Gapless Header)''' or '''tag(Gapless Footer)'''<br>''These two expressions allow gapless information to be queried from mp3 files.'' | ||
− | <br>'''tag(exif: Date)'''<br>''This will return the raw date data from the EXIF data saved inside a jpg file. If this expression is used to import the data into | + | <br>'''tag(exif: Date)'''<br>''This will return the raw date data from the EXIF data saved inside a jpg file. If this expression is used to import the data into Media Center's default [Date] field, Media Center will format the info into legible date information automatically. If importing into a custom field, wrap the tag() function inside a [[#FormatDate(...): Formats a date value in a specified manner|FormatDate()]] function like so: '''formatdate(tag(exif: Date),datetime)'''.''<br>''Note that "tag(exif: date)" will not return any result as the tag to query value is case sensitive and must be entered as "Date"'' |
|} | |} | ||
<div style="text-align:right;">([[#top|Back to top)]]</div> | <div style="text-align:right;">([[#top|Back to top)]]</div> | ||
+ | |||
====TVInfo(...): Returns television-specific information about a file==== | ====TVInfo(...): Returns television-specific information about a file==== | ||
{| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3" | {| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3" | ||
Line 893: | Line 1,569: | ||
* '''IsGuideProgram''': ''Tests whether the file is a guide program or not. (Returns 0 or 1)'' | * '''IsGuideProgram''': ''Tests whether the file is a guide program or not. (Returns 0 or 1)'' | ||
* '''IsRecordedProgram''': ''Tests whether the file is a recorded program or not. (Returns 0 or 1)'' | * '''IsRecordedProgram''': ''Tests whether the file is a recorded program or not. (Returns 0 or 1)'' | ||
+ | * '''Channel''': ''Returns the channel name, given a channel number.'' | ||
+ | * '''ChannelKeywords''': ''Returns channel keywords.'' | ||
* '''NameDisplay''': ''Returns the name.'' | * '''NameDisplay''': ''Returns the name.'' | ||
* '''NameDisplayWithDate''': ''Returns the name + date.'' | * '''NameDisplayWithDate''': ''Returns the name + date.'' | ||
Line 908: | Line 1,586: | ||
|} | |} | ||
<div style="text-align:right;">([[#top|Back to top)]]</div> | <div style="text-align:right;">([[#top|Back to top)]]</div> | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
<br><br> | <br><br> | ||
+ | |||
===Redundant Functions?=== | ===Redundant Functions?=== | ||
− | Taken at face value, all of the functions in this section would appear to be a little on the redundant side, falling neatly into the "a long way for a shortcut" category. | + | Taken at face value, all of the functions in this section would appear to be a little on the redundant side, falling neatly into the "a long way for a shortcut" category. Media Center could possibly rely on these functions internally, exalting their status to "highly useful" or "essential" even, but as this page is designed for end users, not Media Center, end users will find these functions redundant, and they are included here in the name of completeness only. |
====Field(...): Returns the value of a library field==== | ====Field(...): Returns the value of a library field==== | ||
{| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3" | {| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3" | ||
Line 934: | Line 1,596: | ||
! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | Field() | ! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | Field() | ||
| style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | Place the name of any library field inside this function, and it will return the contents of that library field for each file. Entering the field name inside square brackets as normal, without the function, returns the same data. | | style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | Place the name of any library field inside this function, and it will return the contents of that library field for each file. Entering the field name inside square brackets as normal, without the function, returns the same data. | ||
+ | |||
+ | '''Note''': Beginning with version 17, Media Center no longer supports function expansion inside the Field() parameter list; only simple text strings are supported. This is a performance optimization. | ||
|- valign="top" | |- valign="top" | ||
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction | ! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction | ||
Line 946: | Line 1,610: | ||
|- valign="top" | |- valign="top" | ||
! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | FilePath() | ! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | FilePath() | ||
− | | style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | This function will return the file path information from root to parent folder for all files in a list, or for any specified file. | + | | style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | This function will return the file path information from root to parent folder for all files in a list, or for any specified file. Media Center has a [Filename (Path)] library field by default, which is probably easier to use or reference than this function. |
|- valign="top" | |- valign="top" | ||
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction | ! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction | ||
Line 959: | Line 1,623: | ||
|} | |} | ||
<div style="text-align:right;">([[#top|Back to top)]]</div> | <div style="text-align:right;">([[#top|Back to top)]]</div> | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
====FileVolume(...): Returns the volume name from a specified filename==== | ====FileVolume(...): Returns the volume name from a specified filename==== | ||
{| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3" | {| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3" | ||
|- valign="top" | |- valign="top" | ||
! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | FileVolume() | ! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | FileVolume() | ||
− | | style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | This function will return the volume name information for all files in a list, or for any specified file. | + | | style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | This function will return the volume name information for all files in a list, or for any specified file. Media Center has a [Volume Name] library field by default, which is probably easier to use or reference than this function. |
|- valign="top" | |- valign="top" | ||
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction | ! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction | ||
Line 1,023: | Line 1,671: | ||
|- valign="top" | |- valign="top" | ||
! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | AlbumType() | ! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | AlbumType() | ||
− | | style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | This function simply returns the "'''[album type]'''" for each file. [album type] is a default | + | | style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | This function simply returns the "'''[album type]'''" for each file. [album type] is a default Media Center library field that informs the user of an album's status in the library, such as "Single artist (complete)" or "Multiple artists (incomplete)" |
|- valign="top" | |- valign="top" | ||
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction | ! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction | ||
Line 1,064: | Line 1,712: | ||
|} | |} | ||
<div style="text-align:right;">([[#top|Back to top)]]</div> | <div style="text-align:right;">([[#top|Back to top)]]</div> | ||
− | |||
− | |||
[[Category:Frequently_Asked_Questions]] | [[Category:Frequently_Asked_Questions]] |
Revision as of 02:16, 11 January 2013
Contents
- 1 Using this page
- 2 Overview
- 3 Using expressions
- 4 Specify data types for expression based fields
- 5 Fields
- 6 Functions
- 6.1 Conditional Functions
- 6.2 Query, Test and Comparison Functions
- 6.2.1 Compare(...): Compares two numbers
- 6.2.2 IsEqual(...): Compares two values in one of nine specified modes
- 6.2.3 IsEmpty(...): Tests to see if a field is empty
- 6.2.4 IsRange(...): Tests a value for inclusion within a given range
- 6.2.5 IsMissing(...): Tests to see if a file exists on the system
- 6.2.6 IsRemovable(...): Tests to see if a file is stored on removable media
- 6.2.7 IsInPlayingNow & IsPlaying(...): Tests to see if a file is in the Playing Now playlist or currently being played
- 6.3 Formatting Functions
- 6.3.1 Delimit(...): Outputs a value with head/tail strings when value is non-empty
- 6.3.2 FormatBoolean(...): Formats a boolean (true / false) value in a specified manner
- 6.3.3 FormatDuration(...): Presents a duration of seconds in a reader friendly format
- 6.3.4 FormatFileSize(...): Presents a number of bytes in a reader friendly format
- 6.3.5 FormatNumber(...): Formats a number to a specified number of decimal places
- 6.3.6 FormatRange(...): Formats a value as a range
- 6.3.7 Orientation(...): Outputs the orientation of an image
- 6.3.8 PadNumber(...): Adds leading zeros to any given number
- 6.3.9 RatingStars(...): Outputs Rating as star characters
- 6.3.10 Watched(...): Outputs a formatted bookmark position within a video
- 6.4 String Manipulation
- 6.4.1 Clean(...): Returns a cleaned up version of a filled in template
- 6.4.2 FixCase(...): Changes the case of a given string
- 6.4.3 FixSpacing(...): Intelligently splits adjacent camel-cased words
- 6.4.4 Hexify(...): Hexifies a string to make it suitable for website usage
- 6.4.5 Left(...): Retrieves a specified number of characters from the left of a value
- 6.4.6 Length(...): Returns the number of characters in a string
- 6.4.7 Mid(...): Retrieves specified characters from a value.
- 6.4.8 Regex(...): Regular expression pattern matching and capture
- 6.4.9 RemoveCharacters(...): Removes specified characters from a given field or string
- 6.4.10 RemoveLeft(...): Trims characters from the start of a value
- 6.4.11 RemoveRight(...): Trims characters from the end of a value
- 6.4.12 Replace(...): Replace or remove strings from a value.
- 6.4.13 Right(...): Retrieves a specified number of characters from the right of a value
- 6.5 List Manipulation
- 6.6 Date & Time Functions
- 6.7 Other Functions
- 6.7.1 Counter(...): Counts upwards in specified increments
- 6.7.2 CustomData(...): Sequence numbering when renaming files
- 6.7.3 FileName(...): Returns the name from a specified file name
- 6.7.4 FileFolder(...): Returns the name of a parent sub-folder from a specified file path
- 6.7.5 Load(...): Outputs the value of a global variable
- 6.7.6 Math(...): Evaluates a given mathematical formula
- 6.7.7 Note(...): Retrieve information from a note
- 6.7.8 Save(...): Saves a value to a global variable
- 6.7.9 Tag(...): Returns a physical file tag (rather than looking in the database)
- 6.7.10 TVInfo(...): Returns television-specific information about a file
- 6.8 Redundant Functions?
- 6.8.1 Field(...): Returns the value of a library field
- 6.8.2 FilePath(...): Returns the path from a specified filename
- 6.8.3 FileVolume(...): Returns the volume name from a specified filename
- 6.8.4 AlbumKey(...): Returns a unique album key for a file
- 6.8.5 AlbumArtist(...): Returns the calculated album artist for a file
- 6.8.6 AlbumType(...): Returns the album type for a file
- 6.8.7 Size(...): Returns the size of a file in a media type independent manner
- 6.8.8 TrackNumber(...): Returns the track # of a file
Using this page
The 'Contents' box above contains a list of available functions roughly grouped by usage scenario, and each function name gives a fair indication of what it might do. Each of the group headers contain some basic information pertinent to the functions inside the group. Click on a function or function group header in the Contents box to be taken directly to more information about it on the page. At the bottom right of each section there is a "Back to top" link which will take you back up to the Contents box allowing you to quickly get to where on the page you would like to go next.Some of the function descriptions reference other functions to help illustrate their usage. Where this happens, a link to the referenced function is provided if needed. The browser's "Back" button will then return you to the previous place you were at on the page.
The page contains some references that link to external pages. Such links can be identified by the little square icon that follows them, like this--->. These links will not load in new tabs or windows, so, if you would like to keep this page open in your browser, right click on these links and choose to open them in a new tab or window.
Overview
The J. River Media Core database engine supports Excel-style functions for use in view schemes, searches, displayed columns, and tag editing.
An expression is a mixture of text, fields, and functions. A function allows special operations to be performed. Functions are all listed with a name followed by an opening and closing parenthesis. When building expressions, the instructions you wish to pass to the function are placed inside these parenthesis, with multiple instructions separated by commas. When your expression is evaluated, any spaces entered after a comma are ignored. This allows you to compose complex expressions on multiple lines, making it easier to keep track of where you are in your expression. Occasionally, you will find that you want a space, or parenthesis character to be treated literally as part of your instructions, rather than expression syntax, and in these cases, the character is "escaped" by using a preceding forward slash. Examples using this escaping can be seen here and here. As you progress with your expression building, you will begin nesting multiple functions into a single expression; always remember that a completed expression must contain a matching number of opening and closing parenthesis in order to work reliably.
The functions available to us range from highly functional, with a broad range of applicable uses, through specialised, limited use functions that only appeal to a select group of users, to seemingly redundant functions and obscure functions that Media Center uses internally. The functions below are listed with those with the broadest appeal at the top, and the more obscure at the bottom.
Any given expression can only work on any given single file. It is not possible to compare a field in one file with a field in another file.
Batch file operations are possible, and when used in a list, even a grouped list, an expression will be applied to each individual file in turn, not as a group.
A slightly extended overview is also available elsewhere in this wiki, titled Database Expressions, and another page attempts to demonstrate Media Center mimicking the "AND", "OR" and "XOR" database searches.
Using expressions
Expressions are ubiquitous in Media Center, and are useful in a variety of locations such as the following:
- Player Display (right-click the Player Display , choose "Customize")
- Captions & Thumbnail text
- Panes (aka Categories)
- Expression columns (right-click a column header and choose "Add expression column")
- The library field manager (Create expression-based library fields)
- Theater View
- Link manager (Use expressions to format link URLs)
- Rename, Move, & Copy Files tool
The syntax of the expression language is generally consistent throughout Media Center. An expression is evaluated, formatting output that is used in the context where the expression was evaluated. To perform Tag assignment or Search rule filtering, an expression is modified slightly to work in these contexts.
Formatting output
To give usage examples for all of these locations is beyond the scope of this page, so a few tips should suffice to get those interested up and running.
- Using expressions to produce custom Thumbnail text makes it possible to display only relevant or useful data.
- Expressions can be used to reduce link bar clutter by conditionally displaying links based on, for example, Media Type.
- File and directory paths may be based on expressions; this is especially useful in Options > File Locations, and in the "Rename, Move, & Copy Files" tool.
- User-specified library fields may be calculated, based on the output of expressions.
Tag assignment
The output of an expression can be used to assign a value to a tag. This is accomplished by preceding the expression with an "=" character. The "=" character causes the tagging engine to invoke the expression evaluator first, and then to use its output as the value to assign to the tag. Without the prepended "=" character, the expression itself (and not its evaluated value) would be stored in the tag.
An assignment expression can be entered into the Tag Action Window, or by using inline editing in the file list or a pane entry.
Note: Undo is supported, reverting each tag to its value prior to the assignment. Redo is also supported, reapplying the most recent Undo.
The following screenshots illustrates using an expression for tag assignment:
Search rule filtering
Expressions can be used as search filters, and in order to do so, the expression must be entered into the search field using the following format:
[=EXPRESSION]=1 or [=EXPRESSION]=0
All files that match the expression will return "1" and all that don't match, return "0". Decide which is required and use "1" or "0" accordingly.
Remember that the search field appears in many places throughout Media Center, places that include:
- The search field itself (in the top right corner of the program)
- A view scheme search list
- "Edit Files To Show" area of the Customize View dialogue
- Play Radio Files
- The last.fm submission filter
- The links manager
and this method of expression application can be used in all of them.
An example of an expression formatted for use in the search field would be: [=isequal(formatdate([date imported,0],MM//yyyy),formatdate(now(),MM//yyyy),1)]=1 Which will list all files that have been imported this month.
Specify data types for expression based fields
It is often useful to force Media Center to operate on data of one type as if it were another type. This is useful for changing sort order, or handling list data as a simple string. For example, month names are sorted alphabetically by default, but by setting the data type, sorting can be chronological instead. Data types are forced by appending to an expression the string: &datatype=[DATA TYPE], where DATA TYPE is one of the following values:
- List: A list of strings, separated by semicolons
- String: Sorts as strings (with smart number handling)
- Number: Sorts values as numbers (decimal or integer)
- Integer: Sorts values as integers
- Path: Sorts using a smart filename compare style
- Month: Sorts string month names (i.e. January, February, etc.)
The following screen images show these data type instructions in action:
&DataType=[Month] | &DataType=[List] | |||
---|---|---|---|---|
Fields
Any text between brackets [] will be replaced with the corresponding field from your library. As an example, [Artist] would be replaced by Bob Dylan for any Bob Dylan tracks. If the text between brackets doesn't match any known fields, it will be left alone, [My Fake Artist] will be treated literally, square brackets and all. After the field name, a comma can be placed followed by a 0 or 1 to indicate whether the field should be formatted. So, [Duration] and [Duration, 1] will give "4:02" while [Duration, 0] will give "242". This is particularly important when working with the "Format" functions, where most times you will want the evaluator to work with the raw field contents rather than the formatted contents you see in the file list.
Function and field values in expressions are not case-sensitive. Available functions with descriptions and examples are listed below.
Functions
Conditional Functions
The functions in this section evaluate one or more of their arguments to determine if their result is true or false, and execute specific actions depending upon that result.
Although the expression language does not directly support AND, OR, and XOR, these can be easily emulated. See: Database_Expressions_AND_OR_And_XOR.
Beginning with version 17.0.40, Media Center supports the NOT operator (a ! character) in a conditional. This can be used to invert the sense of an If() statement for easier reading, or in an IfElse() to better support if-then-else chains.
If(...): Conditional If/Then/Else evaluator.
If() | This will be the function you will likely use more than any other. It is typically used in conjunction with one or more other functions and allows you to give specific instructions depending upon whether the result is positive (1) or negative (0). The positive instruction is always given first. |
---|---|
Construction | if(expression to test,instructions if positive,instructions if negative) |
Examples | if(isequal([artist],bob dylan,1),Genius,Mediocre) Wherever this expression is applied, be it as an expression column or category, as part of a renaming rule, thumbnail text, if the artist tag is Bob Dylan, Media Center will produce Genius, and for all other artists, it will produce Mediocre. The "IsEqual()" function is described in the first table below.
|
IfElse(...): If/Then/Else sequence of conditional tests and actions.
IfElse() | The IfElse() conditional (available since build 17.0.7) provides a convenient mechanism for shortening and more clearly expressing nested conditionals into an alternating sequence of tests and actions. For example, consider a nested sequence of If() tests such as If(test1, action1, If(test2, action2, If(test3, action3))), shown below in a sequence of if/then/else pseudo-code statements:
The IfElse() statement may be used to more cleanly express the flow of expression by removing the superfluous internal If() statements: IfElse(test1, action1, test2, action2, test3, action3) |
---|---|
Construction | ifelse(test expression 1,instructions 1,test expression 2,instructions 2, ...) |
Examples | ifelse(isequal([media type], Audio), Le Tunes, isequal([media type], Video]), Flix)
If media type is audio, outputs "Le Tunes", else if media type is video, outputs "Flix"
This example, implements the nested if statements from the If() section above, first testing if the artist is Bob Dylan, and if true, outputs "Genius", otherwise evaluates the second test to determine if the album is "Joshua Tree", and if true, outputs "Great Album", otherwise, performs a final test, in this case a degenerate test of 1 (and 1 is always true), thus outputting the value "Mediocre". |
Query, Test and Comparison Functions
All of the functions in this section, when used on their own, will only ever return one of two values, 1 (true) or 0 (false). There is a "FormatBoolean()" function that can be wrapped around these and allows us to specify the output for each case and is discussed in more depth in the Format section. The real power and versatility of these "Is" functions is released when they are wrapped inside the If() function discussed above.
Compare(...): Compares two numbers
Compare() | Compares two numbers, using the operators less than (<), greater than (>), or equal to (=). Outputs 1 if the comparison is true, and 0 otherwise. Available starting with MC17. |
---|---|
Construction | compare(1st number, operator, 2nd number)
Available Operators:
|
Examples | compare([bitrate], <, 320) If the 'bitrate' is less than 320 (Kbps), the output will be 1, otherwise, the output will be 0.
Shows the age of files under 21 days old, or shows 'Expired' for older files. |
IsEqual(...): Compares two values in one of nine specified modes
IsEqual() | Compares two values in one of nine specified modes ("exact match", "Is greater than" etc.) and outputs 1 for a positive match and 0 for a negative match. If no compare mode is specified, the compare will default to 0. |
---|---|
Construction | isequal(1st value to compare,2nd value to compare,compare mode)
Available Compare Modes:
In all cases, the first value is always compared with the second value, never the other way around |
Examples | isequal([artist],[album],1) If the 'artist' and 'album' values are the same, the output will be 1, otherwise, the output will be 0.
|
IsEmpty(...): Tests to see if a field is empty
IsEmpty() | Tests any given field for data. If the field is empty, the function returns 1, and if populated, the function returns 0. There are two different test modes available, a "string" test, and a "number" test. This is because as far as Media Center is concerned, fields designated as containing numerical values that are populated with the number zero, are empty. If no test mode is specified, the function will default to 0.
Pay particular attention to the third example offered below, as it covers a caveat that comes with this particular function. |
---|---|
Construction | isempty([field to test],test mode)
Available test modes:
|
Examples | isempty([comment],0) If the comment field is empty, this expression will return 1, but if the comment field contains data, the expression will return 0.
|
IsRange(...): Tests a value for inclusion within a given range
IsRange() | IsRange allows us to test if any given field falls inside any given range of values. If the field falls inside the given range, the function returns 1, and if outside the given range, the function returns 0. |
---|---|
Construction | IsRange([Field to Test],Specified-Range)
The range to test for can be letters or numbers, separated by a hyphen, without spaces, lowest value first, highest second. Letters and numbers cannot be mixed, the range can only be one or the other
|
Examples | isrange([artist],a-c) Abba or Blondie will return 1 (positive), and ZZ Top will return 0 (negative).
|
IsMissing(...): Tests to see if a file exists on the system
IsMissing() | This function tests the existence of a file in the file system. If the file is missing, the function returns 1 (positive), and if the file is found, the function returns 0 (negative). This function is useful for checking the integrity of your Media Center library as you can use it to produce a list of any files in your library that Media Center cannot find. Beginning with version 17, IsMissing() treats special entries such as ripped Blu-ray or DVDs as single files, even though they physically exist in the file system as several files and directories.
Note: IsMissing() works directly on the file system and will cause performance to suffer: the larger the library, the longer it will take to produce results. |
---|---|
Construction | IsMissing(Full Path To File)
Checks for existence of the file "Full Path To File", or the current file if unspecified. |
Examples | ismissing() Checks if the current file exists, and returns 1 (positive) if the file does not exist, and 0 (negative) if the file does exist.
|
IsRemovable(...): Tests to see if a file is stored on removable media
IsRemovable() | Checks to see if a file resides on removable media and if so, returns 1 (positive), and if not, returns 0 (negative). There is not a lot to say about this function, especially since Media Center comes equipped with a [Removable] field by default that is automatically populated with 1 for all files in the library that are on removable storage. The function works in exactly the same way as the IsMissing function described above, returning 1 (positive) if the file is on removable storage, and 0 (negative) if not. |
---|---|
Construction | IsRemovable(Full Path To File)
If no file path is specified, the function will default to checking the current file. |
Examples | isremovable() Checks if the current file is on removable storage, and if so, returns 1 (positive), if not, the function returns 0 (negative). |
IsInPlayingNow & IsPlaying(...): Tests to see if a file is in the Playing Now playlist or currently being played
IsInPlayingNow() | These two functions will be dealt with together as from their names, they are self-explanatory. One checks to see if a file has been added to the playing now list in any zone, and the other checks if a file in a list is currently playing or not, in any zone. With this in mind, their most practical use is as expression columns in a file list. To add an expression column to a list, right click on any existing column header and click on the "Add expression column" option. |
---|---|
IsPlaying() | |
Construction | IsInPlayingNow() Checks the current file, and if in the Playing Now list, returns 1 (positive), and if not, returns 0 (negative).
|
Examples | if(isinplayingnow(),Selected,Not Selected) As mentioned in the description, the ideal place for these functions is as 'expression columns'. If this example were used in an expression column, then files added to Playing Now will show as "Selected" and all other files would show as "Not Selected". If the idea here is to be able to quickly see which files have been added, this might look a bit 'busy' and defeat the purpose, to which end, it is perfectly acceptable to tell the expression that if a file is not in Playing Now, to output nothing, by simply not giving any instructions for the negative result, like so: if(isinplayingnow(),Selected,). Now, this expression column will only show "Selected" against files that are in Playing Now, leaving all others empty, giving a much easier column to read.
|
Formatting Functions
All of these functions (with the exception of FormatBoolean) take raw data from the library and allow us to present that data in a way that we choose. What does "raw data" mean? Media Center stores duration information in seconds and converts that information into hours (if needed), minutes and seconds for display in the Duration column in a file list. Likewise, file size information is stored in bytes and is converted into Mb for display in the file list. So there you have it, raw data. The following section gives some idea of what is possible using the raw data and the Format functions. To instruct the expression evaluator to use raw data, a zero is added to the library field, inside the square brackets, like so: [Date Imported,0]
Delimit(...): Outputs a value with head/tail strings when value is non-empty
Delimit() | Delimit() outputs a value if the value is non-empty, including head and/or tail strings. Nothing is output when the value is empty. |
---|---|
Construction | Delimit(Value,Tail string,Head string)
|
Examples | delimit([Track #], .) Appends a period (.) after a track number if [Track #] is not empty, e.g. "12.".
Outputs the year surrounded by curly braces, e.g. "{2012}". |
FormatBoolean(...): Formats a boolean (true / false) value in a specified manner
FormatBoolean() | This function is wrapped around another function and will return specified strings for true and false values returned by that other function. |
---|---|
Construction | FormatBoolean(True/False Test,String to use if true,String to use if false)
|
Examples | formatboolean(isempty([number plays]),Never Played,Has Been Played) On it's own, the function isempty([number plays]) will return either 1 or 0. When wrapped inside a formatboolean function as shown here, the output for a true result will be "Never Played", and for a false result, the output will be "Has Been Played".
|
FormatDuration(...): Presents a duration of seconds in a reader friendly format
FormatDuration() | Media Center stores duration data in seconds, at up to sixteen decimal places. The value shown in the default "Duration" column in a file list is an internally formatted interpretation of this raw "Duration" data. As Media Center automatically applies this formatting for us, there is not a lot of call for this particular function. |
---|---|
Construction | FormatDuration(Value to format)
"Value to format" can be either the raw duration data, or a given number of seconds |
Examples | formatduration([duration,0]) This expression will duplicate the contents of the default [duration] field as shown in a file list
|
FormatFileSize(...): Presents a number of bytes in a reader friendly format
FormatFilesize() | Media Center stores file size data internally in bytes. This function will convert those byte values into reader-friendly values, 3.2 Kb or 10.4 Mb, for example. The function will also accept a byte value directly. |
---|---|
Construction | FormatFileSize(Value to format)
"Value to format" can be either the raw [File Size] data or a given number of bytes. |
Examples | formatfilesize([file size,0]) This expression will duplicate the contents of the default [file size] field as shown in a file list
|
FormatNumber(...): Formats a number to a specified number of decimal places
FormatNumber() | FormatNumber() allows to format any given value to a set number of decimal places. |
---|---|
Construction | FormatNumber(Value to format,Number of decimal places,Output if value is zero,Label if value is greater than 1,Label if value equals 1)
Note that even if you are only interested in applying a label for those results that equal 1, you must also indicate the preceding instructions, if only to instruct the evaluator to ignore them, as shown in the examples below. |
Examples | formatnumber([duration,0],2) This will return the duration of a track, in seconds, shown to two decimal places.
|
FormatRange(...): Formats a value as a range
FormatRange() | This function places any given value into its place in any given range. |
---|---|
Construction | FormatRange(Value to format,Range size,Mode)
Value to format: This could be a specific word or number, or any library field
|
Examples | formatrange([artist]) This will return the first letter from the [artist] field. Note that as range size and mode values were not specified, the function defaulted to one and automatic respectively.
Note that this function always starts number ranges from zero, 0-9, 10-19, etc, etc.. If you really need a number grouping that starts from 1, 1-10, 11-20, 21-30,etc. etc., you can use expressions to create a pseudo range. Full details, with a helpful explanation, of "1 based grouping" can be found on this page. |
Orientation(...): Outputs the orientation of an image
Orientation() | Outputs a word indicating the orientation of an image file. |
---|---|
Construction | Orientation()
|
Examples | if(isequal(orientation(), Square), Square, Rectangle)
Outputs "Square" for square images or "Rectangle" for portrait and landscape images. |
PadNumber(...): Adds leading zeros to any given number
PadNumber() | This function is not a 'Format' function by name, but is by nature, hence its inclusion in this section. PadNumber is a nice, simple function that is used to add leading zeros to any given number value. |
---|---|
Construction | PadNumber(Field to pad,Total number of digits required) |
Examples | padnumber([track #],2) This will add a leading zero to all track numbers between one and nine.
|
RatingStars(...): Outputs Rating as star characters
RatingStars() | This function outputs the Rating field's value as the equivalent number of black star characters. |
---|---|
Construction | RatingStars() |
Examples | ratingstars() For a file that has a Rating of 4, outputs "★★★★". |
Watched(...): Outputs a formatted bookmark position within a video
Watched() | Outputs a video's bookmark position in a human-readable format. |
---|---|
Construction | Watched()
|
Examples | Watched()
Outputs formatted watched status, such as, 57% on Sep 25, or Aug 21, or nothing when the video has not been watched. |
String Manipulation
The primary use of the functions in this section is to manipulate the data associated with any given file or files. When used with direct editing in the file list, or in the action window, as decribed here, they offer extremely fast and efficient methods for batch editing the actual tag data associated with multiple files.
Note that when used indirectly, in expression based columns, categories or library fields, the referred fields are not altered in any way, the data is merely presented in the expression field formatted as requested.
Clean(...): Returns a cleaned up version of a filled in template
Clean() | The Clean() function is used to generally strip empty bracketing, superfluous dash characters, leading or trailing articles, or replace filesystem-illegal characters. It is typically employed to clean the joining of several fields, some of which may be empty, or to produce filesystem-safe filenames. |
---|---|
Construction | Clean(Value to clean, Mode)
Value to clean: a string that will be cleaned Mode (optional, defaults to 0):
|
Examples | Clean([Album] - [Date])
Consider the simple expression [Album] - [Date]. When the [Date] value is empty, the result will contain the undesirable dangling separator string " - " following the album name (e.g. "Greatest Hits - "). Using Clean() in the default mode removes this dangling string, and in this example produces "Greatest Hits".
|
FixCase(...): Changes the case of a given string
FixCase() | This function will output any given text string in one of five specified case modes. |
---|---|
Construction | FixCase(String to modify,Case mode to apply) The "String to modify" can be plain text, a library field, or a combination of the two. The five modes available are:
If no case mode is specified, the function will default to using "Title Case". Title case will start each principal word with a capital. More detail regarding title case can be found here |
Examples | fixcase([album]) This will take the contents of the [album] field and present it with the specified capitalisation. As there is no specified mode here, the function defaults to 0, so, if an album is entered in the library as "Time Out Of Mind", the function will return "Time Out of Mind" (note the lower case "of")
|
FixSpacing(...): Intelligently splits adjacent camel-cased words
FixSpacing() | This FixSpacing() function inserts spaces between adjacent camel-cased words. For example, OneWorld becomes One World. This function is useful for helping to clean and convert metadata that favors compactness over standard sentence structure. |
---|---|
Construction | FixSpacing(String to convert, Mode) The "String to convert" is any string of text. The available modes are:
|
Examples | fixspacing([name], 1) Takes the contents of the [name] field and expands any camel-case into standard sentence structure. E.g. MiracleOn34thStreet becomes Miracle On 34th Street.
|
Hexify(...): Hexifies a string to make it suitable for website usage
Hexify() | The only place this function is likely to be used is in the "Link Manager". Websites often don't like spaces in their addresses, and punctuation could confuse a site's search engine. Hexify attempts to take care of this by replacing spaces and punctuation with web friendly alternatives. For example, Bob Dylan would become Bob%20Dylan. |
---|---|
Construction | Hexify(Value to hexify) |
Examples | hexify([artist] - [album]) Oasis - (What's The Story) Morning Glory? becomes: Oasis%20-%20%28What%27s%20The%20Story%29%20Morning%20Glory%3F |
Left(...): Retrieves a specified number of characters from the left of a value
Left() | This function retrieves a specified number of characters from the left of any given value. |
---|---|
Construction | Left(Value to get characters from,Number of characters to get) "Value to get characters from" can be plain text, a library field, or combination of both. If more characters than exist are requested, all available characters are returned. |
Examples | left([filename],3) This will return the drive letter, colon and first back-slash from the filename. If asked to show more characters than actually exist, the expression will return the entire value, also, remember that spaces count as characters too. |
Length(...): Returns the number of characters in a string
Length() | This function returns the number of characters in any given string. |
---|---|
Construction | Length(String to count characters from) The "String to count characters from" can be plain text, a library field, or a combination of the two. |
Examples | length([filename]) This will count the characters in the [filename] field and return the result. Spaces count as characters, so, C:\My File.mp3 would return 14.
|
Mid(...): Retrieves specified characters from a value.
Mid() | Mid() retrieves a specified number of characters from a specified starting point in any given string. |
---|---|
Construction | Mid(Value to get characters from,Character to start at,Number of characters to get)
|
Examples | mid(12345) As values for "Character to start at" and "Number of characters to get" have not been specified, they default to 0 and 1 respectively and the function returns the first character in the string, 1.
|
Regex(...): Regular expression pattern matching and capture
Regex() | This function performs regular expression (RE) pattern matching on its input. It can be used in one of three different modes: a test mode to test for a match, a capture output mode to output the specified captured pattern, and a silent, capture-only mode. All match captures are placed into special variables referenced as [R1], [R2], ... [R9], which can be used in subsequent expressions. The contents of the captures [R1] ... [R9] are available until the entire expression completes, or Regex() is run again, whereby they are replaced. The regular expression implementation used is the Microsoft 2010 TR1 engine. (Available since build 16.0.155.) |
---|---|
Construction | Regex(String to test, Regular expression, Mode, Case sensitivity)
|
Examples | Example: Modes 1 through 9
The examples in this section use one of the modes from 1 through 9, to output the specified capture. Regex([Name], /#(Big.*Man)#/, 1) Matches track names that contain Big followed by Man, with anything (including nothing) in between, and outputs the matched tracks. Sample output:
‾‾‾‾ Regex([Artist], /#([(].+)$#/, 1) Matches against the Artist field and returns items that contain an opening (left) parenthesis followed by additional characters until the end of the artist string. Only the sub-string from any opening parenthesis until the end of the string will be returned, since this is the only captured portion. Sample output:
‾‾‾‾ Regex([Name], /#([(][^)]+)$#/, 1) Similar to the previous example, but matches track names that contain a opening (left) parenthesis, but are missing the closing (right) parentheses through the end of the track name. This might be useful to help detect tagging inconsistencies Sample output:
Examples: Mode 0 The examples in this section use mode 0, to test if a string does or does not match the pattern. The result of the test may be used to drive a conditional statement such as an if() statement. if(Regex([Artist],/#([[:punct:]])#/, 0),[R1] --> [Artist], No Punctuation) Matches against the Artist field looking for any punctuation character. The results of the Regex() expression will be a 0 (false) or 1 (true) since the mode is set to 0, The true side of the if() test is set to output the first (and only) capture, which is expressed as [R1], and is followed by the string " --> " and then the artist name. In the false case, the string "No Punctuation" is output. Sample output:
‾‾‾‾
if(Regex([Artist], /#([[:punct:]])#/, 0),
A more complex example, similar to the previous one. When used inside an expression column, builds an expandable tree with headings Contains Punctuation and No Punctuation that group artists based on whether or not their names contain any punctuation characters. Because semicolon and backslash are list separator characters for the expression language, for the example expression to work properly, these must be replaced (otherwise the list will not build as desired). In the list of punctuation, both backslash and semicolon characters have been replaced with their English equivalent words. In artist names, a semicolon is often used as a separator between the main artist and featured artists, so the expression replaces semicolons within an artist name with the word "and". Likewise, backslashes have been replaced with forward slashes. Sample output:
‾‾‾‾ if(Regex([Album], /#^([^-]+[^\s])- (.*)$#/, 0), [R1]: [R2], / No Change Necessary) Some album names contain characters that are not legal in Windows, and after pulling properties from the file name, such characters will be translated into a dash "-" character (e.g. "Staring at the Sea: The Singles" becomes "Staring at the Sea- The Singles"). If you'd like to identify such possibly re-named album, an expression such the one above might help. The expression matches characters from the beginning of the line that do not contain a dash, followed by a non-space character, followed by a dash, space and everything else. Wrapped in an if() statement, these file names become apparent in an expression column. Examples: Mode -1 The examples in this section use mode -1, which cause Regex() to suppress output. This mode is only useful with captures, where the captures are utilized in subsequent portions of an expression. The previous example (which helped to identify album titles that may have been changed after tags were updated from file properties) used mode 0 to guide an if() evaluation. By using that expression column and selecting only the files whose album name should be changed, the identical Regex() statement can be used to easily fix the album property by changing the mode from 0 to -1: =Regex([Album], /#^([^-]+[^\s])- (.*)$#/, -1)[R1]: [R2] Editing the Album tag and pasting the expression above into the edit field will set the munged album name to use a colon rather than dash. Note: take care to select the correct files, and ensure the tags were changed as desired. Use Undo if not. A safety mechanism can be installed into the tag assignment. By using the same Regex() statement from the last mode 0 example, and setting the false side of the if() statement to [Album], the expression would effectively only change those files whose album names matched the pattern. Non-matched album names would be assigned to themselves, essentially acting as a no-op. For completeness, that statement would be: =if(Regex([Album], /#^([^-]+[^\s])- (.*)$#/, 0), [R1]: [R2], [Album]) ‾‾‾‾ Matches and captures a date formatted as dd.mm.yyyy anywhere within a filename, and rearranges it in a standard format of yyyy/mm/dd. Since Mode is set to -1, no output occurs. However, captured match segments are made available for subsequent use. The three captures, [R1], [R2] and [R3] are arranged in the textual output such that the year, month and day ordering are as desired. Sample output:
‾‾‾‾ Regex([Name], /#^(.+?) \(([^(]+)\)$#/, -1)[R2]: [R1] This example shows how rearranging segments of track titles can help call out naming inconsistencies. The expression captures parenthetical information at the end of a track, and moves it to the beginning. In an expression column, inconsistencies become clearer. Sample output:
‾‾‾‾ listbuild(1, \, Regex([Name], /#^(.+?) \(([^(]+)\)$#/, -1)[R2],[R1])&datatype=[list] Wrapping the previous expression in a listbuild() to create an expandable list provides quick grouping for even easier spotting of naming irregularities, especially when combined with Search to reduce the list size. |
RemoveCharacters(...): Removes specified characters from a given field or string
RemoveCharacters() | This function will remove specified characters from a given field or string using one of three specified modes. (Available in build 16.0.148 onwards.) |
---|---|
Construction | RemoveCharacters(String to test,CharactersToTestFor,Mode)
Available Modes:
|
Examples | RemoveCharacters(Paper,Ppr,0) This will result in "ae" as P, p and r are removed. RemoveCharacters(Paper,Ppr,1) RemoveCharacters(Paper,Ppr,2) RemoveCharacters(Paper,Ppr,3) RemoveCharacters([artist],/(/),) |
RemoveLeft(...): Trims characters from the start of a value
RemoveLeft() | The output from this function will remove a specified number of characters from the start of any given value. |
---|---|
Construction | RemoveLeft(Value to remove characters from,Number of characters to remove) |
Examples | removeleft([name],5) This would show the name field, with the first five characters removed. If asked to remove more characters than actually exist, the output will be blank, also, remember that spaces count as characters too.. |
RemoveRight(...): Trims characters from the end of a value
RemoveRight() | The output from this function will remove a specified number of characters from the end of any given value. |
---|---|
Construction | RemoveRight(Value to remove characters from,Number of characters to remove) |
Examples | removeright([name],5) This would show the name field, with the last five characters removed. If asked to remove more characters than actually exist, the output will be blank, also, remember that spaces count as characters too.. |
Replace(...): Replace or remove strings from a value.
Replace() | Quite simply, this function allows to search for a specified string in a specified value, and if found, remove the specified string, or replace it with another. |
---|---|
Construction | Replace(Value to check,String to check for,String to replace with)
|
Examples | replace(My Sample String,S,Replaced ) All instances of upper-case "S" will be replaced by the text "Replaced ", (note the trailing space), resulting in "My Replaced ample Replaced tring"
|
Right(...): Retrieves a specified number of characters from the right of a value
Right() | This function retrieves a specified number of characters from the right of any given value. |
---|---|
Construction | Right(Value to get characters from,Number of characters to get) "Value to get characters from" can be plain text, a library field, or combination of both. If more characters than exist are requested, all available characters are returned. |
Examples | right([filename],3) This will return the last three characters from the filename. If asked to show more characters than actually exist, the expression will return the entire value, also, remember that spaces count as characters too. |
List Manipulation
The default Media Center library contains many fields that are referred to as "list type" fields. Users are also able to add their own "list type" fields to their libraries. A list type field contains one or more text items seperated by semi-colons. The semi-colons are referred to as the 'delimiter' and when displayed in a view category, text items seperated by semi-colons are displayed in a list of seprately selectable items. The "Keywords" field is a classic example of a list type field, which demonstrates how list type fields allow a single file to be tagged with many different keywords, as opposed to a 'standard' field, such as 'Genre', where a single file can only be tagged with a single genre. The following functions provide the ability to combine or build custom list type fields using the default semi-colon delimiter, or a specified delimiter, count the number of items contained in a given list, or extract a numbered entry from within a list. Two of the functions listed in this section are used to create "list type" data from two or more existing sources and could reasonably be considered to be functions more suited to those who are very familiar with Media Center and how it gets its job done. If these functions are used to create a new 'calculated data' library field, they will not function as 'list type' fields unless the field is first created as a "User Data" field, with "List Type" specified. After creating the field in this way, it is possible to go back and edit the field, changing it to "calculated data" and entering an expression to be used. The "Eureka moment" occurred in November 2009.
ListBuild(...): Build a list from a series of values
ListBuild() | This function provides the ability to create a single list from many different sources and allows a list delimiter to be specified. It has two modes that can be applied and are detailed below. Of these two modes, mode "0" (Combine all values) should be avoided. It has been included for 'function completeness' only, and when used, can produce some very strange results that do not filter as expected. In order for the data generated by this function to be treated as list data, the 'datatype' must be specified as [list]. |
---|---|
Construction | ListBuild(Mode,Delimiter,Items,To,Include) Mode: There are two different modes available:
Delimiter: The character used here will be used as a delimiter between each of the specified list items. To be clear, the keywords field uses a semi-colon delimiter by default; if a list is built using keywords and genre, and the specified delimiter is a back slash, it will be used between the keywords and genre fields when joining them, the semi-colons in the keywords field would not be altered. For example, if [keywords] contained "these;are;keywords" and [genre] contained "Rock", and these two were joined using ListBuild with a "\" specified as the delimiter, the resulting data would be "These;are;keywords\Rock". The real beauty and power of this function can be released when expressions are nested into the ListBuild instructions. For example, "listbuild(1,\,replace([keywords],;,\),[genre]" would return the data "These\are\keywords\Rock"
|
Examples | listbuild(1,;,[keywords],[genre])&datatype=[list] This will return a semi-colon delimited list containing all keywords and genres. If either keyords or genre is empty, they will be ignored, so, the data returned for a file with no keywords, and a genre of "Rock" would be simply "Rock".
|
ListCombine(...): Combines two delimited lists into a single delimited list
ListCombine() | Unlike the ListBuild function above, which can be used to create a list from any number of varying sources, ListCombine() is used to merge two specified lists into one. In order for the data generated by this function to be treated as list data, the 'datatype' must be specified as [list]. |
---|---|
Construction | ListCombine(First list,Second list,Input Delimiter,Output Delimiter) First List and Second List are specified library fields. Input Delimiter: This is the value that will be used to join the two specified lists. The value is optional, and if not specified, the function will default to using a semi-colon. Output Delimiter: This value is also optional. If specified, the function parses the output list (the result of the two lists, joined by the input delimiter) and replaces each occurrence of the input delimiter with the specified output delimiter. |
Examples | listcombine([people],[places])&datatype=[list] The result here would be a single, semi-colon delimited list containing all the values from the [people] and [places] fields.
|
ListCount(...): Returns the number of items in a delimited list
ListCount() | ListCount is used to return the number of items that exist in any given field, using any given delimiter. |
---|---|
Construction | ListCount([Field to count],Delimiter to use) Field to count: Typically, this will be a list type field, but this is not compulsory. The data in any field can be parsed using any chosen delimiter Delimiter to use: This is optional. If not specified, the function will default to using a semi-colon delimiter. Anything can be specified as a delimiter, from a single character to a whole word or words. |
Examples | listcount([People]) No delimiter has been specified here, therefore the function will default to using a semi-colon. The result here will match the number of people shown in a properly tagged photo. Note that the function is smart, so, if a file has no [People] tag, the function will return zero (0), and if it has [People] data, but no semi-colon, the function will return one (1).
|
ListItem(...): Returns a specified value from a delimited list
ListItem() | This function numbers list items starting from zero and returns the value of a specifically numbered item. |
---|---|
Construction | ListItem([Field],Number of item to retrieve,Field delimiter to use)
|
Examples | listitem([filename],0,\) This function will return a file's drive letter plus colon. Note that the same result could be achieved by using left([filename],2), there is no 'right' or 'wrong' with these things, just personal preference, or 'what works for you'. A good rule of thumb is to use the simplest possible way to get to your goal, as less typing is better, and the more simple the expression, the easier it is to follow.
|
Date & Time Functions
Media Center provides several functions for date and time conversion, formatting and generation. Internally, date and time for date fields is stored as a floating point number, where the integer portion represents the number of days since the Epoch, and the decimal portion represents the fraction of a day.
The Windows locale setting will affect the interpretation and formatting of date and time information.
ConvertDate(...): Converts a human-readable date to the internal format required for use in date fields
ConvertDate() |
Converts human-readable date / time strings into the floating point representation used internally by Media Center to represent date and time. |
---|---|
Construction | convertdate(Date string)
|
Examples | convertdate(3/6/2012) Converts the date March 6th, 2012 into a floating point number that can be assigned to a date field.
|
FormatDate(...): Formats a date value in a specified manner
FormatDate() | FormatDate provides custom formatting of date / time fields through the use of special format specifiers. Select from the available format specifiers, and arrange them to produce the desired date and time components. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Construction | formatdate(Date value, Format string, Output if date is empty)
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Examples | formatdate(year-month) Returns the file's date formatted as Year-Month. This uses the default [Date,0] field. Example: 2012-April.
|
Now(...): Retrieve and display the system date
Now() | Now() will return the raw system date. "raw" data is discussed in the Field description, and also in the introduction to the "Format" functions. As Media Center's raw date data is illegible, this function needs to be used with the "FormatDate()" function, which allows the current date, and time, if desired, to be presented in many different styles. |
---|---|
Construction | Now() |
Examples | formatdate(now(),date) Returns the current date, without the time, formatted according to the system settings on which the function is running.
|
Other Functions
The functions in this group are varied, and do not readily fit into the other groups of functions.
Counter(...): Counts upwards in specified increments
Counter() | This function can be used to number objects sequentially, from a specified starting point, in specified increments. The counter resets itself to zero after five seconds of inactivity. Counter() can exhibit a touch of wierdness when used in certain situations, which will be covered in the examples, that demonstrate why this one is not really a 'fits all' function. |
---|---|
Construction | Counter(Number to start counting from,Increments to count up in)
|
Examples | counter() This shows the function in its simplest form. The counter will start at one and count upwards in increments of 1.
|
CustomData(...): Sequence numbering when renaming files
CustomData() | The official description for this function goes as follows: "Returns custom data stored in a file array (used primarily for internal uses)." There is no recorded practical use for this function, with the exception of using it with a hash symbol in the library tool called "Rename, Move, & Copy Files". When used in the directory or filename rules of this tool, this function will number the files in the list from first to last, starting at number one. As long as any desired numbering is to begin at one, this function is a reasonable alternative to combat the wierdness demonstrated by the Counter() function, and could be particularly useful when renaming image files. If the numbering is required to start counting from anywhere other than one, then Counter() will need to be used, taking the wierdness and its work arounds into account. |
---|---|
Construction | CustomData(#) |
Examples | padnumber(customdata(#),4)_Christmas Party 2007 It's important to remember that this function will only work when used as part of the renaming rule for either filename or directory (or both) within the "Rename, Move, & Copy Files" tool. In this example, imagine 324 photos from the Christmas party of 2007 were selected for renaming, and this expression was entered into the filename field. The resulting filenames would be 0001_Christmas Party 2007.jpg through to 0324_Christmas Party 2007.jpg. Note how the "padnumber()" function has been used to add the leading zeros. |
FileName(...): Returns the name from a specified file name
FileName() | This function returns the file name for the files in a list, or for the specified file. A second parameter set to 0 will cause the suffix to be suppressed from the file name. The library field [Filename (Name)] already contains the value that would be returned by FileName(); it generally should be used rather than this function. |
---|---|
Construction | FileName(Filename to check, Suppress suffix)
|
Examples | filename(C:\Music\File.mp3) The result here would be... "File.mp3"
|
FileFolder(...): Returns the name of a parent sub-folder from a specified file path
FileFolder() | This function returns a parent sub-folder name from a file path. A value of Unassigned will be returned when the specified level exceeds the root of the path. |
---|---|
Construction | FileFolder(Filepath, Level)
|
Examples | filefolder() filefolder([Filename,0], 0) Returns the name of the file's parent folder.
|
Load(...): Outputs the value of a global variable
Load() | Loads and outputs the value of the specified global variable that has been previously stored with the Save() function. |
---|---|
Construction | Load(Variable)
|
Examples | load(var1) Loads and outputs the previous stored value of the global variable "var1". If "var1" has not been previously stored, the output will be empty.
|
Math(...): Evaluates a given mathematical formula
Math() | The Math() function provides the ability to perform mathematical calculations. In addition to the standard arithmetic operators, it also supports various numerical, trigonometric, and comparative functions. Simple variables are supported, as are multiple statements.
Variables may be assigned and used by specifying a simple string of letters. Examples: math(val=2) or math(x=pow(2,3)) Multiple equations may be specified, each separated by a semicolon. Expressions are evaluated left to right. The final value of the Math() function will be the result of the right-most equation. Example: math(x=4; pow(2^x))
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Construction | Math(Expression to evaluate) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Examples | math(10 + 4) Returns 14.
|
Note(...): Retrieve information from a note
Note() | Since build 14.0.111, Media Center has shipped with a "Notes" feature. One of the many uses available via notes is the ability to store contact information, and that information can be labelled. Labels are typical contact information labels such as "Home phone", "Work phone", "Email" etc. etc.. This function can retrieve and display the contents of specified labels from a note. |
---|---|
Construction | Note(Field Label,Field Type,Occurrance)
|
Examples | note(phone) note(phone,home) note(phone,home,1) Here are three sample notes expressions. In the image below, they have been used to create expression list columns, with each expression used shown in the column header. The note, with labels on show, is visible on the right hand end of the image. When comparing the note with the data returned by each expression, it should become apparent how each expression is working. |
Save(...): Saves a value to a global variable
Save() | Saves a value into the specified global variable, and optionally outputs the value. |
---|---|
Construction | Save(Value,Variable,Output value)
|
Examples | save(Much Money, local_bank) Saves the value "Much Money" into the global variable "local_bank".
|
Tag(...): Returns a physical file tag (rather than looking in the database)
Tag() | This function originally came into being as a need arose for there to be a way to re-import the exif date information from image files without affecting any other tags. To that end, the function works well, but that's really where it's functionality ends. Success with any other fields has been extremely limited indeed. The main reason for this is because, when using this function to query specific tag data blocks in an image file, the fields referenced by the tag() function must be spelled exactly as they appear in the tag block within the file, and yes, they are case sensitive. It is also extremely important to know that when building a file list that contains a "Tag()" derived column, Media Center will be inordinately slower, 1000's of times slower, in building that list than it would be without the "Tag()" column. This is because each and every file in the list must be queried individually for the contents of the specified tag. This particular function is best used using the "inline editing" method outlined in the "When, Where and How to use expressions" section of this page, to pull the desired data into the main library database and then reference the information from the database. |
---|---|
Construction | Tag(Field to read from the file) Specific tag data blocks from jpg files can also be referenced: Tag(Tag Block To Query: Field to read from the tag block)
|
Examples | tag(artist) This will return the artist information from a file if that file contains the artist tag
|
TVInfo(...): Returns television-specific information about a file
TVInfo() | Used to retieve and display specified televison information for a file. |
---|---|
Construction | TVInfo(Information to retrieve)
Information to retrieve: The options available for use here are:
|
Examples | TVInfo(namedisplay) Click on "Tools > Options > Theater View", then click on "Customize file info panel", then choose "Television Program" from the drop-list at the top. It is then possible to use this function to tailor the information displayed on screen in Theater view when looking at TV programs. Some of the default items already utilise this function offering real world, real time examples of their usage.
|
Redundant Functions?
Taken at face value, all of the functions in this section would appear to be a little on the redundant side, falling neatly into the "a long way for a shortcut" category. Media Center could possibly rely on these functions internally, exalting their status to "highly useful" or "essential" even, but as this page is designed for end users, not Media Center, end users will find these functions redundant, and they are included here in the name of completeness only.
Field(...): Returns the value of a library field
Field() | Place the name of any library field inside this function, and it will return the contents of that library field for each file. Entering the field name inside square brackets as normal, without the function, returns the same data.
Note: Beginning with version 17, Media Center no longer supports function expansion inside the Field() parameter list; only simple text strings are supported. This is a performance optimization. |
---|---|
Construction | Field(Field name to retrieve) |
Examples | field(duration) Returns the formatted duration value for each file. field(duration,0) would return the raw duration data. Simply entering [duration] or [duration,0] returns the same result. |
FilePath(...): Returns the path from a specified filename
FilePath() | This function will return the file path information from root to parent folder for all files in a list, or for any specified file. Media Center has a [Filename (Path)] library field by default, which is probably easier to use or reference than this function. |
---|---|
Construction | FilePath(Filename to check)
|
Examples | filepath(C:\Music\File.mp3) The result here would be... "C:\Music"
|
FileVolume(...): Returns the volume name from a specified filename
FileVolume() | This function will return the volume name information for all files in a list, or for any specified file. Media Center has a [Volume Name] library field by default, which is probably easier to use or reference than this function. |
---|---|
Construction | FileVolume(Filename to check)
|
Examples | filevolume(C:\Music\File.mp3) The result here would be... "C:"
|
AlbumKey(...): Returns a unique album key for a file
AlbumKey() | Testing reveals that this function simply returns an "[album artist (auto)] - [album]" string for each file. If two different albums happen to have the same [album artist (auto)] and [album] data, their respective AlbumKey() will not be unique. |
---|---|
Construction | AlbumKey() |
Examples | AlbumKey() Create a new expression column in a list using this function and the result will be a column populated with the [album artist (auto)] - [album] data for each file. |
AlbumArtist(...): Returns the calculated album artist for a file
AlbumArtist() | This function simply returns the "[album artist (auto)]" data for each file. |
---|---|
Construction | AlbumArtist() |
Examples | AlbumArtist() Create a new expression column in a list using this function and the result will be a column populated with the [album artist (auto)] data for each file. |
AlbumType(...): Returns the album type for a file
AlbumType() | This function simply returns the "[album type]" for each file. [album type] is a default Media Center library field that informs the user of an album's status in the library, such as "Single artist (complete)" or "Multiple artists (incomplete)" |
---|---|
Construction | AlbumType() |
Examples | AlbumType() Create a new expression column in a list using this function and the result will be a column populated with the [album type] data for each file. The [album type] library field will work just as well, and return the same information. |
Size(...): Returns the size of a file in a media type independent manner
Size() | Dependent on media type, this function returns the following information:
|
---|---|
Construction | Size() |
Examples | Size() Create a new expression column in a list using this function and the result will be a column populated with media type dependent data for each file as listed in the function description above. |
TrackNumber(...): Returns the track # of a file
TrackNumber() | This function simply returns the track # of a file. If a file has no track # assigned, the function returns zero. This function has no real use and is actually flagged as "For internal use only", so, not one for end users, and again, only included here for the sake of completeness. |
---|---|
Construction | TrackNumber() |
Examples | TrackNumber() Create a new expression column in a list using this function and the result will be a column populated with the track # information for each file. |