Difference between revisions of "Expression Language"

From JRiverWiki
Jump to: navigation, search
(Moved FilePathI() and FileVolume() and provided more description.)
(Function table replaced with reworked format)
Line 115: Line 115:
 
<div style="text-align:right;">([[#top|Back to top)]]</div>
 
<div style="text-align:right;">([[#top|Back to top)]]</div>
 
==Functions==
 
==Functions==
 +
===Accessing and Storing Functions===
  
===Conditional Functions===
+
The functions in this section access field values, store and load global variables,
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.
+
access file tags, and access note fields.
 +
====Field(&hellip;): Returns a field's value====
  
Although the expression language does not directly support AND, OR, and XOR, these can be easily emulated.  See: [[Database_Expressions_AND_OR_And_XOR]].
+
{| style="width: 100%; border: 2px solid black;" align="top" cellpadding="3"
 +
|- id="Field" valign="top"
 +
! scope="row" style="background: #ecedf3; color: #111; " width=100 | Description
 +
| style="background: #f9f9f9; color: #111; " width=1200 | <span style="font-family: Consolas, monospace; color:#0f3f8d; font-size:110%"><b>field(</b><i>name</i><b>, </b><i>mode</i><b>)</b></span>
 +
The [[#Field|Field()]] function returns the value stored in field <i>name</i>.
 +
The format of return is selected by <i>mode</i>.
  
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.
+
Available <i>mode</i> values:
 +
<div style="margin-left: 20pt;"><table style="background:#f9f9f9; border-spacing:0px; border-collapse:collapse;">
 +
<tr><td style="text-align:left; padding-right:20pt"><b>0</b></td><td>Raw, unformatted data</td></tr>
 +
<tr><td style="text-align:left; padding-right:20pt"><b>1</b></td><td>Formatted data</td></tr>
 +
</table></div>
  
====If(...): Conditional If/Then/Else evaluator.====
+
Argument <i>mode</i> is optional (defaults to 1).
  
{| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3"
 
 
|- valign="top"
 
|- valign="top"
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" width=100 | If()
+
! scope="row" style="background: #ecedf3; color: #111; " | Examples
| style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | 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.
+
|style="background: #f9f9f9; color: #111; " | <span style="font-family: Consolas, monospace;"><b><nowiki>field(album)</nowiki></b></span>
 +
<p style="margin-left:20pt;">Returns the formatted value of field <i>name</i> <span style="font-family: Consolas, monospace;">album</span>.
 +
Note that this is equivalent to <span style="font-family: Consolas, monospace;">[album]</span>.</p>
 +
<span style="font-family: Consolas, monospace;"><b><nowiki>field(date, 0)</nowiki></b></span>
 +
<p style="margin-left:20pt;">Returns the raw, unformatted value stored in the <span style="font-family: Consolas, monospace;">date</span> field.
 +
Note that this is equivalent to <span style="font-family: Consolas, monospace;">[date,0]</span>.</p>
 +
|}
 +
<div style="text-align:right;">([[#top|Back to top)]]</div>
 +
 
 +
====Load(&hellip;): Outputs the value of a global variable====
 +
 
 +
{| style="width: 100%; border: 2px solid black;" align="top" cellpadding="3"
 +
|- id="Load" valign="top"
 +
! scope="row" style="background: #ecedf3; color: #111; " width=100 | Description
 +
| style="background: #f9f9f9; color: #111; " width=1200 | <span style="font-family: Consolas, monospace; color:#0f3f8d; font-size:110%"><b>load(</b><i>varname</i><b>)</b></span>
 +
Loads and outputs the value of the specified global variable <i>varname</i> that has been previously stored with [[#Save|Save()]].
 
|- valign="top"
 
|- valign="top"
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction
+
! scope="row" style="background: #ecedf3; color: #111; " | Examples
| style="background: #ecfeea; color: black; border: 1px solid black" | '''if(''expression to test'',instructions if positive,''instructions if negative'')'''
+
|style="background: #f9f9f9; color: #111; " | <span style="font-family: Consolas, monospace;"><b><nowiki>load(var1)</nowiki></b></span>
|- valign="top"
+
<p style="margin-left:20pt;">Loads and outputs the previous stored value of the global variable named <span style="font-family: Consolas, monospace;">var1</span>.
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples
+
If <span style="font-family: Consolas, monospace;">var1</span> has not been previously stored, the output will be empty.</p>
|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.
+
<span style="font-family: Consolas, monospace;"><b><nowiki>save(math(1 + 2), sum)load(sum)</nowiki></b></span>
<br>
+
<p style="margin-left:20pt;">Saves the output of the [[#Math|Math()]] function into <span style="font-family: Consolas, monospace;">sum</span>, and then loads and outputs the value of <span style="font-family: Consolas, monospace;">sum</span>, which is <span style="font-family: Consolas, monospace;">3</span>.</p>
'''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''
+
<div style="text-align:right;">([[#top|Back to top)]]</div>
 +
 
 +
====Note(&hellip;): Retrieve note fields====
 +
 
 +
{| style="width: 100%; border: 2px solid black;" align="top" cellpadding="3"
 +
|- id="Note" valign="top"
 +
! scope="row" style="background: #ecedf3; color: #111; " width=100 | Description
 +
| style="background: #f9f9f9; color: #111; " width=1200 | <span style="font-family: Consolas, monospace; color:#0f3f8d; font-size:110%"><b>note(</b><i>field label</i><b>, </b><i>field type</i><b>, </b><i>occurrence</i><b>)</b></span>
 +
The [[#Note|Note()]] function retrieves information from a Media Center Note.
 +
Specifically, it returns the contents assosicated with a <i>field label</i>, of a given <i>field type</i>.
 +
The Nth <i>occurrence</i> may be requested.
 +
Notes data may be simple text, or associated with defined a <i>field label</i>.
 +
Currently the only type of <i>field label</i> is contact information.
 +
The first line of a Note is assosciated with the omnipresent <i>field label</i> <span style="font-family: Consolas, monospace;">Name</span>.
  
<br>
+
The <i>field type</i> selects the specific sub-type for a given <i>field label</i>, and <i>occurrence</i> selects which instance of
'''if(!isempty([comment]), Regex([comment], /#^(\S+\s+\S+\s+\S+)#/, 1), *No Comment)'''
+
several <i>field label</i> / <i>field type</i> pairs is returnedThe <i>occurrence</i> value is zero-based.
<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:
+
Argument <i>field type</i> is optional (defaults to FIRST AVAILABLE).
  
: if(!isempty([comment]),
+
Argument <i>occurrence</i> is optional (defaults to 0).
:: Regex([comment], /#^(\S+\s+\S+\s+\S+)#/, 1),
 
:: *No Comment)'''
 
  
 +
|- valign="top"
 +
! scope="row" style="background: #ecedf3; color: #111; " | Examples
 +
|style="background: #f9f9f9; color: #111; " | <span style="font-family: Consolas, monospace;"><b><nowiki>note(phone)</nowiki></b></span>
 +
<p style="margin-left:20pt;">Returns the value found in the first <span style="font-family: Consolas, monospace;">Phone</span> <i>field label</i>.  If no <span style="font-family: Consolas, monospace;">Phone</span> label exists, nothing is returned.</p>
 +
<span style="font-family: Consolas, monospace;"><b><nowiki>note(phone, home)</nowiki></b></span>
 +
<p style="margin-left:20pt;">Returns the value found in the first <span style="font-family: Consolas, monospace;">Home</span> <i>field type</i> from the <span style="font-family: Consolas, monospace;">Phone</span> <i>field label</i>.
 +
If the <span style="font-family: Consolas, monospace;">Phone</span> label, <span style="font-family: Consolas, monospace;">Home</span> type does not exists, nothing is returned.</p>
 +
<span style="font-family: Consolas, monospace;"><b><nowiki>note(phone, home, 1)</nowiki></b></span>
 +
<p style="margin-left:20pt;">Same as the previous example, but the second instance of the <i>field type</i> is selected instead of the first, since occrrence is zero-based.</p>
 
|}
 
|}
 
<div style="text-align:right;">([[#top|Back to top)]]</div>
 
<div style="text-align:right;">([[#top|Back to top)]]</div>
  
====IfElse(...): If/Then/Else sequence of conditional tests and actions.====
+
====Save(&hellip;): Saves a value to a global variable====
 
 
{| 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)
+
{| style="width: 100%; border: 2px solid black;" align="top" cellpadding="3"
:: action1
+
|- id="Save" valign="top"
: else if (test2)
+
! scope="row" style="background: #ecedf3; color: #111; " width=100 | Description
:: action2
+
| style="background: #f9f9f9; color: #111; " width=1200 | <span style="font-family: Consolas, monospace; color:#0f3f8d; font-size:110%"><b>save(</b><i>value</i><b>, </b><i>variable</i><b>, </b><i>mode</i><b>)</b></span>
: else if (test3)
+
This [[#Save|Save()]] function saves the <i>value</i> into the specified global <i>variable</i>, and optionally will return that <i>value</i> if <i>mode</i> is set.
:: action3
+
Once a global <i>variable</i> has been created using [[#Save|Save()]], that <i>variable</i>'s <i>value</i> is available for use with either [[#Load|Load()]] or the pseudo-field "[<i>variable</i>]".
  
The IfElse() statement may be used to more cleanly express the flow of expression by removing the superfluous internal If() statements:
+
<div style="margin-left: 20pt;"><table style="background:#f9f9f9; border-spacing:0px; border-collapse:collapse;">
 +
<tr><td style="text-align:left; padding-right:20pt"><b>0</b></td><td>Suppress output</td></tr>
 +
<tr><td style="text-align:left; padding-right:20pt"><b>1</b></td><td>Output variables <i>value</i></td></tr>
 +
</table></div>
  
'''IfElse(test1, action1, test2, action2, test3, action3)'''
+
Argument <i>mode</i> is optional (defaults to 0).
  
 
|- valign="top"
 
|- valign="top"
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction
+
! scope="row" style="background: #ecedf3; color: #111; " | Examples
| style="background: #ecfeea; color: black; border: 1px solid black" | '''ifelse(''test expression 1'',instructions 1,''test expression 2'',instructions 2, ...)'''
+
|style="background: #f9f9f9; color: #111; " | <span style="font-family: Consolas, monospace;"><b><nowiki>save(Much Money, local_bank)</nowiki></b></span>
|- valign="top"
+
<p style="margin-left:20pt;">Saves the <i>value</i> <span style="font-family: Consolas, monospace;">Much Money</span> into the global <i>variable</i> <span style="font-family: Consolas, monospace;">local_bank</span>.</p>
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples
+
<span style="font-family: Consolas, monospace;"><b><nowiki>save(More Money, My Bank, 1)</nowiki></b></span>
|style="background: #ecfeea; color: black; border: 1px solid black" | '''ifelse(isequal([media type], Audio), Le Tunes, isequal([media type], Video]), Flix)'''
+
<p style="margin-left:20pt;">Saves <span style="font-family: Consolas, monospace;">More Money</span> into <span style="font-family: Consolas, monospace;">My Bank</span> and outputs the variables <i>value</i> <span style="font-family: Consolas, monospace;">More Money</span>.</p>
 +
<span style="font-family: Consolas, monospace;"><b><nowiki>save(math([duration,0] / 60), durmins)if(compare([durmins], &gt;, 5.0), Long Track, Short Track)</nowiki></b></span>
 +
<p style="margin-left:20pt;">Saves the calculated duration in minutes into the <i>variable</i> <span style="font-family: Consolas, monospace;">durmins</span>.
 +
Notice that subsequent expressions fragments such as the <span style="font-family: Consolas, monospace;">if(compare()...)</span> may now use the pseudo-field <span style="font-family: Consolas, monospace;">[durmins]</span> as shorthand
 +
for <span style="font-family: Consolas, monospace;">load(durmins)</span>.</p>
 +
 
 +
Additional Examples
  
''If media type is audio, outputs "Le Tunes", else if media type is video, outputs "Flix"''
+
:[http://yabb.jriver.com/interact/index.php?topic=77826.0 Generating statistics]
<br>
 
  
 +
:[http://yabb.jriver.com/interact/index.php?topic=76581.msg518902#msg518902 Generating album track count]
  
'''ifelse(isequal([artist], Bob Dylan), Genius, isequal([album], Joshua Tree, 8), Great Album, 1, Mediocre)'''
+
:[http://yabb.jriver.com/interact/index.php?topic=72049.0 Generating album ratings]  
  
''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".''
+
:[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>
  
===Query, Test and Comparison Functions===
+
====SaveAdd(&hellip;): Adds to a global variable====
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: 2px solid black;" align="top" cellpadding="3"
{| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3"
+
|- id="SaveAdd" valign="top"
|- valign="top"
+
! scope="row" style="background: #ecedf3; color: #111; " width=100 | Description
! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | Compare()
+
| style="background: #f9f9f9; color: #111; " width=1200 | <span style="font-family: Consolas, monospace; color:#0f3f8d; font-size:110%"><b>saveadd(</b><i>variable</i><b>, </b><i>value</i><b>, </b><i>mode</i><b>)</b></span>
| 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.
+
The [[#SaveAdd|SaveAdd()]] function adds <i>value</i> to a global <i>variable</i> either numerically or as a list item.
|- valign="top"
+
The <i>mode</i> argument indicates how <i>variable</i> is modified.
! 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:''
+
Available <i>mode</i> values:
* =: ''numeric equivalence''
 
* <: ''numeric less than''
 
* <=: ''numeric less than or equal to''
 
* >: ''numeric greater than''
 
* >=: ''numeric greater than or equal to''
 
  
|- valign="top"
+
<div style="margin-left: 20pt;"><table style="background:#f9f9f9; border-spacing:0px; border-collapse:collapse;">
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples
+
<tr><td style="text-align:left; padding-right:20pt"><b>0</b></td><td>Add numeric <i>value</i> (integer or decimal) to <i>variable</i></td></tr>
|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.''
+
<tr><td style="text-align:left; padding-right:20pt"><b>1</b></td><td>Append string <i>value</i> as a list item to <i>variable</i></td></tr>
 +
<tr><td style="text-align:left; padding-right:20pt"><b>2</b></td><td>Prepend string <i>value</i> as a list item to <i>variable</i></td></tr>
 +
</table></div>
  
<br>'''If(Compare(Math(Now() - [Date Modified, 0]), >, 21), Expired, FormatDate([Date Modified, 0], Elapsed))'''
+
Argument <i>mode</i> is optional (defaults to 0).
  
''Shows the age of files under 21 days old, or shows 'Expired' for older files.''
+
|- valign="top"
 +
! scope="row" style="background: #ecedf3; color: #111; " | Examples
 +
|style="background: #f9f9f9; color: #111; " | <span style="font-family: Consolas, monospace;"><b><nowiki>saveadd(v, 1)</nowiki></b></span>
 +
<p style="margin-left:20pt;">Numerically increments the global <i>variable</i> <span style="font-family: Consolas, monospace;">v</span> by <span style="font-family: Consolas, monospace;">1</span>.</p>
 +
<span style="font-family: Consolas, monospace;"><b><nowiki>saveadd(v, math(2 - 6))</nowiki></b></span>
 +
<p style="margin-left:20pt;">Numerically increments the global <i>variable</i> <span style="font-family: Consolas, monospace;">v</span> by the outcome of the [[#Math|Math()]], which is <span style="font-family: Consolas, monospace;">-4</span>.</p>
 +
<span style="font-family: Consolas, monospace;"><b><nowiki>load(foo, v)saveadd(v, bar, 1)load(v)</nowiki></b></span>
 +
<p style="margin-left:20pt;">Loads <i>value</i> <span style="font-family: Consolas, monospace;">foo</span> into <i>variable</i> <span style="font-family: Consolas, monospace;">v</span>, then appends the <i>value</i> <span style="font-family: Consolas, monospace;">bar</span> as a list item, and the final <span style="font-family: Consolas, monospace;">load(v)</span> expression outputs the
 +
result of <span style="font-family: Consolas, monospace;">foo; bar</span>.</p>
 +
<span style="font-family: Consolas, monospace;"><b><nowiki>load(That, v)saveadd(v, This, 2)load(v)</nowiki></b></span>
 +
<p style="margin-left:20pt;">Similar to the previous example, but using the prepend <i>mode</i>, resulting in the output <span style="font-family: Consolas, monospace;">This; That</span>.</p>
 
|}
 
|}
 
<div style="text-align:right;">([[#top|Back to top)]]</div>
 
<div style="text-align:right;">([[#top|Back to top)]]</div>
  
====IsEqual(...): Compares two values in one of nine specified modes====
+
====Tag(&hellip;): Returns a file's physical tag====
{| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3"
+
 
 +
{| style="width: 100%; border: 2px solid black;" align="top" cellpadding="3"
 +
|- id="Tag" valign="top"
 +
! scope="row" style="background: #ecedf3; color: #111; " width=100 | Description
 +
| style="background: #f9f9f9; color: #111; " width=1200 | <span style="font-family: Consolas, monospace; color:#0f3f8d; font-size:110%"><b>tag(</b><i>tag name</i><b>)</b></span>
 +
The [[#Tag|Tag()]] function reads and returns the value of <i>tag name</i> directly from a file.
 +
The Media Center Library database is not used with [[#Tag|Tag()]], and instead the specified file is read for the requested tag.
 +
The spelling and letter case of the <i>tag name</i> must match exactly those stored in the file.
 +
Performance note: This function must open and read the actual file, so its performance is significantly slower than other functions which
 +
operate on database fields.
 
|- valign="top"
 
|- valign="top"
! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | IsEqual()
+
! scope="row" style="background: #ecedf3; color: #111; " | Examples
| style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | 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.
+
|style="background: #f9f9f9; color: #111; " | <span style="font-family: Consolas, monospace;"><b><nowiki>tag(My Personal Tag)</nowiki></b></span>
|- valign="top"
+
<p style="margin-left:20pt;">This will return the value from the tag named <span style="font-family: Consolas, monospace;">My Personal Tag</span> from file referenced by the <span style="font-family: Consolas, monospace;">[filename]</span> field.</p>
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction
+
<span style="font-family: Consolas, monospace;"><b><nowiki>tag(Gapless Header)</nowiki></b></span>
| style="background: #ecfeea; color: black; border: 1px solid black" | '''isequal(''1st value to compare'',2nd value to compare'',compare mode)'''
+
<p style="margin-left:20pt;">Returns the <span style="font-family: Consolas, monospace;">Gapless Header</span> tag value, often contained in an mp3 file.</p><p style="margin-left:20pt;">Examxple:      tag(exif: Date)
 +
Returns the raw date data from the EXIF data saved inside a jpg file.</p>
 +
|}
 +
<div style="text-align:right;">([[#top|Back to top)]]</div>
  
''Available Compare Modes:''
+
===Conditional Functions===
* 0: ''case-sensitive string compare for equality''
 
* 1: ''case-insensitive string compare for equality''
 
* 2: ''numeric compare for equality''
 
* 3: ''numeric less than''
 
* 4: ''numeric less than or equal to''
 
* 5: ''numeric greater than''
 
* 6: ''numeric greater than or equal to''
 
* 7: ''substring search (case sensitive)''
 
* 8: ''substring search (case insensitive)''
 
  
'''In all cases, the first value is always compared with the second value, never the other way around'''
+
The functions in this section test one or more arguments to produce either a true or false outcome, and execute specific actions depending upon that result.
|- valign="top"
 
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples
 
|style="background: #ecfeea; color: black; border: 1px solid black" | '''isequal([artist],[album],1)'''<br>''If the 'artist' and 'album' values are the same, the output will be 1, otherwise, the output will be 0.''
 
  
<br>'''if(isequal([artist],[album],1),Self Titled,[album])'''
+
The expression language does not directly support AND, OR, and XOR operations.
<br>''Wrapped inside an 'If' function, if the 'artist' and 'album' values are the same, the output will be 'Self Titled', otherwise, the output will be the 'album' value.''
+
However, these can be easily emulated using any of several techniques. See: [[Database_Expressions_AND_OR_And_XOR]].
  
<br>'''if(isequal([artist],[album],1),Self Titled/,,[album]/))'''
+
The NOT operator <span style="font-family: Consolas, monospace;"><b>!</b></span> (exclamation point) may be used in a conditional to invert the sense of the conditional test.  Inverting the sense of a test can make reading expressions easier, or support better [[#IfElse|IfElse()]] sequences.
<br>''This example demonstrates the character 'escaping' mentioned in the [[#Overview|overview]] earlier. Here, we want the output to be either "Self Titled," (note the inclusion of the comma) or the album value with a closing parenthesis. In order to achieve this, the comma, and the closing parenthesis, are escaped using a preceding forward-slash character. This informs the expression evaluator that these characters are not part of the expression syntax and are to be treated literally''
+
====If(&hellip;): Conditional if-else evaluator====
  
<br>'''if(isequal([filename (path)],Classical,8),Classical,Not Classical)'''
+
{| style="width: 100%; border: 2px solid black;" align="top" cellpadding="3"
<br>''Here, compare mode number eight has been specified, so, if the letters classical appear anywhere in the file path for a given file, the expression will return "Classical" and if not, it will return "Not&nbsp;Classical".'' '''Note that when using compare modes seven and eight, the subject must be given first, and the term to compare for given second'''
+
|- id="If" valign="top"
 +
! scope="row" style="background: #ecedf3; color: #111; " width=100 | Description
 +
| style="background: #f9f9f9; color: #111; " width=1200 | <span style="font-family: Consolas, monospace; color:#0f3f8d; font-size:110%"><b>if(</b><i>test expression</i><b>, </b><i>true expression</i><b>, </b><i>false expression</i><b>)</b></span>
 +
The [[#If|If()]] function is used to evaluate a <i>test expression</i>, and will output the result of the <i>true expression</i> or <i>false expression</i>, depending upon the evaluation result.  The <i>test expression</i> is expected to return a 0 (false value) or a non-zero (true value).
 +
Nesting is allowed.
 +
If the <i>test expression</i> is preceded by the NOT operator (!, an exclamation point), the sense of the test is inverted.  Non-zero values are inverted to 0, and 0 is inverted to 1.
 +
|- valign="top"
 +
! scope="row" style="background: #ecedf3; color: #111; " | Examples
 +
|style="background: #f9f9f9; color: #111; " | <span style="font-family: Consolas, monospace;"><b><nowiki>if(isequal([artist], bob dylan, 1), Genius, Mediocre)</nowiki></b></span>
 +
<p style="margin-left:20pt;">Outputs <span style="font-family: Consolas, monospace;">Genius</span> when artist is (case insensitive) Bob Dylan and <span style="font-family: Consolas, monospace;">Mediocre</span> otherwise.</p>
 +
<span style="font-family: Consolas, monospace;"><b><nowiki>if(isequal([artist], bob dylan, 1), Genius, if(isequal([album], Joshua Tree, 8), Great Album, Mediocre))</nowiki></b></span>
 +
<p style="margin-left:20pt;">This nested [[#If|If()]] expression expands on the previous example, by first evaluating if the artist is Bob Dylan, and outputs <span style="font-family: Consolas, monospace;">Genius</span> if true.
 +
When the artist is not Bob Dylan, the album is then tested to see if it is <span style="font-family: Consolas, monospace;">Joshua Tree</span>, and if so outputs <span style="font-family: Consolas, monospace;">Great Album</span>, otherwise outputs <span style="font-family: Consolas, monospace;">Mediocre</span>.</p>
 +
<span style="font-family: Consolas, monospace;"><b><nowiki>if(!isempty([comment]), regex([comment], /#^(\\S+\\s+\\S+\\s+\\S+)#/, 1), *No Comment)</nowiki></b></span>
 +
<p style="margin-left:20pt;">Output's the first three words of the comment field; otherwise, outputs *No Comment.  By using the NOT operator, the sense of the conditional is inverted so that the more interesting case is moved ahead of the more mundane case.</p>
 
|}
 
|}
 
<div style="text-align:right;">([[#top|Back to top)]]</div>
 
<div style="text-align:right;">([[#top|Back to top)]]</div>
  
====IsEmpty(...): Tests to see if a field is empty====
+
====IfElse(&hellip;): Conditional if-elseif evaluator====
{| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3"
+
 
|- valign="top"
+
{| style="width: 100%; border: 2px solid black;" align="top" cellpadding="3"
! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | IsEmpty()
+
|- id="IfElse" valign="top"
| 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.
+
! scope="row" style="background: #ecedf3; color: #111; " width=100 | Description
Pay particular attention to the third example offered below, as it covers a caveat that comes with this particular function.
+
| style="background: #f9f9f9; color: #111; " width=1200 | <span style="font-family: Consolas, monospace; color:#0f3f8d; font-size:110%"><b>ifelse(</b><i>test1</i><b>, </b><i>action1</i><b>, </b><i>test2</i><b>, </b><i>action2</i><b>, </b><i>test3</i><b>, </b><i>action3</i><b>, </b><i>&hellip;</i><b>)</b></span>
|- valign="top"
+
The [[#IfElse|IfElse()]] conditional provides a convenient mechanism for shortening and more clearly expressing nested conditionals into an alternating sequence of tests and actions.
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction
+
One or more test/action pairs may be specified.
| style="background: #ecfeea; color: black; border: 1px solid black" | '''isempty([field to test],test mode)'''
+
 
''Available test modes:''
+
For example, consider a nested sequence of [[#If|If()]] tests such as the following pseudo-code:
* 0: ''String test (field must be empty to get a positive result)''
+
<div style="font-family: Consolas, monospace;">
* 1: ''Numerical test (field must be empty, or contain 0 to get a positive result)''
+
<div style="margin-left: 20pt">if (<i>test1</i>)</div>
|- valign="top"
+
<div style="margin-left: 40pt"><i>action1</i></div>
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples
+
<div style="margin-left: 20pt">else if (<i>test2</i>)</div>
|style="background: #ecfeea; color: black; border: 1px solid black" | '''isempty([comment],0)'''<br>''If the comment field is empty, this expression will return 1, but if the comment field contains data, the expression will return 0.''
+
<div style="margin-left: 40pt"><i>action2</i></div>
 +
<div style="margin-left: 20pt">else if (<i>test3</i>)</div>
 +
<div style="margin-left: 40pt"><i>action3</i></div>
 +
</div>
 +
 
 +
The [[#IfElse|IfElse()]] statement may be used to more cleanly express the flow of expression by removing the superfluous internal [[#If|If()]] statements, converting the clumsy expression:
 +
 
 +
<div style="margin-left: 20pt"><span style="font-family: Consolas, monospace;">if(<i>test1</i>, <i>action1</i>, if(<i>test2</i>, <i>action2</i>, if(<i>test3</i>, <i>action3</i>)))</span></div>
 +
 
 +
into the more elegant:
  
<br>'''isempty([track #],1)'''
+
<div style="margin-left: 20pt"><span style="font-family: Consolas, monospace;">ifelse(<i>test1</i>, <i>action1</i>, <i>test2</i>, <i>action2</i>, <i>test3</i>, <i>action3</i>)</span></div>
<br>''This expression will perform a numerical test for data in the [track #] field. If the field is empty, or contains 0, the expression will return a positive result, 1, otherwise, the result will be negative, 0.''
 
  
<br>'''if(isempty([disc #]),,[disc #])'''
+
If any of the test expressions <i>test1</i>, etc. are preceded by the NOT operator (!, an exclamation point), the sense of that test is inverted.  Non-zero values are inverted to 0, and 0 is inverted to 1.
<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&nbsp;[Field&nbsp;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&nbsp;[field&nbsp;name]" we can use '''if([[#IsEqual(...): Compares two values in one of nine specified modes|isequal]]([disc&nbsp;#],unknown,8),,[disc&nbsp;#])''' to achieve the desired result. Note that this only applies when using the rename files tool.''
+
|- valign="top"
 +
! scope="row" style="background: #ecedf3; color: #111; " | Examples
 +
|style="background: #f9f9f9; color: #111; " | <span style="font-family: Consolas, monospace;"><b><nowiki>ifelse(isequal([media type], Audio), Le Tunes, isequal([media type], Video]), Flix)</nowiki></b></span>
 +
<p style="margin-left:20pt;">If media type is audio, outputs <span style="font-family: Consolas, monospace;">Le Tunes</span>, else if media type is video, outputs <span style="font-family: Consolas, monospace;">Flix</span></p>
 +
<span style="font-family: Consolas, monospace;"><b><nowiki>ifelse(isequal([artist], Bob Dylan), Genius, isequal([album], Joshua Tree, 8), Great Album, 1, Mediocre)</nowiki></b></span>
 +
<p style="margin-left:20pt;">This example, implements the nested if statements from the If() section above,
 +
first testing if the artist is Bob Dylan, and if true, outputs <span style="font-family: Consolas, monospace;">Genius</span>,
 +
otherwise evaluates the second test to determine if the album is <span style="font-family: Consolas, monospace;">Joshua Tree</span>,
 +
and if true, outputs <span style="font-family: Consolas, monospace;">Great Album</span>, otherwise, performs a final test,
 +
in this case a degenerate test of 1 (and 1 is always true), thus outputting the value <span style="font-family: Consolas, monospace;">Mediocre</span>.</p>
 
|}
 
|}
 
<div style="text-align:right;">([[#top|Back to top)]]</div>
 
<div style="text-align:right;">([[#top|Back to top)]]</div>
====IsRange(...): Tests a value for inclusion within a given range====
 
{| 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 | IsRange()
 
| style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | 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.
 
|- valign="top"
 
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction
 
| style="background: #ecfeea; color: black; border: 1px solid black" | '''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''
 
* ''1-100''
 
* ''a-z''
 
* ''c-d''
 
* ''23-7542''
 
|- valign="top"
 
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples
 
|style="background: #ecfeea; color: black; border: 1px solid black" | '''isrange([artist],a-c)'''<br>''Abba or Blondie will return 1 (positive), and ZZ Top will return 0 (negative).''
 
  
<br>'''if(isrange([bitrate],96-191),Poor Quality,High Quality)'''
+
====FirstNotEmpty(&hellip;): Returns the first non-empty argument====
<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 Media Center searches, something that was covered earlier'' [[#When, Where and How to use expressions|on this page.]]
+
{| style="width: 100%; border: 2px solid black;" align="top" cellpadding="3"
 +
|- id="FirstNotEmpty" valign="top"
 +
! scope="row" style="background: #ecedf3; color: #111; " width=100 | Description
 +
| style="background: #f9f9f9; color: #111; " width=1200 | <span style="font-family: Consolas, monospace; color:#0f3f8d; font-size:110%"><b>firstnotempty(</b><i>value1</i><b>, </b><i>value2</i><b>, </b><i>&hellip;</i><b>)</b></span>
 +
The [[#FirstNotEmpty|FirstNotEmpty()]] function acts as a conditional by returning the first argument from <i>value1</i>, <i>value2</i>, ... that is not empty.
 +
Two or more arguments may be used, and the first non-empty argument is returned.
 +
With two arguments, is is functionally equivalent to the sequence such as "if(!isempty(<i>value1</i>), <i>value1</i>, <i>value2</i>)".
 +
With more than two arguments, [[#FirstNotEmpty|FirstNotEmpty()]] avoids long nested [[#If|If()]] sequences that simply test for emptiness.
 +
|- valign="top"
 +
! scope="row" style="background: #ecedf3; color: #111; " | Examples
 +
|style="background: #f9f9f9; color: #111; " | <span style="font-family: Consolas, monospace;"><b><nowiki>firstnotempty([media sub type], Misc Video)</nowiki></b></span>
 +
<p style="margin-left:20pt;">Returns the value in <span style="font-family: Consolas, monospace;">media sub type</span> if it is not empty, otherwise returns <span style="font-family: Consolas, monospace;">Music Video</span>.</p>
 +
<span style="font-family: Consolas, monospace;"><b><nowiki>firstnotempty([series], [name], Tag your Videos!)</nowiki></b></span>
 +
<p style="margin-left:20pt;">Returns the first non-empty value from the fields <span style="font-family: Consolas, monospace;">series</span> or <span style="font-family: Consolas, monospace;">name</span>, and if both are empty, returns the reminder to
 +
<span style="font-family: Consolas, monospace;">Tag your Videos!</span>.</p>
 
|}
 
|}
 
<div style="text-align:right;">([[#top|Back to top)]]</div>
 
<div style="text-align:right;">([[#top|Back to top)]]</div>
====IsMissing(...): Tests to see if a file exists on the system====
 
{| 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 | IsMissing()
 
| 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.
+
===Test and Comparison Functions===
|- valign="top"
+
 
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction
+
The functions in this section return a Boolean value of either 1 (true) or 0 (false).
| style="background: #ecfeea; color: black; border: 1px solid black" | '''IsMissing(Full Path To File)'''
+
They are generally used to drive an action specified in one of the [[#Conditional Functions|Conditional Functions]].
''Checks for existence of the file "Full Path To File", or the current file if unspecified.''
+
====Compare(&hellip;): Compares two numbers====
|- valign="top"
+
 
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples
+
{| style="width: 100%; border: 2px solid black;" align="top" cellpadding="3"
|style="background: #ecfeea; color: black; border: 1px solid black" | '''ismissing()'''<br>''Checks if the current file exists, and returns 1 (positive) if the file does not exist, and 0 (negative) if the file does exist.''
+
|- id="Compare" valign="top"
 +
! scope="row" style="background: #ecedf3; color: #111; " width=100 | Description
 +
| style="background: #f9f9f9; color: #111; " width=1200 | <span style="font-family: Consolas, monospace; color:#0f3f8d; font-size:110%"><b>compare(</b><i>value1</i><b>, </b><i>operator</i><b>, </b><i>value2</i><b>)</b></span>
 +
The [[#Compare|Compare()]] function compares two numeric values <i>value1</i> and <i>value2</i> using the specified <i>operator</i>.
  
<br>'''ismissing(C:\Music\My Lost File.mp3)'''
+
Available <i>operator</i> values:
<br>''Checks for "My Lost File.mp3" and returns 1 (positive) if the file does not exist, and 0 (negative) if the file does exist.''
 
  
<br>'''[=ismissing([filename])]=1'''
+
<div style="margin-left: 20pt;"><table style="background:#f9f9f9; border-spacing:0px; border-collapse:collapse;">
<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
+
<tr><td style="text-align:left; padding-right:20pt"><b>=</b></td><td>Equivalence</td></tr>
 +
<tr><td style="text-align:left; padding-right:20pt"><b><</b></td><td>Less than</td></tr>
 +
<tr><td style="text-align:left; padding-right:20pt"><b><=</b></td><td>Less than or equal to</td></tr>
 +
<tr><td style="text-align:left; padding-right:20pt"><b>></b></td><td>Greater than</td></tr>
 +
<tr><td style="text-align:left; padding-right:20pt"><b>>=</b></td><td>Greater than or equal to</td></tr>
 +
</table></div>
  
<br>'''if(ismissing(),File is missing,File exists)'''
+
Outputs 1 if the comparison is true, and 0 otherwise.
<br>''Wrapped inside an "If()" function, the expression outputs "File is missing" or "File Exists" depending on the result returned by IsMissing()''
+
|- valign="top"
 +
! scope="row" style="background: #ecedf3; color: #111; " | Examples
 +
|style="background: #f9f9f9; color: #111; " | <span style="font-family: Consolas, monospace;"><b><nowiki>compare([bitrate], &lt;, 320)</nowiki></b></span>
 +
<p style="margin-left:20pt;">Returns 1 when the bitrate is less than 320 (Kbps), and 0 otherwise.</p>
 +
<span style="font-family: Consolas, monospace;"><b><nowiki>if(compare(math(now() - [date modified, 0]), &gt;, 21), Expired, formatdate([date modified, 0], elapsed))</nowiki></b></span>
 +
<p style="margin-left:20pt;">Outputs the age of files under 21 days old, or <span style="font-family: Consolas, monospace;">Expired</span> for older files.</p>
 
|}
 
|}
 
<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====
+
====IsEqual(&hellip;): Compares two values in one of nine specified modes====
{| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3"
+
 
|- valign="top"
+
{| style="width: 100%; border: 2px solid black;" align="top" cellpadding="3"
! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | IsRemovable()
+
|- id="IsEqual" valign="top"
| 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.
+
! scope="row" style="background: #ecedf3; color: #111; " width=100 | Description
|- valign="top"
+
| style="background: #f9f9f9; color: #111; " width=1200 | <span style="font-family: Consolas, monospace; color:#0f3f8d; font-size:110%"><b>isequal(</b><i>value1</i><b>, </b><i>value2</i><b>, </b><i>mode</i><b>)</b></span>
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction
+
The [[#IsEqual|IsEqual()]] function compares <i>value1</i> with <i>value2</i> using any <i>mode</i> from the list of modes below.
| style="background: #ecfeea; color: black; border: 1px solid black" | '''IsRemovable(Full Path To File)'''
+
Outputs 1 when the comparison succeeds according to the <i>mode</i>, and 0 otherwise.
 +
Although the <i>mode</i> is specified as the last argument, the comparison should be mentally read as: <i>value1</i> <i>mode</i> <i>value2</i>.
 +
 
 +
Available <i>mode</i> values:
 +
 
 +
<div style="margin-left: 20pt;"><table style="background:#f9f9f9; border-spacing:0px; border-collapse:collapse;">
 +
<tr><td style="text-align:left; padding-right:20pt"><b>0</b></td><td>Case-sensitive string compare for equality</td></tr>
 +
<tr><td style="text-align:left; padding-right:20pt"><b>1</b></td><td>Case-insensitive string compare for equality</td></tr>
 +
<tr><td style="text-align:left; padding-right:20pt"><b>2</b></td><td>Numeric compare for equality</td></tr>
 +
<tr><td style="text-align:left; padding-right:20pt"><b>3</b></td><td>Numeric less than</td></tr>
 +
<tr><td style="text-align:left; padding-right:20pt"><b>4</b></td><td>Numeric less than or equal to</td></tr>
 +
<tr><td style="text-align:left; padding-right:20pt"><b>5</b></td><td>Numeric greater than</td></tr>
 +
<tr><td style="text-align:left; padding-right:20pt"><b>6</b></td><td>Numeric greater than or equal to</td></tr>
 +
<tr><td style="text-align:left; padding-right:20pt"><b>7</b></td><td>Substring search (case sensitive)</td></tr>
 +
<tr><td style="text-align:left; padding-right:20pt"><b>8</b></td><td>Substring search (case insensitive)</td></tr>
 +
</table></div>
 +
 
 +
Argument <i>mode</i> is optional (defaults to 0).
  
''If no file path is specified, the function will default to checking the current file.''
 
 
|- valign="top"
 
|- valign="top"
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples
+
! scope="row" style="background: #ecedf3; color: #111; " | Examples
|style="background: #ecfeea; color: black; border: 1px solid black" | '''isremovable()'''<br>''Checks if the current file is on removable storage, and if so, returns 1 (positive), if not, the function returns 0 (negative).''
+
|style="background: #f9f9f9; color: #111; " | <span style="font-family: Consolas, monospace;"><b><nowiki>isequal([artist], [album], 1)</nowiki></b></span>
 +
<p style="margin-left:20pt;">If the artist and album values are the same, the output will be 1, otherwise, the output will be 0.</p>
 +
<span style="font-family: Consolas, monospace;"><b><nowiki>if(isequal([artist], [album], 1), Eponymous, [album])</nowiki></b></span>
 +
<p style="margin-left:20pt;">The [[#If|If()]] function basis its decision on the outcome of [[#IsEqual|IsEqual()]], so if the artist and album values are the same, the output will be Eponymous, otherwise, the output will be the value of album.</p>
 +
<span style="font-family: Consolas, monospace;"><b><nowiki>if(isequal([artist], [album], 1), Eponymous/,, [album]/))</nowiki></b></span>
 +
<p style="margin-left:20pt;">This example demonstrates the character escaping mentioned in the overview earlier.
 +
Here, we want the output to be either <span style="font-family: Consolas, monospace;">Eponymous,</span> (note the inclusion of the comma) or the album value with a closing parenthesis.
 +
In order to achieve this, the comma, and the closing parenthesis, are escaped using a forward-slash character.
 +
This informs the expression evaluator that these characters are not part of the expression syntax and are to be treated literally.</p>
 +
<span style="font-family: Consolas, monospace;"><b><nowiki>if(isequal([filename (path)], classical, 8), Classical, Not Classical)</nowiki></b></span>
 +
<p style="margin-left:20pt;">Because compare <i>mode</i> 8 has been specified, if the word <span style="font-family: Consolas, monospace;">classical</span> appears anywhere in the case-insensitive file path, the expression will return <span style="font-family: Consolas, monospace;">Classical</span>, and if not it will return <span style="font-family: Consolas, monospace;">Not Classical</span>.</p>
 
|}
 
|}
 
<div style="text-align:right;">([[#top|Back to top)]]</div>
 
<div style="text-align:right;">([[#top|Back to top)]]</div>
====IsInPlayingNow & IsPlaying(...): Tests to see if a file is in the Playing Now playlist or currently being played====
 
{| 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 | IsInPlayingNow()
 
| rowspan="2" style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | 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.
 
|- valign="top"
 
! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | IsPlaying()
 
|- valign="top"
 
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction
 
| style="background: #ecfeea; color: black; border: 1px solid black" | '''IsInPlayingNow()'''<br>''Checks the current file, and if in the Playing Now list, returns 1 (positive), and if not, returns 0 (negative).
 
  
<br>'''IsPlaying()'''
+
====IsEmpty(&hellip;): Tests a value for emptiness====
<br>''Checks the current file, and if currently playing, returns 1 (positive), and if not, returns 0 (negative).
+
 
|- valign="top"
+
{| style="width: 100%; border: 2px solid black;" align="top" cellpadding="3"
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples
+
|- id="IsEmpty" valign="top"
|style="background: #ecfeea; color: black; border: 1px solid black" | '''if(isinplayingnow(),Selected,Not Selected)'''<br>''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.
+
! scope="row" style="background: #ecedf3; color: #111; " width=100 | Description
 +
| style="background: #f9f9f9; color: #111; " width=1200 | <span style="font-family: Consolas, monospace; color:#0f3f8d; font-size:110%"><b>isempty(</b><i>value</i><b>, </b><i>mode</i><b>)</b></span>
 +
The [[#IsEmpty|IsEmpty()]] function tests the given <i>value</i> for emptiness.  The <i>value</i> passed is typically an Media Center field, so that some action may be taken when the field is or is not empty.
 +
Returns 1 when the <i>value</i> is empty, otherwise 0.
 +
 
 +
Available <i>mode</i> values:
 +
 
 +
<div style="margin-left: 20pt;"><table style="background:#f9f9f9; border-spacing:0px; border-collapse:collapse;">
 +
<tr><td style="text-align:left; padding-right:20pt"><b>0</b></td><td>String test (field must be empty to get a positive result)</td></tr>
 +
<tr><td style="text-align:left; padding-right:20pt"><b>1</b></td><td>Numerical test (field must be empty, or contain 0 to get a positive result)</td></tr>
 +
</table></div>
 +
 
 +
Note that Media Center does not discriminate between a 0 <i>value</i> and an empty <i>value</i> for fields of type Integer and Decimal - both 0 and empty are considered equivalent for these field types.
 +
This is useful for fields such as the integer field Disc #, where an empty or 0 <i>value</i> implies that Disc # contains no useful data, and should be generally ignored or absent in display output.
 +
 
 +
Pay particular attention to the third example offered below, as it covers a caveat that comes with this particular function.
  
<br>Use'' IsPlaying ''in exactly the same way as IsInPlayingNow()''
+
Argument <i>mode</i> is optional (defaults to 0).
  
<br>''On the Interact support forum,'' '''[http://yabb.jriver.com/interact/index.php?topic=57461.0 mark_h describes how he puts these two functions to work for him]''', ''and rick.ca shows how he tweaked the idea when he answers the question:'' '''"[http://yabb.jriver.com/interact/index.php?topic=58137.msg393905#msg393905 is it possible to play an artist's full work when a genre is shuffling?]"'''
+
|- valign="top"
 +
! scope="row" style="background: #ecedf3; color: #111; " | Examples
 +
|style="background: #f9f9f9; color: #111; " | <span style="font-family: Consolas, monospace;"><b><nowiki>isempty([comment], 0)</nowiki></b></span>
 +
<p style="margin-left:20pt;">If the comment field is empty, [[#IsEmpty|IsEmpty()]] returns 1, otherwise 0.</p>
 +
<span style="font-family: Consolas, monospace;"><b><nowiki>isempty([track #], 1)</nowiki></b></span>
 +
<p style="margin-left:20pt;">Performs a numerical test for data in the [track #] field. If the field is empty or 0, a 1 is returned, otherwise 0 is returned.</p>
 +
<span style="font-family: Consolas, monospace;"><b><nowiki>ifelse(!isempty([disc #]), [disc #])</nowiki></b></span>
 +
<p style="margin-left:20pt;">Outputs the <i>value</i> of the disc # field when it is not empty.</p>
 
|}
 
|}
 
<div style="text-align:right;">([[#top|Back to top)]]</div>
 
<div style="text-align:right;">([[#top|Back to top)]]</div>
<br><br>
 
  
===Formatting Functions===
+
====IsRange(&hellip;): Tests a value for inclusion within a given range====
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&nbsp;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]'''''
+
 
 +
{| style="width: 100%; border: 2px solid black;" align="top" cellpadding="3"
 +
|- id="IsRange" valign="top"
 +
! scope="row" style="background: #ecedf3; color: #111; " width=100 | Description
 +
| style="background: #f9f9f9; color: #111; " width=1200 | <span style="font-family: Consolas, monospace; color:#0f3f8d; font-size:110%"><b>isrange(</b><i>value</i><b>, </b><i>range</i><b>)</b></span>
 +
The [[#IsRange|IsRange()]] function tests if a <i>value</i> falls within a given <i>range</i> of values.
 +
If the <i>value</i> falls within the given <i>range</i>, 1 is returned, otherwise 0 is returned.
 +
 
 +
A <i>range</i> is specified in the form of low-high, where low and high are either letters or numbers.
 +
The lowest <i>value</i> comes first, the highest second. Both low and high must be the same kind (letters or numbers).
 +
The low and high values are inclusive.
  
====Delimit(...): Outputs a value with head/tail strings when value is non-empty====
+
Example Ranges:
{| 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 | Delimit()
 
| 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"
 
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction
 
| 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.''
+
<div style="font-family: Consolas, monospace;">
* "Tail string" ''Optional, defaults to space.  The string to append at the end of a non-empty Value.''
+
<div style="margin-left: 20pt">1-100</div>
* "Head string" ''Optional, defaults to empty.  The string to append to the beginning of a non-empty Value.''
+
<div style="margin-left: 20pt">a-z</div>
 +
<div style="margin-left: 20pt">c-d</div>
 +
<div style="margin-left: 20pt">23-7542 </div>
 +
</div>
 
|- valign="top"
 
|- valign="top"
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples
+
! scope="row" style="background: #ecedf3; color: #111; " | Examples
|style="background: #ecfeea; color: black; border: 1px solid black" | '''delimit([Track #], .)'''<br>
+
|style="background: #f9f9f9; color: #111; " | <span style="font-family: Consolas, monospace;"><b><nowiki>isrange([artist], a-c)</nowiki></b></span>
''Appends a period (.) after a track number if [Track #] is not empty, e.g.  "12.".''
+
<p style="margin-left:20pt;">Artist values of Abba or Blondie will result in a 1, but ZZ Top will return a 0.</p>
 +
<span style="font-family: Consolas, monospace;"><b><nowiki>if(isrange([bitrate], 96-191), Poor Quality, High Quality)</nowiki></b></span>
 +
<p style="margin-left:20pt;">Returns <span style="font-family: Consolas, monospace;">Poor Quality</span> for any file whose bitrate falls in the <i>range</i> of 96 to 191, and returns <span style="font-family: Consolas, monospace;">High Quality</span> for all bitrates.</p>
  
<br />
+
Additional Examples
'''delimit([Date (year)], {, })'''<br />
 
  
Outputs the year surrounded by curly braces, e.g. "{2012}".
+
:[http://wiki.jriver.com/index.php/CD_Reference_Number#Answer_2 Using IsRange() in a Search List.]
 
|}
 
|}
 
<div style="text-align:right;">([[#top|Back to top)]]</div>
 
<div style="text-align:right;">([[#top|Back to top)]]</div>
  
====FormatBoolean(...): Formats a boolean (true / false) value in a specified manner====
+
====IsMissing(&hellip;): Tests to see if a file exists on the system====
{| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3"
+
 
|- valign="top"
+
{| style="width: 100%; border: 2px solid black;" align="top" cellpadding="3"
! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | FormatBoolean()
+
|- id="IsMissing" valign="top"
| 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.
+
! scope="row" style="background: #ecedf3; color: #111; " width=100 | Description
|- valign="top"
+
| style="background: #f9f9f9; color: #111; " width=1200 | <span style="font-family: Consolas, monospace; color:#0f3f8d; font-size:110%"><b>ismissing(</b><i>filepath</i><b>)</b></span>
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction
+
The [[#IsMissing|IsMissing()]] function tests for the existence of a file in the file system.
| style="background: #ecfeea; color: black; border: 1px solid black" | '''FormatBoolean(True/False Test,String to use if true,String to use if false)'''
+
If the file is missing, the function returns 1, otherwise 0 is returned if the file exists.
* '''True/False Test''' ''Other functions perform their respective tests and return 1 to indicate a true result, and 0 to indicate a false result''
+
This function is useful for checking for missing files in a Library.
* '''String to use if true,String to use if false''' ''If these are not specified, the function will default to using "True" and "False"''
+
[[#IsMissing|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: Any view or list that uses [[#IsMissing|IsMissing()]] will be slow, is Media Center must interogate each referenced file in the file system.
 +
The larger the number of files being queried, the longer it will take to produce results.  Use [[#IsMissing|IsMissing()]] with care.
 +
 
 +
Argument <i>filepath</i> is optional (defaults to [filename]).
  
 
|- valign="top"
 
|- valign="top"
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples
+
! scope="row" style="background: #ecedf3; color: #111; " | 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".
+
|style="background: #f9f9f9; color: #111; " | <span style="font-family: Consolas, monospace;"><b><nowiki>ismissing()</nowiki></b></span>
 
+
<p style="margin-left:20pt;">If the referenced file was not found in the file system, 1 is returned; othewise 0 is returned.</p>
<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"''
+
<span style="font-family: Consolas, monospace;"><b><nowiki>ismissing(C:\Music\My Lost File.mp3)</nowiki></b></span>
 +
<p style="margin-left:20pt;">Checks for <span style="font-family: Consolas, monospace;">My Lost File.mp3</span> and returns 1 (positive) if the file does not exist, and 0 (negative) if the file does exist.</p>
 +
<span style="font-family: Consolas, monospace;"><b><nowiki>if(ismissing(), File is missing, File exists)</nowiki></b></span>
 +
<p style="margin-left:20pt;">Outputs <span style="font-family: Consolas, monospace;">File is missing</span> or <span style="font-family: Consolas, monospace;">File Exists</span> depending on the result returned by IsMissing().</p>
 +
<span style="font-family: Consolas, monospace;"><b><nowiki>[=ismissing([filename])]=1</nowiki></b></span>
 +
<p style="margin-left:20pt;">This example demonstrates how to construct an expression for use as a Media Center search query.
 +
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 all files in library exist, this list will be empty. You could also create a view scheme and use this string in the <span style="font-family: Consolas, monospace;">Set rules for file display</span> search to give you a view that you can visit periodically to check that your library is not missing any files.</p>
 
|}
 
|}
 
<div style="text-align:right;">([[#top|Back to top)]]</div>
 
<div style="text-align:right;">([[#top|Back to top)]]</div>
  
====FormatDuration(...): Presents a duration of seconds in a reader friendly format====
+
====IsRemovable(&hellip;): Tests to see if a file is stored on removable media====
{| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3"
+
 
|- valign="top"
+
{| style="width: 100%; border: 2px solid black;" align="top" cellpadding="3"
! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | FormatDuration()
+
|- id="IsRemovable" valign="top"
| 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.
+
! scope="row" style="background: #ecedf3; color: #111; " width=100 | Description
|- valign="top"
+
| style="background: #f9f9f9; color: #111; " width=1200 | <span style="font-family: Consolas, monospace; color:#0f3f8d; font-size:110%"><b>isremovable(</b><i>filepath</i><b>)</b></span>
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction
+
The [[#IsRemovable|IsRemovable()]] function tests if a file resides on removable media and if so, returns 1, and if not, returns 0.
| style="background: #ecfeea; color: black; border: 1px solid black" | '''FormatDuration(Value to format)'''
+
The Media Center field [Removable] also provides the same value for a given file.
 +
 
 +
Argument <i>filepath</i> is optional (defaults to [filename]).
  
''"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: #ecedf3; color: #111; " | Examples
|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''
+
|style="background: #f9f9f9; color: #111; " | <span style="font-family: Consolas, monospace;"><b><nowiki>isremovable()</nowiki></b></span>
 
+
<p style="margin-left:20pt;">Checks if the current file is on removable storage, and if so, returns 1, otherwise returns 0.</p>
<br>'''formatduration(600)'''
 
<br>''This will output ten minutes in the format 10:00''
 
 
|}
 
|}
 
<div style="text-align:right;">([[#top|Back to top)]]</div>
 
<div style="text-align:right;">([[#top|Back to top)]]</div>
  
====FormatFileSize(...): Presents a number of bytes in a reader friendly format====
+
====IsInPlayingNow(&hellip;): Tests to see if a file is in the Playing Now playlist====
{| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3"
+
 
 +
{| style="width: 100%; border: 2px solid black;" align="top" cellpadding="3"
 +
|- id="IsInPlayingNow" valign="top"
 +
! scope="row" style="background: #ecedf3; color: #111; " width=100 | Description
 +
| style="background: #f9f9f9; color: #111; " width=1200 | <span style="font-family: Consolas, monospace; color:#0f3f8d; font-size:110%"><b>isinplayingnow(</b><i>filepath</i><b>)</b></span>
 +
The [[#IsInPlayingNow|IsInPlayingNow()]] function tests if a file is in any zone's Playing Now list.
 +
Used as an expression category, pane or file list column allows distinguishing files that are in the Playing Now list.
 +
 
 +
Argument <i>filepath</i> is optional (defaults to [filename]).
 +
 
 
|- valign="top"
 
|- valign="top"
! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | FormatFilesize()
+
! scope="row" style="background: #ecedf3; color: #111; " | Examples
| 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.
+
|style="background: #f9f9f9; color: #111; " | <span style="font-family: Consolas, monospace;"><b><nowiki>isinplayingnow()</nowiki></b></span>
|- valign="top"
+
<p style="margin-left:20pt;">If the file in the Playing Now list, returns 1, otherwise returns 0.</p>
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction
+
<span style="font-family: Consolas, monospace;"><b><nowiki>if(isinplayingnow(), Queued, Not queued)</nowiki></b></span>
| style="background: #ecfeea; color: black; border: 1px solid black" | '''FormatFileSize(Value to format)'''
+
<p style="margin-left:20pt;">If the file in the Playing Now list, returns <span style="font-family: Consolas, monospace;">Queued</span>, otherwise <span style="font-family: Consolas, monospace;">Not queued</span>.</p>
  
''"Value to format" can be either the raw [File Size] data or a given number of bytes.
+
Additional Examples
|- 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)'''
+
:[http://yabb.jriver.com/interact/index.php?topic=57461.0 How to use IsPlaying() and IsInPlayingNow()]
<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====
+
====IsPlaying(&hellip;): Tests to see if a file is in currently being played====
{| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3"
+
 
|- valign="top"
+
{| style="width: 100%; border: 2px solid black;" align="top" cellpadding="3"
! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | FormatNumber()
+
|- id="IsPlaying" valign="top"
| style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | '''FormatNumber()''' allows to format any given value to a set number of decimal places.
+
! scope="row" style="background: #ecedf3; color: #111; " width=100 | Description
|- valign="top"
+
| style="background: #f9f9f9; color: #111; " width=1200 | <span style="font-family: Consolas, monospace; color:#0f3f8d; font-size:110%"><b>isplaying(</b><i>filepath</i><b>)</b></span>
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction
+
The [[#IsPlaying|IsPlaying()]] function tests if a file is playing in any zone.
| style="background: #ecfeea; color: black; border: 1px solid black" | '''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)'''
+
Used as an expression category, pane or file list column allows distinguishing files that are playing now.
  
* "Value to format" ''This could be a library field, such as [replay gain] or the result of a [[#Math(...): Evaluates a given mathematical formula|Math()]] expression. Any numerical value you encounter where you would like to limit the number of decimal places displayed can have this function applied.''
+
Argument <i>filepath</i> is optional (defaults to [filename]).
* "Number of decimal places" ''This is optional. If not specified, the function will default to zero decimal places. Use -1 to output as many decimal places as necessary.''
 
* "Output if value is zero" ''This is optional. If not specified, the function will return zero.''
 
* "Label if value is greater than 1" ''This is optional. If not specified, the function will not return anything, if specified, and the formatted number is greater than 1, the function will return with the number, plus this label.''
 
* "Label if value equals 1" ''This is optional, as detailed below..''
 
** If not specified, but a label for greater than 1 has been specified, then this "greater than 1" label will always be used.
 
** If neither are specified, the function will not return anything.
 
** If both are specified, and the formatted number equals 1, the function will return with the number, plus this label.''
 
  
''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.''
 
 
|- valign="top"
 
|- valign="top"
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples
+
! scope="row" style="background: #ecedf3; color: #111; " | Examples
|style="background: #ecfeea; color: black; border: 1px solid black" | '''formatnumber([duration,0],2)'''<br>''This will return the duration of a track, in seconds, shown to two decimal places.''
+
|style="background: #f9f9f9; color: #111; " | <span style="font-family: Consolas, monospace;"><b><nowiki>IfElse(IsPlaying(), &lt;font color="ff0000"&gt;&#9834;&lt;//font&gt;, IsInPlayingNow(), &#9834;)</nowiki></b></span>
 +
<p style="margin-left:20pt;">This expression in a file list expression column shows which files are in the Playing Now list and which are currently playing by outputing a musical note in the column.  The musical note will be displayed in red for any currently playing file.</p>
 +
 
 +
Additional Examples
  
<br>'''formatnumber([number plays,0],0,Not played this one yet,Plays,Play)'''
+
:[http://yabb.jriver.com/interact/index.php?topic=57461.0 How to use IsPlaying() and IsInPlayingNow()]  
* "0" decimal places has been specified, therefore the result will be a whole number with no decimals shown.
 
* ''If [number plays] is zero, the result will be "Not played this one yet"''
 
* ''If [number plays] is greater than 1, lets say 6, the result will be "6 Plays"''
 
* ''If [number plays] is 1, the result will be "1 Play"''
 
  
<br>'''formatnumber([number plays,0],,,,Time)'''
+
:[http://yabb.jriver.com/interact/index.php?topic=58137.msg393905#msg393905 How to play an artist's full work when a genre is shuffling?]  
''Here, the function will fall back to its defaults for everything except when the number equals one:''
 
* ''No decimal places have been specified, the result will default to a whole number with no decimals shown.''
 
* ''If [number plays] is zero, the result will be "0"''
 
* ''If [number plays] is greater than 1, lets say 6, the result will be "6"''
 
* ''If [number plays] is 1, the result will be "1 Time"''
 
 
|}
 
|}
 
<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====
+
===Formatting Functions===
{| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3"
+
 
|- valign="top"
+
The functions in this section format their arguments in specific ways.
! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | FormatRange()
+
Some functions are used for formatting values for better presentation, or according to some format, while other functions work on Media Center internal "raw" data to convert to user-friendly formats.
| 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"
+
Certain Media Center fields are used to store values in ways that are internally convenient or effecient.  But these field values are not terribly useful or meaningful when used directly.
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction
+
 
| style="background: #ecfeea; color: black; border: 1px solid black" | '''FormatRange(Value to format,Range size,Mode)'''
+
For example, the Duration field holds values as a number seconds of length, while various Date/Time fields such as Date or Last Played store values as floating point numbers specifying a number of days and fractions of a day since a particular epoch time.
'''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"
 
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples
 
|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.''
+
Media Center will generally format fields using the "display" format where necessary, such as in panes, file list columns, or various tools such as the Rename, Move & Copy tool.
 +
When a function requires a raw field value, or you want to access a raw field value, by sure to use the raw field format.
 +
This is done by appending a <span style="font-family: Consolas, monospace;"><b>,0</b></span> to the field's name inside the brackets, for example <span style="font-family: Consolas, monospace;">[Date Imported,0]</span>.
 +
====Delimit(&hellip;): Outputs a value with head/tail strings when value is non-empty====
  
<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.''
+
{| style="width: 100%; border: 2px solid black;" align="top" cellpadding="3"
 +
|- id="Delimit" valign="top"
 +
! scope="row" style="background: #ecedf3; color: #111; " width=100 | Description
 +
| style="background: #f9f9f9; color: #111; " width=1200 | <span style="font-family: Consolas, monospace; color:#0f3f8d; font-size:110%"><b>delimit(</b><i>expression</i><b>, </b><i>tail</i><b>, </b><i>head</i><b>)</b></span>
 +
The [[#Delimit|Delimit()]] function outputs the value of <i>expression</i> prepended with a <i>head</i> string and/or appended with a <i>tail</i> string, but only if the value of the <i>expression</i> is non-empty. Nothing is output when the <i>expression</i> evaluates to empty.
  
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]].
+
Argument <i>tail</i> is optional (defaults to SPACE).
|}
 
<div style="text-align:right;">([[#top|Back to top)]]</div>
 
  
====Orientation(...): Outputs the orientation of an image====
+
Argument <i>head</i> is optional (defaults to EMPTY).
{| 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 | Orientation()
 
| style="background: #ecfeea; color: black; border: 1px solid black" width=1200 |  Outputs a word indicating the orientation of an image file.
 
|- valign="top"
 
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction
 
| 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: #ecedf3; color: #111; " | Examples
|style="background: #ecfeea; color: black; border: 1px solid black" | '''if(isequal(orientation(), Square), Square, Rectangle)'''
+
|style="background: #f9f9f9; color: #111; " | <span style="font-family: Consolas, monospace;"><b><nowiki>delimit([Track #], .)</nowiki></b></span>
Outputs "Square" for square images or "Rectangle" for portrait and landscape images.''
+
<p style="margin-left:20pt;">Appends a period after a track number if [Track #] is not empty, such as <span style="font-family: Consolas, monospace;">12.</span>.</p>
 +
<span style="font-family: Consolas, monospace;"><b><nowiki>delimit([Date (year)], {, })</nowiki></b></span>
 +
<p style="margin-left:20pt;">Outputs the year surrounded by curly braces, for example <span style="font-family: Consolas, monospace;">{2012</span>}.</p>
 
|}
 
|}
 
<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====
+
====FormatBoolean(&hellip;): 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"
+
{| style="width: 100%; border: 2px solid black;" align="top" cellpadding="3"
! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | PadNumber()
+
|- id="FormatBoolean" valign="top"
| 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.
+
! scope="row" style="background: #ecedf3; color: #111; " width=100 | Description
|- valign="top"
+
| style="background: #f9f9f9; color: #111; " width=1200 | <span style="font-family: Consolas, monospace; color:#0f3f8d; font-size:110%"><b>formatboolean(</b><i>conditional</i><b>, </b><i>true string</i><b>, </b><i>false string</i><b>)</b></span>
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction
+
The [[#FormatBoolean|FormatBoolean()]] function outputs <i>true string</i> and <i>false string</i> values to represent the 0 or 1 Boolean output resulting from the <i>conditional</i> expression.
| style="background: #ecfeea; color: black; border: 1px solid black" | '''PadNumber(Field to pad,Total number of digits required)'''
+
When the <i>conditional</i> evalutes to 1, the <i>true string</i> will be output, otherwise the <i>false string</i> will be output.
 +
 
 +
Argument <i>true string</i> is optional (defaults to True).
 +
 
 +
Argument <i>false string</i> is optional (defaults to False).
 +
 
 
|- valign="top"
 
|- valign="top"
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples
+
! scope="row" style="background: #ecedf3; color: #111; " | Examples
|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.''
+
|style="background: #f9f9f9; color: #111; " | <span style="font-family: Consolas, monospace;"><b><nowiki>formatboolean(isempty([number plays]), Never Played, Has Been Played)</nowiki></b></span>
 
+
<p style="margin-left:20pt;">Returns <span style="font-family: Consolas, monospace;">Never Played</span> when the expression [[#IsEmpty|IsEmpty()]] evaluates to 0, and <span style="font-family: Consolas, monospace;">Has Been Played</span> when it evaluates to 1.</p>
<br>'''padnumber([[#Counter(...): Counts upwards in specified increments|counter()]],4)'''
+
<span style="font-family: Consolas, monospace;"><b><nowiki>formatboolean(math([track #] % 2)</nowiki></b></span>
<br>''here, the output from the counter() function will be 'padded' to 4 characters: 0001, 0002, 0003, etc. etc.''
+
<p style="margin-left:20pt;">Outputs the default True label for odd track numbers, and the default False label for even ones.</p>
 
|}
 
|}
 
<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====
+
====FormatDuration(&hellip;): 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"
+
{| style="width: 100%; border: 2px solid black;" align="top" cellpadding="3"
! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | RatingStars()
+
|- id="FormatDuration" valign="top"
| 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.
+
! scope="row" style="background: #ecedf3; color: #111; " width=100 | Description
|- valign="top"
+
| style="background: #f9f9f9; color: #111; " width=1200 | <span style="font-family: Consolas, monospace; color:#0f3f8d; font-size:110%"><b>formatduration(</b><i>duration value</i><b>)</b></span>
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction
+
The [[#FormatDuration|FormatDuration()]] function formats a <i>duration value</i> into a friendly format. 
| style="background: #ecfeea; color: black; border: 1px solid black" | '''RatingStars()'''
+
The <i>duration value</i> argument is expected to be a value representing a number of seconds, typically used for media file duration.
 +
Media Center internally stores duration values in seconds.
 
|- valign="top"
 
|- valign="top"
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples
+
! scope="row" style="background: #ecedf3; color: #111; " | Examples
|style="background: #ecfeea; color: black; border: 1px solid black" | '''ratingstars()'''<br>''For a file that has a Rating of 4, outputs "★★★★".''
+
|style="background: #f9f9f9; color: #111; " | <span style="font-family: Consolas, monospace;"><b><nowiki>formatduration([duration,0])</nowiki></b></span>
 +
<p style="margin-left:20pt;">Outputs a friendly display of the duration field.  This is the same output shown using the Duration field in a file list.</p>
 +
<span style="font-family: Consolas, monospace;"><b><nowiki>formatduration(600)</nowiki></b></span>
 +
<p style="margin-left:20pt;">This will output ten minutes in the format <span style="font-family: Consolas, monospace;">10:00</span>.</p>
 
|}
 
|}
 
<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====
+
====FormatFileSize(&hellip;): Presents a number of bytes 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 | Watched()
 
| style="background: #ecfeea; color: black; border: 1px solid black" width=1200 |  Outputs a video's bookmark position in a human-readable format.
 
|- valign="top"
 
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction
 
| style="background: #ecfeea; color: black; border: 1px solid black" | '''Watched()'''
 
  
* '''0''': ''Output a human-readable watched status.''
+
{| style="width: 100%; border: 2px solid black;" align="top" cellpadding="3"
* '''1''': ''Output a numeric watched value, 0 if not watched, 1 if partially watched, 2 if entirely watched.''
+
|- id="FormatFileSize" valign="top"
* '''2''': ''Output a watched checkmark () if watched''
+
! scope="row" style="background: #ecedf3; color: #111; " width=100 | Description
 +
| style="background: #f9f9f9; color: #111; " width=1200 | <span style="font-family: Consolas, monospace; color:#0f3f8d; font-size:110%"><b>formatfilesize(</b><i>bytes value</i><b>)</b></span>
 +
The [[#FormatFileSize|FormatFileSize()]] function formats a <i>bytes value</i> into a friendly format.
 +
The <i>bytes value</i> argument is expected to be a value representing a number of bytes, typically used for media file size.
 +
Media Center internally stores file size values in bytes.  [[#FormatFileSize|FormatFileSize()]] will convert those byte values into unitized friendly formats such as 50 bytes, 3.2 KB or 10.4 MB.
 
|- valign="top"
 
|- valign="top"
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples
+
! scope="row" style="background: #ecedf3; color: #111; " | Examples
|style="background: #ecfeea; color: black; border: 1px solid black" | '''Watched()'''
+
|style="background: #f9f9f9; color: #111; " | <span style="font-family: Consolas, monospace;"><b><nowiki>formatfilesize([file size,0])</nowiki></b></span>
Outputs formatted watched status, such as, ''57% on Sep 25'', or ''Aug 21'', or nothing when the video has not been watched.''
+
<p style="margin-left:20pt;">Outputs a friendly format of the file size field.  This is the same output shown using the File Size field in a file list.</p>
 +
<span style="font-family: Consolas, monospace;"><b><nowiki>formatfilesize(56123456)</nowiki></b></span>
 +
<p style="margin-left:20pt;">Outputs the <i>bytes value</i> 56,123,456 as <span style="font-family: Consolas, monospace;">53.5 MB</span>.</p>
 
|}
 
|}
 
<div style="text-align:right;">([[#top|Back to top)]]</div>
 
<div style="text-align:right;">([[#top|Back to top)]]</div>
<br><br>
 
  
===String Manipulation===
+
====FormatNumber(&hellip;): Formats and rounds a number to a specified number of decimal places====
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====
+
{| style="width: 100%; border: 2px solid black;" align="top" cellpadding="3"
{| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3"
+
|- id="FormatNumber" valign="top"
|- valign="top"
+
! scope="row" style="background: #ecedf3; color: #111; " width=100 | Description
! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | Clean()
+
| style="background: #f9f9f9; color: #111; " width=1200 | <span style="font-family: Consolas, monospace; color:#0f3f8d; font-size:110%"><b>formatnumber(</b><i>value</i><b>, </b><i>decimal places</i><b>, </b><i>label zero</i><b>, </b><i>label plural</i><b>, </b><i>label singular</i><b>)</b></span>
| 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 charactersIt is typically employed to clean the joining of several fields, some of which may be empty, or to produce filesystem-safe filenames.
+
The [[#FormatNumber|FormatNumber()]] function formats a numeric <i>value</i> to a specified number of <i>decimal places</i>, rounding its <i>value</i>, and optionally outputs <i>value</i>-dependent labels, which can be used to construct more gramatically-correct output.
|- valign="top"
+
The <i>value</i> can be any numeric <i>value</i>.
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction
+
The <i>decimal places</i> argument specifies the number of digits to be used after the decimal pointUse -1 to output as many <i>decimal places</i> as available.
| style="background: #ecfeea; color: black; border: 1px solid black" | '''Clean(Value to clean, Mode)'''
+
 
 +
The label selected depends on the original <i>value</i>, not the resulting formatted <i>value</i>.
 +
 
 +
The <i>label zero</i> argument is output instead of a formatted <i>value</i> when the original <i>value</i> is 0.  When this label is specified as empty, <i>label plural</i> is used.
 +
The <i>label plural</i> argument is appended to the formatted <i>value</i> when the original <i>value</i> is more than 1.
 +
The <i>label singular</i> argument is appended to the formatted <i>value</i> when the original <i>value</i> is equal to 1.
  
''Value to clean'': a string that will be cleaned
+
Note: [[#FormatNumber|FormatNumber()]] will not output additional zero's after the decimal point.  In otherwords, [[#FormatNumber|FormatNumber()]] rounds fractional values, but does not zero fill.
  
''Mode'' (optional, defaults to 0):
+
Argument <i>decimal places</i> is optional (defaults to 0).
* 0: default clean, removes empty () and [], superfluous dash (-) characters and sometimes comma (be careful)
 
* 1: removes the article 'the' from the beginning and ', the' from the end
 
* 2: removes any article (a, an, the, etc.) from the beginning and end
 
* 3: replaces each filesystem-illegal character --- '''\ / : * ? " < > |''' --- with an underscore (_), and replaces each unprintable character with a space.
 
  
|- valign="top"
+
Argument <i>label zero</i> is optional (defaults to <i>label plural</i>).
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples
 
|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 />
+
Argument <i>label plural</i> is optional (defaults to 0).
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 />
+
Argument <i>label singular</i> is optional.
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 />
+
|- valign="top"
This trivial example demonstrates how all filesystem-illegal characters are converted to underscores, producing the nine-character string consisting entirely of underscores "_________".
+
! scope="row" style="background: #ecedf3; color: #111; " | Examples
 +
|style="background: #f9f9f9; color: #111; " | <span style="font-family: Consolas, monospace;"><b><nowiki>formatnumber([duration,0], 2)</nowiki></b></span>
 +
<p style="margin-left:20pt;">Returns a file's duration (which are in seconds) rounding to two <i>decimal places</i>.</p>
 +
<span style="font-family: Consolas, monospace;"><b><nowiki>formatnumber([number plays,0], 0, Unplayed, Plays, Play)</nowiki></b></span>
 +
<p style="margin-left:20pt;">Outputs values in whole number formats (no decimals shown). When the number of plays is 0, the output will be <span style="font-family: Consolas, monospace;">Unplayed</span>.
 +
When it is more than one, such as six, outputs <span style="font-family: Consolas, monospace;">6 Plays</span>.
 +
And when the number of plays is one, outputs <span style="font-family: Consolas, monospace;">1 Play</span>.</p>
 +
<span style="font-family: Consolas, monospace;"><b><nowiki>formatnumber([number plays,0], 0, , Plays, Play)</nowiki></b></span>
 +
<p style="margin-left:20pt;">Same as the previous example, but uses the default <i>value</i> for <i>label zero</i> (which is <i>label plural</i>), so that when number of plays is zero, output is <span style="font-family: Consolas, monospace;">0 Plays</span>.</p>
 +
<span style="font-family: Consolas, monospace;"><b><nowiki>formatnumber([number plays,0], , , , Time)</nowiki></b></span>
 +
<p style="margin-left:20pt;">In this example, only <i>label singular</i> argument is specified (as <span style="font-family: Consolas, monospace;">Time</span>), so all other arguments use their defaults values.
 +
The output will be <span style="font-family: Consolas, monospace;">0</span> when number of plays is zero, <span style="font-family: Consolas, monospace;">1 Time</span> when number of plays is one, and the actual number of plays for other values (e.g. <span style="font-family: Consolas, monospace;">6</span>).</p>
 
|}
 
|}
 
<div style="text-align:right;">([[#top|Back to top)]]</div>
 
<div style="text-align:right;">([[#top|Back to top)]]</div>
  
====FixCase(...): Changes the case of a given string====
+
====FormatRange(&hellip;): Formats a value as a range====
{| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3"
+
 
|- valign="top"
+
{| style="width: 100%; border: 2px solid black;" align="top" cellpadding="3"
! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | FixCase()
+
|- id="FormatRange" valign="top"
| style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | This function will output any given text string in one of five specified case modes.
+
! scope="row" style="background: #ecedf3; color: #111; " width=100 | Description
|- valign="top"
+
| style="background: #f9f9f9; color: #111; " width=1200 | <span style="font-family: Consolas, monospace; color:#0f3f8d; font-size:110%"><b>formatrange(</b><i>value</i><b>, </b><i>range size</i><b>, </b><i>mode</i><b>)</b></span>
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction
+
The [[#FormatRange|FormatRange()]] function creates numerical or alphabetic groupings of size <i>range size</i>, and returns the grouping where <i>value</i> falls.
| style="background: #ecfeea; color: black; border: 1px solid black" | '''FixCase(String to modify,Case mode to apply)'''<br>''The ''"String to modify"'' can be plain text, a library field, or a combination of the two.''
+
Only the first character of <i>value</i> is considered and used.
 +
The <i>range size</i> is a numerical <i>value</i> specifying how wide the range should be.  Numeric ranges are 0-based.
 +
The <i>mode</i> specifies the type of range grouping.
 +
 
 +
Available <i>mode</i> values:
 +
 
 +
<div style="margin-left: 0pt;"><table style="background:#f9f9f9; border-spacing:0px; border-collapse:collapse;">
 +
<tr><td style="text-align:left; padding-right:20pt"><b>0</b></td><td>Automatically choose between number / letter grouping</td></tr>
 +
<tr><td style="text-align:left; padding-right:20pt"><b>    1</b></td><td>Letter grouping</td></tr>
 +
<tr><td style="text-align:left; padding-right:20pt"><b>    2</b></td><td>Number grouping</td></tr>
 +
</table></div>
  
The five modes available are:
+
Argument <i>range size</i> is optional (defaults to 1).
* '''0:''' ''Title Case''
 
* '''1:''' ''All Words''
 
* '''2:''' ''First word''
 
* '''3:''' ''ALL UPPERCASE''
 
* '''4:''' ''all lowercase''
 
  
''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 [http://www.grammar-monster.com/lessons/capital_letters_title_case.htm here]''
+
Argument <i>mode</i> is optional (defaults to 0).
  
 
|- valign="top"
 
|- valign="top"
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples
+
! scope="row" style="background: #ecedf3; color: #111; " | Examples
|style="background: #ecfeea; color: black; border: 1px solid black" | '''fixcase([album])'''<br>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")
+
|style="background: #f9f9f9; color: #111; " | <span style="font-family: Consolas, monospace;"><b><nowiki>formatrange([artist], 3, 1)</nowiki></b></span>
 +
<p style="margin-left:20pt;">Outputs the range that the artist's first letter falls within.
 +
With a <i>range size</i> of 3 and using <i>mode</i> 1 (letter grouping), ranges will be produced in the form of
 +
<span style="font-family: Consolas, monospace;">a-c</span>, <span style="font-family: Consolas, monospace;">d-f</span>, <span style="font-family: Consolas, monospace;">g-i</span>, etc.</p>
 +
<span style="font-family: Consolas, monospace;"><b><nowiki>formatrange([artist])</nowiki></b></span>
 +
<p style="margin-left:20pt;">With <i>range size</i> and <i>mode</i> values left unspecified, default values are used, so automatic range groupings of size 1 are output.
 +
Hence, the first character of [artist] will be output.</p>
 +
<span style="font-family: Consolas, monospace;"><b><nowiki>formatrange([bitrate], 100, 2)</nowiki></b></span>
 +
<p style="margin-left:20pt;">Numeric range groupings of size 100 will be output, for the <i>value</i> of [bitrate].  Possible outputs are: <span style="font-family: Consolas, monospace;">0-99</span>, <span style="font-family: Consolas, monospace;">100-199</span>, <span style="font-family: Consolas, monospace;">200-299</span>, etc.</p>
 +
 
 +
Additional Examples
  
<br>'''fixcase(MY ALbUm IS cAlLeD [album],4)'''<br>This would return "my album is called time out of mind"
+
:[http://wiki.jriver.com/index.php/CD_Reference_Number How to produce 1-based range values.]  
 
|}
 
|}
 
<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====
+
====Orientation(&hellip;): Outputs the orientation of an image====
{| 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 | FixSpacing()
 
| 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"
 
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction
 
| 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:
+
{| style="width: 100%; border: 2px solid black;" align="top" cellpadding="3"
* '''0:''' ''Disables conversion''
+
|- id="Orientation" valign="top"
* '''1:''' ''Enables camel-case conversion''
+
! scope="row" style="background: #ecedf3; color: #111; " width=100 | Description
 +
| style="background: #f9f9f9; color: #111; " width=1200 | <span style="font-family: Consolas, monospace; color:#0f3f8d; font-size:110%"><b>orientation(</b><b>)</b></span>
 +
The [[#Orientation|Orientation()]] function outputs one of the following words indicating the orientation of an image file:
  
 +
<div style="margin-left: 20pt;"><table style="background:#f9f9f9; border-spacing:0px; border-collapse:collapse;">
 +
<tr><td style="text-align:left; padding-right:20pt">Portrait</td><td>When height > width</td></tr>
 +
<tr><td style="text-align:left; padding-right:20pt">Landscape</td><td>When width > height</td></tr>
 +
<tr><td style="text-align:left; padding-right:20pt">Portrait</td><td>When height = width</td></tr>
 +
</table></div>
 
|- valign="top"
 
|- valign="top"
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples
+
! scope="row" style="background: #ecedf3; color: #111; " | Examples
|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.
+
|style="background: #f9f9f9; color: #111; " | <span style="font-family: Consolas, monospace;"><b><nowiki>if(isequal(orientation(), Square), Square, Rectangle)</nowiki></b></span>
 
+
<p style="margin-left:20pt;">Outputs <span style="font-family: Consolas, monospace;">Square</span> for square images or <span style="font-family: Consolas, monospace;">Rectangle</span> for portrait and landscape images.</p>
<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====
+
====PadNumber(&hellip;): Adds leading zeros to any given number====
{| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3"
+
 
|- valign="top"
+
{| style="width: 100%; border: 2px solid black;" align="top" cellpadding="3"
! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | Hexify()
+
|- id="PadNumber" valign="top"
| 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.''
+
! scope="row" style="background: #ecedf3; color: #111; " width=100 | Description
|- valign="top"
+
| style="background: #f9f9f9; color: #111; " width=1200 | <span style="font-family: Consolas, monospace; color:#0f3f8d; font-size:110%"><b>padnumber(</b><i>value</i><b>, </b><i>number digits</i><b>)</b></span>
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction
+
The [[#PadNumber|PadNumber()]] function adds leading zeros to any given number <i>value</i>, producing a <i>value</i> of length <i>number digits</i>.
| 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: #ecedf3; color: #111; " | Examples
|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''
+
|style="background: #f9f9f9; color: #111; " | <span style="font-family: Consolas, monospace;"><b><nowiki>padnumber([track #], 2)</nowiki></b></span>
 +
<p style="margin-left:20pt;">This will pad the track number with leading zeros sufficient to ensure the output is minimally two digits in length.</p>
 +
<span style="font-family: Consolas, monospace;"><b><nowiki>padnumber(counter(), 4)</nowiki></b></span>
 +
<p style="margin-left:20pt;">Outputs 4 digits of zero-padded numbers produced by [[#Counter|Counter()]]. For example, <span style="font-family: Consolas, monospace;">0001</span>, <span style="font-family: Consolas, monospace;">0002</span>, <span style="font-family: Consolas, monospace;">0003</span>,
 +
etc.</p>
 
|}
 
|}
 
<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====
+
====RatingStars(&hellip;): Outputs the value of Rating as a number of star characters====
{| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3"
+
 
|- valign="top"
+
{| style="width: 100%; border: 2px solid black;" align="top" cellpadding="3"
! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | Left()
+
|- id="RatingStars" valign="top"
| 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.
+
! scope="row" style="background: #ecedf3; color: #111; " width=100 | Description
|- valign="top"
+
| style="background: #f9f9f9; color: #111; " width=1200 | <span style="font-family: Consolas, monospace; color:#0f3f8d; font-size:110%"><b>ratingstars(</b><b>)</b></span>
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction
+
The [[#RatingStars|RatingStars()]] function outputs the Rating field's value as the equivalent number of black star characters.
| 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: #ecedf3; color: #111; " | Examples
|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.''
+
|style="background: #f9f9f9; color: #111; " | <span style="font-family: Consolas, monospace;"><b><nowiki>ratingstars()</nowiki></b></span>
 +
<p style="margin-left:20pt;">For a file that has a Rating of 4, outputs &#9733;&#9733;&#9733;&#9733;.</p>
 
|}
 
|}
 
<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"
+
====Watched(&hellip;): Outputs a formatted video bookmark====
|- valign="top"
+
 
! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | Length()
+
{| style="width: 100%; border: 2px solid black;" align="top" cellpadding="3"
| style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | This function returns the number of characters in any given string.
+
|- id="Watched" valign="top"
|- valign="top"
+
! scope="row" style="background: #ecedf3; color: #111; " width=100 | Description
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction
+
| style="background: #f9f9f9; color: #111; " width=1200 | <span style="font-family: Consolas, monospace; color:#0f3f8d; font-size:110%"><b>watched(</b><i>mode</i><b>)</b></span>
| 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.''
+
Outputs a video's bookmark position in a human-readable format, using a specified <i>mode</i>.
 +
 
 +
Available <i>mode</i> values:
 +
 
 +
<div style="margin-left: 20pt;"><table style="background:#f9f9f9; border-spacing:0px; border-collapse:collapse;">
 +
<tr><td style="text-align:left; padding-right:20pt"><b>0</b></td><td>Output a human-readable watched status.</td></tr>
 +
<tr><td style="text-align:left; padding-right:20pt"><b>1</b></td><td>Output a numeric watched value, 0 if not watched, 1 if partially watched, 2 if entirely watched.</td></tr>
 +
<tr><td style="text-align:left; padding-right:20pt"><b>2</b></td><td>Output a watched checkmark &#x2713; if watched</td></tr>
 +
</table></div>
 +
 
 +
Argument <i>mode</i> is optional (defaults to 0).
 +
 
 
|- valign="top"
 
|- valign="top"
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples
+
! scope="row" style="background: #ecedf3; color: #111; " | Examples
|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.
+
|style="background: #f9f9f9; color: #111; " | <span style="font-family: Consolas, monospace;"><b><nowiki>watched()</nowiki></b></span>
 
+
<p style="margin-left:20pt;">Outputs formatted watched status, such as <span style="font-family: Consolas, monospace;">57% on Sep 25</span>, or <span style="font-family: Consolas, monospace;">Aug 21</span>, or nothing when the video has not been watched.</p>
<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>
====Mid(...): Retrieves specified characters 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 | Mid()
 
| style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | Mid() retrieves a specified number of characters from a specified starting point in any given string.
 
|- valign="top"
 
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction
 
| style="background: #ecfeea; color: black; border: 1px solid black" | '''Mid(Value to get characters from,Character to start at,Number of characters to get)'''
 
* '''Value to get characters from''': ''This can be a library field, plain text, or a combination of both.
 
* '''Character to start at''': ''This is a numerical pointer, and rather confusingly, the function treats the first character as zero and begins from there. If not specified, the function will default to zero.
 
* '''Number of characters to get''': ''If this value is not specified, the function will default to 1. -1 can be used to retrieve all available characters after the specified start point.
 
  
|- valign="top"
+
===String Manipulation Functions===
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples
+
 
|style="background: #ecfeea; color: black; border: 1px solid black" | '''mid(12345)'''<br>''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.''
+
The functions in this section are used primarly to manipulate strings.  Since the Media Center expression language is primarly string-oriented, these functions provide a means to manipulate field values or the output from other expressions.
 +
====Clean(&hellip;): Clean a string to be used for various operations====
  
<br>'''mid(12345,1,2)'''<br>''The start point has been specified as the second character in, and 2 characters have been asked for, the result here will be 23.''
+
{| style="width: 100%; border: 2px solid black;" align="top" cellpadding="3"
 +
|- id="Clean" valign="top"
 +
! scope="row" style="background: #ecedf3; color: #111; " width=100 | Description
 +
| style="background: #f9f9f9; color: #111; " width=1200 | <span style="font-family: Consolas, monospace; color:#0f3f8d; font-size:110%"><b>clean(</b><i>string</i><b>, </b><i>mode</i><b>)</b></span>
 +
The [[#Clean|Clean()]] function is generally used to sanitize a <i>string</i> by stripping empty brackets, remove superfluous dash characters, eliminate leading or trailing articles, or replace filesystem-illegal characters.
 +
It is typically employed before some operation such as Rename to clean the product of joining various fields, some of which may be empty, or to produce filesystem-safe filenames.  It may be used for a variety of purposes, however.
  
<br>An example of Mid() being used to re-order a date field was given in answer to the question "[http://yabb.jriver.com/interact/index.php?topic=52809.0 Can I include seconds in "import date"?]"
+
Available <i>mode</i> values:
|}
 
<div style="text-align:right;">([[#top|Back to top)]]</div>
 
  
====Regex(...): Regular expression pattern matching and capture====
+
<div style="margin-left: 20pt;"><table style="background:#f9f9f9; border-spacing:0px; border-collapse:collapse;">
{| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3"
+
<tr><td style="text-align:left; padding-right:20pt"><b>0</b></td><td>Removes empty () and [], superfluous dash (-) and whitespace characters and sometimes comma (be careful)</td></tr>
|- valign="top"
+
<tr><td style="text-align:left; padding-right:20pt"><b>1</b></td><td>Removes the article 'the' from the beginning and ', the' from the end</td></tr>
! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | Regex()
+
<tr><td style="text-align:left; padding-right:20pt"><b>2</b></td><td>Removes any article (a, an, the, etc.) from the beginning and end</td></tr>
| 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.)
+
<tr><td style="text-align:left; padding-right:20pt"><b>3</b></td><td>Replaces each filesystem-illegal character <span style="font-family: Consolas, monospace;">\ / : * ? " < > |</span> with an underscore <span style="font-family: Consolas, monospace;">_</span>, and replaces each unprintable character with a space</td></tr>
|- valign="top"
+
</table></div>
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction
 
| style="background: #ecfeea; color: black; border: 1px solid black" | '''Regex(String to test, Regular expression, Mode, Case sensitivity)'''
 
  
* '''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.''
+
Argument <i>mode</i> is optional (defaults to 0).
* '''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: #ecedf3; color: #111; " | Examples
|style="background: #ecfeea; color: black; border: 1px solid black" | '''Example: Modes 1 through 9'''
+
|style="background: #f9f9f9; color: #111; " | <span style="font-family: Consolas, monospace;"><b><nowiki>clean([album] - [date])</nowiki></b></span>
 +
<p style="margin-left:20pt;">The concatenation of [Album] - [Date] may leave a dangling <span style="font-family: Consolas, monospace;"> - </span> <i>string</i> when date is empty.  [[#Clean|Clean()]] in the default <i>mode</i> removes this dangling <i>string</i>.</p>
 +
<span style="font-family: Consolas, monospace;"><b><nowiki>clean(The Beatles, 1)</nowiki></b></span>
 +
<p style="margin-left:20pt;">For sorting or grouping purposes, it is often desirable to remove the leading article <span style="font-family: Consolas, monospace;">The</span> from a <i>string</i>. [[#Clean|Clean()]] in <i>mode</i> 1 provides a convenient solution, and in this example produces <span style="font-family: Consolas, monospace;">Beatles</span>.</p>
 +
<span style="font-family: Consolas, monospace;"><b><nowiki>clean(AC//DC: Back In Black, 3)</nowiki></b></span>
 +
<p style="margin-left:20pt;">When an expression is to be used to produce a filename, filesystem-illegal characters must be removed or converted to legal characters.  [[#Clean|Clean()]] in <i>mode</i> 3 will convert such characters into safe underscores.  This example would produce the filesystem-safe value of <span style="font-family: Consolas, monospace;">AC_DC_ Back In Black</span>.</p>
 +
<span style="font-family: Consolas, monospace;"><b><nowiki>clean(\//:*?"&lt;&gt;|, 3)</nowiki></b></span>
 +
<p style="margin-left:20pt;">This trivial example demonstrates how all filesystem-illegal characters are converted to underscores,
 +
producing the nine-character output <span style="font-family: Consolas, monospace;">_________</span> which consists entirely of underscores.</p>
 +
|}
 +
<div style="text-align:right;">([[#top|Back to top)]]</div>
  
The examples in this section use one of the modes from 1 through 9, to output the specified capture.
+
====FixCase(&hellip;): Changes the case of a given string====
  
'''<span style="font-family: Consolas, monospace;"><nowiki>
+
{| style="width: 100%; border: 2px solid black;" align="top" cellpadding="3"
Regex([Name], /#(Big.*Man)#/, 1)
+
|- id="FixCase" valign="top"
</nowiki></span>'''
+
! scope="row" style="background: #ecedf3; color: #111; " width=100 | Description
 +
| style="background: #f9f9f9; color: #111; " width=1200 | <span style="font-family: Consolas, monospace; color:#0f3f8d; font-size:110%"><b>fixcase(</b><i>string</i><b>, </b><i>mode</i><b>)</b></span>
 +
The [[#FixCase|FixCase()]] function will convert the supplied text <i>string</i> according to the specified <i>mode</i>.
  
''Matches track names that contain'' '''Big''' ''followed by'' '''Man''''', with anything (including nothing) in between, and outputs the matched tracks.''
+
Available <i>mode</i> values:
Sample output:
 
:Big Butter and Egg Man
 
:Big Man
 
:Big Manager
 
:It's a Bigman Thing
 
  
&oline;&oline;&oline;&oline;
+
<div style="margin-left: 20pt;"><table style="background:#f9f9f9; border-spacing:0px; border-collapse:collapse;">
 +
<tr><td style="text-align:left; padding-right:20pt"><b>0</b></td><td>Title Case</td></tr>
 +
<tr><td style="text-align:left; padding-right:20pt"><b>1</b></td><td>All Words</td></tr>
 +
<tr><td style="text-align:left; padding-right:20pt"><b>2</b></td><td>First Word</td></tr>
 +
<tr><td style="text-align:left; padding-right:20pt"><b>3</b></td><td>All Uppercase</td></tr>
 +
<tr><td style="text-align:left; padding-right:20pt"><b>4</b></td><td>All Lowercase</td></tr>
 +
</table></div>
  
'''<span style="font-family: Consolas, monospace;"><nowiki>
+
Argument <i>mode</i> is optional (defaults to 0).
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.''
+
|- valign="top"
 +
! scope="row" style="background: #ecedf3; color: #111; " | Examples
 +
|style="background: #f9f9f9; color: #111; " | <span style="font-family: Consolas, monospace;"><b><nowiki>fixcase(enjoy the silence)</nowiki></b></span>
 +
<p style="margin-left:20pt;">The default <i>mode</i> 0 is used, so the output is <span style="font-family: Consolas, monospace;">Enjoy the Silence</span>.</p>
 +
<span style="font-family: Consolas, monospace;"><b><nowiki>fixcase(enjoy the silence, 1)</nowiki></b></span>
 +
<p style="margin-left:20pt;">Using <i>mode</i> 1, all words are uppercased, so the output is <span style="font-family: Consolas, monospace;">Enjoy The Silence</span>.</p>
 +
<span style="font-family: Consolas, monospace;"><b><nowiki>fixcase(MY ALbUm IS cAlLeD: adam, 4)</nowiki></b></span>
 +
<p style="margin-left:20pt;">Outputs <span style="font-family: Consolas, monospace;">my album is called: adam</span>.</p>
 +
|}
 +
<div style="text-align:right;">([[#top|Back to top)]]</div>
  
Sample output:
+
====FixSpacing(&hellip;): Intelligently splits adjacent camel-cased words====
:(Brian Eno/U2)
 
:(feat. DJ Cam)
 
:(Otis Day & The Knights)
 
:(w/Emmylou Harris)
 
  
&oline;&oline;&oline;&oline;
+
{| style="width: 100%; border: 2px solid black;" align="top" cellpadding="3"
 +
|- id="FixSpacing" valign="top"
 +
! scope="row" style="background: #ecedf3; color: #111; " width=100 | Description
 +
| style="background: #f9f9f9; color: #111; " width=1200 | <span style="font-family: Consolas, monospace; color:#0f3f8d; font-size:110%"><b>fixspacing(</b><i>string</i><b>, </b><i>mode</i><b>)</b></span>
 +
The [[#FixSpacing|FixSpacing()]] function inserts spaces between adjacent camel-cased words in <i>string</i>.
 +
It is useful for helping to clean and convert metadata that favors compactness over standard sentence structure.
  
'''<span style="font-family: Consolas, monospace;"><nowiki>
+
Available <i>mode</i> values:
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''
+
<div style="margin-left: 20pt;"><table style="background:#f9f9f9; border-spacing:0px; border-collapse:collapse;">
 +
<tr><td style="text-align:left; padding-right:20pt"><b>0</b></td><td>Disables conversion</td></tr>
 +
<tr><td style="text-align:left; padding-right:20pt"><b>1</b></td><td>Enables camel-case conversion</td></tr>
 +
</table></div>
  
Sample output:
+
Argument <i>mode</i> is optional (defaults to 1).
:(feat. David Bowie
 
  
----
+
|- valign="top"
'''Examples: Mode 0'''
+
! scope="row" style="background: #ecedf3; color: #111; " | Examples
 +
|style="background: #f9f9f9; color: #111; " | <span style="font-family: Consolas, monospace;"><b><nowiki>fixspacing(OneWorld)</nowiki></b></span>
 +
<p style="margin-left:20pt;">Outputs <span style="font-family: Consolas, monospace;">One World</span>.</p>
 +
<span style="font-family: Consolas, monospace;"><b><nowiki>fixspacing([name], 1)</nowiki></b></span>
 +
<p style="margin-left:20pt;">Outputs the name field with any camel-case converted into standard sentence structure.
 +
If the value of name was, <span style="font-family: Consolas, monospace;">MiracleOn34thStreet</span>, the output would be <span style="font-family: Consolas, monospace;">Miracle On 34th Street</span>.</p>
 +
<span style="font-family: Consolas, monospace;"><b><nowiki>fixspacing(Another [name])</nowiki></b></span>
 +
<p style="margin-left:20pt;">Assuming the same [name] as above, this would return <span style="font-family: Consolas, monospace;">Another Miracle On 34th Street</span>.</p>
 +
|}
 +
<div style="text-align:right;">([[#top|Back to top)]]</div>
  
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.
+
====Hexify(&hellip;): Hexifies a string to make it suitable for web usage====
  
'''<span style="font-family: Consolas, monospace;"><nowiki>
+
{| style="width: 100%; border: 2px solid black;" align="top" cellpadding="3"
if(Regex([Artist],/#([[:punct:]])#/, 0),[R1] --> [Artist], No Punctuation)
+
|- id="Hexify" valign="top"
</nowiki></span>'''
+
! scope="row" style="background: #ecedf3; color: #111; " width=100 | Description
 +
| style="background: #f9f9f9; color: #111; " width=1200 | <span style="font-family: Consolas, monospace; color:#0f3f8d; font-size:110%"><b>hexify(</b><i>string</i><b>)</b></span>
 +
The [[#Hexify|Hexify()]] function URI encodes a <i>string</i> to make it useable by a browser or search engine.
 +
[[#Hexify|Hexify()]] is typically used by expressions generating or working on URLs in Media Center's Link Manager.
 +
|- valign="top"
 +
! scope="row" style="background: #ecedf3; color: #111; " | Examples
 +
|style="background: #f9f9f9; color: #111; " | <span style="font-family: Consolas, monospace;"><b><nowiki>hexify(Oasis - /(What's The Story/) Morning Glory?)</nowiki></b></span>
 +
<p style="margin-left:20pt;">The result is <span style="font-family: Consolas, monospace;">Oasis%20-%20%28What%27s%20The%20Story%29%20Morning%20Glory%3F</span>.</p>
 +
|}
 +
<div style="text-align:right;">([[#top|Back to top)]]</div>
  
''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.''
+
====Left(&hellip;): Retrieves a specified number of characters from the left of a string====
  
Sample output:
+
{| style="width: 100%; border: 2px solid black;" align="top" cellpadding="3"
: " &nbsp;--> Clarence "Frogman" Henry
+
|- id="Left" valign="top"
: &      --> Al Cohn & Zoot Sims
+
! scope="row" style="background: #ecedf3; color: #111; " width=100 | Description
: . &nbsp;--> Dr. John
+
| style="background: #f9f9f9; color: #111; " width=1200 | <span style="font-family: Consolas, monospace; color:#0f3f8d; font-size:110%"><b>left(</b><i>string</i><b>, </b><i>quantity</i><b>)</b></span>
: / &nbsp;--> Bootsy Collins/Fatboy Slim
+
The [[#Left|Left()]] function retrieves no more than <i>quantity</i> characters from the left of the <i>string</i>.
 +
|- valign="top"
 +
! scope="row" style="background: #ecedf3; color: #111; " | Examples
 +
|style="background: #f9f9f9; color: #111; " | <span style="font-family: Consolas, monospace;"><b><nowiki>left([filename], 3)</nowiki></b></span>
 +
<p style="margin-left:20pt;">Return the Windows drive letter, colon and first back-slash from the filename.</p>
 +
|}
 +
<div style="text-align:right;">([[#top|Back to top)]]</div>
  
&oline;&oline;&oline;&oline;
+
====Length(&hellip;): Returns the number of characters in a string====
  
'''<div style="font-family: Consolas, monospace;"><nowiki>
+
{| style="width: 100%; border: 2px solid black;" align="top" cellpadding="3"
if(Regex([Artist], /#([[:punct:]])#/, 0),
+
|- id="Length" valign="top"
</nowiki><br />
+
! scope="row" style="background: #ecedf3; color: #111; " width=100 | Description
: '''<nowiki>     Contains Punctuation\replace(replace([R1], ;,Semicolon), \, Backslash),
+
| style="background: #f9f9f9; color: #111; " width=1200 | <span style="font-family: Consolas, monospace; color:#0f3f8d; font-size:110%"><b>length(</b><i>string</i><b>)</b></span>
</nowiki><br />
+
The [[#Length|Length()]] function returns the number of characters contained in <i>string</i>.
: '''<nowiki>    No Punctuation)\replace(replace([Artist], ;, / and/ ), \, //)&DataType=[list]
+
|- valign="top"
</nowiki></div>'''
+
! scope="row" style="background: #ecedf3; color: #111; " | Examples
 +
|style="background: #f9f9f9; color: #111; " | <span style="font-family: Consolas, monospace;"><b><nowiki>length(A Simple Plan)</nowiki></b></span>
 +
<p style="margin-left:20pt;">Returns 13.</p>
 +
<span style="font-family: Consolas, monospace;"><b><nowiki>if(compare(length([filename]), &gt;=, 68), Long, Short)</nowiki></b></span>
 +
<p style="margin-left:20pt;">The length of the filename is calculated, and compared against 68, outputting <span style="font-family: Consolas, monospace;">Long</span> when the length is greater than or equal to 68, and <span style="font-family: Consolas, monospace;">Short</span> otherwise.</p>
 +
|}
 +
<div style="text-align:right;">([[#top|Back to top)]]</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.''
+
====Mid(&hellip;): Retrieves specified characters from a string====
  
Sample output:
+
{| style="width: 100%; border: 2px solid black;" align="top" cellpadding="3"
: &darr; Contains Punctuation
+
|- id="Mid" valign="top"
::  &darr;&nbsp;  $
+
! scope="row" style="background: #ecedf3; color: #111; " width=100 | Description
::: &nbsp;Payola$
+
| style="background: #f9f9f9; color: #111; " width=1200 | <span style="font-family: Consolas, monospace; color:#0f3f8d; font-size:110%"><b>mid(</b><i>string</i><b>, </b><i>start position</i><b>, </b><i>quantity</i><b>)</b></span>
::  &darr;&nbsp;  *
+
The [[#Mid|Mid()]] function returns a specified <i>quantity</i> of characters from the start postion in <i>string</i>.
::: &nbsp;D*Note
 
:: &rarr; +
 
::  &rarr; :
 
::  &rarr; Backslash
 
:: &darr;&nbsp; Semicolon
 
::: &nbsp;Lita Ford and Ozzy Osbourne
 
::: &nbsp;Seal and Jeff Beck
 
: &rarr; No Punctuation
 
  
&oline;&oline;&oline;&oline;
+
The start postion is 0-based (i.e. the first character is considered position 0).
 +
A quantify of -1 returns all characters from the start postion to the end of <i>string</i>.
  
'''<span style="font-family: Consolas, monospace;"><nowiki>
+
Argument <i>start position</i> is optional (defaults to 0).
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.
+
Argument <i>quantity</i> is optional (defaults to 1).
  
----
+
|- valign="top"
'''Examples: Mode -1'''
+
! scope="row" style="background: #ecedf3; color: #111; " | Examples
 +
|style="background: #f9f9f9; color: #111; " | <span style="font-family: Consolas, monospace;"><b><nowiki>mid(12345)</nowiki></b></span>
 +
<p style="margin-left:20pt;">Returns <span style="font-family: Consolas, monospace;">1</span>, using is the default <i>quantity</i> (1) of characters from the default <i>start position</i> of (0 - the beginning of the <i>string</i>).</p>
 +
<span style="font-family: Consolas, monospace;"><b><nowiki>mid(12345, 1, 2)</nowiki></b></span>
 +
<p style="margin-left:20pt;">Returns 2 characters begining at <i>start position</i> 1, which is <span style="font-family: Consolas, monospace;">23</span>.</p>
  
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.
+
Additional Examples
  
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:
+
:[http://yabb.jriver.com/interact/index.php?topic=52809.0 An example that uses Mid() to re-order a date field.]
  
'''<span style="font-family: Consolas, monospace;"><nowiki>
+
:[http://yabb.jriver.com/interact/index.php?topic=75891.0 An example that uses Mid() to output a number of stars based on an arbitrary rating value.]
=Regex([Album], /#^([^-]+[^\s])- (.*)$#/, -1)[R1]: [R2]
+
|}
</nowiki></span>'''
+
<div style="text-align:right;">([[#top|Back to top)]]</div>
  
''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.''
+
====Regex(&hellip;): Regular expression pattern matching and capture====
  
''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:''
+
{| style="width: 100%; border: 2px solid black;" align="top" cellpadding="3"
 +
|- id="Regex" valign="top"
 +
! scope="row" style="background: #ecedf3; color: #111; " width=100 | Description
 +
| style="background: #f9f9f9; color: #111; " width=1200 | <span style="font-family: Consolas, monospace; color:#0f3f8d; font-size:110%"><b>regex(</b><i>string</i><b>, </b><i>regexp</i><b>, </b><i>run mode</i><b>, </b><i>case sensitivity</i><b>)</b></span>
 +
The [[#Regex|Regex()]] function performs regular expression (RE) pattern matching on a <i>string</i>.
 +
The <i>string</i> is evaluated against the regular expression <i>regexp</i>, and <i>run mode</i> dictates the values output by [[#Regex|Regex()]].
 +
The three modes allow for match testing, capture output, or silent operation.
  
'''<span style="font-family: Consolas, monospace;"><nowiki>
+
All match captures are placed into special variables referenced as [R1], [R2], ... [R9], which can be used in later in the expression.
=if(Regex([Album], /#^([^-]+[^\s])- (.*)$#/, 0), [R1]: [R2], [Album])
+
The contents of the captures [R1] ... [R9] are available until the end of the expression, or [[#Regex|Regex()]] is run again, whereby they are replaced.
</nowiki></span>'''
+
The regular expression implementation used prior to Media Cener 19 is the Microsoft 2010 TR1 engine, and in Media Cener 19 it is the Boost engine.
  
&oline;&oline;&oline;&oline;<br />
+
Available <i>run mode</i> values:
'''<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.
+
<div style="margin-left: 20pt;"><table style="background:#f9f9f9; border-spacing:0px; border-collapse:collapse;">
 +
<tr><td style="text-align:left; padding-right:20pt"><b>0</b></td><td>Runs in Boolean test mode, returning either a 1 or 0, indicating whether the <i>string</i> matched (1) or did not match (0) the <i>regexp</i>. This <i>run mode</i> is useful within an [[#If|If()]] test, so that different true or false actions may be taken.</td></tr>
 +
<tr><td style="text-align:left; padding-right:20pt"><b>1 to 9</b></td><td>Outputs the specified Nth capture group's contents, where N ranges from 1 to 9. Only a single capture is output in this mode, but all captures are available in the [R1] ... [R9] capture variables. This <i>run mode</i> is used to easily output a single matching sub-<i>string</i>.</td></tr>
 +
<tr><td style="text-align:left; padding-right:20pt"><b>-1</b></td><td>Runs in silent mode, with no output being produced.  This <i>run mode</i> is useful as a means to capture portions of the <i>string</i> to be later used in subsequent portions of an expression.</td></tr>
 +
</table></div>
  
Sample output:
+
The <i>case sensitivity</i> argument toggles the case-sensitivity of regular expression matching.
: 2011/08/19
+
Note that case insensitivity does not apply to characters inside a character class <span style="font-family: Consolas, monospace;">[ ]</span>.
: 2009/01/22
+
Use both uppercase and lowercase characters when necessary to match either case (e.g. <span style="font-family: Consolas, monospace;">[aAbB]</span> to match either uppercase or lowercase <span style="font-family: Consolas, monospace;">A</span> or <span style="font-family: Consolas, monospace;">B</span>).
  
&oline;&oline;&oline;&oline;
+
Available <i>case sensitivity</i> values:
  
'''<span style="font-family: Consolas, monospace;"><nowiki>
+
<div style="margin-left: 20pt;"><table style="background:#f9f9f9; border-spacing:0px; border-collapse:collapse;">
Regex([Name], /#^(.+?) \(([^(]+)\)$#/, -1)[R2]: [R1]
+
<tr><td style="text-align:left; padding-right:20pt"><b>0</b></td><td>Ignore case when matching (e.g. the letters E and e are identical)</td></tr>
</nowiki></span>'''
+
<tr><td style="text-align:left; padding-right:20pt"><b>1</b></td><td>Consider case when matching (e.g. the letters E and e are considered different)</td></tr>
 +
</table></div>
  
''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.''
+
The regular expression language assigns special meaning to many characters.
 +
A few of these meta-characters, such as forward slash <span style="font-family: Consolas, monospace;">/</span>, comma <span style="font-family: Consolas, monospace;">,</span> and both <span style="font-family: Consolas, monospace;">(</span> and <span style="font-family: Consolas, monospace;">)</span> are also reserved and used by the Media Center expression language.
 +
To force the Media Center expression engine to ignore the meta-characters in <i>regexp</i>, surround the entire regular expression with <span style="font-family: Consolas, monospace;">/#</span> <span style="font-family: Consolas, monospace;">#/</span>.
 +
This is one of Media Center's escapements, which tells the expression engine to ignore everything inside, so that the entire, uninterpreted <i>regexp</i> can be provided to the [[#Regex|Regex()]] regular expression evaluator.
 +
Although surrounding <i>regexp</i> by <span style="font-family: Consolas, monospace;">/#</span> <span style="font-family: Consolas, monospace;">#/</span> is not necessary or required when no conflicting characters are in use, and you may manually escape the expression languages meta-characters with a forward slash <span style="font-family: Consolas, monospace;">/</span>, it is probably a safe practice to always encase every <i>regexp</i> within <span style="font-family: Consolas, monospace;">/#</span> <span style="font-family: Consolas, monospace;">#/</span>.
  
Sample output:
+
Argument <i>run mode</i> is optional (defaults to 0).
: 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
 
  
&oline;&oline;&oline;&oline;
+
Argument <i>case sensitivity</i> is optional (defaults to 0).
  
'''<span style="font-family: Consolas, monospace;"><nowiki>
+
|- valign="top"
listbuild(1, \, Regex([Name], /#^(.+?) \(([^(]+)\)$#/, -1)[R2],[R1])&datatype=[list]
+
! scope="row" style="background: #ecedf3; color: #111; " | Examples
</nowiki></span>'''
+
|style="background: #f9f9f9; color: #111; " | <span style="font-family: Consolas, monospace;"><b><nowiki>ifelse(regex([name], /#^(the|an|a)\b#/, 0, 1), Fix your case!)</nowiki></b></span>
 
+
<p style="margin-left:20pt;">Searches the name field for any of the lowercase articles <span style="font-family: Consolas, monospace;">the</span>, <span style="font-family: Consolas, monospace;">and</span> and <span style="font-family: Consolas, monospace;">a</span> at the beginning of name, and outputs <span style="font-family: Consolas, monospace;">Fix your case!</span> when the match succeeds.
''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.''
+
The <i>run mode</i> is 0 which is a test and capture mode, and <i>case sensitivity</i> is enabled.</p>
 +
<span style="font-family: Consolas, monospace;"><b><nowiki>if(regex([artist], /#([[:punct:]])#/, 0), [R1] --&gt; [Artist], No Punctuation)</nowiki></b></span>
 +
<p style="margin-left:20pt;">Using the default mode 0, [[#Regex|Regex()]] will output a Boolean for use inside a condtional to cause some action to occur based on the match success or failure.
 +
This example matches against the artist field looking for any punctuation character.
 +
If the match succeeds (a punctuation character was found), that character is output followed by the <i>string</i> <span style="font-family: Consolas, monospace;"> --> </span> and the artist. In there was no match, the <i>string</i> <span style="font-family: Consolas, monospace;">No Punctuation</span> is output.</p>
 +
<span style="font-family: Consolas, monospace;"><b><nowiki>regex(D03T02 some track.mp3, /#^D(\d+)T(\d+)#/, 1)Disc: [R1], Track: [R2]</nowiki></b></span>
 +
<p style="margin-left:20pt;">The <i>string</i> is matched against the <i>regexp</i> that is looking for a <span style="font-family: Consolas, monospace;">D</span> followed by any number of digits, followed by a <span style="font-family: Consolas, monospace;">T</span> and then more digits.
 +
Those digits were captured, and later used to output the value <span style="font-family: Consolas, monospace;">Disc: 03, Track: 02</span>.</p>
 +
<span style="font-family: Consolas, monospace;"><b><nowiki>regex([filename (name)], /#^(\d+)-#/, -1)Track number is [R1]</nowiki></b></span>
 +
<p style="margin-left:20pt;">Using <i>run mode</i> -1, the file's name is pattern tested against the <i>regexp</i> which is looking for leading digits followed by a dash.
 +
Those digits are captured in buffer [R1] which is used later in the expression.  If the file name was <span style="font-family: Consolas, monospace;">2-foo.mp3</span>, the output would be <span style="font-family: Consolas, monospace;">Track number is 2</span>.</p>
 +
<span style="font-family: Consolas, monospace;"><b><nowiki>regex([filename], /#(\d{1,2})\.(\d{1,2}).(\d{4})#/, -1)[R3]//[R1]//[R2]</nowiki></b></span>
 +
<p style="margin-left:20pt;">Matches and captures a date formatted as dd.mm.yyyy anywhere within the filename, and rearranges it in a standard format of yyyy/mm/dd.
 +
Since <i>run mode</i> is -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 so that we get the desired year/month/day ordering, such as <span style="font-family: Consolas, monospace;">2011/08/19</span>.</p>
 
|}
 
|}
 
<div style="text-align:right;">([[#top|Back to top)]]</div>
 
<div style="text-align:right;">([[#top|Back to top)]]</div>
====RemoveCharacters(...): Removes specified characters from a given field or string====
 
{| 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 | <small>RemoveCharacters()</small>
 
| style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | 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.)
 
|- valign="top"
 
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction
 
| style="background: #ecfeea; color: black; border: 1px solid black" | '''RemoveCharacters(String to test,CharactersToTestFor,Mode)'''
 
  
* '''String to test''': ''This can be plain text, a library field, or a combination of the two.''
+
====RemoveCharacters(&hellip;): Removes a list of characters from a string====
* '''Characters to test for''': ''series of characters, or strings of characters, placed all together between two commas, that are to be removed'' (note that this function is <ins>case sensitive</ins>)
+
 
* '''Mode''': ''There are four available modes, each detailed below. Note that if no mode is specified, the function will default to using mode 0 (remove all instances)
+
{| style="width: 100%; border: 2px solid black;" align="top" cellpadding="3"
''Available Modes:''
+
|- id="RemoveCharacters" valign="top"
* 0: Remove all instances
+
! scope="row" style="background: #ecedf3; color: #111; " width=100 | Description
* 1: Remove from the beginning only
+
| style="background: #f9f9f9; color: #111; " width=1200 | <span style="font-family: Consolas, monospace; color:#0f3f8d; font-size:110%"><b>removecharacters(</b><i>string</i><b>, </b><i>character list</i><b>, </b><i>mode</i><b>)</b></span>
* 2: Remove from the end only
+
The [[#RemoveCharacters|RemoveCharacters()]] function will remove from <i>string</i> any characters in the <i>character list</i>.  The characters removed depend upon the <i>mode</i> specified.
* 3: Remove from each end
+
The function operates in a case-sensitive manner.
|- valign="top"
 
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples
 
|style="background: #ecfeea; color: black; border: 1px solid black" | '''RemoveCharacters(Paper,Ppr,0)'''<br>This will result in "ae" as P, p and r are removed.
 
  
'''RemoveCharacters(Paper,Ppr,1)'''<br>This will result in "aper" as "mode 1" has been specified, and the capital P is removed from the start.
+
Available <i>mode</i> values:
  
'''RemoveCharacters(Paper,Ppr,2)'''<br>This will result in "Pape" as "mode 2" has been specified, and the lower case r is removed from the end.
+
<div style="margin-left: 20pt;"><table style="background:#f9f9f9; border-spacing:0px; border-collapse:collapse;">
 +
<tr><td style="text-align:left; padding-right:20pt"><b>0</b></td><td>Remove all instances</td></tr>
 +
<tr><td style="text-align:left; padding-right:20pt"><b>1</b></td><td>Remove from the beginning only</td></tr>
 +
<tr><td style="text-align:left; padding-right:20pt"><b>2</b></td><td>Remove from the end only</td></tr>
 +
<tr><td style="text-align:left; padding-right:20pt"><b>3</b></td><td>Remove from each end</td></tr>
 +
</table></div>
  
'''RemoveCharacters(Paper,Ppr,3)'''<br>This will result in "ape" as "mode 3" has been specified, the capital P is removed from the start, and the lower case r is removed from the end.
+
Argument <i>mode</i> is optional (defaults to 0).
  
'''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.
+
|- valign="top"
 +
! scope="row" style="background: #ecedf3; color: #111; " | Examples
 +
|style="background: #f9f9f9; color: #111; " | <span style="font-family: Consolas, monospace;"><b><nowiki>removecharacters(Paper, Ppr)</nowiki></b></span>
 +
<p style="margin-left:20pt;">Removes <span style="font-family: Consolas, monospace;">P</span>, <span style="font-family: Consolas, monospace;">p</span>, and <span style="font-family: Consolas, monospace;">r</span> from <span style="font-family: Consolas, monospace;">Paper</span>, resulting in <span style="font-family: Consolas, monospace;">ae</span>.
 +
The default <i>mode</i> 0 is in effect, removing all instances of the characters specified in the <i>character list</i>.</p>
 +
<span style="font-family: Consolas, monospace;"><b><nowiki>removecharacters(Paper, Ppr, 1)</nowiki></b></span>
 +
<p style="margin-left:20pt;">With <i>mode</i> 1 set, only the inital character <span style="font-family: Consolas, monospace;">P</span> is removed, resulting in <span style="font-family: Consolas, monospace;">aper</span>.</p>
 +
<span style="font-family: Consolas, monospace;"><b><nowiki>removecharacters(Paper, Ppr, 2)</nowiki></b></span>
 +
<p style="margin-left:20pt;">In <i>mode</i> 2, only one character from the end of the <i>string</i> are removed, leaving "Pape.</p>
 +
<span style="font-family: Consolas, monospace;"><b><nowiki>removecharacters(Paper, Ppr, 3)</nowiki></b></span>
 +
<p style="margin-left:20pt;">Both the front and back are affected in <i>mode</i> 3, causing the removal of the leading <span style="font-family: Consolas, monospace;">P</span> and trailing <span style="font-family: Consolas, monospace;">r</span> resulting in <span style="font-family: Consolas, monospace;">ape</span>.</p>
 +
<span style="font-family: Consolas, monospace;"><b><nowiki>removecharacters([artist], /(/))</nowiki></b></span>
 +
<p style="margin-left:20pt;">Removes any <span style="font-family: Consolas, monospace;">(</span> and <span style="font-family: Consolas, monospace;">)</span> characters from anywhere within the [artist] field.</p>
 
|}
 
|}
 
<div style="text-align:right;">([[#top|Back to top)]]</div>
 
<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"
+
====RemoveLeft(&hellip;): Trims characters from the beginning of a string====
|- valign="top"
+
 
! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | RemoveLeft()
+
{| style="width: 100%; border: 2px solid black;" align="top" cellpadding="3"
| 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.
+
|- id="RemoveLeft" valign="top"
|- valign="top"
+
! scope="row" style="background: #ecedf3; color: #111; " width=100 | Description
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction
+
| style="background: #f9f9f9; color: #111; " width=1200 | <span style="font-family: Consolas, monospace; color:#0f3f8d; font-size:110%"><b>removeleft(</b><i>string</i><b>, </b><i>quantity</i><b>)</b></span>
| style="background: #ecfeea; color: black; border: 1px solid black" | '''RemoveLeft(Value to remove characters from,Number of characters to remove)'''
+
The [[#RemoveLeft|RemoveLeft()]] function removes a specified <i>quantity</i> of characters from the left side of a <i>string</i>.
 +
If the <i>quantity</i> is larger than the length of the <i>string</i>, the output will be empty.
 
|- valign="top"
 
|- valign="top"
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples
+
! scope="row" style="background: #ecedf3; color: #111; " | 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.''.
+
|style="background: #f9f9f9; color: #111; " | <span style="font-family: Consolas, monospace;"><b><nowiki>removeleft(Good Deeds, 5)</nowiki></b></span>
 +
<p style="margin-left:20pt;">Removes the first 5 characters from resulting in <span style="font-family: Consolas, monospace;">Deeds</span> being output.</p>
 
|}
 
|}
 
<div style="text-align:right;">([[#top|Back to top)]]</div>
 
<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"
+
====RemoveRight(&hellip;): Trims characters from the end of a string====
|- valign="top"
+
 
! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | RemoveRight()
+
{| style="width: 100%; border: 2px solid black;" align="top" cellpadding="3"
| 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.
+
|- id="RemoveRight" valign="top"
 +
! scope="row" style="background: #ecedf3; color: #111; " width=100 | Description
 +
| style="background: #f9f9f9; color: #111; " width=1200 | <span style="font-family: Consolas, monospace; color:#0f3f8d; font-size:110%"><b>removeright(</b><i>string</i><b>, </b><i>quantity</i><b>)</b></span>
 +
The [[#RemoveRight|RemoveRight()]] function removes a specified <i>quantity</i> of characters from the right side of a <i>string</i>.
 +
If the <i>quantity</i> is larger than the length of the <i>string</i>, the output will be empty.
 
|- valign="top"
 
|- valign="top"
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction
+
! scope="row" style="background: #ecedf3; color: #111; " | Examples
| style="background: #ecfeea; color: black; border: 1px solid black" | '''RemoveRight(Value to remove characters from,Number of characters to remove)'''
+
|style="background: #f9f9f9; color: #111; " | <span style="font-family: Consolas, monospace;"><b><nowiki>removeright(03-02-1959,5)</nowiki></b></span>
|- valign="top"
+
<p style="margin-left:20pt;">Removes the last 5 characters from the given date, leaving only the month and year <span style="font-family: Consolas, monospace;">03-02</span>.</p>
! 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>
 
<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"
+
====Replace(&hellip;): Replace or remove a string segment====
 +
 
 +
{| style="width: 100%; border: 2px solid black;" align="top" cellpadding="3"
 +
|- id="Replace" valign="top"
 +
! scope="row" style="background: #ecedf3; color: #111; " width=100 | Description
 +
| style="background: #f9f9f9; color: #111; " width=1200 | <span style="font-family: Consolas, monospace; color:#0f3f8d; font-size:110%"><b>replace(</b><i>string</i><b>, </b><i>old</i><b>, </b><i>new</i><b>)</b></span>
 +
The [[#Replace|Replace()]] function replaces all instances of <i>old</i> within <i>string</i> with <i>new</i>.
 +
If <i>new</i> is unspecified, it defaults to an empty value, causing <i>old</i> to be removed.
 +
[[#Replace|Replace()]] operates in a case-sensitive manner.
 +
 
 +
Argument <i>new</i> is optional (defaults to EMPTY).
  
<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".
+
|- valign="top"
 +
! scope="row" style="background: #ecedf3; color: #111; " | Examples
 +
|style="background: #f9f9f9; color: #111; " | <span style="font-family: Consolas, monospace;"><b><nowiki>replace(The Daily Show with John Oliver, hn Oliver, n Stewart)</nowiki></b></span>
 +
<p style="margin-left:20pt;">Now that John Oliver has completed his summer stand-in for Jon Stewart, it is time for a replacement.
 +
The <i>old</i> sequence <span style="font-family: Consolas, monospace;">hn Oliver</span> will be replaced with the <i>new</i> sequence <span style="font-family: Consolas, monospace;">n Stewart</span>, resulting in
 +
<span style="font-family: Consolas, monospace;">The Daily Show with Jon Stewart</span>.</p>
 +
<span style="font-family: Consolas, monospace;"><b><nowiki>replace(Sample String, s, Replaced)</nowiki></b></span>
 +
<p style="margin-left:20pt;">In this example, the original <i>string</i> does not contain the <i>old</i> value <span style="font-family: Consolas, monospace;">s</span> anywhere,
 +
so no replacement occurs and the original <i>string</i> is returned.</p>
 +
<span style="font-family: Consolas, monospace;"><b><nowiki>replace(Led Zeppelin.[remastered], .[remastered])</nowiki></b></span>
 +
<p style="margin-left:20pt;">Removes the trailing <i>old</i> value <span style="font-family: Consolas, monospace;">.[remastered]</span> from the original <i>string</i>, resulting in <span style="font-family: Consolas, monospace;">Led Zeppelin</span>.
 +
Because no <i>new</i> <i>string</i> is specified, the default empty value is used as a replacement,
 +
effectively stripping the <i>old</i> value.</p>
 
|}
 
|}
 
<div style="text-align:right;">([[#top|Back to top)]]</div>
 
<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"
+
====Right(&hellip;): Retrieves a specified number of characters from the right of a string====
|- valign="top"
+
 
! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | Right()
+
{| style="width: 100%; border: 2px solid black;" align="top" cellpadding="3"
| 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.
+
|- id="Right" valign="top"
|- valign="top"
+
! scope="row" style="background: #ecedf3; color: #111; " width=100 | Description
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction
+
| style="background: #f9f9f9; color: #111; " width=1200 | <span style="font-family: Consolas, monospace; color:#0f3f8d; font-size:110%"><b>right(</b><i>string</i><b>, </b><i>quantity</i><b>)</b></span>
| 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.''
+
The [[#Right|Right()]] function retrieves the specified <i>quantity</i> of characters from the right of the <i>string</i>.
 +
If <i>quantity</i> is larger than the length of <i>string</i>, the original <i>string</i> is returned.
 
|- valign="top"
 
|- valign="top"
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples
+
! scope="row" style="background: #ecedf3; color: #111; " | 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.''
+
|style="background: #f9f9f9; color: #111; " | <span style="font-family: Consolas, monospace;"><b><nowiki>right([filename], 3)</nowiki></b></span>
 +
<p style="margin-left:20pt;">Returns the last three characters from the filename (typically this is the file's suffix).</p>
 
|}
 
|}
 
<div style="text-align:right;">([[#top|Back to top)]]</div>
 
<div style="text-align:right;">([[#top|Back to top)]]</div>
<br><br>
 
  
 
===List Manipulation===
 
===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 [http://yabb.jriver.com/interact/index.php?topic=54226.msg374211#msg374211 "Eureka moment"] occurred in November 2009.
+
Media Center supports several different types of fields, one of them being the List type.
====ListBuild(...): Build a list from a series of values====
+
A List type is a library field of type List, or an expression coerced into a list type.
{| 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 | ListBuild()
 
| style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | 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 [[#Specify data types for expression based fields|'datatype']] must be specified as [list].
 
|- valign="top"
 
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction
 
| style="background: #ecfeea; color: black; border: 1px solid black" | '''ListBuild(Mode,Delimiter,Items,To,Include)'''<br>
 
'''Mode:''' ''There are two different modes available:
 
* '''0''': ''combine all values. NOTE: <ins>This mode should be avoided as there is no recorded practical use for it, and it's behaviour can be unpredictable.</ins>''
 
* '''1''': ''combine non-empty values''
 
  
'''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"''
+
The functions in this section provide the ability to manipulate lists and list items.  
<br>'''Items To Include''': ''This can be any number of specified text entries, expressions, or library fields, seperated by commas''
+
A list is a sequence of strings, each separated from one another by an arbitrary delimiter.
|- valign="top"
+
The default delimiter is a semicolon.
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples
+
Media Center does not make a strict distinction between a string and a list of strings.
|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".''
+
In fact, a list is just a string, and it is safe to think of a string as a list with zero or more
 +
arbitrary delimiter sequences.
 +
For example, the string "2013-08-17" can be thought of as a dash-delimited list with the three items "2013", "08" and "17".
  
<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.''
+
This weak typing is very useful since a list,
 +
for example, "John; Sally" that contains the two items "John" and "Sally" can be manipulated not only using the
 +
list functions in this section, but because it is just a string, it can also be manipulated with string functions.
 +
For example, taking the same list above and combining it with the string "; Joe" adds a new item
 +
to the list "John; Sally; Joe", and removing the first 6 characters with [[#RemoveLeft|RemoveLeft()]] would
 +
produce a now shortened string/list "Sally; Joe".
 +
The list manipulation functions make this job easier, especially when using the default semicolon delimiter.
 +
Furthermore, since any character or sequence of characters can be considered as a list delimiter,
 +
any string can be treated as a list, and the functions in this section can be used on any string as needed.
  
<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.
+
In some areas such as a panes column, or a category view, Media Center gives special treatment to List types.
|}
+
For example, using semicolon as the delimiter, a List will be automatically split apart into its individual items.
<div style="text-align:right;">([[#top|Back to top)]]</div>
+
====ListBuild(&hellip;): Constructs a list from a series of items====
  
ListClean(c;b;c;a, 1)
+
{| style="width: 100%; border: 2px solid black;" align="top" cellpadding="3"
 +
|- id="ListBuild" valign="top"
 +
! scope="row" style="background: #ecedf3; color: #111; " width=100 | Description
 +
| style="background: #f9f9f9; color: #111; " width=1200 | <span style="font-family: Consolas, monospace; color:#0f3f8d; font-size:110%"><b>listbuild(</b><i>mode</i><b>, </b><i>delimiter</i><b>, </b><i>item1</i><b>, </b><i>item2</i><b>, </b><i>&hellip;</i><b>)</b></span>
 +
The [[#ListBuild|ListBuild()]] function constructs a list from <i>item1</i>, <i>item2</i>, ... using a supplied delimter to separate the individual items in the resulting list.
 +
The construction <i>mode</i> affects how empty items are handled - they can be included or excluded.
 +
The <i>mode</i> typically used exclude empty items, so that lists do not contain empty slots.
 +
However, there are occasions when retaining empty slots is useful, such as when using a list to act like an array where data is stored in particular slots so that the [[#ListItem|ListItem()]] function may later retrieve values at a given index.
 +
It can also be useful when calculating several expressions and combining the results into a single list for presentation; by including all items, items can be made to line-up for visual inspection in a column.
  
====ListClean(...): Clean a list of values====
+
Available <i>mode</i> values:
{| 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 | ListClean()
 
| style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | This function provides the ability to clean a list of values.  It can either remove duplicates or reverse the list. List items are separated by an arbitrary delimiter, which defaults to semicolon.
 
|- valign="top"
 
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction
 
| style="background: #ecfeea; color: black; border: 1px solid black" | '''ListClean(List,Mode,Delimiter)'''<br>
 
  
'''List''' ''Any string''<br />
+
<div style="margin-left: 20pt;"><table style="background:#f9f9f9; border-spacing:0px; border-collapse:collapse;">
'''Mode:''' ''Specifies the clean mode:
+
<tr><td style="text-align:left; padding-right:20pt"><b>0</b></td><td>Include empty values</td></tr>
* '''1''': ''Remove duplicates from the list''
+
<tr><td style="text-align:left; padding-right:20pt"><b>1</b></td><td>Exclude empty values</td></tr>
* '''2''': ''Reverse the list''
+
</table></div>
  
'''Delimiter''': ''One or more characters used to delimit items within the list. The default separator is a semicolon.''
+
The <i>delimiter</i> argument specifies the character or character sequence to be inserted in between items in the list.
|- valign="top"
+
An unspecified <i>delimiter</i> will result in a delimiterless concatenation of the supplied arguments <i>item1</i>, <i>item2</i>, etc.
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples
 
|style="background: #ecfeea; color: black; border: 1px solid black" | '''listclean(c;b;c;a, 1)'''<br>
 
Returns ''c;b;a''.  Uses the default semicolon delimiter.
 
  
<br>'''ListClean(d;c;b;a, 2)'''
+
Argument <i>delimiter</i> is optional (defaults to EMPTY).
<br>Returns ''a;b;c;d''.
 
  
<br>'''ListClean(\a\x\x\x\z, 1, \)'''
+
|- valign="top"
<br>Returns ''\a\x\z''.
+
! scope="row" style="background: #ecedf3; color: #111; " | Examples
 +
|style="background: #f9f9f9; color: #111; " | <span style="font-family: Consolas, monospace;"><b><nowiki>listbuild(1, ;, Bennie, June)</nowiki></b></span>
 +
<p style="margin-left:20pt;">Returns a standard semicolon-separated list containing two items <span style="font-family: Consolas, monospace;">Bennie; June</span>.</p>
 +
<span style="font-family: Consolas, monospace;"><b><nowiki>listbuild(1, \, [album artist (auto)], [album])</nowiki></b></span>
 +
<p style="margin-left:20pt;">Builds a backslash-separated list combining the two fields album artist (auto) and album.
 +
This is useful for building panes column or categories hierarchies in a view.</p>
 
|}
 
|}
 
<div style="text-align:right;">([[#top|Back to top)]]</div>
 
<div style="text-align:right;">([[#top|Back to top)]]</div>
  
====ListCombine(...): Combines two delimited lists into a single delimited list====
+
====ListClean(&hellip;): Various list operations====
{| 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 | ListCombine()
 
| style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | ListCombine() is used to merge two specified lists into a single list.  It can operate in one of two modes, one which remove duplicates from the final list, and the other which outputs only items contained in both lists.  Both input and output delimiters may be specified.  Note that unlike the [[#ListBuild(...): Build a list from a series of values|ListBuild]] function above, which can be used to create a list from any number of varying sources, ListCombine() only accepts two lists.
 
 
 
|- valign="top"
 
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction
 
| style="background: #ecfeea; color: black; border: 1px solid black" | '''ListCombine(First list,Second list,Input Delimiter,Output Delimiter,Mode)'''<br>
 
'''First List''' ''and'' '''Second List''' are two lists.
 
  
'''Input Delimiter''': ''One or more characters used to delimit items within each list. The default separator is a semicolon.''
+
{| style="width: 100%; border: 2px solid black;" align="top" cellpadding="3"
 +
|- id="ListClean" valign="top"
 +
! scope="row" style="background: #ecedf3; color: #111; " width=100 | Description
 +
| style="background: #f9f9f9; color: #111; " width=1200 | <span style="font-family: Consolas, monospace; color:#0f3f8d; font-size:110%"><b>listclean(</b><i>list</i><b>, </b><i>mode</i><b>, </b><i>delimiter</i><b>)</b></span>
 +
The [[#ListClean|ListClean()]] function performs one of the operations specified by <i>mode</i> on the given <i>list</i>.
 +
The specified <i>delimiter</i> separates <i>list</i> items.
  
'''Output Delimiter''': ''One or more characters used as the delimiter between items in the resulting list.  The default separator is a semicolon.
+
<div style="margin-left: 20pt;"><table style="background:#f9f9f9; border-spacing:0px; border-collapse:collapse;">
 +
<tr><td style="text-align:left; padding-right:20pt"><b>1</b></td><td>Remove duplicates</td></tr>
 +
<tr><td style="text-align:left; padding-right:20pt"><b>2</b></td><td>Reverse the order of items</td></tr>
 +
</table></div>
  
'''Mode:''' ''Specifies the mode of operation:
+
Argument <i>delimiter</i> is optional (defaults to SEMICOLON).
* '''0''': ''Combine both lists and remove duplicates (order is preserved).''
 
* '''1''': ''Output only items contained in both lists (order is preserved).''
 
  
 
|- valign="top"
 
|- valign="top"
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples
+
! scope="row" style="background: #ecedf3; color: #111; " | Examples
|style="background: #ecfeea; color: black; border: 1px solid black" | '''listcombine(a;b;e, a;b;c;d)'''<br />
+
|style="background: #f9f9f9; color: #111; " | <span style="font-family: Consolas, monospace;"><b><nowiki>listclean(c;b;c;a, 1)</nowiki></b></span>
Returns ''a;b;e;c;d''.
+
<p style="margin-left:20pt;">Removes duplicates from the <i>list</i>, returning <span style="font-family: Consolas, monospace;">c;b;a</span>.</p>
 +
<span style="font-family: Consolas, monospace;"><b><nowiki>listclean(d;c;b;a, 2) </nowiki></b></span>
 +
<p style="margin-left:20pt;">Reverses the <i>list</i> items, returning <span style="font-family: Consolas, monospace;">a;b;c;d</span>.</p>
 +
<span style="font-family: Consolas, monospace;"><b><nowiki>listclean(\a\x\x\x\z, 1, \) </nowiki></b></span>
 +
<p style="margin-left:20pt;">Removes duplicates from a backslash-separated <i>list</i>, returning <span style="font-family: Consolas, monospace;">\a\x\z</span>.</p>
 +
|}
 +
<div style="text-align:right;">([[#top|Back to top)]]</div>
  
'''listcombine(a;b;e, a;b;c;d, ;, ;, 1)'''<br />
+
====ListCombine(&hellip;): Combines two delimited lists into a single delimited list====
Returns ''a;b''.
 
  
'''listcombine(a-c, c-f, -, ..., 0)'''<br />
+
{| style="width: 100%; border: 2px solid black;" align="top" cellpadding="3"
'''listcombine(a#@#c, c#@#f, #@#, ..., 0)'''<br />
+
|- id="ListCombine" valign="top"
Both functions above return ''a...c...f''.
+
! scope="row" style="background: #ecedf3; color: #111; " width=100 | Description
 +
| style="background: #f9f9f9; color: #111; " width=1200 | <span style="font-family: Consolas, monospace; color:#0f3f8d; font-size:110%"><b>listcombine(</b><i>list1</i><b>, </b><i>list2</i><b>, </b><i>input delimiter</i><b>, </b><i>output delimiter</i><b>, </b><i>mode</i><b>)</b></span>
 +
The [[#ListCombine|ListCombine()]] function returns a single list after performing the operation specified by <i>mode</i> on the two lists <i>list1</i> and <i>list2</i>.
 +
An <i>input delimiter</i> and an <i>output delimiter</i> may be specified.
 +
The <i>input delimiter</i> is effective for both <i>list1</i> and <i>list2</i>, and the <i>output delimiter</i> will be used in the returned list, replacing the
 +
<i>input delimiter</i> from both <i>list1</i> and <i>list2</i>.
  
'''listcombine([people],[places])&datatype=[list]'''<br />
+
Available <i>mode</i> values:
''The result here would be a single, semi-colon delimited list containing all the values from the [people] and [places] fields.''
 
  
* [people] contains ''Family\Mum;Family\Dad;Family\Gran''
+
<div style="margin-left: 20pt;"><table style="background:#f9f9f9; border-spacing:0px; border-collapse:collapse;">
* [places] contains ''United Kingdom\Scotland\Edinburgh;United Kingdom\Scotland\Edinburgh\Edinburgh Castle''
+
<tr><td style="text-align:left; padding-right:20pt"><b>0</b></td><td>Combine lists removing duplicates (order is preserved).</td></tr>
* 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)
+
<tr><td style="text-align:left; padding-right:20pt"><b>1</b></td><td>Output only items contained in both lists (order is preserved).</td></tr>
 +
</table></div>
  
<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.''
+
Argument <i>input delimiter</i> is optional (defaults to SEMICOLON).
  
* [people] contains ''Family\Mum;Family\Dad;Family\Gran''
+
Argument <i>output delimiter</i> is optional (defaults to SEMICOLON).
* [places] contains ''United Kingdom\Scotland\Edinburgh;United Kingdom\Scotland\Edinburgh\Edinburgh Castle''
 
* 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>''Finally, a semi-colon output delimiter has been specified, therefore, all back slashes will be replaced by semi-colons, and the resulting list will be a single, flat list containing all the text entries from each field:''
+
Argument <i>mode</i> is optional (defaults to 0).
  
* [people] contains ''Family\Mum;Family\Dad;Family\Gran''
+
|- valign="top"
* [places] contains ''United Kingdom\Scotland\Edinburgh;United Kingdom\Scotland\Edinburgh\Edinburgh Castle''
+
! scope="row" style="background: #ecedf3; color: #111; " | Examples
* 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)
+
|style="background: #f9f9f9; color: #111; " | <span style="font-family: Consolas, monospace;"><b><nowiki>listcombine(a;b;e, a;b;c;d)</nowiki></b></span>
 +
<p style="margin-left:20pt;">Returns <span style="font-family: Consolas, monospace;">a;b;e;c;d</span>.
 +
This example uses the default <i>mode</i> 0 to combine <i>list1</i> with <i>list2</i>, preserving the order of items.
 +
The default <span style="font-family: Consolas, monospace;">;</span> <i>input delimiter</i> and <i>output delimiter</i> is used.</p>
 +
<span style="font-family: Consolas, monospace;"><b><nowiki>listcombine(a;b;e, a;b;c;d, ;, ;, 1)</nowiki></b></span>
 +
<p style="margin-left:20pt;">Returns <span style="font-family: Consolas, monospace;">a;b</span>.
 +
The <i>input delimiter</i> and <i>output delimiter</i> are both specified as <span style="font-family: Consolas, monospace;">;</span>,
 +
and <i>mode</i> 1 is used to produce a list of only items that exist in both <i>list1</i> and <i>list2</i>.</p>
 +
<span style="font-family: Consolas, monospace;"><b><nowiki>listcombine(a-c, c-f, -, ..., 0)</nowiki></b></span>
 +
<p style="margin-left:20pt;">Returns <span style="font-family: Consolas, monospace;">a...c...f</span>. The <i>input delimiter</i> is <span style="font-family: Consolas, monospace;">-</span>, while the output delimter is <span style="font-family: Consolas, monospace;">...</span>, and <i>mode</i> 0 combines both lists.</p>
 +
<span style="font-family: Consolas, monospace;"><b><nowiki>listcombine(a#@#c, c#@#f, #@#, ., 0)</nowiki></b></span>
 +
<p style="margin-left:20pt;">Returns <span style="font-family: Consolas, monospace;">a.c.f</span>. This example demonstrates how to combine two lists with duplicates removed while replacing a multi-character <i>input delimiter</i> <span style="font-family: Consolas, monospace;">#@#</span> with a single-character <i>output delimiter</i> <span style="font-family: Consolas, monospace;">.</span>.</p>
 +
<span style="font-family: Consolas, monospace;"><b><nowiki>listcombine([people], [places])&amp;datatype=[list]</nowiki></b></span>
 +
<p style="margin-left:20pt;">The result here would be a single, semicolon delimited list containing all the list items from the [people] and [places] fields.
 +
For example, if [people] contains <span style="font-family: Consolas, monospace;">Family\Mum; Family\Dad; Family\Gran</span>, and [places] contains <span style="font-family: Consolas, monospace;">UK\Scotland\Edinburgh; UK\Scotland\Edinburgh\Edinburgh Castle</span>,
 +
the output list would be <span style="font-family: Consolas, monospace;">Family\Mum; Family\Dad; Family\Gran; UK\Scotland\Edinburgh; UK\Scotland\Edinburgh\Edinburgh Castle</span>.
 +
Using the <span style="font-family: Consolas, monospace;">&datatype=[list]</span> cast makes the expression split individual list items in a panes or categories view.</p>
 
|}
 
|}
 
<div style="text-align:right;">([[#top|Back to top)]]</div>
 
<div style="text-align:right;">([[#top|Back to top)]]</div>
====ListCount(...): Returns the number of items in a delimited list====
 
{| 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 | ListCount()
 
| style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | ListCount is used to return the number of items that exist in any given field, using any given delimiter.
 
|- valign="top"
 
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction
 
| style="background: #ecfeea; color: black; border: 1px solid black" | '''ListCount([Field to count],Delimiter to use)'''<br>
 
'''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.''
+
====ListCount(&hellip;): Returns the number of items in a list====
|- valign="top"
+
 
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples
+
{| style="width: 100%; border: 2px solid black;" align="top" cellpadding="3"
|style="background: #ecfeea; color: black; border: 1px solid black" | '''listcount([People])'''<br>
+
|- id="ListCount" valign="top"
''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).''
+
! scope="row" style="background: #ecedf3; color: #111; " width=100 | Description
 +
| style="background: #f9f9f9; color: #111; " width=1200 | <span style="font-family: Consolas, monospace; color:#0f3f8d; font-size:110%"><b>listcount(</b><i>list</i><b>, </b><i>delimiter</i><b>)</b></span>
 +
The [[#ListCount|ListCount()]] function returns the number of items that exist in a <i>list</i> delimited by <i>delimiter</i>.
  
<br>'''listcount([filename (path)],\)'''<br>
+
Argument <i>delimiter</i> is optional (defaults to SEMICOLON).
''This function can be used to count the directories in a filepath by specifying a back slash as the delimiter.''
 
  
<br>'''listcount([keywords],!People)'''<br>
+
|- valign="top"
''This basic expression can be used as a building block to create a more complex expression to count the number of people tagged in a photo. the full expression can be seen [http://yabb.jriver.com/interact/index.php?topic=43975.msg301390#msg301390 here]. That thread is actually the release thread for the 'new' nesting feature, introduced in 2007, and although 2 pages long, is worth a read as it contains some quite useful information.''
+
! scope="row" style="background: #ecedf3; color: #111; " | Examples
 +
|style="background: #f9f9f9; color: #111; " | <span style="font-family: Consolas, monospace;"><b><nowiki>listcount([keywords])</nowiki></b></span>
 +
<p style="margin-left:20pt;">Returns the number of keywords for the file.</p>
 +
<span style="font-family: Consolas, monospace;"><b><nowiki>listcount([filename (path)], \)</nowiki></b></span>
 +
<p style="margin-left:20pt;">Returns the number of the directories in a Windows drive-based file path.
 +
The example demonstrates that non-List type fields can be used with the functions in this section.
 +
While the <i>delimiter</i> specified here is <span style="font-family: Consolas, monospace;">\</span>, an escaped forward slash <span style="font-family: Consolas, monospace;">//</span> could be used when applicable.</p>
 
|}
 
|}
 
<div style="text-align:right;">([[#top|Back to top)]]</div>
 
<div style="text-align:right;">([[#top|Back to top)]]</div>
====ListItem(...): Returns a specified value from a delimited list====
 
{| 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 | ListItem()
 
| style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | This function numbers list items starting from zero and returns the value of a specifically numbered item.
 
|- valign="top"
 
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction
 
| style="background: #ecfeea; color: black; border: 1px solid black" | '''ListItem([Field],Number of item to retrieve,Field delimiter to use)'''
 
  
* '''Field''': ''The function will accept any given field, though is more typically used with list type fields.''
+
====ListItem(&hellip;): Returns an item from a location in a list====
* '''Number of item to retrieve''': ''The number of the item in the list to retrieve. The list items are numbered starting from zero.''
+
 
* '''Field 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.''
+
{| style="width: 100%; border: 2px solid black;" align="top" cellpadding="3"
|- valign="top"
+
|- id="ListItem" valign="top"
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples
+
! scope="row" style="background: #ecedf3; color: #111; " width=100 | Description
|style="background: #ecfeea; color: black; border: 1px solid black" | '''listitem([filename],0,\)'''<br>''This function will return a file's drive letter plus colon. Note that the same result could be achieved by using '''[[#Left(...): Retrieves a specified number of characters from the left of a value|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.''
+
| style="background: #f9f9f9; color: #111; " width=1200 | <span style="font-family: Consolas, monospace; color:#0f3f8d; font-size:110%"><b>listitem(</b><i>list</i><b>, </b><i>position</i><b>, </b><i>delimiter</i><b>)</b></span>
 +
The [[#ListItem|ListItem()]] function returns the item from the specified <i>position</i> in the <i>list</i>.
 +
Items in a <i>list</i> are zero-based, so the first item in the <i>list</i> is located at postition 0.
 +
Nothing is returned with the <i>position</i> is outside the bounds of the <i>list</i>.
  
<br>'''listitem([filename],2,\)'''<br>''Here, the result will be the name of the second directory along a file's folder path from the drive root. C:\Folder1\Folder2\ are itemised as 0\1\2\, so rather confusingly, the second directory is actually the third item in the back slash delimited path.''
+
Argument <i>delimiter</i> is optional (defaults to SEMICOLON).
  
<br>'''listitem([filename (path)],math(listcount([filename (path)],\)-1),\)'''<br>''This expression uses the [[#Math(...): Evaluates a given mathematical formula|math()]] and [[#ListCount(...): Returns the number of items in a delimited list|listcount()]] functions to find the "Number of item to retrieve" value. listcount() returns the total number of directories in the path, and the math function subtracts one from this number (because listcount() starts counting at one, but listitem starts counting from zero), this number is then used by the listitem function. The result will be the name of the parent folder of each file. Setting the expression up in this way means that the result will always be reliable regardless of the number of folders in the filepath as the expression will work all of this out for itself.''
+
|- valign="top"
 +
! scope="row" style="background: #ecedf3; color: #111; " | Examples
 +
|style="background: #f9f9f9; color: #111; " | <span style="font-family: Consolas, monospace;"><b><nowiki>listitem(a;b;c, 1)</nowiki></b></span>
 +
<p style="margin-left:20pt;">Returns <span style="font-family: Consolas, monospace;">b</span>, since postion 1 is the second item in the <i>list</i> <span style="font-family: Consolas, monospace;">a;b;c</span>.</p>
 +
<span style="font-family: Consolas, monospace;"><b><nowiki>listitem(1:04:47, 2, :)</nowiki></b></span>
 +
<p style="margin-left:20pt;">Using the <i>delimiter</i> <span style="font-family: Consolas, monospace;">:</span>, returns item at <i>position</i> 2, which is the seconds value <span style="font-family: Consolas, monospace;">47</span> from the time <span style="font-family: Consolas, monospace;">1:04:47</span>.</p>
 
|}
 
|}
 
<div style="text-align:right;">([[#top|Back to top)]]</div>
 
<div style="text-align:right;">([[#top|Back to top)]]</div>
  
====ListSort(...): Sort a list of values====
+
====ListSort(&hellip;): Sort a list of values====
{| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3"
+
 
|- valign="top"
+
{| style="width: 100%; border: 2px solid black;" align="top" cellpadding="3"
! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | ListSort()
+
|- id="ListSort" valign="top"
| style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | This function provides the ability to sort a list of values in either ascending or descending order.  List items are separated by an arbitrary delimiter, which defaults to semicolon.
+
! scope="row" style="background: #ecedf3; color: #111; " width=100 | Description
|- valign="top"
+
| style="background: #f9f9f9; color: #111; " width=1200 | <span style="font-family: Consolas, monospace; color:#0f3f8d; font-size:110%"><b>listsort(</b><i>list</i><b>, </b><i>mode</i><b>, </b><i>delimiter</i><b>)</b></span>
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction
+
The [[#ListSort|ListSort()]] function sorts a <i>list</i> in the order according to <i>mode</i>, using the specified <i>delimiter</i>.
| style="background: #ecfeea; color: black; border: 1px solid black" | '''ListSort(List,Mode,Delimiter)'''<br>
+
 
 +
Available <i>mode</i> values:
  
'''List''' ''Any string''<br />
+
<div style="margin-left: 20pt;"><table style="background:#f9f9f9; border-spacing:0px; border-collapse:collapse;">
'''Mode:''' ''Specifies the sorting order:
+
<tr><td style="text-align:left; padding-right:20pt"><b>0</b></td><td>Ascending sort</td></tr>
* '''0''': ''Ascending (default)''
+
<tr><td style="text-align:left; padding-right:20pt"><b>1</b></td><td>Descending sort</td></tr>
* '''1''': ''Descending''
+
</table></div>
  
'''Delimiter''': ''One or more characters used to delimit items within the list.  The default separator is a semicolon.''
+
Argument <i>mode</i> is optional (defaults to 0).
|- valign="top"
 
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples
 
|style="background: #ecfeea; color: black; border: 1px solid black" | '''listsort(c;b;a)'''<br>
 
Returns ''a;b;c''.  Uses the default ascending sort order and semicolon delimiter.
 
  
<br>'''listsort(Joe Baxter/, Sally Henson/, Sue Smith, 1, /,)'''
+
Argument <i>delimiter</i> is optional (defaults to SEMICOLON).
<br>Returns ''Sue Smith,Sally Henson,Joe Baxter''.
 
  
<br>'''listsort([Artist];[Composer])'''
+
|- valign="top"
<br>Sorts the combined Artist and Composer lists in ascending order.
+
! scope="row" style="background: #ecedf3; color: #111; " | Examples
 +
|style="background: #f9f9f9; color: #111; " | <span style="font-family: Consolas, monospace;"><b><nowiki>listsort(c;a;b)</nowiki></b></span>
 +
<p style="margin-left:20pt;">Returns <span style="font-family: Consolas, monospace;">a;b;c</span>, using the default ascending <i>mode</i> and (<span style="font-family: Consolas, monospace;">:</span>) <i>delimiter</i>.</p>
 +
<span style="font-family: Consolas, monospace;"><b><nowiki>listsort(Joe Baxter/, Sally Henson/, Sue Smith, 1, /,)</nowiki></b></span>
 +
<p style="margin-left:20pt;">Returns <span style="font-family: Consolas, monospace;">Sue Smith,Sally Henson,Joe Baxter</span>.
 +
Note the requirement to escape the <span style="font-family: Consolas, monospace;">,</span> characters within the <i>list</i> string and in the specified <i>delimiter</i> itself.</p>
 +
<span style="font-family: Consolas, monospace;"><b><nowiki>listsort([artist];[composer])</nowiki></b></span>
 +
<p style="margin-left:20pt;">Sorts the combined artist and composer lists in ascending order.
 +
Note the simple manual construction of a single List by combining the two List type fields, and forcing a <span style="font-family: Consolas, monospace;">;</span> between the two.</p>
 
|}
 
|}
 
<div style="text-align:right;">([[#top|Back to top)]]</div>
 
<div style="text-align:right;">([[#top|Back to top)]]</div>
<br><br>
 
  
===Date & Time Functions===
+
===Date and 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====
 
{| 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.
+
Media Center provides several functions for the conversion, formatting and generation of dates and times.
 +
Date and time for a Date-type field is stored internally as a single 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 in seconds.
 +
The Epoch is defined as December 30th, 1899 at 00:00:01.
 +
Certain fractional values and whole numbers are used to encode Time-only and Year-only values.
 +
For example, the internal Date value of "2" is considered as 1900, without a time when converted using the DateTime conversion format of [[#FormatDate|FormatDate()]], whereas adding a small fraction and using "2.001" instead produces a value of "1/1/1900 12:01 am".
 +
These details are only relevant if you are doing conversions.
  
|- valign="top"
+
The Windows locale setting will affect the interpretation and formatting of date and time information.
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction
+
====ConvertDate(&hellip;): Converts a human-readable date to the internal format required for use in date fields====
| style="background: #ecfeea; color: black; border: 1px solid black" | '''convertdate(Date string)'''
 
  
*'''Date string''' ''A human-readable date string to be converted.''
+
{| style="width: 100%; border: 2px solid black;" align="top" cellpadding="3"
 +
|- id="ConvertDate" valign="top"
 +
! scope="row" style="background: #ecedf3; color: #111; " width=100 | Description
 +
| style="background: #f9f9f9; color: #111; " width=1200 | <span style="font-family: Consolas, monospace; color:#0f3f8d; font-size:110%"><b>convertdate(</b><i>date_time string</i><b>)</b></span>
 +
Converts a human-readable <i>date_time string</i> into the internal floating-point representation used by Media Center to store a date and time.
 
|- valign="top"
 
|- valign="top"
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples
+
! scope="row" style="background: #ecedf3; color: #111; " | 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.''
+
|style="background: #f9f9f9; color: #111; " | <span style="font-family: Consolas, monospace;"><b><nowiki>convertdate(3//6//2012)</nowiki></b></span>
 
+
<p style="margin-left:20pt;">Returns the value <span style="font-family: Consolas, monospace;">40974</span>, which is the internal floating-point represenation of the date string <span style="font-family: Consolas, monospace;">3/6/2012</span>.
<br>'''formatdate(convertdate(12/2/1985), decade))'''
+
This value can used by any field of type Date, or in any function that requires as input a Date type value.</p>
<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.
+
<span style="font-family: Consolas, monospace;"><b><nowiki>formatdate(convertdate(12//2//1985), decade))</nowiki></b></span>
 +
<p style="margin-left:20pt;">Converts the date string <span style="font-family: Consolas, monospace;">12/2/1985</span> (note: December 2nd, not February 12th) into a Date type value,
 +
and then formats the result as a decades grouping, returning <span style="font-family: Consolas, monospace;">1980's</span>.
 +
This might be used for creating decade groupings.</p>
 
|}
 
|}
 
<div style="text-align:right;">([[#top|Back to top)]]</div>
 
<div style="text-align:right;">([[#top|Back to top)]]</div>
  
====FormatDate(...): Formats a date value in a specified manner====
+
====FormatDate(&hellip;): Formats a date value in a specified manner====
{| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3"
+
 
|- valign="top"
+
{| style="width: 100%; border: 2px solid black;" align="top" cellpadding="3"
! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | FormatDate()
+
|- id="FormatDate" valign="top"
| 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.
+
! scope="row" style="background: #ecedf3; color: #111; " width=100 | Description
|- valign="top"
+
| style="background: #f9f9f9; color: #111; " width=1200 | <span style="font-family: Consolas, monospace; color:#0f3f8d; font-size:110%"><b>formatdate(</b><i>date value</i><b>, </b><i>format specifier</i><b>, </b><i>empty label</i><b>)</b></span>
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction
+
The [[#FormatDate|FormatDate()]] function provides custom formatting of date and time values through the use of a <i>format specifier</i>.
| style="background: #ecfeea; color: black; border: 1px solid black" | '''formatdate(Date value, Format string, Output if date is empty)'''
+
Output will be formatted according to <i>format specifier</i>.
  
*'''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]).''
+
The <i>date value</i> is a Media Center interal floating-point date/time representation, stored in Date fields,
 +
and output from various functions such as [[#Now|Now()]] and [[#ConvertDate|ConvertDate()]].
 +
To pass a field of type Date to [[#FormatDate|FormatDate()]], use the raw (unformatted) field specification, such as "[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]''
+
The <i>format specifier</i> provides a recipe for converting the internal value into a human-readable string.
 +
Supported are a variety of Windows style, strftime() style, and Media Center-specific formats specifiers.
 +
Construct the <i>format specifier</i> from any number or combination of those defined in the following table.
 +
Additionally, any non-format characters will be output without interpretation.
 +
This allows creating rich date/time output strings.
 +
To output a word that is a reservered <i>format specifier</i>, surround the word with double-quotes.
  
*'''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.''
+
The <i>empty label</i> argument will be output if the <i>date value</i> is empty.
  
 
<blockquote>
 
<blockquote>
{| style="background: #ecfeea;" border="1" cellpadding="1" cellspacing="0"
+
{| style="background: #f9f9f9;" border="1" cellpadding="1" cellspacing="0"
| || colspan="3" align="center" | '''Specifier''' || '''Description'''
+
| style="background: #ecedf3;" | || colspan="3" align="center" style="background: #ecedf3;" | '''Specifier''' || style="background: #ecedf3;" | '''Description'''
 
|-
 
|-
 
| rowspan="7" width="100" | '''Day'''
 
| rowspan="7" width="100" | '''Day'''
Line 1,295: Line 1,560:
 
|}
 
|}
 
</blockquote>
 
</blockquote>
 +
 +
Argument <i>date value</i> is optional (defaults to [date,0]).
 +
 +
Argument <i>empty label</i> is optional (defaults to EMPTY).
  
 
|- valign="top"
 
|- valign="top"
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples
+
! scope="row" style="background: #ecedf3; color: #111; " | 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.''
+
|style="background: #f9f9f9; color: #111; " | <span style="font-family: Consolas, monospace;"><b><nowiki>formatdate(year-month)</nowiki></b></span>
 +
<p style="margin-left:20pt;">Outputs the file's date formatted as Year-Month, such as <span style="font-family: Consolas, monospace;">2012-April</span>. The default <i>date value</i> of <span style="font-family: Consolas, monospace;">[Date,0]</span> is used.</p>
 +
<span style="font-family: Consolas, monospace;"><b><nowiki>formatdate([last played,0], yyyy//MM//dd, Not Yet)</nowiki></b></span>
 +
<p style="margin-left:20pt;">Returns the file's last played date as year/month/day without the time, ignoring the system locale setting.
 +
If a file has no last played value, the expression will output <span style="font-family: Consolas, monospace;">Not Yet</span> instead.</p>
 +
<span style="font-family: Consolas, monospace;"><b><nowiki>formatdate([date modified,0], month %Y)</nowiki></b></span>
 +
<p style="margin-left:20pt;">Returns the file's modification date/time in the form of a long month name and a four-digit year, such as <span style="font-family: Consolas, monospace;">December 2010</span>.</p>
 +
<span style="font-family: Consolas, monospace;"><b><nowiki>formatdate([date imported,0], The "year" is year)</nowiki></b></span>
 +
<p style="margin-left:20pt;">Outputs the <span style="font-family: Consolas, monospace;">The year is ####</span>, where #### is the year the file was imported into the Library.
 +
Note that the word <span style="font-family: Consolas, monospace;">year</span> must be surrounded in double-quotes to have it considered as literal text,
 +
and not the <span style="font-family: Consolas, monospace;"><b>Year</b></span> <i>format specifier</i>.</p>
 +
<span style="font-family: Consolas, monospace;"><b><nowiki>formatdate([date imported,0], month)&amp;datatype=[month]</nowiki></b></span>
 +
<p style="margin-left:20pt;">This examples is the same as the previous example, but includes a cast to the Month type <span style="font-family: Consolas, monospace;">&datatype=[month]</span>.
 +
This cast can be used to cause chronological month-sorting, rather than month name alphabetic-sorting, in a panes or category view.
 +
Data-type coercion is discussed [[#Specify_data_types_for_expression_based_fields|above]].</p>
  
<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&nbsp;Yet" instead.''
+
Additional Examples
 +
 
 +
:[http://yabb.jriver.com/interact/index.php?topic=71000.msg479314#msg479314 Date formatting development discussion, usage tips and examples.]
 +
|}
 +
<div style="text-align:right;">([[#top|Back to top)]]</div>
  
<br>'''formatdate([date modified,0], month %Y)'''
+
====Now(&hellip;): Retrieve and display the system date====
<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]'''
+
{| style="width: 100%; border: 2px solid black;" align="top" cellpadding="3"
<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]].
+
|- id="Now" valign="top"
 +
! scope="row" style="background: #ecedf3; color: #111; " width=100 | Description
 +
| style="background: #f9f9f9; color: #111; " width=1200 | <span style="font-family: Consolas, monospace; color:#0f3f8d; font-size:110%"><b>now(</b><b>)</b></span>
 +
The [[#Now|Now()]] function returns a floating-point value represeting the current system date and time.
 +
It is generally useful for performing date arithmatic in expressions that desire to figure out elapsed time.
 +
Any raw date field or value representing a date can be subtracted from [[#Now|Now()]] to realize an elapsed time delta.
 +
|- valign="top"
 +
! scope="row" style="background: #ecedf3; color: #111; " | Examples
 +
|style="background: #f9f9f9; color: #111; " | <span style="font-family: Consolas, monospace;"><b><nowiki>now()</nowiki></b></span>
 +
<p style="margin-left:20pt;">When run on Aug 17, 2013 at 19:28:00, returns approximately <span style="font-family: Consolas, monospace;">41503.811115995</span>.</p>
 +
<span style="font-family: Consolas, monospace;"><b><nowiki>formatdate(now(), date)</nowiki></b></span>
 +
<p style="margin-left:20pt;">Returns the current date, without a time component, formatted according to the system's locale settings.</p>
 +
<span style="font-family: Consolas, monospace;"><b><nowiki>formatdate(math(now() - 3, dddd dd MMMM yyyy H:mm)</nowiki></b></span>
 +
<p style="margin-left:20pt;">The date from three days ago is formated as something like <span style="font-family: Consolas, monospace;">Wednesday 14 August 2013 19:35</span>.
 +
This is accomplished by subtracting the value <span style="font-family: Consolas, monospace;">3</span>, which would be days, from [[#Now|Now()]], and its output formatted by [[#FormatDate|FormatDate()]].</p>
 
|}
 
|}
 
<div style="text-align:right;">([[#top|Back to top)]]</div>
 
<div style="text-align:right;">([[#top|Back to top)]]</div>
  
====Now(...): Retrieve and display the system date====
+
===File Path and Identifier Functions===
{| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3"
+
 
|- valign="top"
+
The funcions in this section provide specific file-related information such as
! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | Now()
+
a file's name, path, volume, and other Media Center internal information.
| 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.
+
====FileDBLocation(&hellip;): Identifies a file's databases====
|- valign="top"
 
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction
 
| style="background: #ecfeea; color: black; border: 1px solid black" | '''Now()'''
 
|- valign="top"
 
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples
 
|style="background: #ecfeea; color: black; border: 1px solid black" | '''formatdate(now(),date)'''<br>''Returns the current date, without the time, formatted according to the system settings on which the function is running.''
 
  
<br>'''formatdate(now(),dddd dd MMMM yyyy) [[#PadNumber(...): Adds leading zeros to any given number|padnumber]](formatdate(now(),hour),2):[[#PadNumber(...): Adds leading zeros to any given number|padnumber]](formatdate(now(),minute),2)'''<br>
+
{| style="width: 100%; border: 2px solid black;" align="top" cellpadding="3"
''Here, three seperate expressions have been strung together to return a fully formatted current date and time:'' '''''Sunday 26 September 2010 14:04'''''
+
|- id="FileDBLocation" valign="top"
 +
! scope="row" style="background: #ecedf3; color: #111; " width=100 | Description
 +
| style="background: #f9f9f9; color: #111; " width=1200 | <span style="font-family: Consolas, monospace; color:#0f3f8d; font-size:110%"><b>filedblocation(</b><i>format</i><b>)</b></span>
 +
The [[#FileDBLocation|FileDBLocation()]] function returns identifiers in the specified <i>format</i> specified that indicate to which internal database(s) a file belongs.
 +
Media Center maintains several internal databases to track a file's disposition.
 +
This function is primarly for technical use only, and will have little utility for most users.
  
<br>'''[=isequal(formatdate([date imported,0],MM//yyyy),formatdate(now(),MM//yyyy)]=1 ~sort=[Date Imported]-d'''<br>
+
Available <i>format</i> values:
''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&nbsp;Imported]=<31d&nbsp;~sort=[Date&nbsp;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 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.''
+
<div style="margin-left: 20pt;"><table style="background:#f9f9f9; border-spacing:0px; border-collapse:collapse;">
|}
+
<tr><td style="text-align:left; padding-right:20pt"><b>0</b></td><td>Semicolon-separated list of formatted database names</td></tr>
===Other Functions===
+
<tr><td style="text-align:left; padding-right:20pt"><b>1</b></td><td>Numeric value of OR'd database bit flags</td></tr>
The functions in this group are varied, and do not readily fit into the other groups of functions.
+
</table></div>
  
<div style="text-align:right;">([[#top|Back to top)]]</div>
+
The table below provides common values output from [[#FileDBLocation|FileDBLocation()]]:
 +
<div style="margin-left: 20pt;"><table style="background:#f9f9f9; border-spacing:0px; border-collapse:collapse;" border="1">
 +
<tr><td style="text-align:left; padding-right:20pt">Database name</td><td>Bit position</td></tr>
 +
<tr><td style="text-align:left; padding-right:20pt">Main</td><td>0</td></tr>
 +
<tr><td style="text-align:left; padding-right:20pt">Playing Now</td><td>1</td></tr>
 +
<tr><td style="text-align:left; padding-right:20pt">CD</td><td>2</td></tr>
 +
<tr><td style="text-align:left; padding-right:20pt">Explorer</td><td>3</td></tr>
 +
<tr><td style="text-align:left; padding-right:20pt">Other (16)</td><td>5</td></tr>
 +
<tr><td style="text-align:left; padding-right:20pt">Other (6)</td><td>6</td></tr>
 +
<tr><td style="text-align:left; padding-right:20pt">Grouping</td><td>7</td></tr>
 +
<tr><td style="text-align:left; padding-right:20pt">Removed</td><td>8</td></tr>
 +
<tr><td style="text-align:left; padding-right:20pt">Podcast</td><td>10</td></tr>
 +
<tr><td style="text-align:left; padding-right:20pt">Other (4096)</td><td>12</td></tr>
 +
<tr><td style="text-align:left; padding-right:20pt">Stacks</td><td>14</td></tr>
 +
<tr><td style="text-align:left; padding-right:20pt">Category Images</td><td>18</td></tr>
 +
<tr><td style="text-align:left; padding-right:20pt">Bad</td><td>19</td></tr>
 +
</table></div>
  
====Counter(...): Counts upwards in specified increments====
+
Argument <i>format</i> is optional (defaults to 0).
{| 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"
 
|- valign="top"
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples
+
! scope="row" style="background: #ecedf3; color: #111; " | 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.
+
|style="background: #f9f9f9; color: #111; " | <span style="font-family: Consolas, monospace;"><b><nowiki>filedblocation()</nowiki></b></span>
 +
<p style="margin-left:20pt;">For a file in the <span style="font-family: Consolas, monospace;">Main</span> and <span style="font-family: Consolas, monospace;">Other (4096)</span> databases, the result would be <span style="font-family: Consolas, monospace;">Main; Other (4096)</span>.</p>
 +
<span style="font-family: Consolas, monospace;"><b><nowiki>filedblocation(1)</nowiki></b></span>
 +
<p style="margin-left:20pt;">The result from the same file would be <span style="font-family: Consolas, monospace;">4096</span> (bit 0 and bit 12 set).</p>
  
<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..
+
Additional Examples
  
<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]".
+
:[http://yabb.jriver.com/interact/index.php?topic=77896.msg539271#msg539271 Sample expression that uses FileDBLocation() to show a file's databases.]  
 
|}
 
|}
 
<div style="text-align:right;">([[#top|Back to top)]]</div>
 
<div style="text-align:right;">([[#top|Back to top)]]</div>
  
====CustomData(...): Sequence numbering when renaming files====
+
====FileFolder(&hellip;): Returns the name of a file's parent====
{| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3"
+
 
 +
{| style="width: 100%; border: 2px solid black;" align="top" cellpadding="3"
 +
|- id="FileFolder" valign="top"
 +
! scope="row" style="background: #ecedf3; color: #111; " width=100 | Description
 +
| style="background: #f9f9f9; color: #111; " width=1200 | <span style="font-family: Consolas, monospace; color:#0f3f8d; font-size:110%"><b>filefolder(</b><i>filepath</i><b>, </b><i>level</i><b>)</b></span>
 +
The [[#FileFolder|FileFolder()]] function returns parent sub-folder name for <i>filepath</i>.
 +
The <i>level</i> argument specifies which parent sub-folder name to return,
 +
working the <i>filepath</i> from right-to-left (i.e. bottom of the folder tree upwards to the top).
 +
A value of 0 specifies a file's immediate parent, 1 its grandparent, etc., up to the root of the <i>filepath</i>.
 +
A value of <span style="font-family: Consolas, monospace;">Unassigned</span> will be returned when the specified <i>level</i> exceeds the root of the <i>filepath</i>.
 +
 
 +
Argument <i>filepath</i> is optional (defaults to [filename]).
 +
 
 +
Argument <i>level</i> is optional (defaults to 0).
 +
 
 
|- valign="top"
 
|- valign="top"
! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | CustomData()
+
! scope="row" style="background: #ecedf3; color: #111; " | Examples
| 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.
+
|style="background: #f9f9f9; color: #111; " | <span style="font-family: Consolas, monospace;"><b><nowiki>filefolder()</nowiki></b></span>
 +
<p style="margin-left:20pt;">Returns the name of the file's parent folder.</p>
 +
<span style="font-family: Consolas, monospace;"><b><nowiki>filefolder([filename,0], 0)</nowiki></b></span>
 +
<p style="margin-left:20pt;">Same as the previous example.</p>
 +
<span style="font-family: Consolas, monospace;"><b><nowiki>filefolder(c:\some\folder\for\a\file.ape, 2)</nowiki></b></span>
 +
<p style="margin-left:20pt;">Returns the great grandparent sub-folder named <span style="font-family: Consolas, monospace;">folder</span>.</p>
 +
<span style="font-family: Consolas, monospace;"><b><nowiki>filefolder(c:\some\other\folder\a\, 2)</nowiki></b></span>
 +
<p style="margin-left:20pt;">Returns the folder named <span style="font-family: Consolas, monospace;">other</span>.
 +
Notice the file name is not required in the <i>filepath</i>.
 +
[[#FileFolder|FileFolder()]] works by looking from the end of the <i>filepath</i> until it finds a backslash <span style="font-family: Consolas, monospace;">\</span>.</p>
 +
|}
 +
<div style="text-align:right;">([[#top|Back to top)]]</div>
 +
 
 +
====FileKey()(&hellip;): Returns a file's unique internal identifier====
 +
 
 +
{| style="width: 100%; border: 2px solid black;" align="top" cellpadding="3"
 +
|- id="FileKey" valign="top"
 +
! scope="row" style="background: #ecedf3; color: #111; " width=100 | Description
 +
| style="background: #f9f9f9; color: #111; " width=1200 | <span style="font-family: Consolas, monospace; color:#0f3f8d; font-size:110%"><b>filekey()(</b><b>)</b></span>
 +
The [[#FileKey|FileKey()()]] function returns the unique identifier assosciated with a file.
 +
Media Center assigns a unique identifier to each file in the Libary.
 +
It is useful in expressions when referring to individual files is necessary.
 +
Services such as MCWS use this value to reference a file.
 
|- valign="top"
 
|- valign="top"
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction
+
! scope="row" style="background: #ecedf3; color: #111; " | Examples
| style="background: #ecfeea; color: black; border: 1px solid black" | '''CustomData(#)'''
+
|style="background: #f9f9f9; color: #111; " | <span style="font-family: Consolas, monospace;"><b><nowiki>filekey()</nowiki></b></span>
 +
<p style="margin-left:20pt;">Returns a integer value, such as <span style="font-family: Consolas, monospace;">22029495</span>, unique for eac file in the Library.</p>
 +
|}
 +
<div style="text-align:right;">([[#top|Back to top)]]</div>
 +
 
 +
====FileName(&hellip;): Returns a file's name component====
 +
 
 +
{| style="width: 100%; border: 2px solid black;" align="top" cellpadding="3"
 +
|- id="FileName" valign="top"
 +
! scope="row" style="background: #ecedf3; color: #111; " width=100 | Description
 +
| style="background: #f9f9f9; color: #111; " width=1200 | <span style="font-family: Consolas, monospace; color:#0f3f8d; font-size:110%"><b>filename(</b><i>filepath</i><b>, </b><i>include suffix</i><b>)</b></span>
 +
This function returns the file name part of <i>filepath</i>. Inclusion of the file's suffix depends on the <i>include suffix</i> argument.
 +
 
 +
<div style="margin-left: 20pt;"><table style="background:#f9f9f9; border-spacing:0px; border-collapse:collapse;">
 +
<tr><td style="text-align:left; padding-right:20pt"><b>0</b></td><td>Suppress file suffix</td></tr>
 +
<tr><td style="text-align:left; padding-right:20pt"><b>1</b></td><td>Include file suffix</td></tr>
 +
</table></div>
 +
 
 +
Argument <i>filepath</i> is optional (defaults to [filename]).
 +
 
 +
Argument <i>include suffix</i> is optional (defaults to 1).
 +
 
 
|- valign="top"
 
|- valign="top"
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples
+
! scope="row" style="background: #ecedf3; color: #111; " | 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.
+
|style="background: #f9f9f9; color: #111; " | <span style="font-family: Consolas, monospace;"><b><nowiki>filename(C:\Music\File.mp3)</nowiki></b></span>
 +
<p style="margin-left:20pt;">The output is <span style="font-family: Consolas, monospace;">File.mp3</span>.</p>
 +
<span style="font-family: Consolas, monospace;"><b><nowiki>filename(C:\Music\File 2.wav, 0)</nowiki></b></span>
 +
<p style="margin-left:20pt;">The output does not include the file suffix, and is <span style="font-family: Consolas, monospace;">File 2</span>.</p>
 +
<span style="font-family: Consolas, monospace;"><b><nowiki>filename()</nowiki></b></span>
 +
<p style="margin-left:20pt;">Returns the value contained in the field [filename (name)].</p>
 
|}
 
|}
 
<div style="text-align:right;">([[#top|Back to top)]]</div>
 
<div style="text-align:right;">([[#top|Back to top)]]</div>
  
====FileDBLocation(...): Returns identifiers of the internal databases that include the file====
+
====FilePath(&hellip;): Returns a file's path component====
{| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3"
+
 
 +
{| style="width: 100%; border: 2px solid black;" align="top" cellpadding="3"
 +
|- id="FilePath" valign="top"
 +
! scope="row" style="background: #ecedf3; color: #111; " width=100 | Description
 +
| style="background: #f9f9f9; color: #111; " width=1200 | <span style="font-family: Consolas, monospace; color:#0f3f8d; font-size:110%"><b>filepath(</b><i>filepath</i><b>)</b></span>
 +
This function will return the path portion of the specified file path.
 +
 
 +
The <i>filepath</i> should be a rooted path.  For Windows, this includes the drive letter or leading <span style="font-family: Consolas, monospace;">\\</span> for UNC paths.
 +
For *nix-based systems, this includes the root <span style="font-family: Consolas, monospace;">/</span>.
 +
The field [filename (path)] is equivalent to [[#FilePath|FilePath()]], and is generally preferred.
 +
 
 +
Argument <i>filepath</i> is optional (defaults to [filename]).
 +
 
 
|- valign="top"
 
|- valign="top"
! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | FileDBLocation()
+
! scope="row" style="background: #ecedf3; color: #111; " | Examples
| style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | Returns internal database identifiers indicating to which databases a given file belongs.
+
|style="background: #f9f9f9; color: #111; " | <span style="font-family: Consolas, monospace;"><b><nowiki>filepath(C:\Music\File.mp3)</nowiki></b></span>
 +
<p style="margin-left:20pt;">Returns <span style="font-family: Consolas, monospace;">C:\Music</span>.</p>
 +
<span style="font-family: Consolas, monospace;"><b><nowiki>filepath()</nowiki></b></span>
 +
<p style="margin-left:20pt;">Returns the value contained in the field [filename (path)].</p>
 +
|}
 +
<div style="text-align:right;">([[#top|Back to top)]]</div>
 +
 
 +
====FileVolume(&hellip;): Returns a file's volume name component====
 +
 
 +
{| style="width: 100%; border: 2px solid black;" align="top" cellpadding="3"
 +
|- id="FileVolume" valign="top"
 +
! scope="row" style="background: #ecedf3; color: #111; " width=100 | Description
 +
| style="background: #f9f9f9; color: #111; " width=1200 | <span style="font-family: Consolas, monospace; color:#0f3f8d; font-size:110%"><b>filevolume(</b><i>filepath</i><b>)</b></span>
 +
The [[#FileVolume|FileVolume()]] function returns the volume name component of the specified file path.
 +
The path should be a rooted path (see the same comment above for [[#FilePath|FilePath()]].  For *nix-based systems, the output is empty.
 +
The field [volume name] is equivalent to [[#FileVolume|FileVolume()]], and is generally preferred.
 +
 
 +
Argument <i>filepath</i> is optional (defaults to [filename]).
 +
 
 
|- valign="top"
 
|- valign="top"
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction
+
! scope="row" style="background: #ecedf3; color: #111; " | Examples
| style="background: #ecfeea; color: black; border: 1px solid black" | '''FileDBLocation(format)'''
+
|style="background: #f9f9f9; color: #111; " | <span style="font-family: Consolas, monospace;"><b><nowiki>filevolume(C:\Music\File.mp3)</nowiki></b></span>
 +
<p style="margin-left:20pt;">Outputs <span style="font-family: Consolas, monospace;">C:</span>.</p>
 +
<span style="font-family: Consolas, monospace;"><b><nowiki>filevolume()</nowiki></b></span>
 +
<p style="margin-left:20pt;">Returns the value contained in the field [volume name].</p>
 +
|}
 +
<div style="text-align:right;">([[#top|Back to top)]]</div>
 +
 
 +
===Miscellaneous Functions===
 +
 
 +
The functions in this section are varied and have specialized applicability.
 +
Some are primarly used internally by MC to generate values available in various Library fields.
 +
====AlbumArtist(&hellip;): Returns a file's calculated album artist====
  
'''format''' ''Output format (optional).  Valid values:
+
{| style="width: 100%; border: 2px solid black;" align="top" cellpadding="3"
* 0: ''output is a semicolon-separated list of formatted database names (default).<br />
+
|- id="AlbumArtist" valign="top"
* 1: ''output is the numeric value of OR'd database bit flags.''<br />
+
! scope="row" style="background: #ecedf3; color: #111; " width=100 | Description
<blockquote>
+
| style="background: #f9f9f9; color: #111; " width=1200 | <span style="font-family: Consolas, monospace; color:#0f3f8d; font-size:110%"><b>albumartist(</b><b>)</b></span>
{| style="background: #ecfeea;" border="1" cellpadding="1" cellspacing="0"
+
This function calculates the album artist value used in various views and fields.
!Database name
+
It is used to populate the Library field <span style="font-family: Consolas, monospace;">album artist (auto)</span> with its value.
!Bit position
+
Either the field or [[#AlbumArtist|AlbumArtist()]] can be used.
|-
 
|Main||0
 
|-
 
|Playing Now||1
 
|-
 
|CD||2
 
|-
 
|Explorer||3
 
|-
 
|Other (16)||5
 
|-
 
|Other (6)||6
 
|-
 
|Grouping||7
 
|-
 
|Removed||8
 
|-
 
|Podcast||10
 
|-
 
|Other (4096)||12
 
|-
 
|Stacks||14
 
|-
 
|Category Images||18
 
|-
 
|Bad||19
 
|}
 
</blockquote>
 
 
|- valign="top"
 
|- valign="top"
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples
+
! scope="row" style="background: #ecedf3; color: #111; " | Examples
|style="background: #ecfeea; color: black; border: 1px solid black" |
+
|style="background: #f9f9f9; color: #111; " | <span style="font-family: Consolas, monospace;"><b><nowiki>albumartist()</nowiki></b></span>
'''FileDBLocation()'''<br>''For a file in the "Main" and "Other (4096) databases, the result would be "Main; Other (4096)".''<br />
+
<p style="margin-left:20pt;">Returns the value present in the <span style="font-family: Consolas, monospace;">album artist (auto)</span> field.</p>
  
'''FileDBLocation(1)'''<br>''The result from the same file would be "4096" (bit 0 and bit 12 set).''
+
Additional Examples
  
 +
:[http://wiki.jriver.com/index.php/Album_Artist_and_Album_Artist_%28Auto%29 Describes the algorithm used by AlbumArtist() to calculate the "album artist (auto)" field's value.]
 
|}
 
|}
 +
<div style="text-align:right;">([[#top|Back to top)]]</div>
  
<div style="text-align:right;">([[#top|Back to top)]]</div>
+
====AlbumKey(&hellip;): Returns a unique album key for a file====
====FileFolder(...): Returns the name of a parent sub-folder from a specified filename ====
 
{| 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 [Filename]. Otherwise, the specified path will be used.''
+
{| style="width: 100%; border: 2px solid black;" align="top" cellpadding="3"
* 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.''
+
|- id="AlbumKey" valign="top"
 +
! scope="row" style="background: #ecedf3; color: #111; " width=100 | Description
 +
| style="background: #f9f9f9; color: #111; " width=1200 | <span style="font-family: Consolas, monospace; color:#0f3f8d; font-size:110%"><b>albumkey(</b><b>)</b></span>
 +
The [[#AlbumKey|AlbumKey()]] function returns "[album artist (auto)] - [album]".
 +
It is a convenience function, used to return the generally unique album / artist combination string used to distinguish
 +
between two like-named albums such as "Greatest Hits".
 
|- valign="top"
 
|- valign="top"
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples
+
! scope="row" style="background: #ecedf3; color: #111; " | 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.''
+
|style="background: #f9f9f9; color: #111; " | <span style="font-family: Consolas, monospace;"><b><nowiki>albumkey()</nowiki></b></span>
 
+
<p style="margin-left:20pt;">For an album named <span style="font-family: Consolas, monospace;">Greatest Hits</span> and an album artist (auto) of <span style="font-family: Consolas, monospace;">The Eagles</span>, returns <span style="font-family: Consolas, monospace;">The Eagles - Greatest Hits</span>.</p>
<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>
  
<div style="text-align:right;">([[#top|Back to top)]]</div>
+
====AlbumType(&hellip;): Returns the album type for a file====
====FileName(...): Returns the name from a specified filename ====
 
{| 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 of the specified file. A second parameter set to 0 will cause the suffix to be suppressed from the file name.  The field [Filename (Name)] is equivalent to FileName(), and should generally be preferred.''
 
|- valign="top"
 
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction
 
| style="background: #ecfeea; color: black; border: 1px solid black" | '''FileName(Filepath, Suppress suffix)'''
 
  
* Filepath ''This is optional. If not specified, the function defaults to the current value of [Filename].''
+
{| style="width: 100%; border: 2px solid black;" align="top" cellpadding="3"
* Suppress suffix ''This is optional. If set to 0, the file name's suffix will be suppressed from output.''
+
|- id="AlbumType" valign="top"
 +
! scope="row" style="background: #ecedf3; color: #111; " width=100 | Description
 +
| style="background: #f9f9f9; color: #111; " width=1200 | <span style="font-family: Consolas, monospace; color:#0f3f8d; font-size:110%"><b>albumtype(</b><b>)</b></span>
 +
The [[#AlbumType|AlbumType()]] function returns a description regarding an album's completeness and its quantity of artists.
 +
It is used to populate the Library field <span style="font-family: Consolas, monospace;">album type</span> with its value.
 +
Either the field or [[#AlbumType|AlbumType()]] can be used.
 
|- valign="top"
 
|- valign="top"
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples
+
! scope="row" style="background: #ecedf3; color: #111; " | Examples
|style="background: #ecfeea; color: black; border: 1px solid black" | '''filename(C:\Music\File.mp3)'''<br>''The result here would be... "File.mp3"''
+
|style="background: #f9f9f9; color: #111; " | <span style="font-family: Consolas, monospace;"><b><nowiki>albumtype()</nowiki></b></span>
 +
<p style="margin-left:20pt;">Returns, for example, <span style="font-family: Consolas, monospace;">Single artist (complete)</span>, or <span style="font-family: Consolas, monospace;">Multiple artists (incomplete)</span>.</p>
 +
|}
 +
<div style="text-align:right;">([[#top|Back to top)]]</div>
  
<br />'''filename(C:\Music\File 2.wav, 0)'''<br>''The result here would be... "File 2"''
+
====Counter(&hellip;): Counts upwards in specified increments====
  
<br>'''filename()'''<br>''Returns the same as [filename (Name)].
+
{| style="width: 100%; border: 2px solid black;" align="top" cellpadding="3"
|}
+
|- id="Counter" valign="top"
 +
! scope="row" style="background: #ecedf3; color: #111; " width=100 | Description
 +
| style="background: #f9f9f9; color: #111; " width=1200 | <span style="font-family: Consolas, monospace; color:#0f3f8d; font-size:110%"><b>counter(</b><i>start value</i><b>, </b><i>increment</i><b>)</b></span>
 +
The [[#Counter|Counter()]] function outputs a montonically increasing number (more simply stated, it counts) from a <i>start value</i>,
 +
and each time called, increases by the <i>increment</i> value.
 +
It is useful for sequentially numbering fields.
 +
The [[#Counter|Counter()]] function maintains an internal counter, and it resets itself to zero after five seconds of inactivity.
  
<div style="text-align:right;">([[#top|Back to top)]]</div>
+
Becuase [[#Counter|Counter()]] continues to count, it should only be used in single-use situations such as assigning its output to some field through field value assignment, for example, <span style="font-family: Consolas, monospace;">=counter()</span>.
====FilePath(...): Returns the path from a specified filename====
+
With proper care, it can be used as part of an expression in the Rename, Move & Copy tool, but see also [[#CustomData|CustomData()]].
{| 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 | FilePath()
 
| style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | This function will return the path portion of the specified file path.
 
|- valign="top"
 
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction
 
| style="background: #ecfeea; color: black; border: 1px solid black" | '''FilePath(Filepath)'''
 
  
* Filepath  ''This is optional. If not specified, the function defaults to using the current value of [Filename].  The path should be a rooted path including the drive letter or leading double backslashes for UNC paths.  The field [Filename (Path)] is equivalent to FilePath(), and should generally be preferred.''
+
It is not recommended for use in any context that continually refreshes its content, such as in a panes column, file list, or expression-based custom query.
|- valign="top"
+
Probably the best way to understand the results is to test the first example below as an expression column in a file list, and move the mouse around over that column.
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples
 
|style="background: #ecfeea; color: black; border: 1px solid black" | '''filepath(C:\Music\File.mp3)'''<br>''The result here would be... "C:\Music"''
 
  
<br>'''filepath()'''<br>''Returns the same as [Filename (path)].
+
Argument <i>start value</i> is optional (defaults to 1).
|}
 
  
<div style="text-align:right;">([[#top|Back to top)]]</div>
+
Argument <i>increment</i> is optional (defaults to 1).
====FileVolume(...): Returns the volume name from a specified filename====
 
{| 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 | FileVolume()
 
| style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | This function will return the volume portion of the specified file path.  Media Center has a [Volume Name] library field.
 
|- valign="top"
 
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction
 
| style="background: #ecfeea; color: black; border: 1px solid black" | '''FileVolume(Filepath)'''
 
* Filepath  ''This is optional. If not specified, the function defaults to using the current value of [Filename].  The path should be a rooted path including the drive letter or leading double backslashes for UNC paths.  The field [Volume Name] is equivalent to FileVolume(), and should generally be preferred.''
 
  
 
|- valign="top"
 
|- valign="top"
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples
+
! scope="row" style="background: #ecedf3; color: #111; " | Examples
|style="background: #ecfeea; color: black; border: 1px solid black" | '''filevolume(C:\Music\File.mp3)'''<br>''The result here would be... "C:"''
+
|style="background: #f9f9f9; color: #111; " | <span style="font-family: Consolas, monospace;"><b><nowiki>counter()</nowiki></b></span>
 +
<p style="margin-left:20pt;">Outputs values starting at <span style="font-family: Consolas, monospace;">1</span>, and incrementing by one, it will return <span style="font-family: Consolas, monospace;">1</span>, <span style="font-family: Consolas, monospace;">2</span>, <span style="font-family: Consolas, monospace;">3</span>, ... until no longer called.
 +
This might be used, for example, to assign to the [Track #] field of several tracks using the field assignment expression <span style="font-family: Consolas, monospace;">=counter()</span>.</p>
 +
<span style="font-family: Consolas, monospace;"><b><nowiki>padnumber(counter(370, 2), 4)</nowiki></b></span>
 +
<p style="margin-left:20pt;">Outputs numbers beginning from 370, incremented by two each, and padded to four digits. For example, <span style="font-family: Consolas, monospace;">0370</span>, <span style="font-family: Consolas, monospace;">0372</span>, <span style="font-family: Consolas, monospace;">0374</span>, etc.</p>
 +
|}
 +
<div style="text-align:right;">([[#top|Back to top)]]</div>
  
<br>'''filevolume()'''<br>''Returns the same as [Volume Name].
+
====CustomData(&hellip;): Returns internal data to the expression language====
|}
 
  
<div style="text-align:right;">([[#top|Back to top)]]</div>
+
{| style="width: 100%; border: 2px solid black;" align="top" cellpadding="3"
====Load(...): Outputs the value of a global variable====
+
|- id="CustomData" valign="top"
{| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3"
+
! scope="row" style="background: #ecedf3; color: #111; " width=100 | Description
|- valign="top"
+
| style="background: #f9f9f9; color: #111; " width=1200 | <span style="font-family: Consolas, monospace; color:#0f3f8d; font-size:110%"><b>customdata(</b><i>mode</i><b>)</b></span>
! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | Load()
+
The [[#CustomData|CustomData()]] function supports returning Media Center internal data to the expression language.
| 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.
+
Currently there is only one supported use, which is to use [[#CustomData|CustomData()]] in the Rename, Move & Copy tool to assist in numbering files.
|- 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.''
+
Available <i>mode</i> values:
  
 +
<div style="margin-left: 20pt;"><table style="background:#f9f9f9; border-spacing:0px; border-collapse:collapse;">
 +
<tr><td style="text-align:left; padding-right:20pt"><b>#</b></td><td>Returns a file's row number in the Rename, Move & Copy tool</td></tr>
 +
</table></div>
 
|- valign="top"
 
|- valign="top"
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples
+
! scope="row" style="background: #ecedf3; color: #111; " | Examples
|style="background: #ecfeea; color: black; border: 1px solid black" | '''load(var1)'''<br />
+
|style="background: #f9f9f9; color: #111; " | <span style="font-family: Consolas, monospace;"><b><nowiki>Spring_Break_Bash_padnumber(customdata(#), 4)</nowiki></b></span>
''Loads and outputs the previous stored value of the global variable "var1".  If "var1" has not been previously stored, the output will be empty.''
+
<p style="margin-left:20pt;">In the Rename, Move & Copy tool, each consecutive file would be named <span style="font-family: Consolas, monospace;">Spring_Break_Bash_</span> followed by a four digit, zero-padded number starting at <span style="font-family: Consolas, monospace;">0001</span>.</p>
 
 
<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(&hellip;): Evaluates a given mathematical formula====
{| style="width: 100%; border: 1px solid black" align="top" cellpadding="3"
+
 
|- valign="top"
+
{| style="width: 100%; border: 2px solid black;" align="top" cellpadding="3"
! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | Math()
+
|- id="Math" valign="top"
| 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.
+
! scope="row" style="background: #ecedf3; color: #111; " width=100 | Description
 +
| style="background: #f9f9f9; color: #111; " width=1200 | <span style="font-family: Consolas, monospace; color:#0f3f8d; font-size:110%"><b>math(</b><i>expression</i><b>)</b></span>
 +
The [[#Math|Math()]] function performs mathematical calculations.
 +
Standard arithmetic operators are supported, as are various numerical, trigonometric, and comparative functions.
 +
Simple variables are supported, as are multiple statements.  
  
 
<blockquote>
 
<blockquote>
{| style="background: #ecfeea;" border="1" cellpadding="1" cellspacing="0"
+
{| style="background: #f9f9f9;" border="1" cellpadding="1" cellspacing="0"
 
| rowspan="6" width="100" valign="top" | '''Arithmetic Operators'''
 
| rowspan="6" width="100" valign="top" | '''Arithmetic Operators'''
 
| align="center" width="65" | + || Addition
 
| align="center" width="65" | + || Addition
Line 1,588: Line 1,961:
 
|-
 
|-
 
| align="center" | above(x,y) || Returns 1 when x > y, 0 otherwise.
 
| align="center" | above(x,y) || Returns 1 when x > y, 0 otherwise.
 +
|-
 +
| rowspan="4" | '''Formatting Functions'''
 +
| align="center" | int(x) || Returns the integer portion of x.
 +
|-
 +
| align="center" | frac(x) || Returns the fractional portion of x.
 +
|-
 +
| align="center" | round(x) || Returns x rounded to the nearest whole number.
 +
|-
 +
| align="center" | trunc(x,n) || Returns x truncated to n decimal places.
 
|-
 
|-
 
| rowspan="6" | '''Trigonometric Functions'''
 
| rowspan="6" | '''Trigonometric Functions'''
Line 1,604: Line 1,986:
 
</blockquote>
 
</blockquote>
  
<br />
+
The order of operator precedence is summarized as follows, from top to bottom:  
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>(&nbsp;&nbsp;)</tt>
 
|-
 
| align="center" | <tt>!</tt>
 
|-
 
| align="center" | <tt>^</tt>
 
|-
 
| align="center" | <tt>*&nbsp;&nbsp;/</tt> || Left to right
 
|-
 
| align="center" | <tt>+&nbsp;&nbsp;-</tt> || Left to right
 
|-
 
| align="center" | <tt><nowiki>|</nowiki>&nbsp;&nbsp;&</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"
+
<div style="margin-left: 20pt;"><table style="background:#f9f9f9; border-spacing:0px; border-collapse:collapse;">
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction
+
<tr><td style="text-align:left; padding-right:20pt"><b>(&nbsp;&nbsp;&nbsp;)</b></td><td>&nbsp;</td></tr>
| style="background: #ecfeea; color: black; border: 1px solid black" | '''Math(Expression to evaluate)'''
+
<tr><td style="text-align:left; padding-right:20pt"><b>&nbsp;&nbsp;!</b></td><td>&nbsp;</td></tr>
|- valign="top"
+
<tr><td style="text-align:left; padding-right:20pt"><b>&nbsp;&nbsp;^</b></td><td>&nbsp;</td></tr>
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples
+
<tr><td style="text-align:left; padding-right:20pt"><b>*&nbsp;&nbsp;&nbsp;/</b></td><td>Left to right</td></tr>
|style="background: #ecfeea; color: black; border: 1px solid black" | '''math(10 + 4)'''<br>''Returns 14.''
+
<tr><td style="text-align:left; padding-right:20pt"><b>+&nbsp;&nbsp;&nbsp;-</b></td><td>Left to right</td></tr>
 +
<tr><td style="text-align:left; padding-right:20pt"><b><nowiki>|</nowiki>&nbsp;&nbsp;&nbsp;&amp;</b></td><td>Left to right</td></tr>
 +
</table></div>
  
<br />'''math(10 + 2 * 25)'''<br />
+
Variables may be assigned and used by specifying a simple string of letters. Examples: <span style="font-family: Consolas, monospace;">math(val=2)</span> or <span style="font-family: Consolas, monospace;">math(x=pow(2,3))</span>.
''Returns 60, demonstrating that multiplication has higher precedence than addition.''
 
  
<br />'''math((10 + 2) * 25)'''<br />
+
Multiple equations may be specified, each separated by a semicolon.
''Returns 300, demonstrating that parenthesis grouping has higher precedence than multiplication.''
+
Expressions are evaluated left to right.
 +
The final value of the [[#Math|Math()]] function will be the result of the right-most equation. For example, the equation <span style="font-family: Consolas, monospace;">math(x=4; pow(2^x))</span> will output 16.
  
<br>'''listitem([filename (path)], math(listcount([filename (path)], \) - 1), \)'''<br>''
+
<b>Note</b>: Empty fields
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>
+
Fields used inside of [[#Math|Math()]] are expanded (interpolated) directly.
 +
Fields with empty values may produce incomplete [[#Math|Math()]] statements.
 +
For example, if the field [number plays] is empty, an <i>expression</i> such as <span style="font-family: Consolas, monospace;">math([number plays] + 2)</span> would be seen
 +
by [[#Math|Math()]] as <span style="font-family: Consolas, monospace;"> + 2</span>.
 +
This incomplete <i>expression</i> would produce a syntax error.  See the Additional Examples for more information.
  
====Note(...): Retrieve information from a note====
+
<b>Note</b>: Locales and Commas
{| 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 | Note()
 
| 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"
 
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction
 
| 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.''
+
Special care must be taken with the [[#Math|Math()]] function and locales that use <span style="font-family: Consolas, monospace;">,</span> (comma) as a decimal separator.
* '''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.''
+
Many Media Center fields and the return values from functions may contain comma as the decimal point.
* '''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.''
+
Your expressions will need to [[#Replace|Replace()]] these before passing the values to [[#Math|Math()]],
|- valign="top"
+
which always uses dot <span style="font-family: Consolas, monospace;">.</span> as the numeric decimal point.
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples
 
|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>
 
  
====Save(...): Saves a value to a global variable====
+
For example, the <i>expression</i> <span style="font-family: Consolas, monospace;">math(1,5 + 1,5)</span> will fail since [[#Math|Math()]] does not consider <span style="font-family: Consolas, monospace;">1,5</span> to be a valid number.
{| 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 | Save()
 
| style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | Saves a value into the specified global variable, and optionally outputs the value.  Once a global variable has been created using Save(), that variables value may now be used via the pseudo-field [''Variable''].
 
|- valign="top"
 
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction
 
| style="background: #ecfeea; color: black; border: 1px solid black" | '''Save(Value,Variable,Output value)'''
 
  
* Value ''The value to store into the variable.''
+
Fields that cause problems are any fields that produce floating-point values, such as any Date type field in raw format
* Variable ''The global variable in which to save a value.''
+
(e.g. <span style="font-family: Consolas, monospace;">[date,0]</span>, <span style="font-family: Consolas, monospace;">[last played,0]</span>, <span style="font-family: Consolas, monospace;">[date modified,0]</span>, and <span style="font-family: Consolas, monospace;">[date imported,0]</span>), or any textual field that contains
* Output value ''Optional, outputs Value after the save.''
+
floating-point values that will be used for various calculations (e.g. any of the Dynamic Range variants).
 +
Certain functions such as [[#Now|Now()]] and [[#ConvertTime|ConvertTime()]] also return localized floating-point values.
  
 +
Handling this problem is not difficult.
 +
Before passing any floating point number to [[#Math|Math()]], use [[#Replace|Replace()]] first.  See the examples below.
 
|- valign="top"
 
|- valign="top"
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples
+
! scope="row" style="background: #ecedf3; color: #111; " | Examples
|style="background: #ecfeea; color: black; border: 1px solid black" | '''save(Much Money, local_bank)'''<br />
+
|style="background: #f9f9f9; color: #111; " | <span style="font-family: Consolas, monospace;"><b><nowiki>math(10 + 4)</nowiki></b></span>
''Saves the value "Much Money" into the global variable "local_bank".''
+
<p style="margin-left:20pt;">Returns 14.</p>
 
+
<span style="font-family: Consolas, monospace;"><b><nowiki>math(10 + 2 * 25)</nowiki></b></span>
<br />'''save(More Money, My Bank, 1)'''
+
<p style="margin-left:20pt;">Returns 60, demonstrating that multiplication has higher precedence than addition.</p>
<br />''Saves "More Money" into "My Bank" and outputs "More Money".''
+
<span style="font-family: Consolas, monospace;"><b><nowiki>math((10 + 2) * 25)</nowiki></b></span>
 
+
<p style="margin-left:20pt;">Returns 300, demonstrating that parenthesis grouping has higher precedence than multiplication.</p>
<br />'''save(math([duration,0] / 60), durmins)if(compare([durmins], >, 5.0), Long Track, Short Track) '''
+
<span style="font-family: Consolas, monospace;"><b><nowiki>math(replace(now(), /,, .) - replace([last played,0], /,, .))</nowiki></b></span>
<br />''Saves the calculated duration in minutes into the variable durmins.  Subsequent expressions such as the if(compare()...) above may now use the pseudo-field [durmins] as a shorthand for load(durmins).''
+
<p style="margin-left:20pt;">The <span style="font-family: Consolas, monospace;">,</span> is replaced by a <span style="font-family: Consolas, monospace;">.</span> in the output of both [[#Now|Now()]] and in the raw field value <span style="font-family: Consolas, monospace;">[last played,0]</span>.
 +
Note that the comma must be escaped so that it is seen as an argument and not as an argument separator.</p>
 +
<span style="font-family: Consolas, monospace;"><b><nowiki>math(replace(now() - [last layed,0], /,, .))</nowiki></b></span>
 +
<p style="margin-left:20pt;">The same as the previous example, but is more efficient and simpler since it calls [[#Replace|Replace()]] just once on the entire string to be passed to [[#Math|Math()]].</p>
  
The following links demonstrate usage of global variables:
+
Additional Examples
* [http://yabb.jriver.com/interact/index.php?topic=77826.0 Generating Statistics]
 
* [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]
 
  
 +
:[http://yabb.jriver.com/interact/index.php?topic=58110.0 An explanation and some solutions for fields that evaluate to empty within Math().]
 
|}
 
|}
 
<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)====
+
====Size(&hellip;): Returns a file's size in a format specific to the media type====
{| 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 | 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, 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"
 
! 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)'''
 
  
* 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.
+
{| style="width: 100%; border: 2px solid black;" align="top" cellpadding="3"
* Tag blocks that can be queried from within jpg files are:
+
|- id="Size" valign="top"
** EXIF
+
! scope="row" style="background: #ecedf3; color: #111; " width=100 | Description
** XMP
+
| style="background: #f9f9f9; color: #111; " width=1200 | <span style="font-family: Consolas, monospace; color:#0f3f8d; font-size:110%"><b>size(</b><b>)</b></span>
** IPTC
+
The [[#Size|Size()]] function returns media size information specific to the particular media type.
** MJMD
+
It is used to populate the Library fields <span style="font-family: Consolas, monospace;">duration</span> and <span style="font-family: Consolas, monospace;">dimensions</span> with their values.
|- valign="top"
+
Either the field or [[#Size|Size()]] can be used.
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples
 
|style="background: #ecfeea; color: black; border: 1px solid black" | '''tag(artist)'''<br>''This will return the artist information from a file if that file contains the artist tag''
 
  
<br>'''tag(Gapless Header)''' or '''tag(Gapless Footer)'''<br>''These two expressions allow gapless information to be queried from mp3 files.''
+
Type of information reported by size for the file's media type:
  
<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="margin-left: 20pt;"><table style="background:#f9f9f9; border-spacing:0px; border-collapse:collapse;">
 +
<tr><td style="text-align:left; padding-right:20pt">Audio</td><td>Duration</td></tr>
 +
<tr><td style="text-align:left; padding-right:20pt">Video</td><td>Duration</td></tr>
 +
<tr><td style="text-align:left; padding-right:20pt">Image</td><td>Dimensions</td></tr>
 +
<tr><td style="text-align:left; padding-right:20pt">Data</td><td>No information returned.</td></tr>
 +
</table></div>
 +
|- valign="top"
 +
! scope="row" style="background: #ecedf3; color: #111; " | Examples
 +
|style="background: #f9f9f9; color: #111; " | <span style="font-family: Consolas, monospace;"><b><nowiki>size()</nowiki></b></span>
 +
<p style="margin-left:20pt;">Returns values such as <span style="font-family: Consolas, monospace;">400x225</span> for images, or <span style="font-family: Consolas, monospace;">3:09</span> for audio files.</p>
 
|}
 
|}
 
<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====
+
====TrackNumber(&hellip;): Returns a file's track # 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 | TVInfo()
 
| style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | Used to retieve and display specified televison information for a file.
 
|- valign="top"
 
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction
 
| style="background: #ecfeea; color: black; border: 1px solid black" | '''TVInfo(Information to retrieve)'''
 
'''Information to retrieve''': ''The options available for use here are:''
 
 
 
* '''IsProgram''': ''Tests whether the file is a 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)''
 
* '''Channel''': ''Returns the channel name, given a channel number.''
 
* '''ChannelKeywords''': ''Returns channel keywords.''
 
* '''Date''': ''Returns the date of the program.''
 
* '''DateNoTime''': ''Same as Date display, but without the time.''
 
* '''NameDisplay''': ''Returns the name.''
 
* '''NameDisplayWithDate''': ''Returns the name + date.''
 
* '''Record''': ''Returns 1 if the program is schedule to be recorded, 0 if not.''
 
* '''RecordMark''': ''Outputs a red dot if the program is schedule to be recorded.''
 
* '''SeriesDisplay''': ''Returns Series if defined, otherwise Name.''
 
* '''SeasonDisplay''': ''Returns the season.''
 
* '''SeasonEpisode''': ''Returns the season and episode formated as #.#.''
 
* '''TimeDisplay''': ''Shows the start time of a program using the system time format, but uses "Showing" if the program is on now.''
 
* '''TimeDisplayNoOnNow''': ''Shows the start time of a program using the system time format, without special handling for programs on now.''
 
* '''SizeDisplay''': ''Returns the duration, formatted nicely for a television program.''
 
* '''WatchedDisplay''': ''Watched information, like no, yes, 80%, etc.''
 
  
 +
{| style="width: 100%; border: 2px solid black;" align="top" cellpadding="3"
 +
|- id="TrackNumber" valign="top"
 +
! scope="row" style="background: #ecedf3; color: #111; " width=100 | Description
 +
| style="background: #f9f9f9; color: #111; " width=1200 | <span style="font-family: Consolas, monospace; color:#0f3f8d; font-size:110%"><b>tracknumber(</b><b>)</b></span>
 +
The [[#TrackNumber|TrackNumber()]] function returns a file's track #, or 0 if the no value exists.
 +
It is used to populate the Library field <span style="font-family: Consolas, monospace;">track #</span> with its value.
 +
Either the field or [[#TrackNumber|TrackNumber()]] can be used.
 
|- valign="top"
 
|- valign="top"
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples
+
! scope="row" style="background: #ecedf3; color: #111; " | Examples
|style="background: #ecfeea; color: black; border: 1px solid black" | '''TVInfo(namedisplay)'''<br>Click on "<ins>T</ins>ools > 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.
+
|style="background: #f9f9f9; color: #111; " | <span style="font-family: Consolas, monospace;"><b><nowiki>tracknumber()</nowiki></b></span>
* TV programs use the field "Date Recorded" to store the program time.
+
<p style="margin-left:20pt;">Returns the value present in the <span style="font-family: Consolas, monospace;">track #</span> field.</p>
* The "Date" field is the original air / production date.
 
 
|}
 
|}
 
<div style="text-align:right;">([[#top|Back to top)]]</div>
 
<div style="text-align:right;">([[#top|Back to top)]]</div>
  
<br><br>
+
====TVInfo(&hellip;): Miscellaneous television and other preformatted information====
 
 
===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====
 
{| 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 | 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.
 
  
'''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.
+
{| style="width: 100%; border: 2px solid black;" align="top" cellpadding="3"
|- valign="top"
+
|- id="TVInfo" valign="top"
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction
+
! scope="row" style="background: #ecedf3; color: #111; " width=100 | Description
| style="background: #ecfeea; color: black; border: 1px solid black" | '''Field(Field name to retrieve)'''
+
| style="background: #f9f9f9; color: #111; " width=1200 | <span style="font-family: Consolas, monospace; color:#0f3f8d; font-size:110%"><b>tvinfo(</b><i>type</i><b>)</b></span>
|- valign="top"
+
The [[#TVInfo|TVInfo()]] function is multi-purpose, and returns a specific <i>type</i> of information about television recordings, programs,
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples
+
and preformatted informational strings for use in captions, thumbnails, grouping, etc.
|style="background: #ecfeea; color: black; border: 1px solid black" | '''field(duration)'''<br>''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.
 
|}
 
<div style="text-align:right;">([[#top|Back to top)]]</div>
 
====AlbumKey(...): Returns a unique album key for a file====
 
{| 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 | AlbumKey()
 
| style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | 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&nbsp;artist&nbsp;(auto)] and [album] data, their respective AlbumKey() will not be unique.
 
|- valign="top"
 
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction
 
| style="background: #ecfeea; color: black; border: 1px solid black" | '''AlbumKey()'''
 
|- valign="top"
 
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples
 
|style="background: #ecfeea; color: black; border: 1px solid black" | '''AlbumKey()'''<br>''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.
 
|}
 
<div style="text-align:right;">([[#top|Back to top)]]</div>
 
====AlbumArtist(...): Returns the calculated album artist for a file====
 
{| 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 | AlbumArtist()
 
| style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | This function simply returns the "'''[album artist (auto)]'''" data for each file.
 
|- valign="top"
 
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction
 
| style="background: #ecfeea; color: black; border: 1px solid black" | '''AlbumArtist()'''
 
|- valign="top"
 
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples
 
|style="background: #ecfeea; color: black; border: 1px solid black" | '''AlbumArtist()'''<br>''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.
 
|}
 
<div style="text-align:right;">([[#top|Back to top)]]</div>
 
====AlbumType(...): Returns the album type for a file====
 
{| 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 | 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 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"
 
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction
 
| style="background: #ecfeea; color: black; border: 1px solid black" | '''AlbumType()'''
 
|- valign="top"
 
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples
 
|style="background: #ecfeea; color: black; border: 1px solid black" | '''AlbumType()'''<br>''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.
 
|}
 
<div style="text-align:right;">([[#top|Back to top)]]</div>
 
====Size(...): Returns the size of a file in a media type independent 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 | Size()
 
| style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | Dependent on media type, this function returns the following information:
 
  
* Audio: ''Duration''
+
Available <i>type</i> values:
* Video: ''Duration''
 
* Image: ''Dimensions''
 
* Data: ''No information returned.''
 
  
 +
<div style="margin-left: 20pt;"><table style="background:#f9f9f9; border-spacing:0px; border-collapse:collapse;">
 +
<tr><td style="text-align:left; padding-right:20pt"><b>IsProgram</b></td><td>Returns 1 if the file is a program, 0 otherwise</td></tr>
 +
<tr><td style="text-align:left; padding-right:20pt"><b>IsGuideProgram</b></td><td>Returns 1 if the file is a guide program, 0 otherwise</td></tr>
 +
<tr><td style="text-align:left; padding-right:20pt"><b>IsRecordedProgram</b></td><td>Returns 1 if the file is a recorded program, 0 otherwise</td></tr>
 +
<tr><td style="text-align:left; padding-right:20pt"><b>Channel</b></td><td>Returns Returns the channel name, given a channel number</td></tr>
 +
<tr><td style="text-align:left; padding-right:20pt"><b>ChannelKeywords</b></td><td>Returns channel keywords</td></tr>
 +
<tr><td style="text-align:left; padding-right:20pt"><b>Date</b></td><td>Returns a program's date</td></tr>
 +
<tr><td style="text-align:left; padding-right:20pt"><b>DateNoTime</b></td><td>Same as Date, but without the time.</td></tr>
 +
<tr><td style="text-align:left; padding-right:20pt"><b>NameDisplay</b></td><td>Returns [name]: [series] or just [name]</td></tr>
 +
<tr><td style="text-align:left; padding-right:20pt"><b>NameDisplayWithDate</b></td><td>NameDisplay + ([year])</td></tr>
 +
<tr><td style="text-align:left; padding-right:20pt"><b>Record</b></td><td>Returns 1 if the program is scheduled to be recorded, 0 otherwise</td></tr>
 +
<tr><td style="text-align:left; padding-right:20pt"><b>RecordMark</b></td><td>Returns a red dot if the program is schedule to be recorded.</td></tr>
 +
<tr><td style="text-align:left; padding-right:20pt"><b>SeriesDisplay</b></td><td>Returns [series] or [name]</td></tr>
 +
<tr><td style="text-align:left; padding-right:20pt"><b>SeasonDisplay</b></td><td>Returns [season]</td></tr>
 +
<tr><td style="text-align:left; padding-right:20pt"><b>SeasonEpisode</b></td><td>Returns [season].[episode]</td></tr>
 +
<tr><td style="text-align:left; padding-right:20pt"><b>TimeDisplay</b></td><td>Returns program start time (system time format), or "Showing" if program on now</td></tr>
 +
<tr><td style="text-align:left; padding-right:20pt"><b>TimeDisplayNoOnNow</b></td><td>TimeDisplay without on now handling</td></tr>
 +
<tr><td style="text-align:left; padding-right:20pt"><b>SizeDisplay</b></td><td>Returns [duration] ([file size]) or [dimensions] ([file size])</td></tr>
 +
<tr><td style="text-align:left; padding-right:20pt"><b>WatchedDisplay</b></td><td>Returns Watched() information, such as No, Yes, 80%, etc.</td></tr>
 +
</table></div>
 
|- valign="top"
 
|- valign="top"
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction
+
! scope="row" style="background: #ecedf3; color: #111; " | Examples
| style="background: #ecfeea; color: black; border: 1px solid black" | '''Size()'''
+
|style="background: #f9f9f9; color: #111; " | <span style="font-family: Consolas, monospace;"><b><nowiki>tvinfo(namedisplay)</nowiki></b></span>
|- valign="top"
+
<p style="margin-left:20pt;">Returns formatted name and series output. If the file has no <span style="font-family: Consolas, monospace;">[series]</span> value, only <span style="font-family: Consolas, monospace;">[name]</span> is output.</p>
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples
 
|style="background: #ecfeea; color: black; border: 1px solid black" | '''Size()'''<br>''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.
 
|}
 
<div style="text-align:right;">([[#top|Back to top)]]</div>
 
====TrackNumber(...): Returns the track # of a file====
 
{| 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 | TrackNumber()
 
| style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | This function simply returns the track # of a file. If a file has no track # assigned, the function returns zero.<br>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.
 
|- valign="top"
 
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction
 
| style="background: #ecfeea; color: black; border: 1px solid black" | '''TrackNumber()'''
 
|- valign="top"
 
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples
 
|style="background: #ecfeea; color: black; border: 1px solid black" | '''TrackNumber()'''<br>''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.
 
 
|}
 
|}
 
<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 16:38, 21 August 2013

Contents

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:

Pressing "Enter" copies the Date data into the caption field
Just like that!

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]
Used in a pane, formatdate([date,0],MMMM) returns the months as requested, but the alphabetic order is a little confusing.
Adding the "month" data type, like so, formatdate([date,0],MMMM)&datatype=[month], takes care of the order.
   
No data type has been specified, so the expression results are presented literally, as individual string values.
Add the "list" data type to the expression and it is then formatted correctly in the pane. Here, the ListBuild function has been used to create a nested browsing tree.

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

Accessing and Storing Functions

The functions in this section access field values, store and load global variables, access file tags, and access note fields.

Field(…): Returns a field's value

Description field(name, mode)

The Field() function returns the value stored in field name. The format of return is selected by mode.

Available mode values:

0Raw, unformatted data
1Formatted data

Argument mode is optional (defaults to 1).

Examples field(album)

Returns the formatted value of field name album. Note that this is equivalent to [album].

field(date, 0)

Returns the raw, unformatted value stored in the date field. Note that this is equivalent to [date,0].

Load(…): Outputs the value of a global variable

Description load(varname)

Loads and outputs the value of the specified global variable varname that has been previously stored with Save().

Examples load(var1)

Loads and outputs the previous stored value of the global variable named var1. If var1 has not been previously stored, the output will be empty.

save(math(1 + 2), sum)load(sum)

Saves the output of the Math() function into sum, and then loads and outputs the value of sum, which is 3.

Note(…): Retrieve note fields

Description note(field label, field type, occurrence)

The Note() function retrieves information from a Media Center Note. Specifically, it returns the contents assosicated with a field label, of a given field type. The Nth occurrence may be requested. Notes data may be simple text, or associated with defined a field label. Currently the only type of field label is contact information. The first line of a Note is assosciated with the omnipresent field label Name.

The field type selects the specific sub-type for a given field label, and occurrence selects which instance of several field label / field type pairs is returned. The occurrence value is zero-based.

Argument field type is optional (defaults to FIRST AVAILABLE).

Argument occurrence is optional (defaults to 0).

Examples note(phone)

Returns the value found in the first Phone field label. If no Phone label exists, nothing is returned.

note(phone, home)

Returns the value found in the first Home field type from the Phone field label. If the Phone label, Home type does not exists, nothing is returned.

note(phone, home, 1)

Same as the previous example, but the second instance of the field type is selected instead of the first, since occrrence is zero-based.

Save(…): Saves a value to a global variable

Description save(value, variable, mode)

This Save() function saves the value into the specified global variable, and optionally will return that value if mode is set. Once a global variable has been created using Save(), that variable's value is available for use with either Load() or the pseudo-field "[variable]".

0Suppress output
1Output variables value

Argument mode is optional (defaults to 0).

Examples save(Much Money, local_bank)

Saves the value Much Money into the global variable local_bank.

save(More Money, My Bank, 1)

Saves More Money into My Bank and outputs the variables value More Money.

save(math([duration,0] / 60), durmins)if(compare([durmins], >, 5.0), Long Track, Short Track)

Saves the calculated duration in minutes into the variable durmins. Notice that subsequent expressions fragments such as the if(compare()...) may now use the pseudo-field [durmins] as shorthand for load(durmins).

Additional Examples

Generating statistics
Generating album track count
Generating album ratings
Highlighting playing album

SaveAdd(…): Adds to a global variable

Description saveadd(variable, value, mode)

The SaveAdd() function adds value to a global variable either numerically or as a list item. The mode argument indicates how variable is modified.

Available mode values:

0Add numeric value (integer or decimal) to variable
1Append string value as a list item to variable
2Prepend string value as a list item to variable

Argument mode is optional (defaults to 0).

Examples saveadd(v, 1)

Numerically increments the global variable v by 1.

saveadd(v, math(2 - 6))

Numerically increments the global variable v by the outcome of the Math(), which is -4.

load(foo, v)saveadd(v, bar, 1)load(v)

Loads value foo into variable v, then appends the value bar as a list item, and the final load(v) expression outputs the result of foo; bar.

load(That, v)saveadd(v, This, 2)load(v)

Similar to the previous example, but using the prepend mode, resulting in the output This; That.

Tag(…): Returns a file's physical tag

Description tag(tag name)

The Tag() function reads and returns the value of tag name directly from a file. The Media Center Library database is not used with Tag(), and instead the specified file is read for the requested tag. The spelling and letter case of the tag name must match exactly those stored in the file. Performance note: This function must open and read the actual file, so its performance is significantly slower than other functions which operate on database fields.

Examples tag(My Personal Tag)

This will return the value from the tag named My Personal Tag from file referenced by the [filename] field.

tag(Gapless Header)

Returns the Gapless Header tag value, often contained in an mp3 file.

Examxple: tag(exif: Date) Returns the raw date data from the EXIF data saved inside a jpg file.

Conditional Functions

The functions in this section test one or more arguments to produce either a true or false outcome, and execute specific actions depending upon that result.

The expression language does not directly support AND, OR, and XOR operations. However, these can be easily emulated using any of several techniques. See: Database_Expressions_AND_OR_And_XOR.

The NOT operator ! (exclamation point) may be used in a conditional to invert the sense of the conditional test. Inverting the sense of a test can make reading expressions easier, or support better IfElse() sequences.

If(…): Conditional if-else evaluator

Description if(test expression, true expression, false expression)

The If() function is used to evaluate a test expression, and will output the result of the true expression or false expression, depending upon the evaluation result. The test expression is expected to return a 0 (false value) or a non-zero (true value). Nesting is allowed. If the test expression is preceded by the NOT operator (!, an exclamation point), the sense of the test is inverted. Non-zero values are inverted to 0, and 0 is inverted to 1.

Examples if(isequal([artist], bob dylan, 1), Genius, Mediocre)

Outputs Genius when artist is (case insensitive) Bob Dylan and Mediocre otherwise.

if(isequal([artist], bob dylan, 1), Genius, if(isequal([album], Joshua Tree, 8), Great Album, Mediocre))

This nested If() expression expands on the previous example, by first evaluating if the artist is Bob Dylan, and outputs Genius if true. When the artist is not Bob Dylan, the album is then tested to see if it is Joshua Tree, and if so outputs Great Album, otherwise outputs Mediocre.

if(!isempty([comment]), regex([comment], /#^(\\S+\\s+\\S+\\s+\\S+)#/, 1), *No Comment)

Output's the first three words of the comment field; otherwise, outputs *No Comment. By using the NOT operator, the sense of the conditional is inverted so that the more interesting case is moved ahead of the more mundane case.

IfElse(…): Conditional if-elseif evaluator

Description ifelse(test1, action1, test2, action2, test3, action3, )

The IfElse() conditional provides a convenient mechanism for shortening and more clearly expressing nested conditionals into an alternating sequence of tests and actions. One or more test/action pairs may be specified.

For example, consider a nested sequence of If() tests such as the following pseudo-code:

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, converting the clumsy expression:

if(test1, action1, if(test2, action2, if(test3, action3)))

into the more elegant:

ifelse(test1, action1, test2, action2, test3, action3)

If any of the test expressions test1, etc. are preceded by the NOT operator (!, an exclamation point), the sense of that test is inverted. Non-zero values are inverted to 0, and 0 is inverted to 1.

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

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.

FirstNotEmpty(…): Returns the first non-empty argument

Description firstnotempty(value1, value2, )

The FirstNotEmpty() function acts as a conditional by returning the first argument from value1, value2, ... that is not empty. Two or more arguments may be used, and the first non-empty argument is returned. With two arguments, is is functionally equivalent to the sequence such as "if(!isempty(value1), value1, value2)". With more than two arguments, FirstNotEmpty() avoids long nested If() sequences that simply test for emptiness.

Examples firstnotempty([media sub type], Misc Video)

Returns the value in media sub type if it is not empty, otherwise returns Music Video.

firstnotempty([series], [name], Tag your Videos!)

Returns the first non-empty value from the fields series or name, and if both are empty, returns the reminder to Tag your Videos!.

Test and Comparison Functions

The functions in this section return a Boolean value of either 1 (true) or 0 (false). They are generally used to drive an action specified in one of the Conditional Functions.

Compare(…): Compares two numbers

Description compare(value1, operator, value2)

The Compare() function compares two numeric values value1 and value2 using the specified operator.

Available operator values:

=Equivalence
<Less than
<=Less than or equal to
>Greater than
>=Greater than or equal to

Outputs 1 if the comparison is true, and 0 otherwise.

Examples compare([bitrate], <, 320)

Returns 1 when the bitrate is less than 320 (Kbps), and 0 otherwise.

if(compare(math(now() - [date modified, 0]), >, 21), Expired, formatdate([date modified, 0], elapsed))

Outputs the age of files under 21 days old, or Expired for older files.

IsEqual(…): Compares two values in one of nine specified modes

Description isequal(value1, value2, mode)

The IsEqual() function compares value1 with value2 using any mode from the list of modes below. Outputs 1 when the comparison succeeds according to the mode, and 0 otherwise. Although the mode is specified as the last argument, the comparison should be mentally read as: value1 mode value2.

Available mode values:

0Case-sensitive string compare for equality
1Case-insensitive string compare for equality
2Numeric compare for equality
3Numeric less than
4Numeric less than or equal to
5Numeric greater than
6Numeric greater than or equal to
7Substring search (case sensitive)
8Substring search (case insensitive)

Argument mode is optional (defaults to 0).

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.

if(isequal([artist], [album], 1), Eponymous, [album])

The If() function basis its decision on the outcome of IsEqual(), so if the artist and album values are the same, the output will be Eponymous, otherwise, the output will be the value of album.

if(isequal([artist], [album], 1), Eponymous/,, [album]/))

This example demonstrates the character escaping mentioned in the overview earlier. Here, we want the output to be either Eponymous, (note the inclusion of the comma) or the album value with a closing parenthesis. In order to achieve this, the comma, and the closing parenthesis, are escaped using a forward-slash character. This informs the expression evaluator that these characters are not part of the expression syntax and are to be treated literally.

if(isequal([filename (path)], classical, 8), Classical, Not Classical)

Because compare mode 8 has been specified, if the word classical appears anywhere in the case-insensitive file path, the expression will return Classical, and if not it will return Not Classical.

IsEmpty(…): Tests a value for emptiness

Description isempty(value, mode)

The IsEmpty() function tests the given value for emptiness. The value passed is typically an Media Center field, so that some action may be taken when the field is or is not empty. Returns 1 when the value is empty, otherwise 0.

Available mode values:

0String test (field must be empty to get a positive result)
1Numerical test (field must be empty, or contain 0 to get a positive result)

Note that Media Center does not discriminate between a 0 value and an empty value for fields of type Integer and Decimal - both 0 and empty are considered equivalent for these field types. This is useful for fields such as the integer field Disc #, where an empty or 0 value implies that Disc # contains no useful data, and should be generally ignored or absent in display output.

Pay particular attention to the third example offered below, as it covers a caveat that comes with this particular function.

Argument mode is optional (defaults to 0).

Examples isempty([comment], 0)

If the comment field is empty, IsEmpty() returns 1, otherwise 0.

isempty([track #], 1)

Performs a numerical test for data in the [track #] field. If the field is empty or 0, a 1 is returned, otherwise 0 is returned.

ifelse(!isempty([disc #]), [disc #])

Outputs the value of the disc # field when it is not empty.

IsRange(…): Tests a value for inclusion within a given range

Description isrange(value, range)

The IsRange() function tests if a value falls within a given range of values. If the value falls within the given range, 1 is returned, otherwise 0 is returned.

A range is specified in the form of low-high, where low and high are either letters or numbers. The lowest value comes first, the highest second. Both low and high must be the same kind (letters or numbers). The low and high values are inclusive.

Example Ranges:

1-100
a-z
c-d
23-7542
Examples isrange([artist], a-c)

Artist values of Abba or Blondie will result in a 1, but ZZ Top will return a 0.

if(isrange([bitrate], 96-191), Poor Quality, High Quality)

Returns Poor Quality for any file whose bitrate falls in the range of 96 to 191, and returns High Quality for all bitrates.

Additional Examples

Using IsRange() in a Search List.

IsMissing(…): Tests to see if a file exists on the system

Description ismissing(filepath)

The IsMissing() function tests for the existence of a file in the file system. If the file is missing, the function returns 1, otherwise 0 is returned if the file exists. This function is useful for checking for missing files in a Library. 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: Any view or list that uses IsMissing() will be slow, is Media Center must interogate each referenced file in the file system. The larger the number of files being queried, the longer it will take to produce results. Use IsMissing() with care.

Argument filepath is optional (defaults to [filename]).

Examples ismissing()

If the referenced file was not found in the file system, 1 is returned; othewise 0 is returned.

ismissing(C:\Music\My Lost File.mp3)

Checks for My Lost File.mp3 and returns 1 (positive) if the file does not exist, and 0 (negative) if the file does exist.

if(ismissing(), File is missing, File exists)

Outputs File is missing or File Exists depending on the result returned by IsMissing().

[=ismissing([filename])]=1

This example demonstrates how to construct an expression for use as a Media Center search query. 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 all files in library exist, this list will 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 not missing any files.

IsRemovable(…): Tests to see if a file is stored on removable media

Description isremovable(filepath)

The IsRemovable() function tests if a file resides on removable media and if so, returns 1, and if not, returns 0. The Media Center field [Removable] also provides the same value for a given file.

Argument filepath is optional (defaults to [filename]).

Examples isremovable()

Checks if the current file is on removable storage, and if so, returns 1, otherwise returns 0.

IsInPlayingNow(…): Tests to see if a file is in the Playing Now playlist

Description isinplayingnow(filepath)

The IsInPlayingNow() function tests if a file is in any zone's Playing Now list. Used as an expression category, pane or file list column allows distinguishing files that are in the Playing Now list.

Argument filepath is optional (defaults to [filename]).

Examples isinplayingnow()

If the file in the Playing Now list, returns 1, otherwise returns 0.

if(isinplayingnow(), Queued, Not queued)

If the file in the Playing Now list, returns Queued, otherwise Not queued.

Additional Examples

How to use IsPlaying() and IsInPlayingNow()

IsPlaying(…): Tests to see if a file is in currently being played

Description isplaying(filepath)

The IsPlaying() function tests if a file is playing in any zone. Used as an expression category, pane or file list column allows distinguishing files that are playing now.

Argument filepath is optional (defaults to [filename]).

Examples IfElse(IsPlaying(), <font color="ff0000">♪<//font>, IsInPlayingNow(), ♪)

This expression in a file list expression column shows which files are in the Playing Now list and which are currently playing by outputing a musical note in the column. The musical note will be displayed in red for any currently playing file.

Additional Examples

How to use IsPlaying() and IsInPlayingNow()
How to play an artist's full work when a genre is shuffling?

Formatting Functions

The functions in this section format their arguments in specific ways. Some functions are used for formatting values for better presentation, or according to some format, while other functions work on Media Center internal "raw" data to convert to user-friendly formats.

Certain Media Center fields are used to store values in ways that are internally convenient or effecient. But these field values are not terribly useful or meaningful when used directly.

For example, the Duration field holds values as a number seconds of length, while various Date/Time fields such as Date or Last Played store values as floating point numbers specifying a number of days and fractions of a day since a particular epoch time.

Media Center will generally format fields using the "display" format where necessary, such as in panes, file list columns, or various tools such as the Rename, Move & Copy tool. When a function requires a raw field value, or you want to access a raw field value, by sure to use the raw field format. This is done by appending a ,0 to the field's name inside the brackets, for example [Date Imported,0].

Delimit(…): Outputs a value with head/tail strings when value is non-empty

Description delimit(expression, tail, head)

The Delimit() function outputs the value of expression prepended with a head string and/or appended with a tail string, but only if the value of the expression is non-empty. Nothing is output when the expression evaluates to empty.

Argument tail is optional (defaults to SPACE).

Argument head is optional (defaults to EMPTY).

Examples delimit([Track #], .)

Appends a period after a track number if [Track #] is not empty, such as 12..

delimit([Date (year)], {, })

Outputs the year surrounded by curly braces, for example {2012}.

FormatBoolean(…): Formats a boolean (true / false) value in a specified manner

Description formatboolean(conditional, true string, false string)

The FormatBoolean() function outputs true string and false string values to represent the 0 or 1 Boolean output resulting from the conditional expression. When the conditional evalutes to 1, the true string will be output, otherwise the false string will be output.

Argument true string is optional (defaults to True).

Argument false string is optional (defaults to False).

Examples formatboolean(isempty([number plays]), Never Played, Has Been Played)

Returns Never Played when the expression IsEmpty() evaluates to 0, and Has Been Played when it evaluates to 1.

formatboolean(math([track #] % 2)

Outputs the default True label for odd track numbers, and the default False label for even ones.

FormatDuration(…): Presents a duration of seconds in a reader friendly format

Description formatduration(duration value)

The FormatDuration() function formats a duration value into a friendly format. The duration value argument is expected to be a value representing a number of seconds, typically used for media file duration. Media Center internally stores duration values in seconds.

Examples formatduration([duration,0])

Outputs a friendly display of the duration field. This is the same output shown using the Duration field in a file list.

formatduration(600)

This will output ten minutes in the format 10:00.

FormatFileSize(…): Presents a number of bytes in a reader friendly format

Description formatfilesize(bytes value)

The FormatFileSize() function formats a bytes value into a friendly format. The bytes value argument is expected to be a value representing a number of bytes, typically used for media file size. Media Center internally stores file size values in bytes. FormatFileSize() will convert those byte values into unitized friendly formats such as 50 bytes, 3.2 KB or 10.4 MB.

Examples formatfilesize([file size,0])

Outputs a friendly format of the file size field. This is the same output shown using the File Size field in a file list.

formatfilesize(56123456)

Outputs the bytes value 56,123,456 as 53.5 MB.

FormatNumber(…): Formats and rounds a number to a specified number of decimal places

Description formatnumber(value, decimal places, label zero, label plural, label singular)

The FormatNumber() function formats a numeric value to a specified number of decimal places, rounding its value, and optionally outputs value-dependent labels, which can be used to construct more gramatically-correct output. The value can be any numeric value. The decimal places argument specifies the number of digits to be used after the decimal point. Use -1 to output as many decimal places as available.

The label selected depends on the original value, not the resulting formatted value.

The label zero argument is output instead of a formatted value when the original value is 0. When this label is specified as empty, label plural is used. The label plural argument is appended to the formatted value when the original value is more than 1. The label singular argument is appended to the formatted value when the original value is equal to 1.

Note: FormatNumber() will not output additional zero's after the decimal point. In otherwords, FormatNumber() rounds fractional values, but does not zero fill.

Argument decimal places is optional (defaults to 0).

Argument label zero is optional (defaults to label plural).

Argument label plural is optional (defaults to 0).

Argument label singular is optional.

Examples formatnumber([duration,0], 2)

Returns a file's duration (which are in seconds) rounding to two decimal places.

formatnumber([number plays,0], 0, Unplayed, Plays, Play)

Outputs values in whole number formats (no decimals shown). When the number of plays is 0, the output will be Unplayed. When it is more than one, such as six, outputs 6 Plays. And when the number of plays is one, outputs 1 Play.

formatnumber([number plays,0], 0, , Plays, Play)

Same as the previous example, but uses the default value for label zero (which is label plural), so that when number of plays is zero, output is 0 Plays.

formatnumber([number plays,0], , , , Time)

In this example, only label singular argument is specified (as Time), so all other arguments use their defaults values. The output will be 0 when number of plays is zero, 1 Time when number of plays is one, and the actual number of plays for other values (e.g. 6).

FormatRange(…): Formats a value as a range

Description formatrange(value, range size, mode)

The FormatRange() function creates numerical or alphabetic groupings of size range size, and returns the grouping where value falls. Only the first character of value is considered and used. The range size is a numerical value specifying how wide the range should be. Numeric ranges are 0-based. The mode specifies the type of range grouping.

Available mode values:

0Automatically choose between number / letter grouping
1Letter grouping
2Number grouping

Argument range size is optional (defaults to 1).

Argument mode is optional (defaults to 0).

Examples formatrange([artist], 3, 1)

Outputs the range that the artist's first letter falls within. With a range size of 3 and using mode 1 (letter grouping), ranges will be produced in the form of a-c, d-f, g-i, etc.

formatrange([artist])

With range size and mode values left unspecified, default values are used, so automatic range groupings of size 1 are output. Hence, the first character of [artist] will be output.

formatrange([bitrate], 100, 2)

Numeric range groupings of size 100 will be output, for the value of [bitrate]. Possible outputs are: 0-99, 100-199, 200-299, etc.

Additional Examples

How to produce 1-based range values.

Orientation(…): Outputs the orientation of an image

Description orientation()

The Orientation() function outputs one of the following words indicating the orientation of an image file:

PortraitWhen height > width
LandscapeWhen width > height
PortraitWhen height = width
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

Description padnumber(value, number digits)

The PadNumber() function adds leading zeros to any given number value, producing a value of length number digits.

Examples padnumber([track #], 2)

This will pad the track number with leading zeros sufficient to ensure the output is minimally two digits in length.

padnumber(counter(), 4)

Outputs 4 digits of zero-padded numbers produced by Counter(). For example, 0001, 0002, 0003, etc.

RatingStars(…): Outputs the value of Rating as a number of star characters

Description ratingstars()

The RatingStars() function outputs the Rating field's value as the equivalent number of black star characters.

Examples ratingstars()

For a file that has a Rating of 4, outputs ★★★★.

Watched(…): Outputs a formatted video bookmark

Description watched(mode)

Outputs a video's bookmark position in a human-readable format, using a specified mode.

Available mode values:

0Output a human-readable watched status.
1Output a numeric watched value, 0 if not watched, 1 if partially watched, 2 if entirely watched.
2Output a watched checkmark ✓ if watched

Argument mode is optional (defaults to 0).

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 Functions

The functions in this section are used primarly to manipulate strings. Since the Media Center expression language is primarly string-oriented, these functions provide a means to manipulate field values or the output from other expressions.

Clean(…): Clean a string to be used for various operations

Description clean(string, mode)

The Clean() function is generally used to sanitize a string by stripping empty brackets, remove superfluous dash characters, eliminate leading or trailing articles, or replace filesystem-illegal characters. It is typically employed before some operation such as Rename to clean the product of joining various fields, some of which may be empty, or to produce filesystem-safe filenames. It may be used for a variety of purposes, however.

Available mode values:

0Removes empty () and [], superfluous dash (-) and whitespace characters and sometimes comma (be careful)
1Removes the article 'the' from the beginning and ', the' from the end
2Removes any article (a, an, the, etc.) from the beginning and end
3Replaces each filesystem-illegal character \ / : * ? " < > | with an underscore _, and replaces each unprintable character with a space

Argument mode is optional (defaults to 0).

Examples clean([album] - [date])

The concatenation of [Album] - [Date] may leave a dangling - string when date is empty. Clean() in the default mode removes this dangling string.

clean(The Beatles, 1)

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.

clean(AC//DC: Back In Black, 3)

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 would produce the filesystem-safe value of AC_DC_ Back In Black.

clean(\//:*?"<>|, 3)

This trivial example demonstrates how all filesystem-illegal characters are converted to underscores, producing the nine-character output _________ which consists entirely of underscores.

FixCase(…): Changes the case of a given string

Description fixcase(string, mode)

The FixCase() function will convert the supplied text string according to the specified mode.

Available mode values:

0Title Case
1All Words
2First Word
3All Uppercase
4All Lowercase

Argument mode is optional (defaults to 0).

Examples fixcase(enjoy the silence)

The default mode 0 is used, so the output is Enjoy the Silence.

fixcase(enjoy the silence, 1)

Using mode 1, all words are uppercased, so the output is Enjoy The Silence.

fixcase(MY ALbUm IS cAlLeD: adam, 4)

Outputs my album is called: adam.

FixSpacing(…): Intelligently splits adjacent camel-cased words

Description fixspacing(string, mode)

The FixSpacing() function inserts spaces between adjacent camel-cased words in string. It is useful for helping to clean and convert metadata that favors compactness over standard sentence structure.

Available mode values:

0Disables conversion
1Enables camel-case conversion

Argument mode is optional (defaults to 1).

Examples fixspacing(OneWorld)

Outputs One World.

fixspacing([name], 1)

Outputs the name field with any camel-case converted into standard sentence structure. If the value of name was, MiracleOn34thStreet, the output would be Miracle On 34th Street.

fixspacing(Another [name])

Assuming the same [name] as above, this would return Another Miracle On 34th Street.

Hexify(…): Hexifies a string to make it suitable for web usage

Description hexify(string)

The Hexify() function URI encodes a string to make it useable by a browser or search engine. Hexify() is typically used by expressions generating or working on URLs in Media Center's Link Manager.

Examples hexify(Oasis - /(What's The Story/) Morning Glory?)

The result is Oasis%20-%20%28What%27s%20The%20Story%29%20Morning%20Glory%3F.

Left(…): Retrieves a specified number of characters from the left of a string

Description left(string, quantity)

The Left() function retrieves no more than quantity characters from the left of the string.

Examples left([filename], 3)

Return the Windows drive letter, colon and first back-slash from the filename.

Length(…): Returns the number of characters in a string

Description length(string)

The Length() function returns the number of characters contained in string.

Examples length(A Simple Plan)

Returns 13.

if(compare(length([filename]), >=, 68), Long, Short)

The length of the filename is calculated, and compared against 68, outputting Long when the length is greater than or equal to 68, and Short otherwise.

Mid(…): Retrieves specified characters from a string

Description mid(string, start position, quantity)

The Mid() function returns a specified quantity of characters from the start postion in string.

The start postion is 0-based (i.e. the first character is considered position 0). A quantify of -1 returns all characters from the start postion to the end of string.

Argument start position is optional (defaults to 0).

Argument quantity is optional (defaults to 1).

Examples mid(12345)

Returns 1, using is the default quantity (1) of characters from the default start position of (0 - the beginning of the string).

mid(12345, 1, 2)

Returns 2 characters begining at start position 1, which is 23.

Additional Examples

An example that uses Mid() to re-order a date field.
An example that uses Mid() to output a number of stars based on an arbitrary rating value.

Regex(…): Regular expression pattern matching and capture

Description regex(string, regexp, run mode, case sensitivity)

The Regex() function performs regular expression (RE) pattern matching on a string. The string is evaluated against the regular expression regexp, and run mode dictates the values output by Regex(). The three modes allow for match testing, capture output, or silent operation.

All match captures are placed into special variables referenced as [R1], [R2], ... [R9], which can be used in later in the expression. The contents of the captures [R1] ... [R9] are available until the end of the expression, or Regex() is run again, whereby they are replaced. The regular expression implementation used prior to Media Cener 19 is the Microsoft 2010 TR1 engine, and in Media Cener 19 it is the Boost engine.

Available run mode values:

0Runs in Boolean test mode, returning either a 1 or 0, indicating whether the string matched (1) or did not match (0) the regexp. This run mode is useful within an If() test, so that different true or false actions may be taken.
1 to 9Outputs the specified Nth capture group's contents, where N ranges from 1 to 9. Only a single capture is output in this mode, but all captures are available in the [R1] ... [R9] capture variables. This run mode is used to easily output a single matching sub-string.
-1Runs in silent mode, with no output being produced. This run mode is useful as a means to capture portions of the string to be later used in subsequent portions of an expression.

The case sensitivity argument toggles the case-sensitivity of regular expression matching. Note that 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).

Available case sensitivity values:

0Ignore case when matching (e.g. the letters E and e are identical)
1Consider case when matching (e.g. the letters E and e are considered different)

The regular expression language assigns special meaning to many characters. A few of these meta-characters, such as forward slash /, comma , and both ( and ) are also reserved and used by the Media Center expression language. To force the Media Center expression engine to ignore the meta-characters in regexp, surround the entire regular expression with /# #/. This is one of Media Center's escapements, which tells the expression engine to ignore everything inside, so that the entire, uninterpreted regexp can be provided to the Regex() regular expression evaluator. Although surrounding regexp by /# #/ is not necessary or required when no conflicting characters are in use, and you may manually escape the expression languages meta-characters with a forward slash /, it is probably a safe practice to always encase every regexp within /# #/.

Argument run mode is optional (defaults to 0).

Argument case sensitivity is optional (defaults to 0).

Examples ifelse(regex([name], /#^(the|an|a)\b#/, 0, 1), Fix your case!)

Searches the name field for any of the lowercase articles the, and and a at the beginning of name, and outputs Fix your case! when the match succeeds. The run mode is 0 which is a test and capture mode, and case sensitivity is enabled.

if(regex([artist], /#([[:punct:]])#/, 0), [R1] --> [Artist], No Punctuation)

Using the default mode 0, Regex() will output a Boolean for use inside a condtional to cause some action to occur based on the match success or failure. This example matches against the artist field looking for any punctuation character. If the match succeeds (a punctuation character was found), that character is output followed by the string --> and the artist. In there was no match, the string No Punctuation is output.

regex(D03T02 some track.mp3, /#^D(\d+)T(\d+)#/, 1)Disc: [R1], Track: [R2]

The string is matched against the regexp that is looking for a D followed by any number of digits, followed by a T and then more digits. Those digits were captured, and later used to output the value Disc: 03, Track: 02.

regex([filename (name)], /#^(\d+)-#/, -1)Track number is [R1]

Using run mode -1, the file's name is pattern tested against the regexp which is looking for leading digits followed by a dash. Those digits are captured in buffer [R1] which is used later in the expression. If the file name was 2-foo.mp3, the output would be Track number is 2.

regex([filename], /#(\d{1,2})\.(\d{1,2}).(\d{4})#/, -1)[R3]//[R1]//[R2]

Matches and captures a date formatted as dd.mm.yyyy anywhere within the filename, and rearranges it in a standard format of yyyy/mm/dd. Since run mode is -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 so that we get the desired year/month/day ordering, such as 2011/08/19.

RemoveCharacters(…): Removes a list of characters from a string

Description removecharacters(string, character list, mode)

The RemoveCharacters() function will remove from string any characters in the character list. The characters removed depend upon the mode specified. The function operates in a case-sensitive manner.

Available mode values:

0Remove all instances
1Remove from the beginning only
2Remove from the end only
3Remove from each end

Argument mode is optional (defaults to 0).

Examples removecharacters(Paper, Ppr)

Removes P, p, and r from Paper, resulting in ae. The default mode 0 is in effect, removing all instances of the characters specified in the character list.

removecharacters(Paper, Ppr, 1)

With mode 1 set, only the inital character P is removed, resulting in aper.

removecharacters(Paper, Ppr, 2)

In mode 2, only one character from the end of the string are removed, leaving "Pape.

removecharacters(Paper, Ppr, 3)

Both the front and back are affected in mode 3, causing the removal of the leading P and trailing r resulting in ape.

removecharacters([artist], /(/))

Removes any ( and ) characters from anywhere within the [artist] field.

RemoveLeft(…): Trims characters from the beginning of a string

Description removeleft(string, quantity)

The RemoveLeft() function removes a specified quantity of characters from the left side of a string. If the quantity is larger than the length of the string, the output will be empty.

Examples removeleft(Good Deeds, 5)

Removes the first 5 characters from resulting in Deeds being output.

RemoveRight(…): Trims characters from the end of a string

Description removeright(string, quantity)

The RemoveRight() function removes a specified quantity of characters from the right side of a string. If the quantity is larger than the length of the string, the output will be empty.

Examples removeright(03-02-1959,5)

Removes the last 5 characters from the given date, leaving only the month and year 03-02.

Replace(…): Replace or remove a string segment

Description replace(string, old, new)

The Replace() function replaces all instances of old within string with new. If new is unspecified, it defaults to an empty value, causing old to be removed. Replace() operates in a case-sensitive manner.

Argument new is optional (defaults to EMPTY).

Examples replace(The Daily Show with John Oliver, hn Oliver, n Stewart)

Now that John Oliver has completed his summer stand-in for Jon Stewart, it is time for a replacement. The old sequence hn Oliver will be replaced with the new sequence n Stewart, resulting in The Daily Show with Jon Stewart.

replace(Sample String, s, Replaced)

In this example, the original string does not contain the old value s anywhere, so no replacement occurs and the original string is returned.

replace(Led Zeppelin.[remastered], .[remastered])

Removes the trailing old value .[remastered] from the original string, resulting in Led Zeppelin. Because no new string is specified, the default empty value is used as a replacement, effectively stripping the old value.

Right(…): Retrieves a specified number of characters from the right of a string

Examples right([filename], 3)

Returns the last three characters from the filename (typically this is the file's suffix).

List Manipulation

Media Center supports several different types of fields, one of them being the List type. A List type is a library field of type List, or an expression coerced into a list type.

The functions in this section provide the ability to manipulate lists and list items. A list is a sequence of strings, each separated from one another by an arbitrary delimiter. The default delimiter is a semicolon. Media Center does not make a strict distinction between a string and a list of strings. In fact, a list is just a string, and it is safe to think of a string as a list with zero or more arbitrary delimiter sequences. For example, the string "2013-08-17" can be thought of as a dash-delimited list with the three items "2013", "08" and "17".

This weak typing is very useful since a list, for example, "John; Sally" that contains the two items "John" and "Sally" can be manipulated not only using the list functions in this section, but because it is just a string, it can also be manipulated with string functions. For example, taking the same list above and combining it with the string "; Joe" adds a new item to the list "John; Sally; Joe", and removing the first 6 characters with RemoveLeft() would produce a now shortened string/list "Sally; Joe". The list manipulation functions make this job easier, especially when using the default semicolon delimiter. Furthermore, since any character or sequence of characters can be considered as a list delimiter, any string can be treated as a list, and the functions in this section can be used on any string as needed.

In some areas such as a panes column, or a category view, Media Center gives special treatment to List types. For example, using semicolon as the delimiter, a List will be automatically split apart into its individual items.

ListBuild(…): Constructs a list from a series of items

Description listbuild(mode, delimiter, item1, item2, )

The ListBuild() function constructs a list from item1, item2, ... using a supplied delimter to separate the individual items in the resulting list. The construction mode affects how empty items are handled - they can be included or excluded. The mode typically used exclude empty items, so that lists do not contain empty slots. However, there are occasions when retaining empty slots is useful, such as when using a list to act like an array where data is stored in particular slots so that the ListItem() function may later retrieve values at a given index. It can also be useful when calculating several expressions and combining the results into a single list for presentation; by including all items, items can be made to line-up for visual inspection in a column.

Available mode values:

0Include empty values
1Exclude empty values

The delimiter argument specifies the character or character sequence to be inserted in between items in the list. An unspecified delimiter will result in a delimiterless concatenation of the supplied arguments item1, item2, etc.

Argument delimiter is optional (defaults to EMPTY).

Examples listbuild(1, ;, Bennie, June)

Returns a standard semicolon-separated list containing two items Bennie; June.

listbuild(1, \, [album artist (auto)], [album])

Builds a backslash-separated list combining the two fields album artist (auto) and album. This is useful for building panes column or categories hierarchies in a view.

ListClean(…): Various list operations

Description listclean(list, mode, delimiter)

The ListClean() function performs one of the operations specified by mode on the given list. The specified delimiter separates list items.

1Remove duplicates
2Reverse the order of items

Argument delimiter is optional (defaults to SEMICOLON).

Examples listclean(c;b;c;a, 1)

Removes duplicates from the list, returning c;b;a.

listclean(d;c;b;a, 2)

Reverses the list items, returning a;b;c;d.

listclean(\a\x\x\x\z, 1, \)

Removes duplicates from a backslash-separated list, returning \a\x\z.

ListCombine(…): Combines two delimited lists into a single delimited list

Description listcombine(list1, list2, input delimiter, output delimiter, mode)

The ListCombine() function returns a single list after performing the operation specified by mode on the two lists list1 and list2. An input delimiter and an output delimiter may be specified. The input delimiter is effective for both list1 and list2, and the output delimiter will be used in the returned list, replacing the input delimiter from both list1 and list2.

Available mode values:

0Combine lists removing duplicates (order is preserved).
1Output only items contained in both lists (order is preserved).

Argument input delimiter is optional (defaults to SEMICOLON).

Argument output delimiter is optional (defaults to SEMICOLON).

Argument mode is optional (defaults to 0).

Examples listcombine(a;b;e, a;b;c;d)

Returns a;b;e;c;d. This example uses the default mode 0 to combine list1 with list2, preserving the order of items. The default ; input delimiter and output delimiter is used.

listcombine(a;b;e, a;b;c;d, ;, ;, 1)

Returns a;b. The input delimiter and output delimiter are both specified as ;, and mode 1 is used to produce a list of only items that exist in both list1 and list2.

listcombine(a-c, c-f, -, ..., 0)

Returns a...c...f. The input delimiter is -, while the output delimter is ..., and mode 0 combines both lists.

listcombine(a#@#c, c#@#f, #@#, ., 0)

Returns a.c.f. This example demonstrates how to combine two lists with duplicates removed while replacing a multi-character input delimiter #@# with a single-character output delimiter ..

listcombine([people], [places])&datatype=[list]

The result here would be a single, semicolon delimited list containing all the list items from the [people] and [places] fields. For example, if [people] contains Family\Mum; Family\Dad; Family\Gran, and [places] contains UK\Scotland\Edinburgh; UK\Scotland\Edinburgh\Edinburgh Castle, the output list would be Family\Mum; Family\Dad; Family\Gran; UK\Scotland\Edinburgh; UK\Scotland\Edinburgh\Edinburgh Castle. Using the &datatype=[list] cast makes the expression split individual list items in a panes or categories view.

ListCount(…): Returns the number of items in a list

Description listcount(list, delimiter)

The ListCount() function returns the number of items that exist in a list delimited by delimiter.

Argument delimiter is optional (defaults to SEMICOLON).

Examples listcount([keywords])

Returns the number of keywords for the file.

listcount([filename (path)], \)

Returns the number of the directories in a Windows drive-based file path. The example demonstrates that non-List type fields can be used with the functions in this section. While the delimiter specified here is \, an escaped forward slash // could be used when applicable.

ListItem(…): Returns an item from a location in a list

Description listitem(list, position, delimiter)

The ListItem() function returns the item from the specified position in the list. Items in a list are zero-based, so the first item in the list is located at postition 0. Nothing is returned with the position is outside the bounds of the list.

Argument delimiter is optional (defaults to SEMICOLON).

Examples listitem(a;b;c, 1)

Returns b, since postion 1 is the second item in the list a;b;c.

listitem(1:04:47, 2, :)

Using the delimiter :, returns item at position 2, which is the seconds value 47 from the time 1:04:47.

ListSort(…): Sort a list of values

Description listsort(list, mode, delimiter)

The ListSort() function sorts a list in the order according to mode, using the specified delimiter.

Available mode values:

0Ascending sort
1Descending sort

Argument mode is optional (defaults to 0).

Argument delimiter is optional (defaults to SEMICOLON).

Examples listsort(c;a;b)

Returns a;b;c, using the default ascending mode and (:) delimiter.

listsort(Joe Baxter/, Sally Henson/, Sue Smith, 1, /,)

Returns Sue Smith,Sally Henson,Joe Baxter. Note the requirement to escape the , characters within the list string and in the specified delimiter itself.

listsort([artist];[composer])

Sorts the combined artist and composer lists in ascending order. Note the simple manual construction of a single List by combining the two List type fields, and forcing a ; between the two.

Date and Time Functions

Media Center provides several functions for the conversion, formatting and generation of dates and times. Date and time for a Date-type field is stored internally as a single 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 in seconds. The Epoch is defined as December 30th, 1899 at 00:00:01. Certain fractional values and whole numbers are used to encode Time-only and Year-only values. For example, the internal Date value of "2" is considered as 1900, without a time when converted using the DateTime conversion format of FormatDate(), whereas adding a small fraction and using "2.001" instead produces a value of "1/1/1900 12:01 am". These details are only relevant if you are doing conversions.

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

Description convertdate(date_time string)

Converts a human-readable date_time string into the internal floating-point representation used by Media Center to store a date and time.

Examples convertdate(3//6//2012)

Returns the value 40974, which is the internal floating-point represenation of the date string 3/6/2012. This value can used by any field of type Date, or in any function that requires as input a Date type value.

formatdate(convertdate(12//2//1985), decade))

Converts the date string 12/2/1985 (note: December 2nd, not February 12th) into a Date type value, and then formats the result as a decades grouping, returning 1980's. This might be used for creating decade groupings.

FormatDate(…): Formats a date value in a specified manner

Description formatdate(date value, format specifier, empty label)

The FormatDate() function provides custom formatting of date and time values through the use of a format specifier. Output will be formatted according to format specifier.

The date value is a Media Center interal floating-point date/time representation, stored in Date fields, and output from various functions such as Now() and ConvertDate(). To pass a field of type Date to FormatDate(), use the raw (unformatted) field specification, such as "[Date Imported,0]".

The format specifier provides a recipe for converting the internal value into a human-readable string. Supported are a variety of Windows style, strftime() style, and Media Center-specific formats specifiers. Construct the format specifier from any number or combination of those defined in the following table. Additionally, any non-format characters will be output without interpretation. This allows creating rich date/time output strings. To output a word that is a reservered format specifier, surround the word with double-quotes.

The empty label argument will be output if the date value is empty.

Specifier Description
Day d Day Day of the month as digits without leading zeros for single-digit days.
dd  %d Day of the month as digits with leading zeros for single-digit days.
ddd  %a Day of the week, abbreviated to three letters.
dddd  %A Dayname Day of the week.
 %w Day of the week as a decimal number, Sunday as 0 (0-6).
 %j Day of the year (001-366)
 %j Dayordinal Ordinal day of the month (e.g. 1st, 2nd, etc.).
Month M Month as digits without leading zeros for single-digit months.
MM  %m Month as digits with leading zeros for single-digit months.
MMM  %b Abbreviated month name, three letters (e.g. Apr, Nov).
MMMM  %B Month Full Month name (e.g. April, November).
Year y Year represented only by the last digit.
yy  %y Year represented only by the last two digits. A leading zero is added for single-digit years.
yyyy  %Y Year Year represented by a full four or five digits.
Decade Year expressed as a decade (e.g. 1970's, 2010's)
Hour h Hour Hours with no leading zero for single-digit hours; 12-hour clock.
hh  %I Hours with leading zero for single-digit hours; 12-hour clock.
H Hours with no leading zero for single-digit hours; 24-hour clock.
HH  %H Hours with leading zero for single-digit hours; 24-hour clock.
Minute m Minute Minutes with no leading zero for single-digit minutes.
mm  %M Minutes with leading zero for single-digit minutes.
Second s Second Seconds with no leading zero for single-digit seconds.
ss  %S Seconds with leading zero for single-digit seconds.
AM/PM t One character time marker string, such as A or P.
tt  %p Multi-character time marker string, such as AM or PM.
Combined  %x Date Date expressed in the system's format.
 %X Time Time expressed in the system's format.
 %c DateTime Date and time expressed in the system's format.
ShortDate Age-conditional date formatted as one of "Year", "MMM d", or "MMM d Year".
ShortDateTime Date in ShortDate format plus Time.
Week Number  %U Week number with the first Sunday as the first day of week one (00-53).
 %W Week number with the first Monday as the first day of week one (00-53).
Miscellaneous Elapsed Time expressed as elapsed time (e.g. 2.5 hours).
ElapsedAgo Time expressed as elapsed time ago (e.g. 2.5 hours ago).
Filename Date and time expressed in filename-friendly format, includes seconds to avoid filename collisions (e.g. 20040521-032221).
 %% A percent (%) character.

Argument date value is optional (defaults to [date,0]).

Argument empty label is optional (defaults to EMPTY).

Examples formatdate(year-month)

Outputs the file's date formatted as Year-Month, such as 2012-April. The default date value of [Date,0] is used.

formatdate([last played,0], yyyy//MM//dd, Not Yet)

Returns the file's last played date as year/month/day without the time, ignoring the system locale setting. If a file has no last played value, the expression will output Not Yet instead.

formatdate([date modified,0], month %Y)

Returns the file's modification date/time in the form of a long month name and a four-digit year, such as December 2010.

formatdate([date imported,0], The "year" is year)

Outputs the The year is ####, where #### is the year the file was imported into the Library. Note that the word year must be surrounded in double-quotes to have it considered as literal text, and not the Year format specifier.

formatdate([date imported,0], month)&datatype=[month]

This examples is the same as the previous example, but includes a cast to the Month type &datatype=[month]. This cast can be used to cause chronological month-sorting, rather than month name alphabetic-sorting, in a panes or category view. Data-type coercion is discussed above.

Additional Examples

Date formatting development discussion, usage tips and examples.

Now(…): Retrieve and display the system date

Description now()

The Now() function returns a floating-point value represeting the current system date and time. It is generally useful for performing date arithmatic in expressions that desire to figure out elapsed time. Any raw date field or value representing a date can be subtracted from Now() to realize an elapsed time delta.

Examples now()

When run on Aug 17, 2013 at 19:28:00, returns approximately 41503.811115995.

formatdate(now(), date)

Returns the current date, without a time component, formatted according to the system's locale settings.

formatdate(math(now() - 3, dddd dd MMMM yyyy H:mm)

The date from three days ago is formated as something like Wednesday 14 August 2013 19:35. This is accomplished by subtracting the value 3, which would be days, from Now(), and its output formatted by FormatDate().

File Path and Identifier Functions

The funcions in this section provide specific file-related information such as a file's name, path, volume, and other Media Center internal information.

FileDBLocation(…): Identifies a file's databases

Description filedblocation(format)

The FileDBLocation() function returns identifiers in the specified format specified that indicate to which internal database(s) a file belongs. Media Center maintains several internal databases to track a file's disposition. This function is primarly for technical use only, and will have little utility for most users.

Available format values:

0Semicolon-separated list of formatted database names
1Numeric value of OR'd database bit flags

The table below provides common values output from FileDBLocation():

Database nameBit position
Main0
Playing Now1
CD2
Explorer3
Other (16)5
Other (6)6
Grouping7
Removed8
Podcast10
Other (4096)12
Stacks14
Category Images18
Bad19

Argument format is optional (defaults to 0).

Examples filedblocation()

For a file in the Main and Other (4096) databases, the result would be Main; Other (4096).

filedblocation(1)

The result from the same file would be 4096 (bit 0 and bit 12 set).

Additional Examples

Sample expression that uses FileDBLocation() to show a file's databases.

FileFolder(…): Returns the name of a file's parent

Description filefolder(filepath, level)

The FileFolder() function returns parent sub-folder name for filepath. The level argument specifies which parent sub-folder name to return, working the filepath from right-to-left (i.e. bottom of the folder tree upwards to the top). A value of 0 specifies a file's immediate parent, 1 its grandparent, etc., up to the root of the filepath. A value of Unassigned will be returned when the specified level exceeds the root of the filepath.

Argument filepath is optional (defaults to [filename]).

Argument level is optional (defaults to 0).

Examples filefolder()

Returns the name of the file's parent folder.

filefolder([filename,0], 0)

Same as the previous example.

filefolder(c:\some\folder\for\a\file.ape, 2)

Returns the great grandparent sub-folder named folder.

filefolder(c:\some\other\folder\a\, 2)

Returns the folder named other. Notice the file name is not required in the filepath. FileFolder() works by looking from the end of the filepath until it finds a backslash \.

FileKey()(…): Returns a file's unique internal identifier

Description filekey()()

The FileKey()() function returns the unique identifier assosciated with a file. Media Center assigns a unique identifier to each file in the Libary. It is useful in expressions when referring to individual files is necessary. Services such as MCWS use this value to reference a file.

Examples filekey()

Returns a integer value, such as 22029495, unique for eac file in the Library.

FileName(…): Returns a file's name component

Description filename(filepath, include suffix)

This function returns the file name part of filepath. Inclusion of the file's suffix depends on the include suffix argument.

0Suppress file suffix
1Include file suffix

Argument filepath is optional (defaults to [filename]).

Argument include suffix is optional (defaults to 1).

Examples filename(C:\Music\File.mp3)

The output is File.mp3.

filename(C:\Music\File 2.wav, 0)

The output does not include the file suffix, and is File 2.

filename()

Returns the value contained in the field [filename (name)].

FilePath(…): Returns a file's path component

Description filepath(filepath)

This function will return the path portion of the specified file path.

The filepath should be a rooted path. For Windows, this includes the drive letter or leading \\ for UNC paths. For *nix-based systems, this includes the root /. The field [filename (path)] is equivalent to FilePath(), and is generally preferred.

Argument filepath is optional (defaults to [filename]).

Examples filepath(C:\Music\File.mp3)

Returns C:\Music.

filepath()

Returns the value contained in the field [filename (path)].

FileVolume(…): Returns a file's volume name component

Description filevolume(filepath)

The FileVolume() function returns the volume name component of the specified file path. The path should be a rooted path (see the same comment above for FilePath(). For *nix-based systems, the output is empty. The field [volume name] is equivalent to FileVolume(), and is generally preferred.

Argument filepath is optional (defaults to [filename]).

Examples filevolume(C:\Music\File.mp3)

Outputs C:.

filevolume()

Returns the value contained in the field [volume name].

Miscellaneous Functions

The functions in this section are varied and have specialized applicability. Some are primarly used internally by MC to generate values available in various Library fields.

AlbumArtist(…): Returns a file's calculated album artist

Description albumartist()

This function calculates the album artist value used in various views and fields. It is used to populate the Library field album artist (auto) with its value. Either the field or AlbumArtist() can be used.

Examples albumartist()

Returns the value present in the album artist (auto) field.

Additional Examples

Describes the algorithm used by AlbumArtist() to calculate the "album artist (auto)" field's value.

AlbumKey(…): Returns a unique album key for a file

Description albumkey()

The AlbumKey() function returns "[album artist (auto)] - [album]". It is a convenience function, used to return the generally unique album / artist combination string used to distinguish between two like-named albums such as "Greatest Hits".

Examples albumkey()

For an album named Greatest Hits and an album artist (auto) of The Eagles, returns The Eagles - Greatest Hits.

AlbumType(…): Returns the album type for a file

Description albumtype()

The AlbumType() function returns a description regarding an album's completeness and its quantity of artists. It is used to populate the Library field album type with its value. Either the field or AlbumType() can be used.

Examples albumtype()

Returns, for example, Single artist (complete), or Multiple artists (incomplete).

Counter(…): Counts upwards in specified increments

Description counter(start value, increment)

The Counter() function outputs a montonically increasing number (more simply stated, it counts) from a start value, and each time called, increases by the increment value. It is useful for sequentially numbering fields. The Counter() function maintains an internal counter, and it resets itself to zero after five seconds of inactivity.

Becuase Counter() continues to count, it should only be used in single-use situations such as assigning its output to some field through field value assignment, for example, =counter(). With proper care, it can be used as part of an expression in the Rename, Move & Copy tool, but see also CustomData().

It is not recommended for use in any context that continually refreshes its content, such as in a panes column, file list, or expression-based custom query. Probably the best way to understand the results is to test the first example below as an expression column in a file list, and move the mouse around over that column.

Argument start value is optional (defaults to 1).

Argument increment is optional (defaults to 1).

Examples counter()

Outputs values starting at 1, and incrementing by one, it will return 1, 2, 3, ... until no longer called. This might be used, for example, to assign to the [Track #] field of several tracks using the field assignment expression =counter().

padnumber(counter(370, 2), 4)

Outputs numbers beginning from 370, incremented by two each, and padded to four digits. For example, 0370, 0372, 0374, etc.

CustomData(…): Returns internal data to the expression language

Description customdata(mode)

The CustomData() function supports returning Media Center internal data to the expression language. Currently there is only one supported use, which is to use CustomData() in the Rename, Move & Copy tool to assist in numbering files.

Available mode values:

#Returns a file's row number in the Rename, Move & Copy tool
Examples Spring_Break_Bash_padnumber(customdata(#), 4)

In the Rename, Move & Copy tool, each consecutive file would be named Spring_Break_Bash_ followed by a four digit, zero-padded number starting at 0001.

Math(…): Evaluates a given mathematical formula

Description math(expression)

The Math() function performs mathematical calculations. Standard arithmetic operators are supported, as are various numerical, trigonometric, and comparative functions. Simple variables are supported, as are multiple statements.

Arithmetic Operators + Addition
- Subtraction
* Multiplication
/ Division
^ Power
 % Modulo
Boolean Operators  ! NOT
& AND
| OR
Grouping Operators ( ) Precedence grouping
Comparison Operators } Absolute value maximum (i.e. x or y that is maximum distance from 0).
{ Absolute value minimum (i.e. x or y that is minimum distance from 0).
> Distance between x and y, positive when x greater than y, negative otherwise.
< Distance between x and y, positive when x less than y, negative otherwise.
Functions abs(x) Returns the absolute value of x.
sign(x) Returns the sign of x (1 when x >= 0, -1 when x < 0).
log(x) Returns the natural logarithm (base e) of x.
log10(x) Returns the common logarithm (base 10) of x.
pow(x,y) Returns x raised to the y-th power.
rand(x) Returns a random value ranging between 0 to x.
randn(x) Returns a random value ranging between -x and x.
Comparison Functions min(x,y) Returns the minimum value of x and y.
max(x,y) Returns the maximum value of x and y.
equal(x,y) Returns 1 when x = y, 0 otherwise.
below(x,y) Returns 1 when x < y, 0 otherwise.
above(x,y) Returns 1 when x > y, 0 otherwise.
Formatting Functions int(x) Returns the integer portion of x.
frac(x) Returns the fractional portion of x.
round(x) Returns x rounded to the nearest whole number.
trunc(x,n) Returns x truncated to n decimal places.
Trigonometric Functions atan(x) Returns the arctangent of x.
cos(x) Returns the cosine of x.
sin(x) Returns the sine of x.
tan(x) Returns the tangent of x.
abscos(x) Returns the absolute value of cosine(x).
abssin(x) Returns the absolute value of sin(x).

The order of operator precedence is summarized as follows, from top to bottom:

(   ) 
  ! 
  ^ 
*   /Left to right
+   -Left to right
|   &Left to right

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. For example, the equation math(x=4; pow(2^x)) will output 16.

Note: Empty fields

Fields used inside of Math() are expanded (interpolated) directly. Fields with empty values may produce incomplete Math() statements. For example, if the field [number plays] is empty, an expression such as math([number plays] + 2) would be seen by Math() as + 2. This incomplete expression would produce a syntax error. See the Additional Examples for more information.

Note: Locales and Commas

Special care must be taken with the Math() function and locales that use , (comma) as a decimal separator. Many Media Center fields and the return values from functions may contain comma as the decimal point. Your expressions will need to Replace() these before passing the values to Math(), which always uses dot . as the numeric decimal point.

For example, the expression math(1,5 + 1,5) will fail since Math() does not consider 1,5 to be a valid number.

Fields that cause problems are any fields that produce floating-point values, such as any Date type field in raw format (e.g. [date,0], [last played,0], [date modified,0], and [date imported,0]), or any textual field that contains floating-point values that will be used for various calculations (e.g. any of the Dynamic Range variants). Certain functions such as Now() and ConvertTime() also return localized floating-point values.

Handling this problem is not difficult. Before passing any floating point number to Math(), use Replace() first. See the examples below.

Examples math(10 + 4)

Returns 14.

math(10 + 2 * 25)

Returns 60, demonstrating that multiplication has higher precedence than addition.

math((10 + 2) * 25)

Returns 300, demonstrating that parenthesis grouping has higher precedence than multiplication.

math(replace(now(), /,, .) - replace([last played,0], /,, .))

The , is replaced by a . in the output of both Now() and in the raw field value [last played,0]. Note that the comma must be escaped so that it is seen as an argument and not as an argument separator.

math(replace(now() - [last layed,0], /,, .))

The same as the previous example, but is more efficient and simpler since it calls Replace() just once on the entire string to be passed to Math().

Additional Examples

An explanation and some solutions for fields that evaluate to empty within Math().

Size(…): Returns a file's size in a format specific to the media type

Description size()

The Size() function returns media size information specific to the particular media type. It is used to populate the Library fields duration and dimensions with their values. Either the field or Size() can be used.

Type of information reported by size for the file's media type:

AudioDuration
VideoDuration
ImageDimensions
DataNo information returned.
Examples size()

Returns values such as 400x225 for images, or 3:09 for audio files.

TrackNumber(…): Returns a file's track # value

Description tracknumber()

The TrackNumber() function returns a file's track #, or 0 if the no value exists. It is used to populate the Library field track # with its value. Either the field or TrackNumber() can be used.

Examples tracknumber()

Returns the value present in the track # field.

TVInfo(…): Miscellaneous television and other preformatted information

Description tvinfo(type)

The TVInfo() function is multi-purpose, and returns a specific type of information about television recordings, programs, and preformatted informational strings for use in captions, thumbnails, grouping, etc.

Available type values:

IsProgramReturns 1 if the file is a program, 0 otherwise
IsGuideProgramReturns 1 if the file is a guide program, 0 otherwise
IsRecordedProgramReturns 1 if the file is a recorded program, 0 otherwise
ChannelReturns Returns the channel name, given a channel number
ChannelKeywordsReturns channel keywords
DateReturns a program's date
DateNoTimeSame as Date, but without the time.
NameDisplayReturns [name]: [series] or just [name]
NameDisplayWithDateNameDisplay + ([year])
RecordReturns 1 if the program is scheduled to be recorded, 0 otherwise
RecordMarkReturns a red dot if the program is schedule to be recorded.
SeriesDisplayReturns [series] or [name]
SeasonDisplayReturns [season]
SeasonEpisodeReturns [season].[episode]
TimeDisplayReturns program start time (system time format), or "Showing" if program on now
TimeDisplayNoOnNowTimeDisplay without on now handling
SizeDisplayReturns [duration] ([file size]) or [dimensions] ([file size])
WatchedDisplayReturns Watched() information, such as No, Yes, 80%, etc.
Examples tvinfo(namedisplay)

Returns formatted name and series output. If the file has no [series] value, only [name] is output.