A Perl script catalogs books and CDs with the help of barcodes
Off to the Base
The upcscan program uses the CPAN Rose::DB database wrapper to identify the database schema and insert new records into the articles table (Figure 6). Line 23 identifies the database file articles.dat in the current directory as an SQLite database, and the subsequent AutoCommit and RaiseError options ensure that new entries are written to the database without an explicit commit command and that any error that occurs immediately throws an exception.
The make_classes() method in line 27 imports the database objects into the script code, and because of this, I can simply say Article->new() later on to prepare a new entry in the articles database table.
Widgets in the POE Flow
The graphical interface is running in the main window, $top, which line 29 accepts from the $poe_main_window variable, which is exported from POE. The GUI's event loop is not left to its own devices in the script but needs to cooperates with POE's kernel.
If use Tk appears before use POE in the code, POE knows that it has to prepare an event loop for the Tk GUI; it initializes the main window and creates a pointer to it in $poe_main_window.
The configure() command in line 30 stores the UPC Reader title string in the window header and sets the background color for the GUI to #a2b2a3 (light olive green).
At the top of the window, you can see the entry widget $entry, which accepts sequences of numbers from the scanner and stores them in the global variable $UPC_VAR. Farther down is a photo widget for the book and CD covers; for organizational reasons, it is embedded in a label widget. Four Label-type widgets follow that store the title ($PRODUCT), the author/artist ($BYWHO), the scanned UPC or EAN code ($UPC), and a status message ($FOOTER).
The for loop in line 50ff. drops the widgets, top down, into the main window and calls -fill => "x" and -expand => 1 to ensure that the labels fill the horizontal space up to the border and automatically scale when the main window is expanded.
The bind() command in line 56 plays an important role. The entry widget ignores the Return character sent by the scanner because the input field is a single-line field. The bind method binds the Return key's keyboard code to the scan_done() function defined in line 68ff. to trigger processing of the code read in by the scanner.
First, the photo object's blank() method is called to remove the previous cover image. Then the title and author/artist names are replaced with blank strings. A "Processing …" message appears in $FOOTER, and the request is sent to Amazon by calling amzn_fetch(). To get ready for the next scan, line 78 immediately deletes the code read by the scanner from the entry widget. The barcode for the current product is stored in the $UPC widget.
After completing these preparations, line 58 defines a POE session, and line 65 launches the POE kernel, which controls the program from this point on until it is terminated. The POE kernel accepts user input, mouse clicks, or keyboard/scanner input and makes sure that a time slot is assigned to each handler triggered by an event. POE is very strict with the sessions it controls. If they do not have a task to complete, they are eliminated. POE does not understand that a Tk application might just be waiting for user input. To prevent it from killing the GUI, lines 58 through 63 define a session that jumps to the _start event every 60 seconds.
Once the scanner has returned a UPC or EAN code, the amzn_fetch() function in line 82ff. creates an instance of a Net::Amazon object and passes in both the developer token (you will need to apply to Amazon if you do not have one yet – see the "Installation" section below), and the global special agent LWP::UserAgent::POE, which not only retrieves web requests, like its base class LWP::UserAgent, but also collaborates with POE.
A Net::Amazon::Request::UPC-type request object talks to the Amazon web service that provides the UPC/EAN lookup facility. The request must state up front whether it wants to search for the UPC/EAN code in the Books, Music, or DVD sections.
Because the scanner does not know whether it is scanning a book or a CD, the for loop that begins in line 93 simply tries all three supported sections and terminates as soon as Amazon reports a successful search. The response returned here offers the is_success() method, which tells you whether a matching code has been found.
The amzn_fetch() function returns three parameters: the response object $resp, the section in which the match was found (Books, Music, or DVD), and the scanned UPC/EAN code.
The resp_process() function defined in line 114ff. grabs the results and uses it to update the GUI fields. The ImageUrlMedium() method for the retrieved article in $property includes a URL for a medium-sized JPEG image on Amazon's server depicting the product cover.
The Raspberry Pi Foundation has announced an even smaller version of the tiny computer that will fit into a DIMM slot.
A new class of problems lets a malicious app pre-configure an invisible privilege update.
New Hack language adds static typing and other conveniences.
New crypto policy system will offer easier configuration and more uniform security.
Ubuntu founder denounces insecurity in proprietary, close-source software blobs.
Vulnerability affects many Linux web servers
The Bavarian capital shuns Microsoft, Google, and other alternatives to implement an open source groupware solution.
Phone vendor partnerships bring Mark Shuttleworth's dream of Ubuntu on a phone a step closer to reality.
Donors will get to vote on new features for the free video editor.
Debian project puts init out to pasture and says no to Ubuntu's Upstart.