Category — All things code
OSX Style Monitor Switching On Ubuntu
I recently decided it was complete bullshit that you can’t just plug in an external monitor and switch to it easily in Ubuntu. In OSX you’ve been able to do this for years. You just plug in your external monitor and it automatically switches to the last known good configuration for that monitor.
Anyway, with a little searching I discovered that there are some tools that you can use to get very close to this behavior on Ubuntu. I’ve been using two tools, disper and auto-disper for a few months now and they are fantastic.
Firstly, disper will let you switch to an external monitor effortlessly from the command line. Whether it’s ever seen that monitor or not, it will choose the sensible default resolution and just make it so. To wit: disper -S to switch to external, disper -s to switch back to internal (the difference is the case of the ‘s’). This tool can do much more, but that’s my 99% use case.
Then you add auto-disper --save <profile-name> to the mix. This will let you store a profile for the current configuration of the monitors that are present. Then when you call it with auto-disper --change, it detects the present set of monitors and switches to the profile that matches them.
Depending on your graphics driver, you may or may not be able to go a step further and automatically call auto-disper --change when a new monitor is plugged in. My NVIDIA drivers won’t do that, unfortunately. If they could then it would be almost equal to the OSX functionality. As it is, it’s quite close enough, and I am happy.
I did a full writeup on how to do all of this on the Ubuntu wiki. See DynamicMultiMonitor.
December 9, 2011 No Comments
Ajaxy Edit-In-Place with Autocomplete
I’ve been working on creating a slick UI for WikiGini, a new genealogy project I’m building. As part of that I’m using the “Best In Place” jQuery plugin for in-place editing, and the corresponding gem for Rails 3. I’ve also been using the jQuery Autocomplete plugin to provide an autocomplete drop-down as you type. Today I managed to marry the two, for a rather spectacular result.
Here’s how it goes. First, we add this JavaScript code to our page.
$( function() {
/* Initialize a custom form type "autocomplete" for best_in_place */
BestInPlaceEditor.forms.autocomplete = {
activateForm : function() {
var output = '<form class="form_in_place" action="javascript:void(0)" style="display:inline;">';
output += '<input type="text"';
output += this.inner_class ? ' class="' + this.inner_class + '"' : '';
output += this.options.autocomplete ? ' data-autocomplete="' + this.options.autocomplete + '"' : '';
output += this.options.id_element ? ' data-id_element="#' + this.options.id_element + '"' : '';
output += ' />';
output += this.options.id_element
? '<input type="hidden" id="' + this.options.id_element + '" name="' + this.options.id_element_name + '" />'
: '';
output += '</form>';
this.element.html( output );
this.element.find( "input" )[0].select();
autoCompletePerson( null, this.element.find( 'input' )[0] );
this.element.find( "form" ) .bind( 'submit', {editor: this}, BestInPlaceEditor.forms.autocomplete.submitHandler );
this.element.find( "input" ).bind( 'blur', {editor: this}, BestInPlaceEditor.forms.autocomplete.inputBlurHandler );
this.element.find( "input" ).bind( 'keyup', {editor: this}, BestInPlaceEditor.forms.autocomplete.keyupHandler );
this.element.find( "input" ).bind( 'keypress', stopSubmitOnEnter );
},
getValue : function() {
return this.sanitizeValue( this.element.find("input")[1].value );
},
inputBlurHandler : function(event) {
event.data.editor.abort();
},
submitHandler : function(event) {
event.data.editor.update();
},
keyupHandler : function(event) {
if ( event.keyCode == 27 ) {
event.data.editor.abort();
}
}
}
/* Activate in-place ajaxy editing with best_in_place */
$( ".best_in_place" ).best_in_place()
} );
/* Activate autocomplete plugin for specified element */
function autoCompletePerson( index, element ) {
$( element ).autocomplete( {
minLength: 2,
select: function( event, ui ) {
var $autoCompleteField = $( this );
$( $autoCompleteField.data( 'id_element' ) ).val( ui.item.id );
$( $autoCompleteField[0].form ).submit();
}
} );
}
/* prevent form from being submitted on "enter" keypress */
function stopSubmitOnEnter(e) {
var eve = e || window.event;
var keycode = eve.keyCode || eve.which || eve.charCode;
if (keycode == 13) {
eve.cancelBubble = true;
eve.returnValue = false;
if (eve.stopPropagation) {
eve.stopPropagation();
eve.preventDefault();
}
return false;
}
}
The first block you see is extending the capability of Best In Place with a custom type of form, “autocomplete”. You can look in the best_in_place.js file to see how this compares to the implementations of the other form types.
Next, we activate the Best In Place editor with $( ".best_in_place" ).best_in_place().
Then we declare a function autoCompletePerson() that is called from our Best In Place code up above. This function initializes the Autocomplete plugin on the input element created when Best In Place creates the editing form.
Finally, we declare a function stopSubmitOnEnter(), which is bound to the input element to prevent the form from being submitted when the user presses the enter key. This forces them to choose an element from the drop-down.
Then on the Rails side, we initialize our Best In Place element in the “show.html.erb” file:
<%=
best_in_place( @person, :father_id, {
:type => :autocomplete,
:nil => '<span class="nil">Click to add father</span>',
:path => update_father_person_path,
:value => @person.father ? @person.father.name : '',
:autocomplete => autocomplete_person_name_people_path,
:id_element => "person_father_id",
:id_element_name => "person[father_id]"
} )
%>
Here we’re using the standard Best In Place Rails gem features as described in Bernat Farrero’s blog post, as well as a custom :value, and several custom elements that will be used by the JavaScript code we discussed above to create the edit-in-place form — :autocomplete, :id_element, and :id_element_name.
And that’s it! The modifications I made to the Best In Place code allow for the custom elements to be specified through the Rails helper, and places them in the this.options array in the JavaScript, so they can be used in our custom Best In Place “autocomplete” form type.
I had to make some updates to the Best In Place code, which you can find on my Github fork of the project.
The code here has been simplified from the actual code in the application, so leave a comment if something is missing or confusing.
I should also note that the code given has an additional feature, which may or may not be desired by the reader. The Rails model I’m working on here is called Person, and each Person can have an associated “father”, which is a one-to-one relationship with another Person. This autocomplete code doesn’t just autocomplete on the names of People in the database and store the name string. It autocompletes on the names of the people in the database, and when you select the person from the dropdown it actually submits the ID of that person, so that the proper association can be made on the model. This is both awesome, and extra complicated if all you want to do is autocomplete on a string. To do that, you’d just strip out all of the “id_element” related code and it should work for you.
February 27, 2011 No Comments
Skype Extension for Chrome
I’m working on a Chrome extension that will link phone numbers within pages so you can call them with Skype. It’s rough, but check it out if you’re interested:
https://github.com/jacksenechal/Skype-for-Chrome
In particular, I haven’t figured out how to make the external URL handler that Chrome uses on Linux (xdg-open) recognize the `callto:` link format. This plugin may just work for y’all out there on Windows or OS X though, I don’t know. I’ll post an update when I have more.
February 17, 2011 No Comments
Android video encoder
I wasn’t having much luck finding an easy way to encode videos for viewing on my phone, so I cooked one up. I followed the instructions for ffmpeg as listed here, and wrote a Ruby wrapper that detects the dimensions of the video and scales them down to the right size for you phone.
The script is simple so it can be easily edited to include your preference of encoding switches to ffmpeg. It’s using the h264 codec, which is a bit slower to encode but makes beautifully smooth high quality videos and a fraction of the size of quicker methods.
Grab the script at Github: https://gist.github.com/823686
February 12, 2011 No Comments
Flex Text height within a List
There’s a little trick if you’re trying to use a Text component as part of a custom itemRenderer for a List. The Text component will automatically wrap the text and set its correct height. However, when it’s in a list, you may find it gets cut off anyway. You have to set the variableRowHeight attribute of the List to true.
January 9, 2011 No Comments
Bi-directional relationships in Rails
Really that should be “Bi-directional self-referential relationships in ActiveRecord models”, but that’s just too much to say!
A common example for this would be if you had a Person model and a Friendship model, and you wish the friendship between two people to be a two-way road, like on Facebook. The project I’m working on is a genealogy application that has partnerships (eg. marriage) between two people, but it’s the same deal.
Now typically, :has_many relationships in ActiveRecord are uni-directional. You have to do a little bit of trickery to get it to happen both ways. Here’s the code.
January 3, 2011 No Comments
Getting started with OSMF & Flex 4 on the Linux Command Line
If you’re using Flex on the command line without Flex Builder, the documentation for getting up and running with OSMF is pretty slim. Here’s what has worked for me. (I upgraded to Flex 4 to get access to all of the OSMF features, but you should be able to do this with Flex 3 as well).
First, get the latest OSMF from the downloads page: http://sourceforge.net/adobe/osmf/home/. There’s an older version packaged with Flex 4, but OSMF is evolving very quickly so get the most recent.
Unzip that basically anywhere. It doesn’t fit neatly into the Flex directory structure, and if you try to replace the old OSMF files in the Flex package you’ll have problems building the asdocs, so just pop the new OSMF in the Flex home directory or something.
Now to get Flex to use it you have to tell the compiler where to find it, and add a few tweaks. Here’s my mxmlc command:
mxmlc \ -compiler.source-path=/path_to_new_osmf/framework/OSMF/ \ -define CONFIG::LOGGING false \ -define CONFIG::DEBUG true \ -define CONFIG::FLASH_10_1 false \ -compiler.debug=true \ -static-link-runtime-shared-libraries \ YourFlexApp.mxml
That should get you running! Check out these resources for some basic examples. Keep in mind that since OSMF is changing so quickly, you may have to look around for where this or that package is hiding today…
OSMF + Flex Example [brooksandrus.com]
New Intro to Adobe OSMF Videos [almerblank.com]
December 18, 2010 No Comments
Using Flex 4 with the Flex 3 ‘Halo’ Theme
With Flex 4 comes “Spark”: a much more “flexible” (haha), and in my opinion much less beautiful theme than the one in Flex 3. Of course, you can use Spark to create all sorts of beautiful things, but if you’re looking for something pretty out of the box, it’s not that.
The Flex 3 theme is called “Halo”, and as described here, you can still use it in your application with the inclusion of a compiler argument:
-theme=${flexlib}/themes/Halo/halo.swc
However, I found that there is an annoying bug whereby a warning message is now shown when you compile the application.
frameworks/libs/framework.swc$defaults.css(488): Warning: The style 'dropShadowVisible' is only supported by type 'mx.controls.List' with the theme(s) 'spark'.
I realize it’s a deplorable hack, but my simple solution is as follows. Open framework.swc (it’s just a zip file), and edit defaults.css. Comment out or delete line 488, save it back to framework.swc, and voilà! No more nasty warning.
December 16, 2010 1 Comment
Batch CD and DVD ripping/burning
I was faced with the task of ripping a few box sets of DVDs and CDs today, and after a quick and fruitless “topeka” search for a way to automate this, I wantonly decided to write my own.
A short time later I had a nice Ruby script capable of ripping discs to images without any user input, except sticking in the next disc after one is ejected. It can also reverse the process and take sequentially named image files and burn them with the same ease.
I’d been wanting to try out this great Ruby gem “commander” for a while. It was a breeze to get a full-blown command-line interface up and running with this thing. Truly amazing, Ruby style. Following some very sage advice I have recently forsworn bash programming in favor of more friendly modern scripting languages, and I must say… I’m definitely not going back!
I was quite pleased with the way it turned out, so I thought I ought to share. This is another first for me today: it’s the first open source project I’ve released! Well, almost. I wrote a 4D fractal generator back in university, and it’s probably still lurking around on SourceForge somewhere… with a grand total of 240 downloads after 1964 days of inactivity
. It was pretty alpha-state software, so I’d be surprised if it got much use. I honestly still think about going back and improving it one of these days, when I have time. Haha… time. We’ll see eh?
Anyhow, I’ve called this script “Jack’s TehRipper”, and you can find it on Github at http://github.com/jacksenechal/TehRipper. I released it under the MIT license, so grab a copy, fork it to your heart’s content, whatever.
Using it is quite easy. Running tehripper by itself gives you a list of the available commands:
NAME:
tehripper
DESCRIPTION:
A program to batch read/write raw CD audio or CD/DVD data for backup
COMMANDS:
help Display global or [command] help documentation.
read-audio Reads audio data from CD to new local directory, eg. "./cd1/"
read-iso Reads DVD image to working directory, eg. "./dvd1.iso"
write-audio Writes audio data to CD from local directory, eg. "./cd1/"
write-iso Writes DVD image from working directory, eg. "./dvd1.iso"
The commands also take some arguments, for instance:
OPTIONS:
--start n
The starting number for image file naming (defaults to 1)
--end n
The ending number for image file naming (defaults to 1)
--prefix string
The prefix for the image file name (defaults to "dvd")
So to copy a disc image in ISO format to your local working directory from a DVD in your drive, you would just say:
tehripper read-iso
Or to make ISOs of your uber-favorite i luv u 4evar 10-DVD set, you would issue a command like:
tehripper read-iso --start 1 --end 10 --prefix The_Princess_Bride_Collectors_Edition_Box_Set
How much cooler could that get?
August 29, 2010 No Comments










