gmyth/src/gmyth_vlc.c
author melunko
Wed Aug 22 14:55:41 2007 +0100 (2007-08-22)
branchtrunk
changeset 820 a223e9d89b01
parent 750 312d6bc514f3
permissions -rw-r--r--
[svn r826] gmyth-ls and gmyth_query now considers db_port. Thanks to Bastien Nocera for his patch.
     1 /**
     2  * GMyth Library
     3  *
     4  * @file gmyth/gmyth_vlc.c
     5  *
     6  * @brief <p> GMythVLC library provides functions that
     7  * interact with a VLC server running telnet interface.
     8  *
     9  * Copyright (C) 2007 INdT - Instituto Nokia de Tecnologia.
    10  * @author Artur Duque de Souza <artur.souza@indt.org.br>
    11  *
    12  * 
    13  * This program is free software; you can redistribute it and/or modify
    14  * it under the terms of the GNU Lesser General Public License as published by
    15  * the Free Software Foundation; either version 2 of the License, or
    16  * (at your option) any later version.
    17  *
    18  * This program is distributed in the hope that it will be useful,
    19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    21  * GNU General Public License for more details.
    22  *
    23  * You should have received a copy of the GNU Lesser General Public License
    24  * along with this program; if not, write to the Free Software
    25  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    26  */
    27 
    28 #ifdef HAVE_CONFIG_H
    29 #include "config.h"
    30 #endif
    31 
    32 #include <assert.h>
    33 
    34 #include "gmyth_vlc.h"
    35 #include "gmyth_debug.h"
    36 #include "gmyth_socket.h"
    37 
    38 /*
    39  * static functions 
    40  */
    41 static int      _socket_send(int socket, gchar * msg);
    42 static int      _socket_recv(int socket, gchar * buf);
    43 
    44 /** Primitive function to send a message through the socket
    45  *
    46  * @param socket 
    47  * @param msg the message itself
    48  * @return 0 if success
    49  */
    50 static int
    51 _socket_send(int socket, gchar * msg)
    52 {
    53     size_t          size = strlen(msg) + 2; // (\n + \0)
    54     gchar          *final = (gchar *) g_malloc0(sizeof(gchar) * size);
    55 
    56     g_snprintf(final, size, "%s\n", msg);
    57 
    58     if (send(socket, final, strlen(final), 0) == -1)
    59         perror("GMyth_VLC: send error");
    60 
    61     g_free(final);
    62     return 0;
    63 }
    64 
    65 
    66 /** Primitive function to receive a message through the socket
    67  *
    68  * @param socket 
    69  * @param buf Buffer to put the message
    70  * @return 0 if success
    71  */
    72 static int
    73 _socket_recv(int socket, gchar * buf)
    74 {
    75     int             numbytes = 0;
    76 
    77     if ((numbytes = recv(socket, buf, BUFFER - 1, 0)) == -1) {
    78         perror("GMyth_VLC: recv error");
    79         return -1;
    80     }
    81 
    82     buf[numbytes - 1] = '\0';
    83     return numbytes;
    84 }
    85 
    86 
    87 /** Function that adds options to the output media
    88  *
    89  * @param vlc structure with options for vlc
    90  * @param output the number of the output media
    91  * @param kind the type of option we'll change
    92  * @param the params for the option
    93  * @return 0 if success
    94  */
    95 int
    96 gmyth_vlc_setup_output(GMythVlc * vlc, int output, gchar * kind,
    97                        gchar * opts)
    98 {
    99     int             ret;
   100 
   101     size_t          size = strlen(opts) + 25;
   102     gchar          *msg = g_malloc0(sizeof(gchar) * size);
   103 
   104     g_snprintf(msg, size, "setup output%d %s %s", output, kind, opts);
   105 
   106     ret = _socket_send(vlc->sockfd, msg);
   107 
   108     g_free(msg);
   109     return ret;
   110 }
   111 
   112 
   113 /** Function to clean the playlist
   114  *
   115  * @param vlc structure with options for vlc
   116  * @param output the number of the output media
   117  * @param file the file we want to insert in the playlist
   118  * @return 0 if success
   119  */
   120 int
   121 gmyth_vlc_clean_playlist(GMythVlc * vlc)
   122 {
   123     return _socket_send(vlc->sockfd, "del all");
   124 }
   125 
   126 
   127 /** Function to control the playlist
   128  *
   129  * @param vlc structure with options for vlc
   130  * @param output the number of the output media
   131  * @param command play, stop or pause(just for vod)
   132  * @return 0 if success
   133  */
   134 int
   135 gmyth_vlc_control_input(GMythVlc * vlc, int output, gchar * command)
   136 {
   137     size_t          size = 25;
   138     gchar          *msg = g_malloc0(sizeof(gchar) * size);
   139 
   140     g_snprintf(msg, size, "control output%d %s", output, command);
   141 
   142     int             ret = _socket_send(vlc->sockfd, msg);
   143 
   144     g_free(msg);
   145     return ret;
   146 }
   147 
   148 
   149 
   150 /** Function to insert an item in the playlist
   151  *
   152  * @param vlc structure with options for vlc
   153  * @param output the number of the output media
   154  * @param file the file we want to insert in the playlist
   155  * @return 0 if success
   156  */
   157 int
   158 gmyth_vlc_create_input(GMythVlc * vlc, int output, gchar * file)
   159 {
   160     return gmyth_vlc_setup_output(vlc, output, "input", file);
   161 }
   162 
   163 
   164 /** Function to create a channel in vlc
   165  *
   166  * @param vlc structure with options for vlc
   167  * @param type the type of channel (broadcast, vod...)
   168  * @param port
   169  * @return 0 if success
   170  */
   171 int
   172 gmyth_vlc_create_channel(GMythVlc * vlc, gchar * type, int port,
   173                          int vcodec)
   174 {
   175     int             ret;
   176     size_t          size = 40;
   177     gchar          *msg = (gchar *) g_malloc0(sizeof(gchar) * size);
   178 
   179     g_snprintf(msg, size, "new output%d %s enabled loop", vlc->n_outputs,
   180                type);
   181 
   182     ret = _socket_send(vlc->sockfd, msg);
   183 
   184     if (ret > -1) {
   185         gmyth_vlc_setup_output(vlc, vlc->n_outputs, "option",
   186                                "sout-keep=1");
   187 
   188         g_free(msg);
   189         size = 256;
   190         msg = (gchar *) g_malloc0(sizeof(gchar) * size);
   191 
   192         if (vcodec == MPEG1)
   193             // Best transcode option for N800 (MP1V)
   194             g_snprintf(msg, size, "#transcode{vcodec=mp1v,vb=384,"
   195                        "fps=25.0,scale=1,acodec=mpga,"
   196                        "ab=64,channels=1}:duplicate{dst="
   197                        "std{access=http,mux=mpeg1,dst=" ":%d}}", port);
   198         else
   199             // Best transcode option for N800 (THEORA)
   200             g_snprintf(msg, size, "#transcode{vcodec=theo,vb=384,"
   201                        "fps=25.0,scale=1,acodec=vorb,"
   202                        "ab=64,channels=1}:duplicate{dst="
   203                        "std{access=http,mux=ogg,dst=" ":%d}}", port);
   204 
   205         ret = gmyth_vlc_setup_output(vlc, vlc->n_outputs, "output", msg);
   206 
   207         vlc->n_outputs++;
   208     }
   209 
   210     g_free(msg);
   211 
   212     return ret;
   213 }
   214 
   215 
   216 /** Function to connect to vlc on the backend
   217  *
   218  * @param vlc structure with options for vlc
   219  * @param backend_info infos about the backend
   220  * @param passwd the password for telnet interface
   221  * @return 0 if success
   222  */
   223 int
   224 gmyth_vlc_connect(GMythVlc * vlc, GMythBackendInfo * backend_info,
   225                   gchar * passwd, int port)
   226 {
   227     int             numbytes;
   228 
   229     if ((vlc->he = gethostbyname(backend_info->hostname)) == NULL) {
   230         herror("GMyth_VLC: gethostbyname error");
   231         return -1;
   232     }
   233 
   234     if ((vlc->sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1) {
   235         perror("GMyth_VLC: socket error");
   236         return -1;
   237     }
   238     // Socket properties
   239     vlc->their_addr.sin_family = AF_INET;
   240     vlc->their_addr.sin_port = htons(port);
   241     vlc->their_addr.sin_addr = *((struct in_addr *) vlc->he->h_addr);
   242     memset(&(vlc->their_addr.sin_zero), '\0', 8);
   243 
   244     if (connect(vlc->sockfd, (struct sockaddr *) &(vlc->their_addr),
   245                 sizeof(struct sockaddr)) == -1) {
   246         perror("GMyth_VLC: connect error. Check VLC's telnet interface");
   247         return -1;
   248     }
   249     // Receive the Password's Prompt
   250     numbytes = _socket_recv(vlc->sockfd, vlc->buf);
   251 
   252     // Send the Password. We don't have to
   253     // care about passwords being sent in plain text
   254     // because telnet protocol does it.
   255     _socket_send(vlc->sockfd, passwd);
   256 
   257     // Receive the Welcome msg
   258     numbytes = _socket_recv(vlc->sockfd, vlc->buf);
   259     if (numbytes > -1)
   260         if (strncmp(vlc->buf, "\r\nWrong password.", 17) == 0) {
   261             perror("Gmyth_VLC: passwd error. Check your passwd");
   262             return -2;
   263         }
   264 
   265 
   266     return 0;
   267 }
   268 
   269 
   270 /** Function to disconnect from vlc
   271  *
   272  * @param vlc structure with options for vlc
   273  * @param backend_info infos about the backend
   274  * @return 0 if success
   275  */
   276 int
   277 gmyth_vlc_disconnect(GMythVlc * vlc)
   278 {
   279 
   280     int             ret;
   281 
   282     ret = gmyth_vlc_clean_playlist(vlc);
   283 
   284     if (ret > -1) {
   285         vlc->n_outputs = 0;
   286         vlc->n_inputs = 0;
   287     }
   288 
   289     return close(vlc->sockfd);
   290 }