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