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