SageTV Community  

Go Back   SageTV Community > SageTV Development and Customizations > SageTV Studio

Notices

SageTV Studio Discussion related to the SageTV Studio application produced by SageTV. Questions, issues, problems, suggestions, etc. relating to the Studio software application should be posted here.

Reply
 
Thread Tools Search this Thread Display Modes
  #1  
Old 10-05-2008, 09:20 PM
stuckless's Avatar
stuckless stuckless is offline
SageTVaholic
 
Join Date: Oct 2007
Location: London, Ontario, Canada
Posts: 9,626
Library: Remote APIs for SageTV

Wiki | Download | Project Site | Http/Rest Guide

For another project I am continuing to work on, I ended up creating this Sage API Wrapper that also provides Remote Execution of Sage services (RPC) using either Java or Xml capabilities. You can download it here.

Features
* Remote/Local Java Calls to the Sage Services
* REST Services for all SageTV commands (Xml over Http)
* Returns complete sage objects and lists in either Xml or Json format
* Can return results in the SageXmlWriter format the Niel's Web Server users
* Publish your own remote services using server side javascript
* Access Media artifacts, such as posters, backgrounds, etc, (requires phoenix apis)

What can you do with this Api?
Using the Java API, you can write java code that runs outside the main sage server. ie, if you wanted to write a script that finds all matched tv shows and then deletes them, you can do that without needing to run that code inside SageTV

Using the Xml API, you can make requests from a browser and execute sage calls, or get back server information, using nothing more than javascript in a browser.

Documentation
You can read more about from the download site or the project site.

Use this Thread to discuss the library, etc.

Last edited by stuckless; 05-21-2009 at 05:24 PM. Reason: Added More Info
Reply With Quote
  #2  
Old 10-05-2008, 11:36 PM
Slugger Slugger is offline
SageTVaholic
 
Join Date: Mar 2007
Location: Kingston, ON
Posts: 4,008
Just saw this before calling it a night so I haven't looked at the details/code yet, but my first question, before I forget, is, do the API calls return strongly typed objects/use strongly typed arguments much like Greg's API?

Your RPC example uses an Object[] where I might expect to see MediaFile[] or MediaFile.List (if using Greg's API as an example).
Reply With Quote
  #3  
Old 10-06-2008, 05:40 AM
stuckless's Avatar
stuckless stuckless is offline
SageTVaholic
 
Join Date: Oct 2007
Location: London, Ontario, Canada
Posts: 9,626
The fundamental difference between this API and Greg's API is that this API does not return Strongly Typed objects. It doesn't create any wrappers or additional objects. It's simply a collection of Static Classes and Methods, as the original Javadoc portrays. If it did provide a Stongly typed set of object, then I'd really see no point in creating it, Since Greg's API does that already.

The only way to do Strongly Typed objects for Sage's API, is to do as Greg's API did, which is create an Object instance for each Sage object, because Sage does not export a usable type for their objects (they obfuscate). While typed objects makes for a better object structure, it does lead some object overhead (in this case), which I was trying to avoid for the purposes of RPC. Typed objects (in this case) would also require marhaling and unmarhalling even when used in embedded mode. The RPC api does mashall and unmarshall in RPC mode, but in embedded mode, it does not require it, which should make it slightly more efficient.

So, instead of using something like...
Code:
media.getTitle()
You'll do as the Sage Javadoc says....
Code:
MediaFileAPI.GetTitle(media)

Last edited by stuckless; 10-06-2008 at 05:46 AM.
Reply With Quote
  #4  
Old 10-06-2008, 10:02 AM
jreichen's Avatar
jreichen jreichen is offline
Sage Icon
 
Join Date: Jul 2004
Posts: 1,192
I got a chance to look over your source code. I like your use of the sagex.* package naming. I'm converting over to that myself.

Have you seen the Jetty plugin I created? Any number of HTTP-based applications can be deployed in there, so you might take a look at that as an option for the server side. It can provide security as well as allow multiple apps running on the same port. That said, I like your mini httpd for its simplicity and some people may want the option of using it if that's the only HTTP app they're using.

Another benefit of Jetty is it should also provide each app with its own class loader, although I haven't tested it. There have been problems in the past with different plugins using different versions of the same jar file. This should reduce those conflicts for apps deployed in Jetty.

Anyway, nice work on the RPC API
__________________
Server: Intel Core i5 760 Quad, Gigabyte GA-H57M-USB3, 4GB RAM, Gigabyte GeForce 210, 120GB SSD (OS), 1TB SATA, HD HomeRun.
Extender: STP-HD300, Harmony 550 Remote,
Netgear MCA1001 Ethernet over Coax.
SageTV: SageTV Server 7.1.8 on Ubuntu Linux 11.04, SageTV Placeshifter for Mac 6.6.2, SageTV Client 7.0.15 for Windows, Linux Placeshifter 7.1.8 on Server and Client
, Java 1.6.
Plugins: Jetty, Nielm's Web Server, Mobile Web Interface.

Reply With Quote
  #5  
Old 10-06-2008, 10:07 AM
jreichen's Avatar
jreichen jreichen is offline
Sage Icon
 
Join Date: Jul 2004
Posts: 1,192
There is a related RMI plugin, but it doesn't look it's gone anywhere in a few years and I don't even see a download. I thought it was worth linking to it from here, though.
__________________
Server: Intel Core i5 760 Quad, Gigabyte GA-H57M-USB3, 4GB RAM, Gigabyte GeForce 210, 120GB SSD (OS), 1TB SATA, HD HomeRun.
Extender: STP-HD300, Harmony 550 Remote,
Netgear MCA1001 Ethernet over Coax.
SageTV: SageTV Server 7.1.8 on Ubuntu Linux 11.04, SageTV Placeshifter for Mac 6.6.2, SageTV Client 7.0.15 for Windows, Linux Placeshifter 7.1.8 on Server and Client
, Java 1.6.
Plugins: Jetty, Nielm's Web Server, Mobile Web Interface.

Reply With Quote
  #6  
Old 10-06-2008, 11:23 AM
stuckless's Avatar
stuckless stuckless is offline
SageTVaholic
 
Join Date: Oct 2007
Location: London, Ontario, Canada
Posts: 9,626
Quote:
There is a related RMI plugin, but it doesn't look it's gone anywhere...
I thought about RMI... for about 10 seconds.... I've used it in the past, and I really don't like the complexity that it provides. As well, the RMI would have required me to create a ton of interfaces and object that represented the sage objects, which was what I was trying to avoid in the first place RMI is a good choice for enterprise applications, especially if you have a large development team and professional services

Quote:
Have you seen the Jetty plugin I created? Any number of HTTP-based applications can be deployed in there...
I don't need to be sold on the virtues of Jetty I use it all the time, it's a great embedded web server. I did consider releasing it as a war file, but in the end, I resurrected an old micro server that I wrote many years ago. For this particular instance it works fine. The one challenge that I would have in hosting it inside a jetty container, is that I need to find the server and port the server is running on. For my micro server, that was easy, and I'm sure I can find a way to do it in jetty as well. What I may do, is provide a jetty adapter so that people could choose to host the RPC server inside a Jetty container. And, the microserver is not meant to be a replacement for a real server, it's just a simple http connection handler. I would think that most people would go the jetty route, just to take advantage of the real servlet capabilities.

I did seriously look as using jetty, and I also looked at the tiny web server that nielm uses... but in the end, both were overkill in terms of dependencies, and configuration. And to be honest, the reason I created the API was so that I could start embedding less into Sage and more into an external server process

Thanks for your feedback.
Reply With Quote
  #7  
Old 10-10-2008, 07:02 AM
cslatt's Avatar
cslatt cslatt is offline
Sage Advanced User
 
Join Date: Nov 2005
Posts: 239
I see on the project page that your end goal is to export an XML web service - just wanted to mark myself down as looking forward to that. As a .NET programmer who has just never managed to find the time to get into Java, I'd love to finally have an easy way to access the Sage API.
Reply With Quote
  #8  
Old 10-10-2008, 07:45 AM
stuckless's Avatar
stuckless stuckless is offline
SageTVaholic
 
Join Date: Oct 2007
Location: London, Ontario, Canada
Posts: 9,626
Code:
I see on the project page that your end goal is to export an XML web service
I may actually have a release this weekend. I've finished the API, but there are some minor things that i need to work out, mainly related to argument passing and signature matching.... The Java RPC api handles those things pretty easily, but when every argument that comes in the url is a string, it's a little harder to do signature matching
Reply With Quote
  #9  
Old 10-11-2008, 01:48 PM
stuckless's Avatar
stuckless stuckless is offline
SageTVaholic
 
Join Date: Oct 2007
Location: London, Ontario, Canada
Posts: 9,626
I just released the Xml over Http api for SageTV... See the Wiki for more information on how to make Sage Http calls. Checkout the Xml Rpc Guide as well.

The Xml Rpc API has not been well tested. So if you encounter issues, then please add bugs to the project bug page, or post a note in this thread.

The xml rpc is basically a set of rest service that return xml responses. The complete Sage API is exposed as Rest services, but not all aspects of the API lends itself well to rpc services, so don't expect to be able to do everything over http. But, if all you need is to do things things like refresh your media library, so see what tuners you have installed, then you can do calls like this...

Code:
http://sageserver:8080/sagex/rpcXml/CaptureDeviceAPI/GetCaptureDevices
and you'll back a response like...
Code:
<response>
  <header>
  </header>
  <body>
    <array size="2">
      <value index="0">adapter0</value>
      <value index="1">video0</value>
    </array>
  </body>
</response>
Please read ALL the wiki before using the API, since crafting an incorrect url will just lead to confusion and frustration...

Good luck, and if you have issue, then I'll try my best to help.

Last edited by stuckless; 10-13-2008 at 03:50 PM.
Reply With Quote
  #10  
Old 10-13-2008, 03:50 PM
stuckless's Avatar
stuckless stuckless is offline
SageTVaholic
 
Join Date: Oct 2007
Location: London, Ontario, Canada
Posts: 9,626
I just released a new version of the Sage RPC API. This relase now uses Nielm's webserver instead of it's own micro server. Please refere to the wiki for installation instructions.

I decided to follow jreichen's advice and use an existing server. Nielm's Web Server was easy to integrate with, just add an entry to the servlets.properties. I'm currently looking at providing an integration with Jreichen's Jetty Plugin as well.

This new release also adds thumbnail support via a servlet call. ie, you can request the thumbnail, as an image url, for a given media file entry.
Reply With Quote
  #11  
Old 10-13-2008, 11:20 PM
jreichen's Avatar
jreichen jreichen is offline
Sage Icon
 
Join Date: Jul 2004
Posts: 1,192
On the Jetty plugin wiki, I briefly mention the BeanShell servlet. It accepts BeanShell code (basically Java) and interprets it, so you could write a script to do several operations at once and submit it to the supplied servlet, or a custom servlet, possibly via RPC wrappers. It may also be possible to do the same with other JVM-compatible scripting languages (e.g. Groovy).

That would be one more possibility for remotely executing SageTV code.

I attached an example zip that can be extracted to the SageTV folder if you already have the Jetty plugin installed.
Attached Files
File Type: zip bshservlet.zip (259.4 KB, 423 views)
__________________
Server: Intel Core i5 760 Quad, Gigabyte GA-H57M-USB3, 4GB RAM, Gigabyte GeForce 210, 120GB SSD (OS), 1TB SATA, HD HomeRun.
Extender: STP-HD300, Harmony 550 Remote,
Netgear MCA1001 Ethernet over Coax.
SageTV: SageTV Server 7.1.8 on Ubuntu Linux 11.04, SageTV Placeshifter for Mac 6.6.2, SageTV Client 7.0.15 for Windows, Linux Placeshifter 7.1.8 on Server and Client
, Java 1.6.
Plugins: Jetty, Nielm's Web Server, Mobile Web Interface.

Reply With Quote
  #12  
Old 10-18-2008, 05:52 AM
bcjenkins bcjenkins is offline
SageTVaholic
 
Join Date: Jan 2006
Posts: 3,761
I am thinking about writing an iPhone application leveraging the REST services aspect. I have a few questions about the servlet available.

1) Does it support authentication?
2) Does it support SSL?
3) Is it a capable streaming server?
4) Can it be proxied through a server (Apache/Lighttpd) to enable support of the above? (When proxying nielm's webserver through Apache, IIRC there are issues with streaming files esp. when SSL is used)

Thanks,

B
__________________
Running SageTV on unRAID via Docker
Tuning handled by HDHR3-6CC-3X2 using OpenDCT
Reply With Quote
  #13  
Old 10-18-2008, 10:30 AM
stuckless's Avatar
stuckless stuckless is offline
SageTVaholic
 
Join Date: Oct 2007
Location: London, Ontario, Canada
Posts: 9,626
Quote:
Originally Posted by bcjenkins View Post
I am thinking about writing an iPhone application leveraging the REST services aspect. I have a few questions about the servlet available.
That's interesting... because I'll probably be doing something similar in next couple of months. I don't have an iphone, but I ordered a couple of ipod touch units for my kids. My goal is to selectively take some recorded shows and movies, and transcode them for the ipod. My thinking was that I'd run a nightly cron to transcode certain recorded shows.

Quote:
1) Does it support authentication?
The rest APIs should support whatever authentication is in the running container. I haven't done anything special to handle authentication.

Quote:
2) Does it support SSL?
Again, similar to question 1, the rest servlet is simply a servlet, so if you run it within a ssl container, then you should be fine.

Quote:
3) Is it a capable streaming server?
It's capable of streaming, but it's not a capable streaming server The /sagex/mediafile/ service simply finds the media file and sends back its contents as a stream. It does not perform any on the fly transcoding, etc, which is why, my intention would be to transcode selected files on a nightly basis, using a cron. My current server can't transcode HD content on the fly, so I didn't invest much time into the streaming portion.

Just a note about a streaming and ssl. If you are thinking of using ssl, I would still NOT stream media over ssl. Encrypting a mediafile would be intense, and I can't immagine that you'd need/want to do it. So I would use ssl for authentication, get, but stream all media over http. (personal oppinion)

Quote:
4) Can it be proxied through a server (Apache/Lighttpd) to enable support of the above? (When proxying nielm's webserver through Apache, IIRC there are issues with streaming files esp. when SSL is used)
I would think that if you used jreichen's jetty plugin, you could enable the ajp connector (I think that jetty supports this), and if so, then you can definately use apache as a frontend.

If you are simply looking to do url forwarding/proxing, then I would think it would work ok for most calls, but the streaming apis may not work... I haven't tested this for myself.... since in my testing, I'm just running inside nielm's server and accessing it directly.
Reply With Quote
  #14  
Old 10-18-2008, 12:59 PM
jreichen's Avatar
jreichen jreichen is offline
Sage Icon
 
Join Date: Jul 2004
Posts: 1,192
Quote:
Originally Posted by stuckless View Post
Again, similar to question 1, the rest servlet is simply a servlet, so if you run it within a ssl container, then you should be fine.
Some devices may require SSL connections to use port 443, and may not allow unsigned certificates. I think it's probably the exception rather than the rule and those restrictions will disappear as devices become more mature.

Quote:
Originally Posted by stuckless View Post
Just a note about a streaming and ssl. If you are thinking of using ssl, I would still NOT stream media over ssl. Encrypting a mediafile would be intense, and I can't immagine that you'd need/want to do it. So I would use ssl for authentication, get, but stream all media over http. (personal oppinion)
One of the advantages of Jetty is that it can serve SSL and non-SSL connections at the same time. The UI could connect to the SSL port for web pages and RPC calls, and to the non-SSL port for streaming.

Quote:
Originally Posted by stuckless View Post
I would think that if you used jreichen's jetty plugin, you could enable the ajp connector (I think that jetty supports this), and if so, then you can definately use apache as a frontend.

If you are simply looking to do url forwarding/proxing, then I would think it would work ok for most calls, but the streaming apis may not work... I haven't tested this for myself.... since in my testing, I'm just running inside nielm's server and accessing it directly.
Jetty has built-in AJP connectors but I haven't tried them[1][2]. It also has support for modifying HTTP headers to support reverse proxies.

There is also a thread about reverse proxy and the web servers. I think jhh had pretty good luck, but his Apache was on the same machine as Sage. I tried it with Apache on a different machine and couldn't quite get it working.
__________________
Server: Intel Core i5 760 Quad, Gigabyte GA-H57M-USB3, 4GB RAM, Gigabyte GeForce 210, 120GB SSD (OS), 1TB SATA, HD HomeRun.
Extender: STP-HD300, Harmony 550 Remote,
Netgear MCA1001 Ethernet over Coax.
SageTV: SageTV Server 7.1.8 on Ubuntu Linux 11.04, SageTV Placeshifter for Mac 6.6.2, SageTV Client 7.0.15 for Windows, Linux Placeshifter 7.1.8 on Server and Client
, Java 1.6.
Plugins: Jetty, Nielm's Web Server, Mobile Web Interface.

Reply With Quote
  #15  
Old 10-28-2008, 10:06 PM
jreichen's Avatar
jreichen jreichen is offline
Sage Icon
 
Join Date: Jul 2004
Posts: 1,192
Quote:
Originally Posted by bcjenkins View Post
I am thinking about writing an iPhone application leveraging the REST services aspect....
One of the speakers at the Denver Java User's Group in November is presenting how to write iPhone apps that work with Java web services. I talked to him today and it sounds interesting. I'll be happy to report back anything you might find helpful.
__________________
Server: Intel Core i5 760 Quad, Gigabyte GA-H57M-USB3, 4GB RAM, Gigabyte GeForce 210, 120GB SSD (OS), 1TB SATA, HD HomeRun.
Extender: STP-HD300, Harmony 550 Remote,
Netgear MCA1001 Ethernet over Coax.
SageTV: SageTV Server 7.1.8 on Ubuntu Linux 11.04, SageTV Placeshifter for Mac 6.6.2, SageTV Client 7.0.15 for Windows, Linux Placeshifter 7.1.8 on Server and Client
, Java 1.6.
Plugins: Jetty, Nielm's Web Server, Mobile Web Interface.

Reply With Quote
  #16  
Old 11-04-2008, 01:22 AM
shadeblue.com's Avatar
shadeblue.com shadeblue.com is offline
Sage Aficionado
 
Join Date: Jun 2008
Posts: 435
Hi Sean,

I have been playing with your SageTVApi library and testing a few concepts that I would like to develop further.

I ran into one problem, and I'm not sure if it is a problem in the library or if I am not using the API correctly. Basically any methods I call attempting to get a Widget object using the WidgetApi all fail.

Here is one simple example:
Code:
System.out.println("Widget: " + WidgetAPI.GetCurrentSTVFile());
Calling this method returns:
Widget: null
Any ideas or pointers? Ultimately I am trying to get a menu widget and execute it to display the menu on screen. i.e.:

Code:
Object widget = sagex.api.WidgetAPI.GetWidgetSymbol("CDSWT-46001");
sagex.api.WidgetAPI.ExecuteWidgetChain(widget);
PS.. methods in other parts of the API are working from my client ... such as:
sagex.api.Global.GetUIContextNames()
I am using your API ver: "sagex.api-6.4.8-1.jar" in under the remoting option (running from separate JVM on same computer as Sage)



Thanks!
__________________
Server Hardware: Intel Core 2 Quad Q6700 2.66GHz CPU, 4GB DDR2 RAM, NVIDIA nForce 780i SLI Motherboard, GeForce 8600 GT, Seagate Barracuda 7200.11 2.5TB
Operating System: Windows XP Professional
HTPC/DVR Software: SageTV 7
Capture Devices: 2 @ Hauppauge HD-PVR (1212), Hauppauge WinTV-HVR-1600 ATSC/QAM, HD Homerun
Media Extenders: 2 @ Sage HD100 & 1 @ Sage HD200
Signals/Providers: AT&T UVerse, OTA ATSC
Set-Top-Box: 2 @ Motorola Box VIP 1200

Last edited by shadeblue.com; 11-04-2008 at 01:26 AM.
Reply With Quote
  #17  
Old 11-04-2008, 10:24 AM
stuckless's Avatar
stuckless stuckless is offline
SageTVaholic
 
Join Date: Oct 2007
Location: London, Ontario, Canada
Posts: 9,626
I have put some thought into how to transparently handle the "context" problem. Initially, I didn't need to use the context, so it got put on the back burner, but I'll spend some time and try to come up with something.

My initial thoughts are along these lines....
1. for each generated method, generate a second method that also can accept a context parameter, so WidgetAPI would include a method ExecuteWIdgetChain(widget) and ExecuteWidgetChain(widget, context).

2. add a theadlocal variable to generated class, so that you can set the context before executing the method. So, when you call ExecuteWidgetChain, you'd have to set the context first, so something like this...
Code:
sagex.api.WidgetAPI.SetContext(context);
sagex.api.WidgetAPI.ExecuteWidgetChain(widget);
sagex.api.WidgetAPI.SetContext(null);
The issue I see with the ThreadLocal approach is that I don't know how Sage handles it's UI code on the server. ie, if you were to run this code within sage, does sage execute each ui in it's own thread, or do all threads share the same thread....

3. Create a static list of "context" enabled fields and modify the generator to ONLY create context aware methods for methods that can accept a context...

Any thoughts?
Reply With Quote
  #18  
Old 11-04-2008, 12:09 PM
GKusnick's Avatar
GKusnick GKusnick is offline
SageTVaholic
 
Join Date: Dec 2005
Posts: 5,083
This is where wrapper objects come in handy, because you can wrap the context up once when you instantiate the API object and not have to worry about it again. I understand your reasons for wanting to stick with static methods only, but the price you pay for that is pushing the burden of keeping track of instance data (like UI context) back onto the caller.

And by the way, shadeblue, you want FindWidgetBySymbol instead of GetWidgetSymbol, and LaunchMenuWidget instead of ExecuteWidgetChain.
__________________
-- Greg
Reply With Quote
  #19  
Old 11-04-2008, 01:03 PM
stuckless's Avatar
stuckless stuckless is offline
SageTVaholic
 
Join Date: Oct 2007
Location: London, Ontario, Canada
Posts: 9,626
Quote:
This is where wrapper objects come in handy, because you can wrap the context up once when you instantiate the API object and not have to worry about it again
I totally agree.... wrapper objects are definately better when you need to store instance data.... (and I encourage everyone to use your API if their intention is to embed their code inside of sage tv process)

So I guess I could generate a set of wrapper objects to fix the problem
Reply With Quote
  #20  
Old 11-04-2008, 01:51 PM
shadeblue.com's Avatar
shadeblue.com shadeblue.com is offline
Sage Aficionado
 
Join Date: Jun 2008
Posts: 435
Quote:
Originally Posted by GKusnick View Post
This is where wrapper objects come in handy, because you can wrap the context up once when you instantiate the API object and not have to worry about it again. I understand your reasons for wanting to stick with static methods only, but the price you pay for that is pushing the burden of keeping track of instance data (like UI context) back onto the caller.

And by the way, shadeblue, you want FindWidgetBySymbol instead of GetWidgetSymbol, and LaunchMenuWidget instead of ExecuteWidgetChain.
Hi GKusnick,

Thank you for the correction. I knew the 'FindWidgetBySymbol' was correct, I must have copied it wrong when I was creating the forum post. I must have missed 'LaunchMenuWidget', I did not know that was the correct call.

Again, Thank You!
shadeBlue
__________________
Server Hardware: Intel Core 2 Quad Q6700 2.66GHz CPU, 4GB DDR2 RAM, NVIDIA nForce 780i SLI Motherboard, GeForce 8600 GT, Seagate Barracuda 7200.11 2.5TB
Operating System: Windows XP Professional
HTPC/DVR Software: SageTV 7
Capture Devices: 2 @ Hauppauge HD-PVR (1212), Hauppauge WinTV-HVR-1600 ATSC/QAM, HD Homerun
Media Extenders: 2 @ Sage HD100 & 1 @ Sage HD200
Signals/Providers: AT&T UVerse, OTA ATSC
Set-Top-Box: 2 @ Motorola Box VIP 1200
Reply With Quote
Reply


Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
Hauppauge Remote Issue yacht_boy Hardware Support 4 05-01-2008 09:25 PM
MCE remote transmitting keypresses twice arnabbiswas Hardware Support 1 02-22-2007 10:55 AM
MCE Remote not work fully with Placeshifter devinteske SageTV Placeshifter 5 02-08-2007 11:45 PM
Harmony Remote IR Reciever Help brundag5 Hardware Support 2 01-13-2007 09:08 PM
How to get SageTV to release focus to NVDVD for remote IncredibleHat SageTV Software 4 07-06-2006 07:47 AM


All times are GMT -6. The time now is 07:49 PM.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2021, vBulletin Solutions Inc.
Copyright 2003-2005 SageTV, LLC. All rights reserved.