DTAB SCRIPT V1.04 TUTORIAL / OVERVIEW
Since V1.03, DTAB has included a web page downloader with deciphering feature. This feature is made possible by the inclusion of a specifically designed scripting language we call DTAB SCRIPT. Dtab uses these script to grab extra information from a web page about a drum tab or even apply some pre-posting to drum tab before showing it to the user. This is all a transparent process from the general users perspective, but for those will a bit programming experience should be able to write their own custom scripts for their favorite drum tab web sites.
Learning a programming language, even an extremely simplified one is way beyond the scope of this documentation, so the following is mostly for those who have experience with the BASIC programming in particular string handling, which is all DTAB script is capable of. If you're interesting in learning BASIC program then you can download the Learning Edition of PlayBASIC.com (http://playbasic.com) which will help you get some idea of the type of programming DTAB script uses.
Note: This information may be out of date, for the latest consult the DTAB documentation
DTAB SCRIPT QUICK OVERVIEW
DTAB script is highly simplified procedural BASIC, meaning programs execute in a top down fashion. When a Dtab script is loaded, it's compiled to byte code and passed to an internal interpreter each time it's used. The interpreter will execute a script program instructions until it either reaches the bottom of the script or a maximum of 100,000 instructions have been executed, where the interpreter exits. This limitation prevents a script from completely hanging the entire application if execution gets caught in a loop, but can mean iterating through a web page character by character it can run out of execution time. Some we recommend using the string functions providing to locate and grab any information from a page.
DTAB SCRIPT Variables:
Even though Dtab Script is based on the BASIC language (which is generally implicit) Dtab Script requires explicit declaring of Variables, but they're not case sensitive. Variables are all of type variant. Meaning you don't need to explicitly declare a numeric variable or string variable. Just place the name after the VAR keyword and it'll be available from use bellow it's declaration. Variable declarations can be stacked by separating them with a coma.
Example: Var Score
Var Lp, Score,
DTAB SCRIPT Literals:
Literals are supported in three basic forms, Integer (whole numbers) , Float and String.
Example: Var Counter, Pi, Name
Counter = 45 ; Assign Counter variable the the literal value of 45
Pi = 3.14 ; Assign the variable PI a literal float value
Name = "Joe Smith" ; Literal strings can be represented between a pair of " characters.
Name = 'Joe Smith' ; Alternative Literal strings can be represented between ' characters.
DTAB SCRIPT Math Operators:
DTAB script supports the Math operators, those being + , - , / and * When these operators are applied to variables that contain number data, the operation will be numeric. The only exception to this rule are when the addition operators are applied to a variable containing string data. When this occurs the characters in the strings will be joined/appended together.
Math Example: Var Counter
Counter = 45 ; Assign Counter variable the the literal value of 45
Counter = Counter + 45 ; Add 45 to the pre existing value in Counter, then store the answer in the counter variable
Counter = Counter /2 ; Divide the current value of in counter by 2 and store the answer back in Counter variable. Which would be 45
These types of expression can be short cut using the
++ ,
--,
=+ ,
=- ,
=/ ,
=* assignment operators .
DTAB SCRIPT Comparison Operators:
The script supports all the common comparisons operators such as equally tests ( == ) and inequality ( != ) (not equal too), (<) Less than, (<=) Less than equal, (>) Greater than, (>=) Greater Than equal. Comparisons return a numeric condition that's either
0 (false) or
1 for True.
Compare Example: Var LP
LP= 0 ; Assign the LP variable to 0
Do
LP++ ; Add one to LP variable
Loop ( LP==100) ; Compare LP to 100, if it's not equal to 100, then execution jumps back to the DO statement to keep the loop running
Those familiar with traditional BASIC will notice a departure here with the introduction of the == and != operators for equally and inequality tests.
DTAB SCRIPT Binary Operators:
DTAB script V1.04 only two binary operators at this time, those being & (AND), | (OR) operators. You can use either the symbol or the name of the operator. In BASIC programmers generally use the names. Both the AND / OR operators performs a binary (bit wise) AND/OR operation between the terms on either side of it. They have the same precedence in expressions. So operators in row will evaluate left to right. See the table bellow for most about They operators
Binary Operator Example: Var Result
Result = 240 or 15 ; Result would = 255 after this line of code is executed.
Result = 255 and 15 ; This performs a binary and between 255 (%11111111) with 15 (%00001111) which will result in %11110000 =240
The AND / OR operators are most frequently used in comparisons with decision (IF / ENDIF) statement blocks. They allow us to combine the results of various comparisons down into a single true(
1) / false(
0) result, with the IF statement jumps accordingly.
Binary AND Rule: 1 and 1 = 1 0 and 1 = 0 1 and 0 = 0 0 and 0 = 0 So the AND rule only gives 1 when BOTH or 1 or 1 = 1
|
Binary OR Rule: 1 or 1 = 1 0 or 1 = 1 1 or 0 = 1 0 or 0 = 0 So the OR rule gives a 1 when either or 1 or 1 = 1
|
DTAB SCRIPT Loops & Decisions:
DTAB script supports two primary types of looping block, those being the For / Next and the Do / LOOP construct. For decisions we use the IF / ELSE / ENDIF blocks, in conjunction with comparison operators above.
The For / Next implementation is the same as regular BASIC, with the For statement being followed by the assignment expression. This expression is the starting value of the loop. The END expression is declared after a TO keyword. Ie.
For LP = 1 to 10 The block is then closing using the Next keyword on a following line.
For Next Loop Example: Var LP, TALLY
TALLY =1000 ; Assign the TALLY variable a value of 1000
For LP= 1 to 100
TALLY ++ ; Add one to the TALLY variable
Next ; End of the For / Next Looping block- We don't need the Counter variable LP after NEXT like in some BASIC's
This For / NEXT loop will execute the code inside it
100 times. The value in the TALLY Variable would be 1100 when the loop concludes. The loop concludes when the counter variable is greater than the end expression. In this case, when LP is bigger than 100, the loop exits. If LP is less than or equal to 100, it would jump back to the start of the loop it keep it running.
The Do / Loop implementation is much the same as most modern BASIC. You can use these blocks to execute a section of the code infinitely, or conditionally. Supporting expressions means the one looping construct can replace Repeat / Until and While / EndWhile blocks. A while block is created by placing the condition expression after the opening Do statement and repeat behavior is created by placing the conditional statement after the LOOP statement.
Here's some examples Do loops
Infinite Do / LOOP Example: Var TALLY
TALLY =1000 ; Assign the TALLY variable a value of 1000
Do ; Start of the section of code that will execute forever
TALLY ++ ; Add one to the TALLY variable
Loop ; End of the Loop construct. Since there's no condition, this loop will execute forever
This Do / LOOP block will execute the code inside it forever. Since the program there has no conclusion Dtab Script would stop execution the script eventually for you.
The following examples use conditions so the loop will only condition to execute until a condition is meet, then it'll exits the loop and conditions with the rest of the program.
While styled Do / LOOP Example: Var TALLY
TALLY =1000 ; Assign the TALLY variable a value of 1000
Do (TALLY <2000) ; Here we can only enter this loop when TALLY is less than 2000.
TALLY ++ ; Add one to the TALLY variable
Loop ; End of the Loop construct. Sop it jumps back to it's matching Do statement above.
This Do / Loop (WHILE) block is conditional, so the code inside it will therefore only execute while the Do condition is true(1). Since the TALLY variable is set to 1000 initially, then the DO/Loop will execute 1000 times since the code inside the loop is adding 1 to TALLY value. When TALLY is equal to or greater than the 2000 limit, the loop is exited and execution continues on from whatever is following the LOOP statement.
Repeat Styled Do / LOOP Example: Var TALLY
TALLY =1000 ; Assign the TALLY variable a value of 1000
Do ; Start of the Do loop block.
TALLY ++ ; Add one to the TALLY variable
Loop (TALLY <2000) ; Check if Tally is still within our required range, if it is, execution jumps back to the Do statement to continue running the code
This Do / Loop (REPEAT) block is conditional, so the code inside it will therefore only continue to execute when the LOOP condition is true(1). Since the TALLY variable is set to 1000 initially, then the DO/LOOP will execute 1000 times since the code inside the loop is adding 1 to the TALLY variable. When TALLY is equal to or greater than the 2000 limit, the loop is exited and execution continues on from whatever is following the LOOP statement.
Both the Do and LOOP conditions can be used to create a loop that will only execute when an initial condition is true and will only keep executing while another condition is true also. Giving you a number of simple logic possibilities.
IF / ELSE /ENDIF decision Example: Var NAME, VALUE
NAME = "JOHN" ; Store the string JOHN in the variable NAME
If (NAME== "JOHN") ; Check if the Variable NAME contains the string "JOHN"
NAME = NAME + " DUDE" ; Append the string " DUDE" to the NAME variable
EndIF
If (NAME== "JOHN DUDE") ; Check if the Variable NAME contains the string "JOHN DUDE"
; If the comparison in the IF decision was TRUE, this line code will be executed up to the ELSE statement
NAME = NAME + " DUDE" ; Append the string " DUDE" to the NAME variable
Else
; If the comparison and IF decision above was FALSE, this code here will be executed instead
NAME = " THIS IS NOT THE PERSON I WAS LOOKING FOR" ; Copy a string to the NAME variable
EndIF
This IF / ELSE / ENDIF blocks gives us a way to make decisions in our script. The expression following the IF statement is expected to be in brackets.
IF / ELSE / ENDIF decision With AND /OR Operators Example: Var FirstNAME, LastNAME
FirstNAME= "JOHN" ; Store the string JOHN in the variable FirstNAME
LastNAME= "JOHN" ; Store the string JOHN in the variable LastNAME
If (FirstNAME== "JOHN" and LastNAME=="SMITH") ; Check if the First NAME is JOHN and the last name is SMITH.
NAME = NAME + " DUDE" ; Append the string " DUDE" to the NAME variable
EndIF
DTAB SCRIPT Function List:
DTAB script includes a selection of mainly string based manipulation functions. This is because scripts are intended for picking apart the raw HTML (TEXT) what was downloaded from a web site. So the user is expected to have some familiarity with both BASIC programming and HTML, you can find lots of extra information about DTAB on our forums and there's thousands of web sites that will teach you HTML basics.
Here's a list of functions that Dtab Script V1.04 supports, we're assuming the reading here is familiar with BASIC programming and therefore should be able to derive the usage of these statements. If you're completely new to BASIC programming, go and start learning PlayBASIC.com (http://playbasic.com), it comes with everything you'll ever need to get started.
String Functions: DTAB script includes a selection of mainly string based manipulation functions. This is because scripts are intended for picking apart the raw HTML (TEXT) what was downloaded
StringResult=Left( String, CutPosition) ; This function returns the characters from the start to the start up till the nominated CutPosition
StringResult=Right( String, CutPosition) ; This function returns the characters after the nominated CutPosition to the end of the string
StringResult=Mid( String, Position, NumberOfCharacter) ; This function returns a selection characters after the nominated Position.
StringResult=Upper( String) ; This function returns the input string with all the characters converted to upper case
StringResult=Lower( String) ; This function returns the input string with all the characters converted to lower case
StringResult=Trim( String) ; This function returns the input string after any what space/tab characters from the head or end of it have been removed.
StringResult=TrimLeft( String) ; This function returns the input string after any white space/tab characters from the head have been removed
StringResult=TrimRight( String) ; This function returns the input string after any white space/tab characters from the head have been removed
IntegerResult=Len( String) ; This function returns the length in characters of the input string.
IntegerResult=Asc( String) ; This function returns the ASCII code of the first character in the input string
StringResult=Str( Value) ; This function converts the passed value to a string
StringResult =Chr( IntegerAscIICode) ; This function return the ASCII code equivalent ASCII character as a string.
IntegerPosition=Instr( HeyStackString , NeedleString, StartingPosition) ; This function does a case insensitive search of the HeyStackString for the first occurrence of the NeedleString. The position is returned if one is found, otherwise it returns zero (false)
IntegerPosition=InstrB( HeyStackString , NeedleString, StartingPosition) ; This function does a case sensitive search the HeyStackString for the first occurrence of the NeedleString. The position is returned if one is found, otherwise it returns zero (false)
StringResult=Replace( HeyStackString , NeedleString, ReplacementString) ; This function does a case insensitive replace on the HeyStackString. The function searches the HeyStackString and replaces all occurrences of the NeedleString with the ReplacementString. The resulting string is returned.
StringResult=ReplaceB( HeyStackString , NeedleString, ReplacementString) ; This function does a case sensitive replace on the HeyStackString. The function searches the HeyStackString and replaces all occurrences of the NeedleString with the ReplacementString. The resulting string is returned.
Control Commands: End ; Force program to end execution now.
DTAB SCRIPT Web Site / Domain Importer Script Global Variables:
When DTAB is asked to download a webpage and grab the Drum Tab from that page, DTAB checks there's a decipher script for that web site. If there is, the script is loaded / compiled and then passed a series of Global variables. The variables range from a complete copy of the HTML, the TITLE string from the page through the various information variables that you can pass back.
The global variables are all the declared by DTAB and exist in your script. The Input globals contain data that DTAB sets up for you, where as return globals are empty. Dtab will only append the data from global variables to the Drum Tab if they contain information.
Input Global Variables: WebPAGE = This variable hold the raw HTML from the downloaded webpage.
PageTITLE = This variable holds pages title text. The text that's between the <TITLE> tags.
PageURL = This complete URL of this web page.
Return Global Variables: SongNAME = The name of the song. (STRING)
ArtistNAME = The name of the artist/performer of the song (STRING)
AlbumNAME = The name of the album this song comes from (STRING)
TabberNAME = The name of the person who transcribed this song (STRING)
TabberEmail = The email address of the person who transcribed this song (STRING)
Comments = Any general comment information that a site might have about this song. (STRING)
DrumTab = The Drum Tab text. (STRING)
DrumTabStatus = A flag (INTEGER) indicating that that script has decode the drum tab from the WebPage html. So Dtab should use the text in the DrumTab variable as the drum tab.
DTAB SCRIPT Example:
You can find the domain importer scripts in your DTAB installation under the
Data\Script\DomainImporter. The following is the script for importing drum tabs from
Ultimate-Guitar.Com
; ---------------------------------------------------------------------
; [DTAB SCRIPT]--------------------------------------------------------
; ---------------------------------------------------------------------
; Global INPUT Script Variables
; ---------------------------------------------------------------------
; WebPage = THe entire document
; PageURL = The full URL of this page
; PageTitle = The Title string from the page
; ---------------------------------------------------------------------
; Script (Info) RETURN Variables
; ---------------------------------------------------------------------
; SongName = The name of the song (TEXT)
; ArtistName = The artist/band name (TEXT)
; TabberName = The name of the tabber (TEXT)
; DrumTab = The Drum Body (TEXT)
;DrumTabStatus = Status Flag, did this script find the tab body ?
var StartPos,EndPos,AtPos,TabbedByStart,TabbedByEnd,Tag
;---------------------------------------------------------------------------------------
;---------------------------------------------------------------------------------------
If (InStr(PageTitle,"Ultimate-Guitar.Com",1)>0)
;---------------------------------------------------------------------------------------
;-------------------------------------------- -------------------------------------------
print("Ultimate-Guitar.Com Page")
Tag = "drum tab by"
EndPos = InStr( PageTitle, Tag,1)
If (EndPos>0)
EndPos = EndPos - 1
StartPos = 1
SongName = Trim(Mid(PageTitle, StartPos, EndPos - StartPos))
Print( "Song:" + SongName)
AtPos = InStr( PageTitle,"@",1)
if (AtPos>EndPOs)
StartPos = EndPos + Len(Tag)+1
ArtistName = Mid(PageTitle, StartPos, AtPos - StartPos)
ArtistName = Trim(ArtistName)
Print( "Artist:" + ArtistName)
endif
EndIf
; ---------------------------------------------------------------------
; -[ GRAB TAB BODY ]---------------------------------------------------
; ---------------------------------------------------------------------
Var lp,SearchPos,PreTagStart,PreTagEnd,PreTagSize
Var PreTagText
SearchPos =1
PreTagStart=1
PreTagEnd=0
PreTagText=""
; print("_______________________________GET DRUM TAB________________________")
Tag="<pre>"
for lp=0 to 3
SearchPos=instr(WebPage,tag,SearchPos)
if (SearchPos>0)
PreTagSTart =SearchPos
PreTagEnd =instr(WebPage,"</pre>",SearchPos)
if (PreTagEnd>PreTagStart)
PreTagSTart+=Len(Tag)
PreTagSize=PreTagEnd-PreTagStart
if (PreTagSize>10)
if (PreTagSize > len(PreTagText) )
PreTagText = Mid(WebPage, PreTagSTart, PreTagEnd - PreTagSTart)
endif
endif
SearchPos=PreTagEnd
else
SearchPos=SearchPos+1
endif
else
lp=10000
endif
next
; Check the size
if (Len(PreTagText)>10)
; strip leading tags
Tag="</i>"
SearchPos =instr(PreTagText,tag,1)
if (SearchPos>0)
SearchPos+=Len(tag)
PreTagText = Mid(PreTagText, SearchPos, Len(PreTagText) - SearchPos)
endif
DrumTABStatus=1
DrumTAB=PreTagText
endif
endif
done:
print("End of Program")