In order to communicate with Myth, you have to create 1 or more sockets and pass a series of commands via the socket streams. All in all not hard if you use a language that can easily deal with sockets.
Consult the Myth Protocol document for an overview of the protocol packet information. Also refer to the Myth Protocol Command List for a list of commands. This document refers to the commands in a language neutral manner, where possible.
This document refers to a command socket and a data socket. Please note the socket reference when issuing commands.
A Myth TV backend typically runs on port 6543 and the first thing you will need to do when you connect, is tell Myth the protocol version that you speak. This is done by sending the MYTH_PROTO_VERSION command. The only argument to this command is the version.
Here's the catch. If you send a version that is different than what the server is currently running, then it will reject you. When you are rejected, Myth does tell you what version you need to be at in order for the backend to talk to you. Do NOT claim support for a version that you do not understand, at a minimum you risk your application not working, at worst you destroy the users data and/or de-stabilise the backend.
Once you get connected to Myth for the first time, you'll be excited. But, you're not really doing anything yet. I'll explain the series of commands required in order to tell Myth that you want to watch Live TV and then start sending that stream back to your client.
In a nutshell, here is a summary of the commands that you need to execute...
- Announce your playback intentions
- Get the next available recorder
- Spawn Live TV for the recorder
- Get the program info for the recorder
- Transfer the file that the recorder is creating
All in all, not too much, but enough, none the less.
Using the command socket, send the ANN PLAYBACK command. And ensure that you get a valid response back.
Get the Next Available Recorder
Using the command socket, send the GET_NEXT_FREE_RECORDER command. If it suceeds, then you now have a valid recorder from the Myth backend.
Spawn Live TV
In order to spawn live tv, you need to create a chain id. A chain ID typically looks like livetv-YOURHOST-DATETIME_STAMP. I don't think that Myth cares what the ID is, as long as it is unique. It ends up writing it to the TVCHAIN table.
Using the connected socket, send the QUERY_RECORDER command with the SPAWN_LIVETV sub command. You need to pass the recorder id, and the chain id.
Once this command completes, it will return OK.
The next 2 commands are issued by the existing Myth Frontend, and I assume that they tell myth to update itself with the current chainid that you are using for your live tv. Using the connected socket, send the RECORDING_LIST_CHANGE and the LIVETV_CHAIN UPDATE command from the BACKEND_MESSAGE command set.
Check the Recorder
Once you spawn live TV, you will want to query the recorder to see if it's recording. You can query multiple times until you get a good response, or until you give up. Typically, I've never had to call it more than once, although the myth frontend calls it twice, and get a valid response both times. use the IS_RECORDING sub command from the QUERY_RECORDER command set.
Getting the File for the Current Recording
There are a couple of ways of doing this. The first is to query the RECORDED table for your chain id, and then read the basename field. This will be filename on the Myth server.
I wanted to avoid using the database, so I issued the GET_CURRENT_RECORDING command from the QUERY_RECORDER command set. In it's reply, you can see that the 8th list element is the filename on the myth server. I stripped the path and used the filename only and my argument to the ANN FileTransfer command.
Starting the File Transfer
This is the good part. This is where you ask myth to start sending the file stream, so that you can pass it to your video player frontend.
First, you need open a second socket connection to myth. This is called the data socket. You need to issue the MYTH_PROTO_VERSION command in the data socket, then issue the ANN FileTransfer command passing the filename that you received in the previous step. The filename will look something like /123123_12312312312312312.mpg. Note the filename has the preceding forward slash. This DOES NOT mean the root of the filesystem, but rather the root of the myth tv recording directory. ANN FileTransfer will give you a socket id as the response. You need to pass this socket id in each of the QUERY_FILETRANSFER commands.
You have to tell myth to send you a block from the file using the command socket, and then read that block from the data socket. Using the command socket, send the QUERY_FILETRANSFER REQUEST BLOCK command and pass a block size, say 32768, and the socket id. The response to this command will be the # of bytes that myth was able to send. It should never be more than what you asked for, but it may be less. Once you have this #, then read the data sock for that # of bytes. Then pass those bytes off to your video player. Keep doing this over and over and over until your program stops.
Some notes, about the file transfer. If you request too much information, the myth backend will stop sending data all together. When I wrote my sample frontend, I used a variable buffer size. Mythfrontend does something similar. Basically I send 32k and if I got back 32K, then for the next request I add 16K. I keep doing this until I reached a max buffer size of 132k. If I got back less than what I asked for, then for the next request, I asked for 16K less then the previous request. When I watch the logging, I can see that usually myth can keep sending what I ask for, but there are times when it doesn't and my request sizes drop. When I use a static buffer size my video player either does not get enough video (buffer too small) or the backend stops sending me data (I asked for too much). This whole process is very tedious, and it's probably why I see that some clients require that you smb mount the MythTV recordings directory. The drawback to using a file as the input source for your video player is that if you reach the end of the file, then the play may stop.
Another note about the file transfer. If you want your video player to be smooth, you will want to buffer the video in the player for a few seconds. The nice thing about using a video stream is that most players will buffer for you.
Getting Guide Data
Unfortunately, there is no known Myth Command to fetch all guide data given a criteria. This was confirmed by running Ethereal and monitoring the network stream while telling mythfrontend to fetch its guide information. The resulting network traffic on port 6543 was minimal, and did not contain any guide queries. After checking the mythfrontend code, it was confirmed that guide information does come from the database. You can get the guide data for a recorded program, and as described in the previous section. The only way to get bulk guide data is from the database table, PROGRAM.
This is unfortunate if you want to write a client without needing a database connection. In doing research, I noticed that all clients require a database connection. The good news is that you do not need to store configuration for both the database and the mythbackend server. If you write a client that starts with a database connection, then you can pull the mythbackend settings from the SETTINGS table. Search where host name is null and read the VALUE field for MasterServerIP and MasterServerPort.
Possible Solutions for Guide Retrieval
Myth front end solution
Mythfrontend executes a query per channel for the given time frame that is being displayed. It then merges that information in a 2D grid. Even though executing a query per row results in an excessive amount of queries to the database, it does make processing the guide information fairly easy. Using a single query model would result in better use of the database but would add more code logic for processing the results. Given that the database and frontend both reside on a closed network, the current myth front end model does seem to be the most practical way to get the guide information. Refer to guidegrid.cpp for more details on how mythfrontend creates its guide grid.