Western Digital Caviar GP 500GB 5400 to 7200 RPM SATA Hard Drive
So I needed a new hard drive for my mp3’s and went to my fav site newegg.com, since they deliver next day in NYC from Edison NJ for most items for free or with just standard shipping. I found a new class of hard drives (if you consider one to be a class), that I decided to give a whirl, the new Western Digital Caviar GP WD5000AACS 500GB 5400 to 7200 RPM 16MB Cache SATA 3.0Gb/s Hard Drive. In general, I am not looking for the highest performance from an mp3 hard drive, and most of my hard drives in general really. What I focus on is cool and quiet operation, and reliability. Man, is this thing cool and quiet! It uses a lot less power since it can spin down to 5400 rpm, and essentially feels room temperature when running at 5MB/s when transferring my collection over the network. It can ramp up to 7200 rpm if it gets under serious load, but I doubt I will stress it too much with my usage patterns. I’ve had problems with drive heat in some of my recent drives, a just had to RMA my Maxtor MaxLine 500GB drive that started developing the ‘click of death’. This drive only comes with a 3 year warranty, though that is much better than the standard 1 year warranty of a couple of years ago from most consumer grade devices. That was why I originally switched to MaxLine, as they had 3 year warranties back when everyone else had 1 year, and now they have 5 year warranties. But this thing is so much cooler and quieter (less vibration), that my gut instinct says it should fare very well. The only other thing I’m not sure of is if this drive is suited to be used in a hardware RAID setup. Seems more and more drives come in ‘RAID’ editions these days, or you may need to upgrade the firmware, etc.
Drive noise, and drive cooling fan noise is a major contributor to overall system noise in many cool and quiet designs. Cool and quiet is important for me, as my main system is in my bedroom. This thing is sitting right next to me in a usb enclosure and I can’t hear a thing. I’ve never really used Western Digital drives, though for speed I know the Raptor is the best out there. They certainly got it right with this drive. And the price is the same as regular 500GB hard drives, so you don’t have to pay extra for the privilege.
UPDATE: It’s come to my attention that these drives are simply 5400RPM, not some hybrid speed changer. That said, these are still green, quiet drives. While you might not want to use them for a system disk, they are great for anything else that would actually need 500GB, like videos/mp3/downloads/etc.
Docuverse: Idea for Peer to Peer Anonymous Document Repository
So in my dealings with various document communities out there (first rule of Fight Club = Don’t talk about Fight Club), I see a huge inefficiency out there, and single points of failure. This has led me to the think about ways in which these various problems could be solved. Here are the main problems with these communities I see:
- Format proliferation: Everyone has a favorite document type they want for their particular viewer/reader application. HTML, TEXT, RTF, DOC, PDB, LIT, etc.
- Versioning Issues: Many times these documents are flawed when initially released and require iterative improvements. And while many documents adhere to the community standard version rules (which are themselves pretty lax), many do not. So when combined with the format proliferation mentioned above, it can be challenging to find the best version of a document out there, and clogs up hard drives with all of the various versions. Both this and format proliferation also increase the time it takes to search for and retrieve the document the user wants.
- Single or few points of failure: Many documents that are older no longer get served by many of the community members, or if those members decide to no longer be involved in the community, whole swathes of documents may be lost. While there is a certain level of redundancy built in to the system, it is not the type of redundancy that leads to a long-term healthy document library. Also, in many cases there are choke points for document distribution. There are several brave and dedicated souls who contribute the bulk of the effort and bandwidth required to provide the document library maintenance and distribution capability. But this leads to longer download times and strain on these ‘backbone’ users.
- Proofing Effort: Again, because of the release cycle and existing methods, there is a barrier to entry for new and less dedicated users to contributing to the community by editing flaws found in the documents. Ideally, as each and every reader was reading their document, they would be able to easily indicate corrections, that would then propagate to the rest of the community without having to deal with the whole verisoning/format/duplicate files issues.
- Lack of Anonymity: Due to the nature of some of documents, there may be liability if any individual is recognized as the creator/distributor of the document, so creating some sense of anonymity would be preferable.
So my idea is to create a p2p application that incorporates solutions to these issues, while hiding much of the complexity needed to solve them.
- Create a standardized, extensible format (XML based presumably) for document encoding. Provide converters for all of the major file types, with user customizable styles, so when files are released they can be converted to the user’s contentment. Provide for all standard document entities and formatting, as well as the aforementioned extensibility to allow for more arcane formatting innovations.
- Provide for Wiki style versioning of these documents, where anyone may be allowed to edit a document for corrections, but that the entire history of corrections is preserved so that malicious edits can easily be reverted. Limit edit size and frequency to prevent mass malicious corruption. Create a voting/approval system whereby corrections can easily be undone for any malicious edits on a mass level.
- Create a giant massively redundant distributed and encrypted database to store these encoded documents. Users would be required to provide a minimum amount of shared space on their hard drives to store file indexing information and database storage (say 1GB minimum). Many ‘power users’ would obviously provide much more space. Most document communities are around the 1TB range. Ideally, many users providing 100GB or more of storage would allow for redundancy on the order of 10x. Users would not know which files/portions of files they were hosting. Popularity would be used to provide more redundancy for those files requested by many users, while still maintaining a certain level of redundancy for unpopular files or for users entering and leaving the peer group. This would avoid the problems of other p2p communities hopefully, where files may be available shortly after release, but quickly disappear if not for a few dedicated seeders.
- Provide for decentralized pseudo-anonymity where all file requests would be delivered through an intermediary user, who acted strictly as a conduit for that request. This would double the bandwidth requirements for the system, but should fall well within the realm of acceptability considering these are mostly text documents, while providing a level of security to everyone in the community. More research would be required to see if there was a way to make it truly anonymous, without the need for centralized servers.
- Create reader/viewers for all major operating systems and devices, that allowed the user to read and edit the documents seamlessly.
Anyway, this is an idea rattling around in my head. Not sure if it could ever go anywhere, but it would go a long way in my opinion to solving a lot of the inefficiencies inherent in the existing communities.
I Like Bulleted Lists
If you haven’t noticed from my blog postings, I like bulleted lists. It just helps me order my thoughts as well as makes it easier for me to edit/correct/add ideas without having to search for the right place to say it. This probably corresponds to the ‘outline’ phase of actual writing, but then I was never really that great at writing to begin with. :P
Biting the Hand That Feeds Me
So this is a note to all of the uploaders of the world. Your efforts are much appreciated…but…I do have a few gripes about some of the more annoying and time consuming aspects of poorly uploaded files. All of these fall in the ‘if you spend the 30 seconds to do it, then you will save hundreds or thousands of other people that 30 seconds and the added frustration’ category.
General
- It is OK to use spaces in file names. No, really. If you are using an OS that doesn’t handle spaces in the filenames, then you probably aren’t reading this blog. Underscores (_) are NOT spaces. There was probably some rational against using spaces in file names years and years ago, but that ship has long since sailed. The ONLY possible issue I could see is if you are using bash or some other shell that escapes spaces with a slash (\). Or maybe you have a MIRC server script that is older than you are. There really is no excuse.
- When creating PAR2 repair volumes, do NOT put other crap into the volume set that isn’t part of the final product. That means, I shouldn’t need to have an SFV, and NFO, a 100mb sample file, or any other garbage besides the RAR files to get my download to repair.
MP3s
- If you are going to go to the trouble of uploading MP3s somewhere, have the decency to put accurate id3 tags in the files. Seriously. It just wastes a ton of time for a ton of people to have to redo them.
- It is a good idea to upload par2 files with your mp3s, so people can fix them. This mostly means NNTP these days, since p2p does a good job of validating these days.
- If you do upload par2 files, then please name them appropriately…don’t name them .par2. Because, sadly this seems like a common issue, and you just end up with overwritten par2 files. Or ‘D.par2’ isn’t really helpful either.
- Rip your stuff at least at 192 VBR. That’s pretty much the sweet spot for size/quality. Go higher if you want, but definitely don’t upload stuff at 128 CBR.
- Don’t tag your mp3’s with spaces between the characters. ‘R E D H O T C H I L I P E P P E R S’ is not really helpful. Maybe it’s a UNICODE thing, but how often do you actually see unicode in id3 tags?
Movies
- Along with the spaces thing…File names no longer need to by 8.3. You can use literally hundreds of characters if you want. ‘tia-ree.iso’ is sooo not helpful. Why not just name it ‘Resident Evil Extinction.iso’ instead? Then we won’t have to waste time mounting the iso’s and opening our media players just to see what it is. I have no problem with including a group name in the filename, just make the whole thing actually useful. ‘Resident Evil Extinction.DVD9.TIA.iso’ is fine too.
- Do NOT ask me to join some IRC channel just so I can find out what your 5GB upload actually is, I like the idea of being able to go somewhere and request something, and think it is a handy way to add value to some of the larger USENET groups, but still, just leeching shouldn’t require me to join an IRC channel.
- Don’t release a 9GB HD rip of something. If your encode went over, then suck it up and reencode it to DVD9 size (which is more like 8GB). Same with 5GB files and DVDR size. Maybe in another year or so, when harddrives are 10 cents a GB, that would make less non-sense, but until then, lets stick to the program.
- Don’t have your release NFO files have spaces between everything: ‘h t t p : / / u s . i m d b . c o m / s o m e t h i n g’ just pisses everyone off since the are just going to have to type the name now anyway rather than deal with the spaces.
- This one may just be me, but I actually prefer RAR volume sets that have ‘part001’ in the name, only because it means that the only RAR file you care about, the first one, shows up first in a directory listing, rather than what happens with ‘R01’, etc.
- Learn how to post in USENET so that the files are ordered properly in an alphabetic list! Starting your post with [001/100] is not acceptable. It just leads to dozens of uploads being ignored. Always put the title of your upload first, like ‘The Bourne Ultimatum.rar [001/100]’ so the files stick together and are easy to select without having to use search filters.
TV
- Consistency in naming would be nice. ‘tds’, ’the daily show’, ’the.daily.show’, ’daily_show’: just go with ‘the daily show’ and be done with it. ‘s01e21`, ‘01x21’, ‘121’: Executive decision here, go with s01e21. It isn’t any better or worse than the others. but just stick with one.
- Don’t put the episode name into the file name, unless you are releasing an entire season at once, especially on bittorrent. Everyone’s uTorrent RSS feed regular expressions break if you start throwing stuff other than the show name and episode number in there.
These are all minor things, I know. But like so many ‘little things’ in life they add up. So take this with a grain of salt, but it’s something I needed to say. :)
Flivver: Building a SWF to FLV server application
Working in the ‘media sharing’ space, I’ve come across the need for a SWF to FLV application (swf2flv). There are a number of products out there, and some oldish Python scripts, but none of them really satisfied my needs. Some of the products out there are by Sothink and Scout. I needed something that could be called from a command line/console, and Scout does have a version that does that, though it costs $1000ish for a single server license. But it didn’t have one key feature I needed, so I started to look into what it would take to build my own. Hence Flivver (think FLV, not Aldous Huxley).
Here are the basic things that Flivver needed, with the one extra feature that I haven’t seen in any other SWF2FLV app:
- Process a SWF without any human interaction from a server: This won’t work with swf’s that require button presses, but for my needs I needed to take an audio/visual playlist created by a user and have it converted into something that user could possibly upload to YouTube.
- Video/Visual capture: Capture everything that happened in the FLV, including bitmap manipulations, and text, effects and transitions. While it wouldn’t be too hard to append a bunch of video files together, once you start adding affects like ‘Black & White’ to the video, you have to really consider how you are going to integrate you playlist with some pretty serious Adobe Premiere/iMovie type application to replicate it in a standalone video file.
- Audio Capture: In the same way as video, you need to be able to capture the audio as it occurs in the playlist, with transitions and effects.
- Be able to assign a playlist id to the SWF, so it can load the playlist from the internet. One of the key things missing in all of the SWF2FLV and SWF2AVI apps is the ability to set flashvars or otherwise interact with the SWF in any meaningful way. Specifically for my needs, I have to load the playlist from a web server application that stores the playlists created by the users. As far as all of the other server/console style converters, they don’t support any way of interacting with the swf being processed.
So as any good hacker would, I started searching google for info on how to do the various pieces: Video Capture, Audio Capture, Hosting Flash in an Application, & Talking to Flash from a Hosting Application. I found a lot of good information, but it is all about weeding out the bad. The first decision I made was that I was going to have to use the Windows environment for the application, simply because I am more familiar with it as far as GUI programming goes, and there was a lot more information on screen capture out there for it, as well as using video card acceleration to speed up the process. I had done some work with xine back in the day (dealing with the Via EPIA Hardware a few years ago, though nothing official), and just felt that for my needs the effort would have been to great to get a working version on linux. Also, in general our production servers didn’t have X11 running or sound cards anyway, so we needed our own GUI server for everything to work.
So then the question was whether to do it in C++ or C#. Although there are more examples in C++, I decided to go with C#, because I wanted to try something new. So that decision helped me narrow down my google searches.
First I needed to find C# versions of the DirectShow SDK, with examples, as I really didn’t want to learn all the ins and outs of dealing with DirectShow filters & COM. I finally came across the DirectX.Capture demo at CodeProject, which had about 50% of what I needed, and was the scariest part for me. The next piece I needed was a DirectShow Filter that did screen capture. I found a couple of those: UScreenCapture and VH Screen Capture filters. VH Screen Capture has a few more options I believe, but for now I am using UScreenCapture. So another 25% of the project down. Next I needed a way to capture the audio that was being played through the sound card. This is easily accomplished by setting the Audio source to ‘Stereo Mix’, and capturing with a reasonable volume at 44khz, 16 bit stereo. (NOTE TO LAPTOP/MACBOOK BOOT CAMP USERS: You may need to download some hacked SigmaTel HD Audio drivers or make some changes to your driver installation files to get ‘Stereo Mix’ to be an option for your Volume Mixer. Do some googling for “Sigmatel MacBook Stereo Mix”.) Finally, I needed a way to embed Flash into my C# application in a way that allowed me to call Flash methods. I found the instructions to this at this site. Note: that if you are using Visual Studio 2005 or newer, you will need to download a Flash ActiveX COM definition file as Microsoft stopped shipping one after VS2k3. You can find information here.
One challenge I wasn’t able to solve is having the output be in FLV format directly form the C# app. I specifically wanted to output On2 VP6 format rather than Sorenson, as it is much better quality at the same or even lower bitrates. I couldn’t find any free DirectShow filters for this, and the one’s from On2 cost $1000 per server again. The way to work around this is to use MPlayer’s MEncoder with the VP6.2 codec/filter installed (which even works on Linux although you need to create the settings vcf file on Windows). So Flivver is a bit of a misnomer, since it actually outputs AVI in xvid/mp3 formats, which is then converted by mencoder.
Now that I had all of my major technological hurdles taken care of, it was just a matter of integrating them into a single application. The basics pieces were:
- Add command line handling to the application so it could have information passed in from the server. Specifically, this app is called by a Ruby on Rails library. The app receives a post from the production Rails servers telling it which playlist needs to be processed, and this is then passed in on the command line.
- Get rid of any of the DirectX.Capture settings and UI that we don’t need. We know which specific filters we want to use, so we don’t need to deal with all of the selection menus, etc.
- Add some timing handling. There is no way I could tell to discover automatically the state of the SWF being loaded into the ActiveX control. The Flash onReadyStateChange didn’t really give me anything useful. Because I had access to the code for the SWF I wished to capture, I was able to add some communication between the the SWF and the C# app, so that things could be coordinated, like when to start capturing and when to end.
That’s basically it. I have created a SourceForge project for Flivver, though there is nothing there at the moment. I am still finishing up some of the integration details, and changing things from hard-coded stuff I needed for my particular usage to more flexible settings/command line based options. While there may be limited usage for something like this, I think it is still a cool little project and maybe will help someone else who has to solve a similar challenge. I’ve picked an MIT license for release, though I still need to go through all of the code I cribbed off of and see what the details for those licenses are, so that may change. At the very least you can use my instructions here to get going on your own if need be.
Sadly, flivver.com is a parked domain as a misspelling of ‘flower’.
And finally, thanks to my peeps at UGENmedia for paying my bills and encouraging me to put this out there for others.
Let me know what you think!
Aveda Anti-Humectant Pomade Replacement?
Ok. so I’m finally getting fed up with the crazy prices for Aveda Anti-Humectant Pomade(AAHP). It’s not that I can’t afford it, it’s just the principal. It’s the only product I’ve found that tamed my wooly mane, and back when I first started using it, it was $10 a jar for 2.5oz. Now it is approaching $20 a jar. One would think that as Aveda has become more popular, that economies of scale would kick in and the price would at least be able to maintain. In fact, it probably has, but in the standard ‘if it’s expensive it must be better’ mentality surrounding all things beauty, inflating the prices is probably part of the marketing strategy.
In response, I’ve decided to go on a hair product odyssey, trying out everything that drugstore.com has in the pomade/wax section in the $5-6 range. Since I spend over $100 a year on the AAHP, I’ve got a little leeway to see if I can’t find something else that’s as good. So if you see me having a bad hair day, you know the reason. If anyone out there in the Intarweb has any thoughts or recommendations, let me know!
Update:
So far, the only product that I’ve found that even comes close is Canu’s Shea Butter, lol. It’s basically like putting petroleum jelly in your hair. It does a pretty good job, not quite as good as Aveda, but at a quarter of the price. Though it makes me think of those hair/AstroGlide moments.
I actually found a site that sells raw ingredients for beauty products: The Personal Formulator. They have most of the main ingredients for AAHP, Capric/Caprylic Triglycerides for 12$ for 32oz., Isopropyl Palmitate for 8$ for 32oz., and others. I’m almost tempted to try my hand at making my own since the price is so nice: $1 for 2.5oz-ish versus $20. If I get up the nerve and actually try it, I’ll let you know.
Using Drop Down Menus for Birthday and State in Web Forms
So in my dealings with clients and filling out the forms of websites in general, one thing keeps bugging me over and over: sites that ask for your birthday using drop down list for month/day/year and sites that use drop down for state selection for your address. There are some basic usuability issues here that really drive me nuts, if the web designers thought about it for more than a minute.
First off, why do you even need to know my birthday to begin with? I guarantee that 90% of the people just go straight to the drop down list for year, set it to something over 21 and go on their way. It isn’t like ‘birthday’ is any more legally helpful than simply asking for your age. Why not just let the user enter ‘35’ for their age and be done with it. I bet you would find that you end up getting a lot more accurate information out of your users in that situation. Typing two numbers is sooo much easier than dealing with drop down menus. If you want to keep the age up to date, all you need to do is keep track of the date they set their age, and adjust it accordingly when you retrieve it. Barring that, if for some reason you just have to have birthday info, then why not at least provide an easy way for the user to put in ‘4’ for the month, ‘16’ for the day, and ‘1982’ for the year? Again it is just that much easier to do.
With states, the same thing applies. I live in New York (NY), but apparently I can’t be trusted to type ‘NY’ for my state (2 keys). Instead, I have to click the drop down, then scroll through 50+ state abbreviations (if say PR for Puerto Rico, etc. is included), and then click my state. If I accidentally click the wrong one, I have to do it all over. Or if I want to use a ‘shortcut’, I have to press N 5 times to get past the other ‘N’ states, and usually I have to go through it a couple of times because I overshoot, since just typing ‘N’ then ‘Y’ as a shortcut doesn’t actually work in most browsers. The only other thought is that maybe the web developers are using this as some sort of easy data validation, to prevent someone from putting in ‘NX’ or something. But that is precisely what server-side validation should do for you, not rely on the client to send ‘clean’ input. Someone could easily call your registration method directly (without using a web form), so you had better implement server-side validation anyway.
Oh well, it is the little things that get to me, when you have to do them over and over and over…
My Favorites...
So, since this blog is all about me, I wanted to list some of the various media I consume that I’ve enjoyed above the rest.
Books
- Jacqueline Carey’s Kushiel Series: This is a dark fantasy series, soemwhat racy at times, but simply breathtaking it it’s scope and character development. Each of these weighs in at 600-700 pages.
- David Foster Wallace’s Infinite Jest: The funniest, strangest, and most intellectual book you could ever want to read.
- Don DeLillo’s White Noise
TV
- Deadwood: HBO blows for canceling this
- Carnivale: HBO sucks for canceling this
- Kyle XY: What can I say I like teen paranormal drama
- Roswell: What can I say I like teen paranormal drama
- Smallville (First 3 seasons)
- Buffy the Vampire Slayer: ROCKS!
- Spooks: Great Brit 24-esque spy show
- One Tree Hill/Everwood: I like teen drama in general I guess
- Scrubs: Funny, funny, funny
- Family Guy: Funniest, Funniest, Funniest
- Sopranos
- The Shield: Except that part where my ex was Vic’s love interest
- Rescue Me: Dramedy FTW
Music:
- The Cure
- Death Cab for Cutie
- Beth Orton/Mazzy Star/Elysian Fields
- The Smiths
- Tool
- NIN (Old school)
- Dinosaur Jr.
Movies:
- American Beauty
- Irreversible
- The Matrix (I)
- Henry Fool
- Fifth Element
- Love Actually
- Insomnia (Danish/Swedish version)
- The Celebration
- Leon - The Professional
- Killing Zoe
- Closer
That’s it for now. I’m sure I’ll add more as I think of them.
Ruby on Rails AJAX Back button support using Script.aculo.us and Prototype
So I don't really want to get into a debate on 'breaking' the back button with full javascript/AJAX based sites, instead of having pages use regular navigation and only using AJAX within the same page. Let's just assume you are here because you need to fix the back button for your Rails site after using link_to_remote throughout. There are a number of solutions out there for various javascript toolkits, but I never was able to find anything that was terribly helpful for Prototype/Scriptaculous. So I took some of the existing ones out there and adapted them to the Rails environment.
This code uses the same basic methodology as the others out there: manipulating the location bar URL so that it has a hash (#) in it with additional information about the AJAX link which creates back and forward history entries when it is changed. It uses an iframe to support this functionality in IE6 and IE7, otherwise using location.hash manipulation in Firefox, Opera, and Safari 3. A thread (PeriodicalExecuter) is created that checks for changes to the location bar and makes a new Ajax request if needed). Both single step back and forward buttons work, but using the back and forward drop downs will not. Reload/Refresh also works properly, as does Open in New Window/Tab right click and Bookmarks. It simply does normal link_to_remote processing for other browsers, such as old versions of Safari/WebKit (so no history support but the site still works).
The key difference between this method and the others however, is that instead of using some obscure mapping or number for the hash, we simply append all of the Rails controller/action/id?params information after the hash, so if you click an AJAX link http://my.domain.com/controller/action/id?param1=something your location bar will change to http://my.domain.com/#/controller/action/id?param1=something
In the Rails code, you don't always want to have a history/back button entry created for every AJAX call we make, so to differentiate we replace link_to_remote with history_remote whenever we wish to generate a browser history entry. The format is identical, it just adds an extra parameter to the request: history: true. Another key feature to note is that link_to_remote :update => 'some_div' also works with this code (when used as history_remote :update => 'some_div').
///////////////////////////////////////////////////////////
// Slain Jamison Wilde
// This source code is released into the public domain
var PrototypeBackButton = {
start: function(root, title) {
this.browser_id = 0;
this.history_clicks = 0;
this.ajax_object = null;
this.history_current_cache = "";
this.root = root; // this is the initial page we are loading.
this.title = title;
is_backable_webkit = false;
if (Prototype.Browser.WebKit) {
navigator.userAgent.match(/AppleWebKit\/([^ ]+)/)
if(parseInt(RegExp.$1) > 420) {
is_backable_webkit = true;
}
}
if (Prototype.Browser.IE) {
this.browser_id = 1;
var history = $("ie_hash_history");
var iframe = history.contentWindow.document;
iframe.open();
iframe.close();
iframe.location.hash = location.hash + location.search; // ie breaks up the hash
this.is_started = true;
if (location.hash + location.search == "" || location.hash + location.search == "#") {
new Ajax.Request(root, {asynchronous:true, history:true, evalScripts:true});
}
this.checker_thread = new PeriodicalExecuter(function() {
PrototypeBackButton.url_hash_check();
}, 0.2);
} else if (Prototype.Browser.Gecko || Prototype.Browser.Opera || is_backable_webkit == true ) {
this.browser_id = 2;
this.is_started = true;
if (location.hash == "") {
new Ajax.Request(root, {asynchronous:true, history:true, evalScripts:true});
}
this.checker_thread = new PeriodicalExecuter(function() {
PrototypeBackButton.url_hash_check();
}, 0.2);
} else {
this.is_started = false;
new Ajax.Request(root, {asynchronous:true, evalScripts:true});
}
},
// Destructor
destroy: function() {
this.stop();
},
set_root: function(root) {
this.root = root;
},
set_title: function(title) {
this.title = title;
},
stop: function() {
if (this.checker_thread) {
this.checker_thread.stop();
this.checker_thread = null;
this.is_started = false;
}
},
url_hash_check: function() {
if(this.browser_id > 0 && document.title != this.title)
// hack
document.title = this.title;
if (this.browser_id == 1) {
var history = $("ie_hash_history");
var iframe = history.contentDocument || history.contentWindow.document;
var current_hash = iframe.location.hash + iframe.location.search; // ie splits it
if(current_hash != this.history_current_cache || this.history_clicks > 0) {
this.history_clicks = 0;
location.hash = current_hash;
this.history_current_cache = current_hash;
if (this.ajax_object) {
this.ajax_object.request(current_hash.replace(/^#/, ''));
this.ajax_object = null; // dont reuse the request object
} else {
new Ajax.Request(current_hash.replace(/^#/, '')); // reloads dont have an existing object
}
}
} else if (this.browser_id == 2) {
var current_hash = location.hash;
if(current_hash != this.history_current_cache || this.history_clicks > 0) {
this.history_clicks = 0;
if (this.ajax_object) {
this.ajax_object.request(current_hash.replace(/^#/, ''));
this.ajax_object = null; // dont reuse the request object
} else {
new Ajax.Request(current_hash.replace(/^#/, '')); // reloads dont have an existing object
}
this.history_current_cache = current_hash;
}
}
},
ie_history_click: function(hash) {
var newhash = '#' + hash;
location.hash = newhash;
var history = $("ie_hash_history");
var iframe = history.contentWindow.document;
iframe.open();
iframe.close();
iframe.location.hash = newhash;
}
}
////////////////////////////////////////////////////////////You will need to modify the Prototype.js Ajax.Request.request definition to (the changed piece is simply the first 2 conditionals so you should be able to use this with updated Prototype.js versions by moving those pieces into the new version):
request: function(url) {
if (PrototypeBackButton.is_started && PrototypeBackButton.browser_id == 1 && this.options.history == true) {
PrototypeBackButton.ajax_object = this;
this.options.history = null; // prevent inf loop
PrototypeBackButton.ie_history_click(url);
PrototypeBackButton.history_clicks = 1;
} else if (PrototypeBackButton.is_started && PrototypeBackButton.browser_id == 2 && this.options.history == true) {
PrototypeBackButton.ajax_object = this;
this.options.history = null; // prevent inf loop
parent.location = '#' + url;
location.hash = '#' + url
PrototypeBackButton.history_clicks = 1;
} else {
this.url = url;
this.method = this.options.method;
var params = Object.clone(this.options.parameters);
if (!['get', 'post'].include(this.method)) {
// simulate other verbs over post
params['_method'] = this.method;
this.method = 'post';
}
this.parameters = params;
if (params = Hash.toQueryString(params)) {
// when GET, append parameters to URL
if (this.method == 'get')
this.url += (this.url.include('?') ? '&' : '?') + params;
else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent))
params += '&_=';
}
try {
if (this.options.onCreate) this.options.onCreate(this.transport);
Ajax.Responders.dispatch('onCreate', this, this.transport);
this.transport.open(this.method.toUpperCase(), this.url,
this.options.asynchronous);
if (this.options.asynchronous)
setTimeout(function() { this.respondToReadyState(1) }.bind(this), 10);
this.transport.onreadystatechange = this.onStateChange.bind(this);
this.setRequestHeaders();
this.body = this.method == 'post' ? (this.options.postBody || params) : null;
this.transport.send(this.body);
/* Force Firefox to handle ready state 4 for synchronous requests */
if (!this.options.asynchronous && this.transport.overrideMimeType)
this.onStateChange();
}
catch (e) {
this.dispatchException(e);
}
}
},And here is the code for history_remote. Put this into your application_helper.rb. The code as given looks for a global variable $config['enable_back_button'] to determine if it should use the back button code. You can either define this in your environment.rb or simply remove the conditional as needed:
def history_remote(name, options = {}, html_options = {})
if $config['enable_back_button'] && $config['enable_back_button'] == true
html_options[:href] = "#" + url_for(options[:url]) # lets 'open in new tab' etc work
options[:history] = true
function = remote_function(options);
function.gsub!(/asynchronous\:true/, 'asynchronous:true, history:true')
# logger.dbg function
link_to_function(name, function, html_options)
else
link_to_remote(name, options, html_options)
end
endIn your layout/application.rhtml, you should add a call to PrototypeBackbutton.start("/controller/action", "My WebPage Title"); The title is there to deal with a bug I never got around to fixing that would keep appending the stuff after the # in the location bar to the title. We just force the title to this instead. You will also need an iframe for IE history:
<iframe id="ie_hash_history" style="display: none;"></iframe>
UPDATED: Here is a link to a full Rails 2.0 demo application with all of the pieces. Download the demo. Here is the demo runnning: Live Demo.
SiliconDust HDHomeRun HDTV Network Player
So the HDHomerun is a little bit difficult to describe, but it does a lot in a little package. Basically this is a little device that attaches to your router and allows any computer on your network to watch and record HDTV from OTA (Over the Air) antenna or from any unencrypted HDTV channels from your cable provider using the QAM protocol. Here in New York City, RCN and Time Warner both use QAM, which helps as OTA is less than ideal in the NYC apartment environment. (It can also connect directly to a single computer if necessary.) There is an added benefit that all of the normal, unencrypted, non-HDTV digital channels are also available for watching and recording, as well as the Digital Music Choice channels, at least on RCN. The HDHomerun has 2 antenna inputs, so you can a) watch and record 2 TV shows at once from the same or different computers, or b) have one set of HD channels from OTA and another from QAM.
Arguably, you have to commit to a fully computer mediated AV experience for this to really be useful to you, meaning that your primary TV viewing/music listening experience is through your computers attached to LCD/Plasma displays and connected to your stereo, rather than through cable boxes. But if you are willing to do that, you can save yourself 10-15$ a month in HDTV and cable box fees from your cable provider per month. For me, because I download so much of my TV, and have so many mp3’s on a server for playback thorughout my house, it is a no-brainer. But there is still this reticence in peopel to use their brand new 1080p LCD/Plasmas as the awesome computer monitors they really are.
Since HDTV is the real draw here, this is a list of the HD channels I get on RCN NYC:
- CBS
- NBC
- FOX
- ABC
- CW
- My9 (formally UPN, local origination)
- PBS HD (WNET-HD)
- NGC-HD (National Geographic Channel)
- TNT
- TBS
So no Discovery HD or HDNet, as those channels are encrypted. But you also get digital versions of regular Discovery, BRavo, A&E, MTV, etc. that your normal basic cable package has, all without dealing with cable boxes.
The one caveat here is that setup can be a little bit of a pain. There are tools for mapping the channels from QAM/OTA to get them to work with various media center software out there, like Windows Media Center, GBPVR, Team Media Portal, Beyond TV, and SageTV, but it will take you an hour or so and possibly a forum post to get everything in order, with the channel guides, etc.
The technology behind this puppy is pretty cool: It basically takes the raw ATSC/QAM data and strips it of a few headers, and then transmits the raw MPEG2 TS/TP (Transport Stream/Transport Program) data at full resolution over the network, which uses a couple of megabytes a second on your router. I may have the details slightly off here, but you should get the basic idea.
This device isn;t for everyone, but if you have a little bit of the computer geek in you, then this is hard to pass up.
Older posts: 1 2