21bfd720c12b7ac6c7f6b1ef8a6409791995c628
[vlc.git] / src / stream_output / stream_output.c
1 /*****************************************************************************
2  * stream_output.c : stream output module
3  *****************************************************************************
4  * Copyright (C) 2002 VideoLAN
5  * $Id: stream_output.c,v 1.5 2002/11/11 14:39:12 sam Exp $
6  *
7  * Authors: Christophe Massiot <massiot@via.ecp.fr>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
22  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #include <stdlib.h>                                                /* free() */
28 #include <stdio.h>                                              /* sprintf() */
29 #include <string.h>                                            /* strerror() */
30
31 #include <vlc/vlc.h>
32
33 #include <vlc/sout.h>
34
35 /*****************************************************************************
36  * Local prototypes
37  *****************************************************************************/
38 static int      InitInstance      ( sout_instance_t * );
39
40 /*****************************************************************************
41  * sout_NewInstance: creates a new stream output instance
42  *****************************************************************************/
43 sout_instance_t * __sout_NewInstance ( vlc_object_t *p_parent,
44                                        char * psz_dest )
45 {
46     sout_instance_t * p_sout;
47
48     /* Allocate descriptor */
49     p_sout = vlc_object_create( p_parent, VLC_OBJECT_SOUT );
50     if( p_sout == NULL )
51     {
52         msg_Err( p_parent, "out of memory" );
53         return NULL;
54     }
55
56     p_sout->psz_dest = psz_dest;
57     if ( InitInstance( p_sout ) == -1 )
58     {
59         vlc_object_destroy( p_sout );
60         return NULL;
61     }
62
63     return p_sout;
64 }
65
66 /*****************************************************************************
67  * InitInstance: opens appropriate modules
68  *****************************************************************************/
69 static int InitInstance( sout_instance_t * p_sout )
70 {
71     /* Parse dest string. Syntax : [[<access>][/<mux>]:][<dest>] */
72     /* This code is identical to input.c:InitThread. FIXME : factorize it ? */
73     char * psz_parser = p_sout->psz_dest;
74
75     /* Skip the plug-in names */
76     while( *psz_parser && *psz_parser != ':' )
77     {
78         psz_parser++;
79     }
80 #if defined( WIN32 ) || defined( UNDER_CE )
81     if( psz_parser - p_sout->psz_dest == 1 )
82     {
83         msg_Warn( p_sout, "drive letter %c: found in source string",
84                            p_sout->psz_dest ) ;
85         psz_parser = "";
86     }
87 #endif
88
89     if( !*psz_parser )
90     {
91         p_sout->psz_access = p_sout->psz_mux = "";
92         p_sout->psz_name = p_sout->psz_dest;
93     }
94     else
95     {
96         *psz_parser++ = '\0';
97
98         /* let's skip '//' */
99         if( psz_parser[0] == '/' && psz_parser[1] == '/' )
100         {
101             psz_parser += 2 ;
102         } 
103
104         p_sout->psz_name = psz_parser ;
105
106         /* Come back to parse the access and mux plug-ins */
107         psz_parser = p_sout->psz_dest;
108
109         if( !*psz_parser )
110         {
111             /* No access */
112             p_sout->psz_access = "";
113         }
114         else if( *psz_parser == '/' )
115         {
116             /* No access */
117             p_sout->psz_access = "";
118             psz_parser++;
119         }
120         else
121         {
122             p_sout->psz_access = psz_parser;
123
124             while( *psz_parser && *psz_parser != '/' )
125             {
126                 psz_parser++;
127             }
128
129             if( *psz_parser == '/' )
130             {
131                 *psz_parser++ = '\0';
132             }
133         }
134
135         if( !*psz_parser )
136         {
137             /* No mux */
138             p_sout->psz_mux = "";
139         }
140         else
141         {
142             p_sout->psz_mux = psz_parser;
143         }
144     }
145
146     msg_Dbg( p_sout, "access `%s', mux `%s', name `%s'",
147              p_sout->psz_access, p_sout->psz_mux, p_sout->psz_name );
148
149
150     /* Find and open appropriate access module */
151     p_sout->p_access =
152         module_Need( p_sout, "sout access", p_sout->psz_access );
153
154     if( p_sout->p_access == NULL )
155     {
156         msg_Err( p_sout, "no suitable sout access module for `%s/%s://%s'",
157                  p_sout->psz_access, p_sout->psz_mux, p_sout->psz_name );
158         return -1;
159     }
160
161     /* Find and open appropriate mux module */
162     p_sout->p_mux =
163         module_Need( p_sout, "sout mux", p_sout->psz_mux );
164
165     if( p_sout->p_mux == NULL )
166     {
167         msg_Err( p_sout, "no suitable mux module for `%s/%s://%s'",
168                  p_sout->psz_access, p_sout->psz_mux, p_sout->psz_name );
169         module_Unneed( p_sout, p_sout->p_access );
170         return -1;
171     }
172
173     return 0;
174 }
175
176
177 /*****************************************************************************
178  * sout_DeleteInstance: delete a previously allocated instance
179  *****************************************************************************/
180 void sout_DeleteInstance( sout_instance_t * p_sout )
181 {
182     /* Unlink object */
183     vlc_object_detach( p_sout );
184
185     /* Free structure */
186     vlc_object_destroy( p_sout );
187 }
188