]> git.sesse.net Git - vlc/blob - modules/access/dshow/crossbar.cpp
macosx: fixed menubar appearance in fullscreen mode by partially reverting [46c93c9cc...
[vlc] / modules / access / dshow / crossbar.cpp
1 /*****************************************************************************
2  * crossbar.c : DirectShow access module for vlc
3  *****************************************************************************
4  * Copyright (C) 2002 the VideoLAN team
5  * $Id$
6  *
7  * Author: Damien Fouilleul <damien dot fouilleul at laposte dot net>
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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27
28 #ifdef HAVE_CONFIG_H
29 # include "config.h"
30 #endif
31
32 #include <vlc_common.h>
33 #include <vlc_vout.h>
34
35 #ifndef _MSC_VER
36     /* Work-around a bug in w32api-2.5 */
37 #   define QACONTAINERFLAGS QACONTAINERFLAGS_ANOTHERSOMETHINGELSE
38 #endif
39
40 #include "common.h"
41
42
43
44 // Helper function to associate a crossbar pin name with the type.
45 static const char * GetPhysicalPinName(long lType)
46 {
47     switch (lType)
48     {
49     case PhysConn_Video_Tuner:            return "Video Tuner";
50     case PhysConn_Video_Composite:        return "Video Composite";
51     case PhysConn_Video_SVideo:           return "S-Video";
52     case PhysConn_Video_RGB:              return "Video RGB";
53     case PhysConn_Video_YRYBY:            return "Video YRYBY";
54     case PhysConn_Video_SerialDigital:    return "Video Serial Digital";
55     case PhysConn_Video_ParallelDigital:  return "Video Parallel Digital";
56     case PhysConn_Video_SCSI:             return "Video SCSI";
57     case PhysConn_Video_AUX:              return "Video AUX";
58     case PhysConn_Video_1394:             return "Video 1394";
59     case PhysConn_Video_USB:              return "Video USB";
60     case PhysConn_Video_VideoDecoder:     return "Video Decoder";
61     case PhysConn_Video_VideoEncoder:     return "Video Encoder";
62
63     case PhysConn_Audio_Tuner:            return "Audio Tuner";
64     case PhysConn_Audio_Line:             return "Audio Line";
65     case PhysConn_Audio_Mic:              return "Audio Microphone";
66     case PhysConn_Audio_AESDigital:       return "Audio AES/EBU Digital";
67     case PhysConn_Audio_SPDIFDigital:     return "Audio S/PDIF";
68     case PhysConn_Audio_SCSI:             return "Audio SCSI";
69     case PhysConn_Audio_AUX:              return "Audio AUX";
70     case PhysConn_Audio_1394:             return "Audio 1394";
71     case PhysConn_Audio_USB:              return "Audio USB";
72     case PhysConn_Audio_AudioDecoder:     return "Audio Decoder";
73
74     default:                              return "Unknown Type";
75     }
76 }
77 /*****************************************************************************
78  * DeleteCrossbarRoutes
79  *****************************************************************************/
80 void DeleteCrossbarRoutes( access_sys_t *p_sys )
81 {
82     /* Remove crossbar filters from graph */
83     for( int i = 0; i < p_sys->i_crossbar_route_depth; i++ )
84     {
85         p_sys->crossbar_routes[i].pXbar->Release();
86     }
87     p_sys->i_crossbar_route_depth = 0;
88 }
89
90 /*****************************************************************************
91  * RouteCrossbars (Does not AddRef the returned *Pin)
92  *****************************************************************************/
93 static HRESULT GetCrossbarIPinAtIndex( IAMCrossbar *pXbar, LONG PinIndex,
94                                        BOOL IsInputPin, IPin ** ppPin )
95 {
96     LONG         cntInPins, cntOutPins;
97     IPin        *pP = NULL;
98     IBaseFilter *pFilter = NULL;
99     IEnumPins   *pins = NULL;
100     ULONG        n;
101
102     if( !pXbar || !ppPin ) return E_POINTER;
103
104     *ppPin = 0;
105
106     if( S_OK != pXbar->get_PinCounts(&cntOutPins, &cntInPins) ) return E_FAIL;
107
108     LONG TrueIndex = IsInputPin ? PinIndex : PinIndex + cntInPins;
109
110     if( pXbar->QueryInterface(IID_IBaseFilter, (void **)&pFilter) == S_OK )
111     {
112         if( SUCCEEDED(pFilter->EnumPins(&pins)) )
113         {
114             LONG i = 0;
115             while( pins->Next(1, &pP, &n) == S_OK )
116             {
117                 pP->Release();
118                 if( i == TrueIndex )
119                 {
120                     *ppPin = pP;
121                     break;
122                 }
123                 i++;
124             }
125             pins->Release();
126         }
127         pFilter->Release();
128     }
129
130     return *ppPin ? S_OK : E_FAIL;
131 }
132
133 /*****************************************************************************
134  * GetCrossbarIndexFromIPin: Find corresponding index of an IPin on a crossbar
135  *****************************************************************************/
136 static HRESULT GetCrossbarIndexFromIPin( IAMCrossbar * pXbar, LONG * PinIndex,
137                                          BOOL IsInputPin, IPin * pPin )
138 {
139     LONG         cntInPins, cntOutPins;
140     IPin        *pP = NULL;
141     IBaseFilter *pFilter = NULL;
142     IEnumPins   *pins = NULL;
143     ULONG        n;
144     BOOL         fOK = FALSE;
145
146     if(!pXbar || !PinIndex || !pPin )
147         return E_POINTER;
148
149     if( S_OK != pXbar->get_PinCounts(&cntOutPins, &cntInPins) )
150         return E_FAIL;
151
152     if( pXbar->QueryInterface(IID_IBaseFilter, (void **)&pFilter) == S_OK )
153     {
154         if( SUCCEEDED(pFilter->EnumPins(&pins)) )
155         {
156             LONG i=0;
157
158             while( pins->Next(1, &pP, &n) == S_OK )
159             {
160                 pP->Release();
161                 if( pPin == pP )
162                 {
163                     *PinIndex = IsInputPin ? i : i - cntInPins;
164                     fOK = TRUE;
165                     break;
166                 }
167                 i++;
168             }
169             pins->Release();
170         }
171         pFilter->Release();
172     }
173
174     return fOK ? S_OK : E_FAIL;
175 }
176
177 /*****************************************************************************
178  * FindCrossbarRoutes
179  *****************************************************************************/
180 HRESULT FindCrossbarRoutes( vlc_object_t *p_this, access_sys_t *p_sys,
181                             IPin *p_input_pin, LONG physicalType, int depth )
182 {
183     HRESULT result = S_FALSE;
184
185     IPin *p_output_pin;
186     if( FAILED(p_input_pin->ConnectedTo(&p_output_pin)) ) return S_FALSE;
187
188     // It is connected, so now find out if the filter supports IAMCrossbar
189     PIN_INFO pinInfo;
190     if( FAILED(p_output_pin->QueryPinInfo(&pinInfo)) ||
191         PINDIR_OUTPUT != pinInfo.dir )
192     {
193         p_output_pin->Release ();
194         return S_FALSE;
195     }
196
197     IAMCrossbar *pXbar = NULL;
198     if( FAILED(pinInfo.pFilter->QueryInterface(IID_IAMCrossbar,
199                                                (void **)&pXbar)) )
200     {
201         pinInfo.pFilter->Release();
202         p_output_pin->Release ();
203         return S_FALSE;
204     }
205
206     LONG inputPinCount, outputPinCount;
207     if( FAILED(pXbar->get_PinCounts(&outputPinCount, &inputPinCount)) )
208     {
209         pXbar->Release();
210         pinInfo.pFilter->Release();
211         p_output_pin->Release ();
212         return S_FALSE;
213     }
214
215     LONG inputPinIndexRelated, outputPinIndexRelated;
216     LONG inputPinPhysicalType = 0, outputPinPhysicalType;
217     LONG inputPinIndex = 0, outputPinIndex;
218     if( FAILED(GetCrossbarIndexFromIPin( pXbar, &outputPinIndex,
219                                          FALSE, p_output_pin )) ||
220         FAILED(pXbar->get_CrossbarPinInfo( FALSE, outputPinIndex,
221                                            &outputPinIndexRelated,
222                                            &outputPinPhysicalType )) )
223     {
224         pXbar->Release();
225         pinInfo.pFilter->Release();
226         p_output_pin->Release ();
227         return S_FALSE;
228     }
229
230     /*
231     ** if physical type is 0, then use default/existing route to physical connector
232     */
233     if( physicalType == 0 )
234     {
235         /* use following as default connector type if we fail to find an existing route */
236         physicalType = PhysConn_Video_Tuner;
237         if( SUCCEEDED(pXbar->get_IsRoutedTo(outputPinIndex, &inputPinIndex)) )
238         {
239
240             if( SUCCEEDED( pXbar->get_CrossbarPinInfo( TRUE,  inputPinIndex,
241                            &inputPinIndexRelated, &inputPinPhysicalType )) )
242             {
243                 // remember connector type
244                 physicalType = inputPinPhysicalType;
245  
246                 msg_Dbg( p_this, "found existing route for output %ld (type %s) to input %ld (type %s)",
247                          outputPinIndex, GetPhysicalPinName( outputPinPhysicalType ),
248                          inputPinIndex, GetPhysicalPinName( inputPinPhysicalType ) );
249  
250                 // fall through to for loop, note 'inputPinIndex' is set to the pin we are looking for
251                 // hence, loop iteration should not wind back
252
253             }
254         }
255         else {
256             // reset to first pin for complete loop iteration
257             inputPinIndex = 0;
258         }
259     }
260  
261     //
262     // for all input pins
263     //
264     for( /* inputPinIndex has been set */ ; (S_OK != result) && (inputPinIndex < inputPinCount); ++inputPinIndex )
265     {
266         if( FAILED(pXbar->get_CrossbarPinInfo( TRUE,  inputPinIndex,
267             &inputPinIndexRelated, &inputPinPhysicalType )) ) continue;
268
269         // Is this pin matching required connector physical type?
270         if( inputPinPhysicalType != physicalType ) continue;
271
272         // Can we route it?
273         if( FAILED(pXbar->CanRoute(outputPinIndex, inputPinIndex)) ) continue;
274  
275  
276         IPin *pPin;
277         if( FAILED(GetCrossbarIPinAtIndex( pXbar, inputPinIndex,
278                                            TRUE, &pPin)) ) continue;
279
280         result = FindCrossbarRoutes( p_this, p_sys, pPin,
281                                      physicalType, depth+1 );
282
283         if( S_OK == result || (S_FALSE == result &&
284             physicalType == inputPinPhysicalType &&
285             (p_sys->i_crossbar_route_depth = depth+1) < MAX_CROSSBAR_DEPTH) )
286         {
287             // hold on crossbar, will be released when graph is destroyed
288             pXbar->AddRef();
289
290             // remember crossbar route
291             p_sys->crossbar_routes[depth].pXbar = pXbar;
292             p_sys->crossbar_routes[depth].VideoInputIndex = inputPinIndex;
293             p_sys->crossbar_routes[depth].VideoOutputIndex = outputPinIndex;
294             p_sys->crossbar_routes[depth].AudioInputIndex = inputPinIndexRelated;
295             p_sys->crossbar_routes[depth].AudioOutputIndex = outputPinIndexRelated;
296
297             msg_Dbg( p_this, "crossbar at depth %d, found route for "
298                      "output %ld (type %s) to input %ld (type %s)", depth,
299                      outputPinIndex, GetPhysicalPinName( outputPinPhysicalType ),
300                      inputPinIndex, GetPhysicalPinName( inputPinPhysicalType ) );
301
302             result = S_OK;
303         }
304     }
305
306     pXbar->Release();
307     pinInfo.pFilter->Release();
308     p_output_pin->Release ();
309
310     return result;
311 }