2dbc9c8d4795057b1dc9f838648a8e8284f63fec
[vlc.git] / modules / gui / wince / dialogs.cpp
1 /*****************************************************************************
2  * dialogs.cpp : WinCE plugin for vlc
3  *****************************************************************************
4  * Copyright (C) 2000-2005 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Gildas Bazin <gbazin@videolan.org>
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_aout.h>
34 #include <vlc_interface.h>
35
36 #include "wince.h"
37
38 #include <commctrl.h>
39 #include <commdlg.h>
40 #include <shlobj.h>
41
42 /* Dialogs Provider */
43 class DialogsProvider: public CBaseWindow
44 {
45 public:
46     /* Constructor */
47     DialogsProvider( intf_thread_t *, CBaseWindow *, HINSTANCE = 0 );
48     virtual ~DialogsProvider();
49
50 protected:
51     virtual LRESULT WndProc( HWND, UINT, WPARAM, LPARAM );
52
53 private:
54
55     void OnExit( void );
56     void OnIdle( void );
57     void OnPlaylist( void );
58     void OnMessages( void );
59     void OnFileInfo( void );
60     void OnPreferences( void );
61     void OnPopupMenu( void );
62
63     void OnOpen( int, int );
64     void OnOpenFileSimple( int );
65     void OnOpenDirectory( int );
66     void OnOpenFileGeneric( intf_dialog_args_t * );
67
68     /* GetOpenFileName replacement */
69     BOOL (WINAPI *GetOpenFile)(void *);
70     HMODULE h_gsgetfile_dll;
71
72 public:
73     /* Secondary windows */
74     OpenDialog          *p_open_dialog;
75     Playlist            *p_playlist_dialog;
76     Messages            *p_messages_dialog;
77     PrefsDialog         *p_prefs_dialog;
78     FileInfo            *p_fileinfo_dialog;
79 };
80
81 CBaseWindow *CreateDialogsProvider( intf_thread_t *p_intf,
82                                     CBaseWindow *p_parent, HINSTANCE h_inst )
83 {
84     return new DialogsProvider( p_intf, p_parent, h_inst );
85 }
86
87 /*****************************************************************************
88  * Constructor.
89  *****************************************************************************/
90 DialogsProvider::DialogsProvider( intf_thread_t *p_intf,
91                                   CBaseWindow *p_parent, HINSTANCE h_inst )
92   :  CBaseWindow( p_intf, p_parent, h_inst )
93 {
94     /* Initializations */
95     p_open_dialog = NULL;
96     p_playlist_dialog = NULL;
97     p_messages_dialog = NULL;
98     p_fileinfo_dialog = NULL;
99     p_prefs_dialog = NULL;
100
101     /* Create dummy window */
102     hWnd = CreateWindow( _T("VLC WinCE"), _T("DialogsProvider"), 0,
103                          0, 0, CW_USEDEFAULT, CW_USEDEFAULT,
104                          p_parent->GetHandle(), NULL, h_inst, (void *)this );
105
106     GetOpenFile = 0;
107     h_gsgetfile_dll = LoadLibrary( _T("gsgetfile") );
108     if( h_gsgetfile_dll )
109     {
110         GetOpenFile = (BOOL (WINAPI *)(void *))
111             GetProcAddress( h_gsgetfile_dll, _T("gsGetOpenFileName") );
112     }
113
114     if( !GetOpenFile )
115         GetOpenFile = (BOOL (WINAPI *)(void *))::GetOpenFileName;
116 }
117
118 DialogsProvider::~DialogsProvider()
119 {
120     /* Clean up */
121     delete p_open_dialog;
122     delete p_playlist_dialog;
123     delete p_messages_dialog;
124     delete p_fileinfo_dialog;
125     delete p_prefs_dialog;
126
127     if( h_gsgetfile_dll ) FreeLibrary( h_gsgetfile_dll );
128 }
129
130 LRESULT DialogsProvider::WndProc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp )
131 {
132     switch( msg )
133     {
134     case WM_APP + INTF_DIALOG_FILE: OnOpen( FILE_ACCESS, wp ); return TRUE;
135     case WM_APP + INTF_DIALOG_NET: OnOpen( NET_ACCESS, wp ); return TRUE;
136     case WM_APP + INTF_DIALOG_FILE_SIMPLE: OnOpenFileSimple( wp ); return TRUE;
137     case WM_APP + INTF_DIALOG_DIRECTORY: OnOpenDirectory( wp ); return TRUE;
138     case WM_APP + INTF_DIALOG_FILE_GENERIC:
139         OnOpenFileGeneric( (intf_dialog_args_t*)lp ); return TRUE;
140     case WM_APP + INTF_DIALOG_PLAYLIST: OnPlaylist(); return TRUE;
141     case WM_APP + INTF_DIALOG_MESSAGES: OnMessages(); return TRUE;
142     case WM_APP + INTF_DIALOG_FILEINFO: OnFileInfo(); return TRUE;
143     case WM_APP + INTF_DIALOG_PREFS: OnPreferences(); return TRUE;
144     case WM_APP + INTF_DIALOG_POPUPMENU: OnPopupMenu(); return TRUE;
145     }
146
147     return DefWindowProc( hwnd, msg, wp, lp );
148 }
149
150 void DialogsProvider::OnIdle( void )
151 {
152     /* Update the log window */
153     if( p_messages_dialog ) p_messages_dialog->UpdateLog();
154
155     /* Update the playlist */
156     if( p_playlist_dialog ) p_playlist_dialog->UpdatePlaylist();
157
158     /* Update the fileinfo windows */
159     if( p_fileinfo_dialog ) p_fileinfo_dialog->UpdateFileInfo();
160 }
161
162 void DialogsProvider::OnPopupMenu( void )
163 {
164     POINT point = {0};
165     PopupMenu( p_intf, hWnd, point );
166 }
167
168 void DialogsProvider::OnPlaylist( void )
169 {
170 #if 1
171     Playlist *playlist = new Playlist( p_intf, this, hInst );
172     CreateDialogBox( hWnd, playlist );
173     delete playlist;
174 #else
175     /* Show/hide the playlist window */
176     if( !p_playlist_dialog )
177         p_playlist_dialog = new Playlist( p_intf, this, hInst );
178
179     if( p_playlist_dialog )
180     {
181         p_playlist_dialog->ShowPlaylist( !p_playlist_dialog->IsShown() );
182     }
183 #endif
184 }
185
186 void DialogsProvider::OnMessages( void )
187 {
188     /* Show/hide the log window */
189     if( !p_messages_dialog )
190         p_messages_dialog = new Messages( p_intf, this, hInst );
191
192     if( p_messages_dialog )
193     {
194         p_messages_dialog->Show( !p_messages_dialog->IsShown() );
195     }
196 }
197
198 void DialogsProvider::OnFileInfo( void )
199 {
200 #if 1
201     FileInfo *fileinfo = new FileInfo( p_intf, this, hInst );
202     CreateDialogBox( hWnd, fileinfo );
203     delete fileinfo;
204 #else
205     /* Show/hide the file info window */
206     if( !p_fileinfo_dialog )
207         p_fileinfo_dialog = new FileInfo( p_intf, this, hInst );
208
209     if( p_fileinfo_dialog )
210     {
211         p_fileinfo_dialog->Show( !p_fileinfo_dialog->IsShown() );
212     }
213 #endif
214 }
215
216 void DialogsProvider::OnPreferences( void )
217 {
218 #if 1
219     PrefsDialog *preferences = new PrefsDialog( p_intf, this, hInst );
220     CreateDialogBox( hWnd, preferences );
221     delete preferences;
222 #else
223     /* Show/hide the open dialog */
224     if( !p_prefs_dialog )
225         p_prefs_dialog = new PrefsDialog( p_intf, this, hInst );
226
227     if( p_prefs_dialog )
228     {
229         p_prefs_dialog->Show( !p_prefs_dialog->IsShown() );
230     }
231 #endif
232 }
233
234 void DialogsProvider::OnOpen( int i_access, int i_arg )
235 {
236     /* Show/hide the open dialog */
237     if( !p_open_dialog )
238         p_open_dialog = new OpenDialog( p_intf, this, hInst, i_access, i_arg );
239
240     if( p_open_dialog )
241     {
242         p_open_dialog->Show( !p_open_dialog->IsShown() );
243     }
244 }
245
246 void DialogsProvider::OnOpenFileGeneric( intf_dialog_args_t *p_arg )
247 {
248     if( p_arg == NULL )
249     {
250         msg_Dbg( p_intf, "OnOpenFileGeneric() called with NULL arg" );
251         return;
252     }
253
254     /* Convert the filter string */
255     TCHAR *psz_filters = (TCHAR *)
256         malloc( (strlen(p_arg->psz_extensions) + 2) * sizeof(TCHAR) );
257     _tcscpy( psz_filters, _FROMMB(p_arg->psz_extensions) );
258
259     int i;
260     for( i = 0; psz_filters[i]; i++ )
261     {
262         if( psz_filters[i] == '|' ) psz_filters[i] = 0;
263     }
264     psz_filters[++i] = 0;
265
266     OPENFILENAME ofn;
267     TCHAR szFile[MAX_PATH] = _T("\0");
268
269     memset( &ofn, 0, sizeof(OPENFILENAME) );
270     ofn.lStructSize = sizeof(OPENFILENAME);
271     ofn.hwndOwner = hWnd;
272     ofn.hInstance = hInst;
273     ofn.lpstrFilter = psz_filters;
274     ofn.lpstrCustomFilter = NULL;
275     ofn.nMaxCustFilter = 0;
276     ofn.nFilterIndex = 1;
277     ofn.lpstrFile = (LPTSTR)szFile;
278     ofn.nMaxFile = MAX_PATH;
279     ofn.lpstrFileTitle = NULL;
280     ofn.nMaxFileTitle = 40;
281     ofn.lpstrInitialDir = NULL;
282     ofn.lpstrTitle = _FROMMB(p_arg->psz_title);
283     ofn.Flags = 0;
284     ofn.nFileOffset = 0;
285     ofn.nFileExtension = 0;
286     ofn.lpstrDefExt = NULL;
287     ofn.lCustData = 0L;
288     ofn.lpfnHook = NULL;
289     ofn.lpTemplateName = NULL;
290
291     SHFullScreen( GetForegroundWindow(), SHFS_HIDESIPBUTTON );
292
293     if( p_arg->b_save && GetSaveFileName( &ofn ) )
294     {
295         p_arg->i_results = 1;
296         p_arg->psz_results = (char **)malloc( p_arg->i_results *
297                                               sizeof(char *) );
298         p_arg->psz_results[0] = strdup( _TOMB(ofn.lpstrFile) );
299     }
300
301     if( !p_arg->b_save && GetOpenFile( &ofn ) )
302     {
303         p_arg->i_results = 1;
304         p_arg->psz_results = (char **)malloc( p_arg->i_results *
305                                               sizeof(char *) );
306         p_arg->psz_results[0] = strdup( _TOMB(ofn.lpstrFile) );
307     }
308
309     /* Callback */
310     if( p_arg->pf_callback )
311     {
312         p_arg->pf_callback( p_arg );
313     }
314
315     if( p_arg->psz_results )
316     {
317         for( int i = 0; i < p_arg->i_results; i++ )
318         {
319             free( p_arg->psz_results[i] );
320         }
321         free( p_arg->psz_results );
322     }
323     free( p_arg->psz_title );
324     free( p_arg->psz_extensions );
325
326     free( p_arg );
327 }
328
329 void DialogsProvider::OnOpenFileSimple( int i_arg )
330 {
331     OPENFILENAME ofn;
332     TCHAR szFile[MAX_PATH] = _T("\0");
333     static TCHAR szFilter[] = _T("All (*.*)\0*.*\0");
334
335     playlist_t *p_playlist = pl_Yield( p_intf );
336     if( p_playlist == NULL ) return;
337
338     memset( &ofn, 0, sizeof(OPENFILENAME) );
339     ofn.lStructSize = sizeof(OPENFILENAME);
340     ofn.hwndOwner = hWnd;
341     ofn.hInstance = hInst;
342     ofn.lpstrFilter = szFilter;
343     ofn.lpstrCustomFilter = NULL;
344     ofn.nMaxCustFilter = 0;
345     ofn.nFilterIndex = 1;
346     ofn.lpstrFile = (LPTSTR)szFile;
347     ofn.nMaxFile = MAX_PATH;
348     ofn.lpstrFileTitle = NULL;
349     ofn.nMaxFileTitle = 40;
350     ofn.lpstrInitialDir = NULL;
351     ofn.lpstrTitle = _T("Quick Open File");
352     ofn.Flags = 0;
353     ofn.nFileOffset = 0;
354     ofn.nFileExtension = 0;
355     ofn.lpstrDefExt = NULL;
356     ofn.lCustData = 0L;
357     ofn.lpfnHook = NULL;
358     ofn.lpTemplateName = NULL;
359
360     SHFullScreen( GetForegroundWindow(), SHFS_HIDESIPBUTTON );
361
362     if( GetOpenFile( &ofn ) )
363     {
364         char *psz_filename = _TOMB(ofn.lpstrFile);
365         playlist_Add( p_playlist, psz_filename, psz_filename,
366                       PLAYLIST_APPEND | (i_arg?PLAYLIST_GO:0), PLAYLIST_END );
367     }
368
369     pl_Release( p_intf );
370 }
371
372 void DialogsProvider::OnOpenDirectory( int i_arg )
373 {
374     TCHAR psz_result[MAX_PATH];
375     LPMALLOC p_malloc = 0;
376     LPITEMIDLIST pidl;
377     BROWSEINFO bi;
378     playlist_t *p_playlist = 0;
379
380 #ifdef UNDER_CE
381 #   define SHGetMalloc MySHGetMalloc
382 #   define SHBrowseForFolder MySHBrowseForFolder
383 #   define SHGetPathFromIDList MySHGetPathFromIDList
384
385     HMODULE ceshell_dll = LoadLibrary( _T("ceshell") );
386     if( !ceshell_dll ) return;
387
388     HRESULT (WINAPI *SHGetMalloc)(LPMALLOC *) =
389         (HRESULT (WINAPI *)(LPMALLOC *))
390         GetProcAddress( ceshell_dll, _T("SHGetMalloc") );
391     LPITEMIDLIST (WINAPI *SHBrowseForFolder)(LPBROWSEINFO) =
392         (LPITEMIDLIST (WINAPI *)(LPBROWSEINFO))
393         GetProcAddress( ceshell_dll, _T("SHBrowseForFolder") );
394     BOOL (WINAPI *SHGetPathFromIDList)(LPCITEMIDLIST, LPTSTR) =
395         (BOOL (WINAPI *)(LPCITEMIDLIST, LPTSTR))
396         GetProcAddress( ceshell_dll, _T("SHGetPathFromIDList") );
397
398     if( !SHGetMalloc || !SHBrowseForFolder || !SHGetPathFromIDList )
399     {
400         msg_Err( p_intf, "couldn't load SHBrowseForFolder API" );
401         FreeLibrary( ceshell_dll );
402         return;
403     }
404 #endif
405
406     if( !SUCCEEDED( SHGetMalloc(&p_malloc) ) ) goto error;
407
408     p_playlist = pl_Yield( p_intf );
409     if( !p_playlist ) goto error;
410
411     memset( &bi, 0, sizeof(BROWSEINFO) );
412     bi.hwndOwner = hWnd;
413     bi.pszDisplayName = psz_result;
414     bi.ulFlags = BIF_EDITBOX;
415 #ifndef UNDER_CE
416     bi.ulFlags |= BIF_USENEWUI;
417 #endif
418
419     if( (pidl = SHBrowseForFolder( &bi ) ) )
420     {
421         if( SHGetPathFromIDList( pidl, psz_result ) )
422         {
423             char *psz_filename = _TOMB(psz_result);
424             playlist_Add( p_playlist, psz_filename, psz_filename,
425                           PLAYLIST_APPEND | (i_arg ? PLAYLIST_GO : 0),
426                           PLAYLIST_END );
427         }
428         p_malloc->Free( pidl );
429     }
430
431  error:
432
433     if( p_malloc) p_malloc->Release();
434     if( p_playlist ) pl_Release( p_intf );
435
436 #ifdef UNDER_CE
437     FreeLibrary( ceshell_dll );
438 #endif
439 }