Wednesday, October 29, 2008

Recent video updates

Over the last couple of weeks some fixes for video bugs have landed that should improve the playing experience. In particular playback and sound should work on Pulse Audio based Linux distributions. A quick summary of the changes are:
The list of audio and video bugs is available in the Mozilla bugzilla database. Try out <video> usage, exercise the JavaScript API, use sites like tinyvid.tv to test the playback and please report any problems you find.

A couple of additional backends have seen some visible progress as well. Work in progress patches for the WAV backend for <audio> (for all platforms) and a DirectShow backend for Windows are available.

Categories: ,

Labels:

Tuesday, October 21, 2008

Playing Blues on the Ukulele

Al Woodshed, author of the Ukulele Hunt website, has written an e-book on How to play Blues Ukulele. This is a great book, over 70 pages, and includes many MP3 files playing the examples from the book. Al goes into good depth covering different styles and techniques. It's the most practical book on playing blues that I've read let alone playing for the ukulele.

There are other blues material out there for the ukulele. These include Del Rey's 'Blue Uke' instructional DVD and Rigk Sauer's Learn to play Blues Ukulele. Combined with Al's e-book I think these show that the Ukulele is a great instrument for playing Blues.

Al Woodshed has an audio sample and table of contents of his book at his site.


Rigk Sauer Blues video



Del Rey Blues video



Categories:

HTML 5 Video Element Examples

If you're looking for some sites to play <video> and <audio> using the new elements, I've listed some below. Please add any you know of in the comments:Categories: , ,

Labels:

Monday, October 20, 2008

Video Element Update

Some updates to the video element have landed and are now in the Firefox nightly builds. Bug 449159 was landed which refactors the Ogg backend to improve stability and add seeking support. Some of the changes include:
  • Improved stability. Deadlocks and crashes involving shutdown have been fixed.
  • Improved performance. CPU usage of video playback is better. There were problems that would result in the CPU usage pegging at 100% at times, especially after playback. These have been resolved.
  • After a video has completed playing, calling the play() method, or using the built in controls, will now restart playback.
  • The totalBytes DOM attribute is implemented.
  • Seeking is supported in certain cases. If the playback is from a local file, or a server that supports HTTP byte ranges, then seeking should work. There is no UI yet, but setting the currentTime attribute to a floating point value representing the number of seconds to seek should work. A 'seeking' event is raised when seek starts, and a 'seeked' event is raised when seeking completes.
  • Playback of video and audio would miss a portion of the end of the file. This was especially noticeable on small audio samples. Now files should play back completely.
My video test page has byte range support if you want to test seeking out. Since there's no user interface I recommend using the JavaScript Shell bookmarklet and interact with the video from JavaScript. Here's an example interaction:
var v = document.getElementsByTagName("video")[0];
v.play()
v.addEventListener("seeked", function() { print('seek completed!'); }, true);
v.currentTime=10
Categories: , ,

Labels:

Saturday, October 11, 2008

Revisiting the Linear recursion combinator in Factor four years on

The Joy programming language has a linrec combinator for performing linear recursion. Some time ago I took a stab at implementing linrec in Factor. Slava also posted his version that was originally a part of Factor.

As can be seen from Slava's version, juggling the stack when four quotations are involved can be problematic. I thought I'd revisit linrec using Factor's locals library and see how it compares. This is my attempt at an implementation using locals:
:: linrec 
( if-quot: ( -- ? )
then-quot: ( -- )
else1-quot: ( -- )
else2-quot: ( -- )
-- )
if-quot call [
then-quot call
] [
else1-quot call
if-quot then-quot else1-quot else2-quot linrec
else2-quot call
] if ; inline recursive
This is pretty readable compared to the solutions in the prior posts. Because linrec is a combinator it needs to be declared 'inline'. It recursively calls itself so needs to be declared 'inline recursive' to enable calls of linrec to be compiled. More details about this can be found in the Factor documentation. Usage of the linrec word looks like:
5 [ dup 1 = ] [ ] [ dup 1- ] [ * ] linrec .
=> 120

[ 5 [ dup 1 = ] [ ] [ dup 1- ] [ * ] linrec ] infer.
=> ( -- object )

{ 1 2 3 } [ dup rest empty? ] [ first ] [ rest ] [ ] linrec
=> 3

[ { 1 2 3 } [ dup rest empty? ] [ first ] [ rest ] [ ] linrec ] infer.
=> ( -- object )

[ 1000 [ dup 1 = ] [ ] [ dup 1- ] [ * ] linrec drop ] time
=> 22ms

: fac ( n -- n ) dup 1 = [ dup 1- fac * ] unless ;
[ 1000 fac drop ] time
=> 19ms
It's nice that the 'fac' word and the linrec definition seem to compile down to the same code:
[ [ dup 1 = ] [ ] [ dup 1- ] [ * ] linrec ] optimized.
=> [
\ ( gensym ) [
dup 1 dupd eq?
[ drop t ]
[ dup 1 swap tag eq? [ 1 bignum= ] [ drop f ] if ] if
[ ] [ dup 1 - ( gensym ) * ] if
] label
]

\ fac optimized.
=> [
dup 1 dupd eq?
[ drop t ]
[ dup 1 swap tag eq? [ 1 bignum= ] [ drop f ] if ] if
[ ] [ dup 1 - fac * ] if
]
One confusing aspect of this linrec definition is having to declare the stack effects of the quotations passed to linrec. Depending on the linear recursion task the stack effects may be different. Compare factorial vs finding the last element of a sequence:
{ [ dup 1 = ] 
[ ]
[ dup 1- ]
[ * ]
} [ infer. ] each
=> ( object -- object object )
( -- )
( object -- object object )
( object object -- object)

{
[ dup rest empty? ]
[ first ]
[ rest ]
[ ]
} [ infer. ] each
=> ( object -- object object )
( object -- object )
( object -- object )
( -- )
Both usages of linrec still infer and compile so I guess the fact that the stack effects balance out allows this. I'm not sure whether it's just a side effect of implementation or intended.

Working on this example I can say that, for me, Factor programming has become easier compared to four years ago.

Categories:

Labels:

The Left Fold Enumerator for i/o

There have been some interesting papers and talks about approaches to handling i/o using left folds recently.

First was the galois tech talk about a safe and efficient i/o interface in Haskell using left fold enumerators. PDF slides are here. The example web server, Hyena, is available on github.

Oleg Kiselyov then gave a talk at DEFUN about using left folds for web servers. The slides and source for the talk are available at Oleg's site in the Haskell Iteratee I/O section.
We explain input processing with left-fold enumerator, using as an example HTTP request processing in Haskell. The approach is general and applies to processing data from various collections, from in-memory data structures to databases, files, sockets, etc.

Our approach differs in: permitting incremental processing; i/o interleaving comes by default; we shall see an example of i/o multiplexing with no need for threads and related locking and synchronization.

Unlike lazy IO, our approach is correct. There is not even hint of UnsafePerformIO. Unlike Handle-based IO, accessing a disposed resource like a closed handle is just impossible in our approach. Our approach has some other nice properties, permitting composing streams and stream processors.

One can use the same processor to handle several streams one after another. Or use two processors to process parts of the same source. One can combine processors vertically, which is very useful when one stream is embedded (chunk-encoded, escaped, UTF8-encoded) into another. Enumerators and iteratees, which generalize fold, have nice algebraic properties. But we won’t talk about them.
Interesting weekend reading!

Categories:

Friday, October 10, 2008

Factor Web Framework Example

The Factor web framework was recently redeveloped and my previous post on the topic is out of date. I'm re-learning how to write Factor web applications as I work through a simple app I'm building.

At first I was overwhelmed by the large number of features in the new framework, but once I got a bit of an understanding I was pleasantly surprised how easy it was to put an application together.

Starting the web server hasn't changed much. Start a web server running on port 8888 in a background thread:
USING: http.server threads ;
[ 8888 httpd ] in-thread
A web application is written as a bunch of responders. Each responder handles a request from the client browser. An easy way of creating a responder is to create an 'action' object. An 'action' object has a number of slots, one of which is called 'display'. Setting 'display' to a quotation will cause that quotation to be called when the client browser makes a request. The quotation should return a 'response' object. The 'response' object defines what gets sent back to the client browser. The 'body' slot of the 'response' object can be a string which is returned to the browser as the contents of the request. So a basic responder is:
<action> [
<response>
200 >>code
"text/plain" >>content-type
"Hello World" >>body
] >>display
The web browser uses a global variable called 'main-responder' as the first responder to try when a request is made. If we set 'main-responder' to the value of our responder then it immediately becomes available to a web request. So our entire simple web application is:
USING: http http.server threads furnace.actions ;
[ 8888 httpd ] in-thread
<action> [
<response>
200 >>code
"text/plain" >>content-type
"Hello World" >>body
] >>display main-responder set-global
Visiting http://localhost:8888/ should display a page with 'Hello World' as the text.

A responder that works just from the root of the URL is not very practical. A dispatcher is an object that can acts as a responder that calls other responders based on part of the URL. Here's a dispatcher that calls one responder when /hello is requested, and another when /goodbye is requested.
USING: 
furnace.actions
http
http.server
http.server.dispatchers
threads
;
[ 8888 httpd ] in-thread

TUPLE: my-dispatcher < dispatcher ;

my-dispatcher new-dispatcher
<action> [
<response>
200 >>code
"text/plain" >>content-type
"Hello World" >>body
] >>display "hello" add-responder
<action> [
<response>
200 >>code
"text/plain" >>content-type
"Goodbye World" >>body
] >>display "goodbye" add-responder
main-responder set-global
First I create a tuple called 'my-dispatcher' that inherits from the base dispatcher class. The I create an instance of this using 'new-dispatcher', create my actions and add them under the paths 'hello' and 'goodbye'.

Writing response objects gets a bit tedious. Factor provides two template systems that can be used to make writing web applications easier. One is 'fhtml' which existed in the previous web framework incarnation. The other, chloe, is an XML based templating language, and is covered quite well in the Factor documentation.

To create an action that uses a Chloe template, create a 'page-action' instead of an 'action'. Set the 'template' slot of the page-action to be a two element array containing the dispatcher class and the template filename (without the .xml extension):
USING: 
furnace.actions
html.templates.chloe
http
http.server
http.server.dispatchers
threads
;
[ 8888 httpd ] in-thread

TUPLE: my-dispatcher < dispatcher ;

my-dispatcher new-dispatcher
<page-action>
{ my-dispatcher "main" } >>template
"foo" add-responder
main-responder set-global
When this '/foo' is accessed on the webserver, this action will run. It will look for main.xml which needs to be a chloe template file. Here's a simple example template:
<?xml version='1.0' ?>
<t:chloe xmlns:t="http://factorcode.org/chloe/1.0">
<html>
<body>
<p>Hello!</p>
</body>
</html>
</t:chloe>
The chloe help goes into a lot of detail about how to use the template to substitute variable values, etc. I'll cover that in a later post.

The web framework has a lot of other features. Sessions, Authentication, Database, Validation, etc. Hopefully this will help you get started. All the example above can be entered and run (barring typo's and unescaped html entities) in a Factor listener. Download it and try it!

Update: There is a wiki page on the concatenative wiki with more information about the web framework.

Categories:

Labels: