Posts tagged "programming"
MythTV Script to allow multiple Telnet connections
Sat Jan 12, 2008 11:41:08 PM by Travis
So, my roomate Brock has a MythTV box set up in our apartment, which we use as a free, open-source alternative to Tivo and other commercial DVR products.
One of the nifty things that myth provides is a Telnet interface for controlling the system: just telnet into a certain port, and you can enter in commands to control the system remotely. Works great if you don't have a remote control for the computer that's running myth. Brock and I both have GUI programs we can run on our laptops to provide a nice remote-control-esque interface to the Telnet connection (he uses one he found for Mac, I use one I developed in C# (but that's another blog post)).
It's a great setup, except for one problem: only one user can be connected to myth's telnet interface at a time. So, if Brock is using his remote control program, and I use mine, it automatically disconnects Brock. It's a stupid limitation, in my opinion, but that's the way it is.
Earlier this evening, Brock suggested a way to get around that problem: set up a simple telnet proxy server, which allows multiple clients to connect to it, and forwards all commands over a single connection to the myth telnet interface. Since I was in a mood to code, I decided I'd see if I could write up a simple Ruby program to do just that.
An hour and a half later, I had it working. Well, kinda - it's a little rough, and it doesn't forward the server's replies back to the clients, but it's enough to have multiple remotes simultaneously connected. I've pasted the code at the bottom of this post, as it's only about 90 lines. I'm really rather amazed that it was so easy, largely in part to the excellent gserver library, which may be my new favorite standard library class ever.
Edit 1/17: Updated the code to a cleaner, slightly more concise version.
I love ruby.
#!/usr/bin/ruby require "gserver" require "net/telnet" require "thread" class TelnetProxy < GServer def initialize(*args) super(*args) @@total_num_clients = 0 @cmds = Queue.new end def start(*args) start_myth_connection super(*args) end def serve(io) @@total_num_clients += 1 my_client_id = @@total_num_clients puts("New Client #{my_client_id} detected") # send the initial login msg welcome_msg = "MythFrontend Network Control\nType 'help' for usage information---------------------------------\n# " io.write(welcome_msg) loop do puts "Client #{my_client_id} is still alive" # every 2 seconds check for newly received commands if IO.select([io], nil, nil, 2) # retrieve the data cmd = io.gets puts "Client #{my_client_id} got cmd '#{cmd}'" # if the command was "exit", then disconnect the user, but not the main connection if cmd =~ /exit/ puts "Closing client #{my_client_id} connection..." break end # forward the command to myth @cmds << cmd puts "Client #{my_client_id} placed cmd on queue" # send the response to the user response = "OK\n# " io.write(response) end end end private def start_myth_connection @myth_thread = Thread.new do loop do myth = Net::Telnet::new("Host" => "myth", "Port" => 6545, "Timeout" => 10, "Prompt" => /# /) puts "Connected to myth" cmds_to_run = [] until myth.closed? # get command from the shared buffer (sleeps if none available) cmd = @cmds.pop # send the commands to myth puts "Sending command to myth: #{cmd}" myth.cmd(cmd) puts "Cmd sent" end # until myth.closed? puts "Lost connection to myth" end # loop do end end end proxy = TelnetProxy.new(6546, "myth") proxy.start proxy.join
Misprediction and Evolution vs Revolution
Tue Oct 30, 2007 12:33:03 AM by Travis
On the walk home tonight, I found myself thinking about the difficulty of making predictions, specifically in the technology and business world. The problem is not that the predictors are unintelligent; see Bill Gate's infamous "640K ought to be enough for anybody" quote. Others are well documented at the bad predictions archive.
So, if we can't blame the bad predictions on the predictors, there must be something inherently difficult about making predictions. This idea is, I think, where the difficulty comes in. It turns out, making good predictions isn't really all that hard. See, for example, Moore's Law, Brook's Law, and Hofstadter's Law. All it takes is understanding of past trends, a little insight, and the egotism to name a Law after yourself. Easy, right?
Okay, so if making predictions is really so simple, why aren't we better at it? This is the realization that I had tonight: people are very good at predicting evolutionary changes, often well in advance of when they happen. People are terrible at predicting revolutionary changes, often even when the change is happening around them.
For the sake of this argument, evolutionary changes are defined as conceptually improvements and refinements of existing techniques. For example, cramming more circuits onto a chip, or making fuels that burn cleaner. These kind of changes come from a process of slow and steady improvement, and as such can be easily predicted based on past results.
Revolutionary changes are a little harder to define. They often take the form of a completely different way of doing things, a complete paradigm shift. They might be completely new inventions, or a sudden inspired combination of existing technologies into a whole greater than the sum of its parts. Examples: the computer, the printing press, the cell phone, the internet. These kind of changes are nearly impossible to predict, and are often even incredibly difficult to recognize as they are happening. Predicting revolutionary changes is firmly set in the realm of Science Fiction.
So, what's the moral of the story? Evolutionary changes are easy to predict. Revolutionary changes are not. We must simply remember that there is a difference between the two, and hope to be lucky enough to correctly identify a revolutionary change when it's happening.
Mutated growths don't make a good analogy
Fri Jun 15, 2007 12:43:03 AM by Travis
Today at work I was putting together a presentation for a talk I'm giving tomorrow on the project I've been working on for the first half of my internship. Put simply, I added some functionality and a new user interface to an existing application.
Of course, that's not how my twisted brain thought about it. I started envisioning the code as the torso of a person, and the original interface as the head. In this analogy, my extensions would be like a cancerous mutant second head sprouting from the shoulder, with its tendrils extending down into the torso. It'd be all twisted and weird, and it'd always be drooling and chewing on the main head's hair. It'd have like five teeth and one eye would be bigger than the other.
I was this close to using the analogy.
Paved with Good Intentions
Tue Apr 17, 2007 02:28:11 PM by Travis
I read an interesting article today on trying to get more women to major in computer science in U.S. colleges. What grabbed my attention was the techniques they're using to draw more women to the field:
"Moving emphasis away from programming proficiency was a key to the success of programs Dr. Blum and her colleagues at Carnegie Mellon instituted to draw more women into computer science."
This disturbs me. Don't get me wrong, I'm all for more women in the field - but not if it means changing what computer science is. Moving the focus away from programming skills in computer science programs is like moving the focus away from engine mechanics skills in car mechanics programs. Sure, you can probably be a car mechanic without a strong basis in how an engine works, but you're not going to be a good one.
They worry that the decrease of women joining the field is a bad sign, and I agree. I don't think the answer is to try and downplay one of the key proficiencies that a computer scientist should have.
Why I don't write about code
Mon Apr 09, 2007 01:39:02 AM by Travis
Over the past 6 months I've started reading some good computer science / programming / software engineering blogs. Looking back over my own posts, I realized recently that my chosen profession is not a topic I have actually ever written about in any detail. A non-zero number of my peers maintain blogs where they talk about all kinds of interesting aspects of the field and projects that interest them. Why don't I do the same?
I've decided that the reason is that, while I do enjoy computer science, I don't love it. At least, not with the passion that some do. Sure, I enjoy the intellectual challenges and puzzles involved with coding. Sure, I can get excited about seemingly bizarre things like "elegant" code. Sure, I can get into long, drawn out debates about coding styles, algorithm design, and the like. But, and this I think is the key difference, at the end of the day I get to a point where I just have to stop. I like it just fine, but I can only take so much of it.
It's because I can only take so much thinking about computer science that I don't write about it, I think. I'm in school; I practically spend all day every day thinking about designing software and the various problems associated with it. In my free time, the times which I post to this blog, the last thing I want to do is think about it some more.
Does that make me a bad code artist? Maybe. Probably. People who have that twenty-four hour passion for all things programming are going to be better than I am, merely by the fact that they spend so much more time thinking about it.
On the other hand, I think that not being so obsessive is going to make me a better person. There are, after all, only 24 hours in a day. By not spending all of them thinking about code, I'll free up brain-time for other interests, making me, I hope, a more well-rounded individual.