META INFORMATION: This is the technical blog and wiki of Brock Wilcox (awwaiid). Entries focus on my current projects, interests, and sometimes life events. If you'd like you can check out the list of All Entries or the RSS Feed. I also have a LiveJournal syndication feed for LJ friends.
Oh how I love linux... perl... scriptability. I have a fun little command line music player named [Polly]. It is pretty minimalist, really just starting whatever player I like with whatever preferences I like on a whole directory tree of files. One thing that is annoying is that I have to switch over to the terminal and it ^Z to pause and then do 'fg' to play.
So I finally decided to write a simple pause toggle script. I approached this in the most brute force way I could... I just take the list of all my media players and send a massive STOP (effectively ^Z) command to all to pause, and then a massive CONT (effectively 'fg') to all to continue. To determine if I want to pause or continue, I just look to see if I have any paused player processes.
my @commands = qw( ogg123 mpg123 mplayer vlc sidplay2 );
my $cmd = join '\|', @commands;
if(`ps a -o state,cmd | grep '$cmd' | grep ^T`) {
map { `killall -SIGCONT $_ 2>/dev/null` } @commands;
} else {
map { `killall -SIGSTOP $_ 2>/dev/null` } @commands;
}Scott linked an article from new scientist, Memories may be stored on your DNA, which relates with what has been on my mind lately.
I was reading about some hardware evolution experiments while at the bookstore the other day. They were using a FPGA to create (evolve) a sine wave generator, if I recall correctly. The end result of the first run worked perfectly, but had some bizzare attributes -- it programmed a section of the gate array but didn't wire that section to the rest. When the unconnected section was turned off, the circut no longer worked. It also didn't work when the same design was put onto an identical FPGA. As far as the experimenters could tell, the evolved solution depended upon some subtle property of that specific FPGA chip.
In other words: GP solutions cheat like hell.
They will use absolutely any available subtle or side-effect aspects of environmental conditions to push themselves to the next rung on the fitness ladder. An important lesson that I've taken from GP is that artificial / automatic program generation mostly results in programs that make almost no sense from a human programmer perspective, at least partly because of all this cheating. The solutions produced by GP are mostly twisted convoluted things which mostly don't look like they work at all, let alone solve anything.
When a human abstracts things, it ends up taking a much more layered structure, with the meat of the problem usually ending up on the highest layer. Automatic techniques do not succumb to such niceties.
Speaking of human abstraction, I recently stumbled upon the Discordia page of Mark-Jason Dominus which makes a keen observation with fascinating attributes - "In a well-designed computer program, No two components are alike, or even similar." Conceptually, that is, all similar aspects of a program are abstracted. Good programs are themselves not like the beautiful fractals of recursion that lay in the mind of their creator or the algorithms that they represent. You could perhaps think of them as the compressed version -- the most informationally dense form of the logic, information theory might say.
Now take it full circle... from the biological inspired computation back to biology. Biological evolution cheats just like artificial evolution does. At first glance we see all this lovely DNA-level abstraction... but as they dig in they find all sorts of trickery that operates on all levels low and high. Like throwing in some assembly (or even better, some binary executable blobs) into the middle of my blog software. The re-use of DNA (or perhaps the coating on DNA was it?) as memory storage in the brain is completely typical.
If the designers were indeed intelligent, they sure didn't plan on doing any maintenance.
It's been over 4 hours since Android was released... but still no port to the Neo. Pft.
At the last minute I ended up giving a Lightning talk at OSCON 2008 (in the Perl track). I showed my Devel::REPL + Continuity debugging tool.
Here are my notes:
Lightning Talk OSCON 2008
Brock Wilcox
awwaiid@thelackthereof.org
See also:
* Continuity
* Continuity::REPL
* Devel::REPL
* Carp::REPL
* PadWalker
# .... These were then run in the REPL ....
# counter.pl at:
# http://thelackthereof.org/projects/perl/Continuity-Monitor/eg/counter.pl
use PadWalker 'peek_my';
my $h = peek_my 23;
${ $h->{'$counter'} } = 77;
# Then...
sub new_prompt {
my ($request) = @_;
$request->print("Muahahaha!");
return old_prompt(@_);
}
*old_prompt = *prompt;
*prompt = *new_prompt;Some of my family came to visit this weekend, and we did a bunch of sight-seeing. Here are the distance estimates, this is definitely a lower-bound of the amount we walked. I tried to include walks that I know everyone did, and left off a bunch of random trips to the store. Distances are in miles.
TOTAL: 7.14
TOTAL: 3.6
TOTAL: 1.96
TOTAL: 4.2
GRAND TOTAL: 16.9 miles
I'm guessing that adding in more detail could easily add another mile or more. In the end I bet we walked about 20 miles in all. When you trade a car for your feet, make sure you have good shoes!
Comments on TLT - 2008.07.08 - Walkabout
great walkabout notes! --- btw, if in DC area and want a walking companion any time, don't hesitate to ping me (though I'm mostly into jogging) ... (confession: main purpose of this is to test the Comment Count feature) — ^z
-- Mark Zimmermann 2008-08-11 11:53 UTC
I got another new camera!
The last two didn't work out for very long, but this one has promise. I won it at our recent Corporate Bowling event... it was clearly my best score ever at 167. I got second place and thus the camera. Woot!
This first image is one of Sophia's flowers. Sophia is the rose bush that Beth got from my family in condolence of her appendectomy. After almost killing her (Sophia, that is), I've nursed her back to health and we've been rewarded with new blooms.
Other than random events and trips, one thing I'd like more photos of is my balcony garden.
Time lapse or something fun. I sit there and stare at the thing enough... I may as well share the green joy with the world!
Lets see... what what other sorts of boring photos do people put on their blogs... CATS! I must have some of those somewhere around here...
I've been using the Tree Style Tabs Firefox extension for a few months now, and love it! Having vertical tabs has always been fabulous, ever since I first encountered them in Galeon. The chrome-css hack that I have been using for the last few years in Firefox stopped working in Firefox 3 (beta), so I went exploring and am very glad I did.
Not only does the Tree Style Tabs extension give my my vertical tabs, it also gives me (surprise surprise) a tree of them! Each has it's own browsing history, and subtrees can be collapsed and reordered and all that wonderful goo.
Just now I was playing around with the settings and thought I'd try the auto-hide feature. I'm not sure I'll keep it because there is a slight flicker that bothers me... but it is neat none-the-less! The tab bar is hidden, and then when I mouse or keyboard activate it the bar appears translucently on top of the page. It might need some kinks worked out (or perhaps there is some other cause for the flickering), but I think I like it!
Highly recommended.
I love to create and build -- lately I've made a few songs! My friends like to play guitar and sing, and I play the harmonica and am learning guitar. So here are my recent creations (all with the help or in conjunction with friends):
Only the middle one has a recording posted so far, but I'll get recordings of the others sooner or later. More to come I hope :)
Happy New Year!
I've been grappling with a concept for a long time now (years), and thought I'd put it down here to cast about for insight.
Here is one way to handle UI events:
$page->add_action(add_new => 'Add New Entry');
$page->display; # displays template, waits for input
$action = $page->get_action;
if($action eq 'add_new') {
add_new_entry();
}Here is another:
$page->add_action('Add New Entry' => sub {
add_new_entry();
});
$page->display; # displays template, waits for input, runs callbacksThe first is quite imperative. Show the page. Give me the result. Examine the result. Act. The second is much more declarative. I declare that were such an action to occur, this is what you should execute.
The second is the way that Seaside handles things. I'm not quite sure why I'm reluctant to adopt this method... perhaps simply my lack of experience with this construct is to blame. I think it's some sort of voice in the back of my head that doesn't like it because it is a bit too much like desktop GUI callbacks. But why should that be a bad thing? It seems to work just fine for those applications.
I think I'm thinking about this too much.
Tonight I am doing a bit of work on the EPFarms User Panel and Effin, our financial database. The Panel is a Continuity application running under FastCGI and suexec. The security model is different from most other web applications I've done, we use suexec to run the application as the individual Eggplant Farms user.
Philosophically, running the panel as the user is an extension of our overall security model, which is to build as directly upon the unix security model as we can. The interesting aspect of this is that, since the panel is running without any special privileges, the user could modify or replace the panel and still have all the same security access. They also have all the same access from the command line.
Sharing dynamic data with the user, such as their current account balance, is a bit tricky. We also need the ability for the user to modify some of their own metadata. Our current plan is to create command line tools that allow them user-specific access to our data, which is stored in MySQL.
Another way, the one that I'm going to switch to after tonight's research, is to utilize some new features of MySQL 5. We'll use views to emulate row-level security, and MySQL's own column-level security to allow them to directly read, and as appropriate write, to our database. Though it's always handy to have a command line interface, the extra intermediary was a bit cumbersome.
Here's how to do it.
Lets say we have a single userinfo table, which just holds their username, unix id, full name, and emergency contact info. And heck, let's insert a few rows.
create table userinfo (
userinfo_id int primary key auto_increment,
unixid int,
username varchar(100),
fullname varchar(100),
contact varchar(100)
);
insert into userinfo set
unixid = 1001,
username = 'awwaiid',
fullname = 'Brock',
contact = 'a@b.org';
insert into userinfo set
unixid = 1001,
username = 'aardvarq',
fullname = 'David',
contact = 'x@y.org';Now we create a view, limiting to the current logged in user with the USER() function.
create view userview_userinfo as
select *
from userinfo
where username = SUBSTRING_INDEX(USER(),'@',1);Finally we grant some access to user 'awwaiid' (though really we could grant access to '%' if we were so inclined).
grant select on userview_userinfo to 'awwaiid'
grant update (fullname, contact) on userview_userinfo to 'awwaiid'Now when I log in as awwaiid I have access to my own rows, and can update my full name and contact info. The panel application logs into the database as the user, accessing and editing their data in a much more direct fashion than the command-line-wrapper method.
2 Comments.
Thanks for adding links!
-- awwaiid 2009-06-13 04:00 UTC
You're very welcome. I hope that clears it up for future readers.
-- Mortal 2009-06-13 22:08 UTC
2 Add Comment