I made the switch to sattelite TV today because cable is getting more expensive and they’re slow to add HD channels. One thing I was pretty happy about was that you didn’t have to pay any upfront fees for DVRs, and the Scientific Atlantic models they offered are really pretty good, although the hard drive could be a lot bigger.
Now I have Dish Networks top DVR and while the hard drive is certainly bigger, the interface, especially when it comes to setting up recordings, is a disaster. It gives you the feeling that it’s very powerful, but it’s really just complicated and doesn’t work very well at all.
I don’t know whether it’s because the programmers didn’t care or because they didn’t feel like working around certain software patents. Whatever it is, I already miss the old interface.
To set up recording with Scientific Atlantic’s DVR, you select a show from the timeline or search for it by name (if there is more than one episode for a show with a certain title, the list is collapsed to make scrolling through the result set faster) . With one click, you can then decide to record the item you selected, or all instances of this show on this channel. Very simple and straightforward. Additional options are also easy to set up. You can select to record the show only on the current channel or all channels, only record new or all episodes, only at the currently selected time or all times, etc.
Contrast that with Dish Network. I select a show from the time line. I hit one button to record only the item I selected, another button for a more complicated setup. I get a new screen, to select frenquency of recording. Another screen from there to select delete protection, start early/end late. If I want more options than that, I have to create the recording as something called Dish Pass, which is basically a custom search. It records everything that matches a set of criteria such as title, channels, frequency and resolution(!). But not time, and that where I get pissed off. You see, The Daily Show and The Colbert Report are repeated four times a day, and they are apparently all marked as new. I don’t know whose fault that is, but Dish Network and Scientific Atlantic’s guides both have the same problem. However, with SA’s DVR I can just set it to record only at the time when it show new episodes. Easy enough, with Dish Network, I have to create a custom, time-based recording that I can’t even give a title. But that means it’s gonna record episodes Monday through Friday, while new episodes are on only Monday through Thurdays. And there’s no way around that.
Also, there’s more than one menu to do the same thing. I hate it.
Update: Toggling subtitles is a huge pain in the ass now as well. Nice font, though.
January 10th, 2009 in
Uncategorized |
No Comments
Godaddy is insufferably slow today. I wonder if 1&1 is any better.
Update: Took advantage of Dreamhosts new year’s sale and got 2 years of hosting for $20. Can’t wait to make the change.
January 2nd, 2009 in
Uncategorized |
1 Comment
Like probably everyone else, I was amused when the news broke that most 30gb Zune players died simultaneously on the morning of December 31st, 2008. I looked like a blunder of epic proportions on Microsoft’s part (Epic Fail, as it’s called now). However, now that more information is available it’s apparent that it’s not really Microsoft fault. The only thing they can be blamed for is trusting the drivers Freescale provided for their parts. It’s not unreasonable to assume that a big semiconductor maker would properly unit test their drivers. That did not happen, as a look at the source code reveals.
Someone helpfully posted the source code of the driver here. The guilty loop is located at line 259:
while (days > 365)
{
if (IsLeapYear(year))
{
if (days > 366)
{
days -= 366;
year += 1;
}
}
else
{
days -= 365;
year += 1;
}
}
At first, it looks like a simple off-by-one error. If it’s a leap year, and the last day in the year (366), nothing is substracted and the loop never stops. However, replacing “days > 366″ with “days >= 366″ is incorrect as well, because that would set day to 0. Before I give the correct solution, let’s look at some more problems with this driver.
The same loop, albeit slightly modified, is used in a different part of the driver:
while (day > 365)
{
if (IsLeapYear(year))
{
numOfLeap++;
if (day > 366)
{
OALMSG(OAL_RTC&&OAL_INFO, (TEXT("Leap Year: %u"),year));
day -= 366;
year += 1;
OALMSG(OAL_RTC&&OAL_INFO, (TEXT(", Days left: %u\r\n"),day));
}
else
{
OALMSG(OAL_ERROR, (TEXT("ERROR calculate day\r\n")));
break;
}
}
else
{
OALMSG(OAL_RTC&&OAL_INFO, (TEXT("Not Leap Year: %u"),year));
day -= 365;
year += 1;
OALMSG(OAL_RTC&&OAL_INFO, (TEXT(", Days left: %u\r\n"),day));
}
}
The irony here is that although it pops out an error message when days is 366, it breaks the loop and cotinues as if nothing happened, actually creating the correct results. Here, a unit test wouldn’t have shown any problems, save for the debug message.
It’s a bit unclear at first whether the first day in this timestamp schema is supposed to be 1 or 0. Consider this validity check for date input:
if ((lpst->wYear < ORIGINYEAR) || (lpst->wYear > MAXYEAR))
return FALSE;
if ((lpst->wMonth < 1) ||(lpst->wMonth > 12))
return FALSE;
if((lpst->wDay < 0) ||(lpst->wDay > month_tab[lpst->wMonth-1]))
return FALSE;
if ((lpst->wHour > 23) ||(lpst->wMinute > 59) ||(lpst->wSecond > 59))
return FALSE;
This code would let day 0 pass. It also doesn’t have a problem with negative hours, minutes and seconds, but that’s beside the point. The #define block at the top of the source file reveals that day 1 is supposed to be the first day:
#define JAN1WEEK 2 // Jan 1 1980 is a Tuesday
#define GetDayOfWeek(X) (((X-1)+JAN1WEEK)%7)
With that cleared up, the solution for the loop is that the boundary is variable, not constant. In a normal year, it needs to keep going until 365 days or less are left. In a leap year, the number is 366. Of course, since the actual year in unknown until the end of the (correct) loop, you can’t simply decide that beforehand. The shortest fix would be just to break if 366 days are left in a leap year. Someone also provided this replacement for the loop:
while (days > 365+IsLeapYear(year))
{
days -= 365+IsLeapYear(year);
year++;
}
High marks for simplicity and elegance, low marks for calling the leap year check twice per loop. I propose:
while (days > (daysInYear = IsLeapYear(year) ? 366 : 365))
{
days -= daysInYear;
year++;
}
I’ll be interested to see how they end up fixing it and if they decide to take on the other issues as well.
For some reason, I never have time for anything over the Christmas holidays. Blogging suffered especially. Let’s fix that:
If there’s one software solution I had always wanted, it’s the ability to share folders across multiple machines and operating systems in a completely transparent way. That means the syncronization has to be as hands off as possible and the folder has to behave like a normal folder. I finally got my wish with Dropbox. It’s entirely possible there has been a solution like that before, and I missed it. Regardless, Dropbox is perfect because it’s free (for up to 2GB of storage) and clients are avaible for Windows, Mac and Linux. That’s great for me because I use each one on a daily basis.
The client can currently monitor only one folder, but it comes with some file sharing capabilities. For people with security concerns, I think it should be possible to store a TrueCrypt volume in Dropbox. The client is smart enough to segment files and upload only the segments that have changed.
The next new tool in the mix is VirtualBox. VirtualBox is an open-source virtualization solution by Sun that is, again perfectly for me, available on all OS. It allows me to have a Linux server for development whenever I need it, which saves me the money of building or hosting one. It’s not feasible to upload the whole server image to Drobox, but you can create a shared HDD image. I created the server image on one machine that I copied to all my machines. Then I created a 50mb (or whatever) harddrive that I copied into Dropbox and mounted in the server. It’s hardly a perfect solution but it will have to do until I come up with a better solution. This way doesn’t allow me to duplicate config and packages between the server images on the different machines, but at least working data will be.
And finally, Eclipse 3.4 is out and PDT 2.0 has just been released. It’s still a bit rough around the edges, but Eclipse now has a vastly improved update manager. There’s an irritating issue with the plugin-source manager (can’t edit source URLs). PDT has finally added “Mark Occurences”, which I’ve missed since I switched to PDT from an abandoned PHP plugin for Eclipse. It also and seems to be handling variable typing better.
All around exciting new stuff. Most of it is open source, too, and while Dropbox is not, it’s built on top of Amazon Web Services. And I can’t get enough of those.
January 1st, 2009 in
Uncategorized |
1 Comment
I’ll be at a preparatory meeting for the BarCamp in Charlotte tomorrow.
December 17th, 2008 in
Uncategorized | tags:
barcamp |
No Comments
I’m reading Steve Yegge’s presentation Dynamic Languages Strike Back and I’m imagining him as talking with Craig Ferguson’s voice. It makes a funny talk even funnier. Seriously, if some of my professors had at least been funny…
OK: I went to the University of Washington and [then] I got hired by this company called Geoworks, doing assembly-language programming, and I did it for five years. To us, the Geoworkers, we wrote a whole operating system, the libraries, drivers, apps, you know: a desktop operating system in assembly. 8086 assembly! It wasn’t even good assembly! We had four registers! [Plus the] si [register] if you counted, you know, if you counted 386, right? It was horrible.
I mean, actually we kind of liked it. It was Object-Oriented Assembly. It’s amazing what you can talk yourself into liking, which is the real irony of all this. And to us, C++ was the ultimate in Roman decadence. I mean, it was equivalent to going and vomiting so you could eat more. They had IF! We had jump CX zero! Right? They had “Objects”. Well we did too, but I mean they had syntax for it, right? I mean it was all just such weeniness. And we knew that we could outperform any compiler out there because at the time, we could!
December 15th, 2008 in
Uncategorized |
2 Comments
I missed both the release of PHP 5.2.8 and Symfony 1.2.1 by a couple of days. Freshmeat sucks because nobody ever remembers to update their software. At least that seems to be the case with stuff I use.
December 12th, 2008 in
Uncategorized |
No Comments
I’ve been looking at Erlang for a couple of days now, and although writing code in this language felt truly weird at first, it occured to me early that programming can probably be abstracted like this:
1. Do one thing and do it well
2. Repeat
It’s the Unix philosophy applied to function-level programming.
I haven’t done anything outside examples and tutorials yet, but I can think of at least two projects I’ve worked on, adTracker and adAggregator, that would be terrific to re-implement in Erlang.
December 7th, 2008 in
Uncategorized | tags:
erlang |
1 Comment
The new symfony release sort of snuck by under my radar. Thus, it so happened that upgrading my current project to the new version fell on a friday (afternoon). The upgrade guide made everything sound easy enough. Unfortunately, some things related to the Doctrine plugin had been changed without deprecating (as far as I know at least) them first. That, plus a bug, made the upgrade task take a lot longer than I had planned.
So, I can’t really say much yet, but some things have certainly gotten easier and more elegant. As long as the performance stays the same, I probably won’t complain. No, I’ll probably find something regardless.
December 6th, 2008 in
symfony | tags:
symfony |
1 Comment
I came across a curious bug today when after deploying a revision of one of web apps I’ve been working on. The automatic test suite had run its course, no errors. However, when I repeated one of the processes covered by a test manually, I ended up with a fatal error.
The reason the test worked fine while the real process didn’t is a not entirely unimportant weakness in the test framework. The individual requests simulated by functional tests are not isolated from one another like regular requests would be. They all happen inside the same request context, so there is no teardown at the end and no cleanup. There are certain things in PHP that you can’t undo unless you finish a request. One of those things is registering functions.
So what happened was that I included a helper (collection of functions) only in the template of the first request in the process. That was no problem in the test run because the functions stayed defined throughout, whereas in the real world, they wouldn’t.
I’m trying to figure out what would be the best way to address this problem. The most thorough way, isolating every request into its own CLI session, would be impractical. Although it would address more than this very specific problem. The less general but easier to implement way would be to write a parser that checks whether every function used in the templates is defined or included in the template it’s used in.
December 4th, 2008 in
symfony | tags:
symfony,
tdd |
No Comments