Showing posts with label adobe director. Show all posts
Showing posts with label adobe director. Show all posts

Wednesday, December 22, 2010

Open AL, Adobe Director - No sound in projector [FIX]

One of the most annoying thing about Adobe Director is its lack of support. Open AL Xtra enables director to use OpenAL runtimes for 3D sound manipulation. Unfortunately, in a projector/exe, it doesn't play any sound. This issue was pointed out at multiple forums (here and here), without any fix so far. After struggling for nearly 4-5 hrs, I finally figured it out. The solution couldn't be any simpler. Just include these two xtras in the projector.

- Mix Services
- Sound Import Export

I got he hint from playFile() documentation for Director. It mentions the use of "Correct Mix Xtra" to play sound properly.

Tuesday, July 20, 2010

Validation framework for adobe director

Validation can be a real pain in the ass. After all no developer likes doing labor tasks. With Java, there are many excellent validation frameworks. To know about my take on validation with java see this article. Adobe director however doesn't have anything like it. So i decided to go ahead and make a simple framework in lingo.

Lets start with usage point of view. We need the name of text field, type of validator (regex, length etc..) and the error message when validation fails. Lets represent this as a list L = {"text field name", "Validator name", "error msg"}. To keep it simple, I only consider validation on text fields (I could have extended it, but it'd make the code look ugly, I wanted to keep it simple. Also, 99% of validation is on text fields)

Its obvious that a field can have multiple validators. Also, it'd be nice to validate everything in one call. So we can have input as List {L1, L2, ...Ln), where Li aforementioned list format.

But validators can have parameters. For example length validator can have 'length' parameter. So L should be List("text field name", List ("validator name", param1, param2, ...), "error message"). From the usage point of view we could have something like:
oValidator = new(script "ValidationUtil")
isValid = oValidator.validate([ \
["txtField1", ["NonEmptyValidator"],"Please enter textField1"], \
["txtSSN", ["LengthValidator", 4],"Please enter 4 digit ssn"], \
["txtSSN", ["NumberValidator"],"Please enter a numeric value"]
)
Predefined validators (functions) can be called by their string name using call(...) method.
Since we have all the necessary things are worked out, heres a complete listing of ValidationUtils class. You are free to use and modify this class as per your requirements. Just let me know if your are using it. At least i'll know it was useful to someone.
-----------------------------------------------------
-- This class manages all the validation stuff --
-- @author : Raghavendra Kotikalapudi --
-- @email : ragha.unique2000@gmail.com --
-----------------------------------------------------

--Currently works only for text fields..
--Checks for validation on the given validator..
on isValidOnValidator me, memberName, lstValidatorAndParams

val = sprite(memberName).text
--Extract validator name..
validator = lstValidatorAndParams[1]
otherParams = lstValidatorAndParams
--Remove validator name...it now has params only.
otherParams.deleteAt(1)
--Achieves dynamic function calling..
return call(symbol(validator), me, val, otherParams)

end

--This is the main function to be called.
on validate me, lstMembersAndValidators

ret = true
repeat with lst in lstMembersAndValidators

if isValidOnValidator(me, lst[1], lst[2]) = false then
alert(lst[3])
ret = false
exit repeat
end if

end repeat

return ret

end


--Validates non emptiness..
on NonEmptyValidator me, str, lstOptionalParams

if voidP(str) then
return false
else if length(str) = 0 then
return false
else
return true
end if

end

--Validates of length of str in in the range (low, hi) inclusive
--lstOptParams has low, high pair
on LengthRangeValidator me, str, lstOptionalParams

len = length(str)
if len >= lstOptionalParams[1] and len <= lstOptionalParams[2] then return true else return false end if end --Validates for non existence of special symbols.. --i.e, str can contain a-z, A-Z or 0-9 on NoSpecialSymbolsValidator me, str, lstOptionalParams foundCount = PRegEx_Search([str], "~+|`+|!+|@+|#+|\$+|%+|\^+|&+|\*+|\(+|\)+|\{+|\}+|\[+|\]+|\++|\\+|\|+|:+|;+|/+|\<+|\>+|\?+|,+")

--If special char is found, validate to false
if foundCount > 0 then
return false
else
return true
end if

end

--Validates if the given str is a valid name or not, i.e., it should not contain
--special symbols or 0-9
on NameValidator me, str, lstOptionalParams

val = NoSpecialSymbolsValidator(me, str, lstOptionalParams)
if val = false then
return false
else
foundCount = PRegEx_Search([str], "[0-9]+")
--If number if found..
if foundCount > 0 then
return false
else
return true
end if
end if

end
New Validators can be added as an when needed. PRegEX_search(...) comes from PRegEx Xtra. Fortunately, it is free to download. This framework handles error notifications by showing alert messages whenever validation fails. Neat isn't it.

If you have any suggestions or improvements, please let me know through comments. Hope you find this useful!

Monday, June 7, 2010

Report generation in adobe director..

Report generation is perhaps the most plagued problem with director. There are a lot of xtras out there, but are commercial. Most of them are around $100-350, and all are limited in one way or another. After weeks of exploration, few of which included:
  1. Using adobe reader
  2. Interfacing it via. java program (this one almost worked)
  3. Wasted time with lots of useless xtras
I decided to make my own scheme, one which works in most situations. The idea is as follows:
  1. Create a HTML template of your report. For instance, if you wanted customer information report. You create a HTML template, fill in all the blanks with $1, $2, ... $n.
  2. From director, while generating the report, you first read in the template (preferably from root folder\templates\).
  3. Replace $1, $2, with appropriate values.
  4. Generate HTML file and open it with default browser.
I created a utility class for the above tasks. You'll be needing FileIO xtra and FileXtra4 (both of which are available for free)

-------------------------------------------------------------
--------------Report generation Utility class----------------
-------------------------------------------------------------

--Finds and replaces the first occurrence of 'aLookForString' with 'aReplaceString'
--in 'aString' and returns the new string
on findAndReplace me, aString, aLookForString, aReplaceString

n = aLookForString.length -1
is_ok = false

repeat while is_ok = false

place = offset(aLookForString, aString)

if (place = 0) then
is_ok = true
exit repeat
else
put aReplaceString into char place to (place+n) of aString
exit repeat
end if

end repeat

return aString
end

--Saves the text in given filename
on saveText me, text, filename

-- create the FileIO instance
fileObj = new(xtra "FileIO")

-- delete existing file, if any
openFile (fileObj,filename,2)
delete(fileObj)

-- create and open the file
createFile(fileObj,filename)
openFile(fileObj,filename,2)

-- check to see if file opened ok
if status(fileObj) <> 0 then
err = error(fileObj,status(fileObj))
alert "Error:"&&err
return FALSE
end if

-- write the file
writeString(fileObj,text)

-- close the file
closeFile(fileObj)

return TRUE

end

--Reads the text from a given filename
on readFromFile me, filename

-- create the FileIO instance
fileObj = new(xtra "FileIO")

-- open the file
openFile(fileObj,filename,1)

-- check to see if file opened ok
if status(fileObj) <> 0 then
err = error(fileObj,status(fileObj))
alert "Error:"&&err
return ""
end if

-- read the file
text = readFile(fileObj)

-- close the file
closeFile(fileObj)

--return the text
return text

end


Sample usage is illustrated below:

oUtilClass = new(script "UtilClass")

--Read html from the template
html = oUtilClass.readFromFile(the moviepath & "\\Templates\\summary report.htm")

--Fill in data..
global strSelectedDate
html = oUtilClass.findAndReplace(html, "$1", someVar)
html = oUtilClass.findAndReplace(html, "$2", anotherVar)

filename = the moviepath & "print.html"
oUtilClass.saveText(html, filename)

--Invoke through a browser..
fileXtra4Obj = xtra("FileXtra4").new()
fileXtra4Obj.fx_FileRunApp(the moviepath & "run.bat")



In run.bat, you just have to call print.html by writing "print.html", Duh!
Therefore, run.bat opens print.html with the default browser, which can then be printed, previewed by the courtesy of browser. Whats more, you also get to fiddle with niche layout settings at runtime. In other operating systems like linux, you just have to replace run.bat with a shell script.

Some Minor Tidbits

What if you wanted to generate a table at runtime? Here's what I'd do:

Generate HTML template from dreamweaver or MS word with one row of data in the table..
For example...
<html>
Some blah blah..

Name: $1 </br>
Age : $2 </br>

<table>
<tr>
<td> Subject </td>
<td> Marks </td>
</tr>

<tr>
<td> Some subject </td>
<td> 85 </td>
</tr>
</table>

</html>

Now, create a file template1_rows.txt containing the row data..<html>
<tr>
<td> $1 </td>
<td> $2 </td>
</tr>
Here's the big idea. Whenever you build a table, read in the row data template, fill it and append it to the main html. Here's an example. Highlighted code achieves dynamic table generation behavior.
 --Read html from the template
html = oUtilClass.readFromFile(the moviepath & "\\Templates\\template1.htm")

--Fill in data..
global strSelectedDate
html = oUtilClass.findAndReplace(html, "$1", name)
html = oUtilClass.findAndReplace(html, "$2", age)

tableRows = ""
--Read in the row template..
rowTemplate = oUtilClass.readFromFile(the moviepath & "\\Templates\\template1_rows.htm")

--Generate table rows..
repeat with row=1 to numRows
tableRow = rowTemplate
tableRow = oUtilClass.findAndReplace(tableRow , "$1", subject)

--Append data to tableRows..
tableRows = tableRows & rowTemplate
end repeat

--Fill in table data..
html = oUtilClass.findAndReplace(html, "$3", tableRows)

filename = the moviepath & "print.html"
oUtilClass.saveText(html, filename)

fileXtra4Obj = xtra("FileXtra4").new()
fileXtra4Obj.fx_FileRunApp(the moviepath & "run.bat")
I know, it looks complicated. But atleast this is transparent and you exactly know whats going on. Moreover, this approach gives you unlimited formatting options, works and is free. Once you get a hand of it, it'll seem pretty simple.

Controlling print behavior

If you don't want your table to break across pages, you can use . Beware, this only works with opera browser. So be sure to ship your software with opera. Even better, use opera portable (requires no installation), make appropriate changes to run.bat to invoke html with the shipped browser.

Comments and suggestions are welcome. If anyone has simpler and free approach, please let me know by posting comments.