/* This program was written from information conained in the document * "TCP Remote Protocol, version 1.1" located at: http://www.tivo.com/assets/images/abouttivo/resources/downloads/brochures/TiVo_TCP_Network_Remote_Control_Protocol.pdf */ #include #include /* The buffer to hold the responses from the TiVo */ static char responseData[1024]; /* This function will abstract the differences in sleeping among various OSes */ static void sleep( int milliSeconds ) { #ifdef _WIN32 Sleep( milliSeconds ); #else usleep( milliSeconds * 1000 ); #endif } /* end sleep */ /* This function will wait for the response from the TiVo */ static void waitForResponse( unsigned tivoSocket ) { /* the number of bytes received into the buffer */ int receiveCount = 0; /* a counter for the loops to determine if I should give up */ int timeoutCount = 0; /* the max number of iterations before giving up */ const int timeoutLimit = 20; /* clear out the response buffer so I can use it to print the responses */ memset( responseData, 0, sizeof(responseData) ); /* while there is more data toreceive, and I haven't wated too long */ while (((receiveCount == 0) || (responseData[receiveCount -1] != '\r')) && !(timeoutCount > timeoutLimit)) { /* the number of bytes received from the "recv" call */ int receiveBytes; /* count this iteration */ timeoutCount += 1; /* try to receive data */ receiveBytes = recv( tivoSocket, &responseData[receiveCount], sizeof( responseData ), 0 ); /* if there were no bytes received */ if (receiveBytes <= 0) { sleep( 50 ); } else { /* count the number of bytes the buffer has */ receiveCount += receiveBytes; } } /* print the data that was received from the TiVo */ puts(responseData); } /* end waitForResponse */ int main( int argc, char *argv[]) { struct hostent *hostAddr; struct in_addr inAddr; struct sockaddr_in tivoAddr; unsigned int tivoSocket; short tivoPort = htons( 31339 ); #if defined(_WIN32) WORD winsockVersion = MAKEWORD(2, 2); WSADATA startupData; #endif int nonblocking; int result; #if defined(_WIN32) (void) WSAStartup(winsockVersion, &startupData); #endif hostAddr = gethostbyname(argv[1]); tivoPort = htons(31339); inAddr.s_addr = *(ULONG *) hostAddr->h_addr_list[0]; // create the socket tivoSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); // define the TiVo side connection memset(&tivoAddr, 0, sizeof(tivoAddr)); tivoAddr.sin_addr.S_un.S_addr = inAddr.S_un.S_addr; tivoAddr.sin_port = tivoPort; tivoAddr.sin_family = AF_INET; // connect to the TiVo result = connect( tivoSocket, (void *)&tivoAddr, sizeof( tivoAddr ) ); // if the connection was established if (result >= 0) { char tivoCommand[80]; int i; nonblocking = 1; result = ioctlsocket( tivoSocket, FIONBIO, (void *)&nonblocking ); waitForResponse( tivoSocket ); // send the command to go to LIVETV (void) sprintf( tivoCommand, "%s\r", "TELEPORT LIVETV" ); (void) send( tivoSocket, tivoCommand, strlen( tivoCommand ), 0 ); /* wait so the response will be ready */ waitForResponse( tivoSocket ); // record the command and response to the log file /* send the command to change the channel */ for (i = 0; i < strlen( argv[2] ); i++) { (void) sprintf( tivoCommand, "KEYBOARD NUM%c\r", argv[2][i] ); puts(tivoCommand); (void) send( tivoSocket, tivoCommand, strlen( tivoCommand ), 0 ); } /* send the ENTER command so I won't have to wait for the timeout * period */ (void) sprintf( tivoCommand, "KEYBOARD %s\r", "ENTER" ); (void) send( tivoSocket, tivoCommand, strlen( tivoCommand ), 0 ); // The KEYBOARD commands don't have a response /* wait a little bit so the channel will be tuned, otherwise the * CLEAR command will be ignored */ sleep( 500 ); // send the command to clear the overlay from the screen (void) sprintf( tivoCommand, "%s\r", "KEYBOARD CLEAR" ); (void) send( tivoSocket, tivoCommand, strlen( tivoCommand ), 0 ); // The KEYBOARD commands don't have a response // close the socket #if defined(_WIN32) closesocket( tivoSocket ); #else close( tivoSocket ); #endif } printf( "%d\n", WSAGetLastError()); return 0; }