In the last installment of my little series on turning Internet feeds into TV feeds, I had decided to use IronPython to fetch data from the Internet, but C# to drive the WPF (Windows Presentation Foundation) application whose display my local public access TV station will broadcast. This division of labor between C# and IronPython arose because the XAML that drives the display needs to be refreshed periodically, and I didn’t know how, in IronPython, to properly delegate a timer-based event handler for WPF.
I haven’t yet decided which version to deploy, but I’m leaning toward the IronPython version. Not because it’s more concise. It isn’t, really. Nor because I feel any need to use the same language for both components of the solution — that is, the feed fetcher and the feed displayer. I don’t care about language uniformity for its own sake.
I am, however, thinking that the folks at the TV station may want to modify these programs themselves. They’re pretty simple, and there’s no reason they shouldn’t be able to tinker with them. From that perspective, code that can be modified with nothing more than a text editor will be more accessible than code which requires a compiler.
I’m reminded of my early days as a website operator, when I was always glad to discover that a third-party application was written in Perl, rather than in C. That meant I could, and sometimes did, tweak the application in ways that otherwise would have been difficult or even (lacking C source code) impossible.
The difference here, of course, is that all of the underlying machinery — XAML, WPF, and the entire .NET Framework — is exactly the same1 when approached from a scripting language like IronPython or a compiled language like C#. This ability to use common infrastructure from different langages — and from very different kinds of languages — has always seemed like a big deal to me, and still does.
1 The same, that is, modulo the kind of boundary-crossing issue that stumped me until Michael Foord pointed me to CallTarget0, the wrapper for creating a delegate in IronPython.
import clr clr.AddReferenceByPartialName("PresentationCore") clr.AddReferenceByPartialName("PresentationFramework") clr.AddReferenceByPartialName("WindowsBase") clr.AddReferenceByPartialName("IronPython") from System import * from System.Windows import * from System.Windows.Markup import * from System.Windows.Media import * from System.Windows.Input import * from System.Windows.Threading import * from IronPython.Runtime.Calls import CallTarget0 def LoadXaml(filename): from System.IO import * from System.Windows.Markup import XamlReader f = FileStream(filename, FileMode.Open) try: element = XamlReader.Load(f) finally: f.Close() return element class Scroller(Application): def tickhandler(self,sender,args): def update_xaml(): self.window.Content = LoadXaml(self.xaml) self.timer.Dispatcher.Invoke(DispatcherPriority.Normal, CallTarget0(update_xaml)) def __init__(self): Application.__init__(self) self.xaml = "scroller.xaml" self.window = Window() self.window.Content = LoadXaml(self.xaml) self.window.WindowStyle = WindowStyle.None # go fullscreen self.window.WindowState = WindowState.Maximized # self.window.Topmost = True # self.window.Cursor = Cursors.None # self.window.Background = Brushes.Black # self.window.Foreground = Brushes.White # self.window.Show() self.timer = DispatcherTimer() self.timer.Interval = TimeSpan(0, 60, 0) # refresh hourly self.timer.Tick += self.tickhandler # self.timer.Start() # Scroller().Run()