1 /*
2  *			GPAC - Multimedia Framework C SDK
3  *
4  *			Authors: Jean Le Feuvre
5  *			Copyright (c) Telecom ParisTech 2006-2012
6  *					All rights reserved
7  *
8  *  This file is part of GPAC / Symbian GUI player
9  *
10  *  GPAC is free software; you can redistribute it and/or modify
11  *  it under the terms of the GNU Lesser General Public License as published by
12  *  the Free Software Foundation; either version 2, or (at your option)
13  *  any later version.
14  *
15  *  GPAC is distributed in the hope that it will be useful,
16  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  *  GNU Lesser General Public License for more details.
19  *
20  *  You should have received a copy of the GNU Lesser General Public
21  *  License along with this library; see the file COPYING.  If not, write to
22  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
23  *
24  */
25 
26 #include <eiktxlbx.h>
27 #include <eiktxlbm.h>
28 
29 
30 #include <gpac/utf.h>
31 
32 // INCLUDE FILES
33 #include "osmo4_ui.h"
34 #include "playlist.h"
35 
36 #ifdef USE_SKIN
37 #include <aknlists.h>
38 #include <akntabgrp.h>
39 #include <AknsDrawUtils.h>// skin
40 #include <AknsBasicBackgroundControlContext.h> //skin
41 #endif
42 
43 
CPlaylist()44 CPlaylist::CPlaylist()
45 {
46 	playlist_mode = 0;
47 	view_all_files = 0;
48 }
~CPlaylist()49 CPlaylist::~CPlaylist()
50 {
51 	delete iListBox;
52 	delete iBackGround;
53 }
54 
NewL(const TRect & aRect,GF_User * user)55 CPlaylist* CPlaylist::NewL( const TRect& aRect, GF_User *user)
56 {
57 	CPlaylist* self = CPlaylist::NewLC( aRect, user);
58 	CleanupStack::Pop( self );
59 	return self;
60 }
NewLC(const TRect & aRect,GF_User * user)61 CPlaylist* CPlaylist::NewLC( const TRect& aRect, GF_User *user)
62 {
63 	CPlaylist* self = new ( ELeave ) CPlaylist;
64 	CleanupStack::PushL( self );
65 	self->ConstructL( aRect, user);
66 	return self;
67 }
68 
ConstructL(const TRect & aRect,GF_User * user)69 void CPlaylist::ConstructL(const TRect& aRect, GF_User *user)
70 {
71 	CreateWindowL();
72 
73 #ifdef USE_SKIN
74 	iListBox = new (ELeave) CAknSingleStyleListBox();
75 #else
76 	iListBox = new (ELeave) CEikTextListBox();
77 #endif
78 	iListBox->ConstructL(this);
79 	iListBox->SetContainerWindowL(*this);
80 	iListBox->SetListBoxObserver(this);
81 
82 	CDesCArray* textArray = new (ELeave) CDesCArrayFlat(16);
83 	iListBox->Model()->SetItemTextArray( textArray );
84 	iListBox->Model()->SetOwnershipType( ELbmOwnsItemArray );
85 
86 	// Creates scrollbar.
87 	iListBox->CreateScrollBarFrameL( ETrue );
88 	iListBox->ScrollBarFrame()->SetScrollBarVisibilityL(CEikScrollBarFrame::EAuto, CEikScrollBarFrame::EAuto);
89 	//iListBox->ActivateL();
90 
91 	iListBox->SetFocus(ETrue);
92 
93 	SetRect(aRect);
94 	ActivateL();
95 	MakeVisible(EFalse);
96 
97 	strcpy(szCurrentDir, "");
98 
99 #ifndef GPAC_GUI_ONLY
100 	m_user = user;
101 
102 	strcpy(ext_list, "");
103 	u32 count = gf_cfg_get_key_count(user->config, "MimeTypes");
104 	for (u32 i=0; i<count; i++) {
105 		char szKeyList[1000], *sKey;
106 		const char *sMime = gf_cfg_get_key_name(user->config, "MimeTypes", i);
107 		const char *opt = gf_cfg_get_key(user->config, "MimeTypes", sMime);
108 		strcpy(szKeyList, opt+1);
109 		sKey = strrchr(szKeyList, '\"');
110 		if (!sKey) continue;
111 		sKey[0] = 0;
112 		strcat(ext_list, szKeyList);
113 		strcat(ext_list, " ");
114 	}
115 
116 	const char *opt = gf_cfg_get_key(m_user->config, "General", "LastWorkingDir");
117 	if (opt) strcpy(szCurrentDir, opt);
118 #endif
119 
120 }
121 
SizeChanged()122 void CPlaylist::SizeChanged()
123 {
124 	iListBox->SetRect( Rect() );
125 }
126 
Draw(const TRect & aRect) const127 void CPlaylist::Draw(const TRect& aRect) const
128 {
129 #ifdef USE_SKIN
130 	CWindowGc& gc = SystemGc();
131 	MAknsSkinInstance* skin = AknsUtils::SkinInstance();
132 	MAknsControlContext* cc = AknsDrawUtils::ControlContext( this );
133 	AknsDrawUtils::Background( skin, cc, this, gc, aRect );
134 #endif
135 
136 }
137 
138 #ifdef USE_SKIN
MopSupplyObject(TTypeUid aId)139 TTypeUid::Ptr CPlaylist::MopSupplyObject(TTypeUid aId)
140 {
141 	if(aId.iUid == MAknsControlContext::ETypeId && iBackGround) {
142 		return MAknsControlContext::SupplyMopObject( aId, iBackGround);
143 	}
144 	return CCoeControl::MopSupplyObject( aId );
145 }
146 #endif
147 
148 
CountComponentControls() const149 TInt CPlaylist::CountComponentControls() const
150 {
151 	return 1;
152 }
ComponentControl(TInt aIndex) const153 CCoeControl* CPlaylist::ComponentControl(TInt aIndex) const
154 {
155 	switch (aIndex) {
156 	case 0:
157 		return iListBox;
158 	default:
159 		return NULL;
160 	}
161 }
162 
OfferKeyEventL(const TKeyEvent & aKeyEvent,TEventCode aType)163 TKeyResponse CPlaylist::OfferKeyEventL(const TKeyEvent& aKeyEvent, TEventCode aType)
164 {
165 	if (aType != EEventKey) return iListBox->OfferKeyEventL(aKeyEvent, aType);
166 
167 	switch (aKeyEvent.iScanCode) {
168 	case EStdKeyEnter:
169 		HandleSelection();
170 		return EKeyWasConsumed;
171 	default:
172 		return iListBox->OfferKeyEventL(aKeyEvent, aType);
173 	}
174 }
HandleListBoxEventL(CEikListBox * aListBox,TListBoxEvent aEventType)175 void CPlaylist::HandleListBoxEventL(CEikListBox* aListBox, TListBoxEvent aEventType )
176 {
177 	if (aEventType == MEikListBoxObserver::EEventItemClicked ||
178 	        aEventType == MEikListBoxObserver::EEventEnterKeyPressed)
179 
180 		HandleSelection();
181 }
182 
ShowHide(Bool show)183 void CPlaylist::ShowHide(Bool show)
184 {
185 	if (show) {
186 		RefreshPlaylist();
187 		MakeVisible(ETrue);
188 		DrawNow();
189 	} else {
190 		/*cleanup*/
191 		ResetView();
192 		MakeVisible(EFalse);
193 		((COsmo4AppUi *) CEikonEnv::Static()->AppUi())->SetTitle(NULL, 0);
194 	}
195 }
196 
197 
FlushItemList()198 void CPlaylist::FlushItemList()
199 {
200 	iListBox->HandleItemAdditionL();
201 	iListBox->SetCurrentItemIndexAndDraw(0);
202 }
203 
ResetView()204 void CPlaylist::ResetView()
205 {
206 	CDesCArray* array = static_cast<CDesCArray*>(iListBox->Model()->ItemTextArray());
207 	array->Reset();
208 	iListBox->Reset();
209 }
210 
AddItem(const char * name,int is_directory)211 void CPlaylist::AddItem(const char *name, int is_directory)
212 {
213 	TBuf<100> tmp;
214 	char szName[100];
215 	CDesCArray* array = static_cast<CDesCArray*>(iListBox->Model()->ItemTextArray());
216 
217 	if (is_directory) {
218 #ifdef USE_SKIN
219 		sprintf(szName, "\t+ %s\t\t", name);
220 #else
221 		sprintf(szName, "+ %s", name);
222 #endif
223 	} else {
224 #ifdef USE_SKIN
225 		sprintf(szName, "\t%s\t\t", name);
226 #else
227 		strcpy(szName, name);
228 #endif
229 	}
230 	tmp.SetLength(strlen(szName)+1);
231 	tmp.Copy( TPtrC8(( TText8* ) szName) );
232 	tmp.ZeroTerminate();
233 	array->AppendL(tmp);
234 }
235 
enum_dirs(void * cbk,char * name,char * path,GF_FileEnumInfo * file_info)236 static Bool enum_dirs(void *cbk, char *name, char *path, GF_FileEnumInfo *file_info)
237 {
238 	CPlaylist *of = (CPlaylist *)cbk;
239 	of->AddItem(name, 1);
240 	return 0;
241 }
242 
enum_files(void * cbk,char * name,char * path,GF_FileEnumInfo * file_info)243 static Bool enum_files(void *cbk, char *name, char *path, GF_FileEnumInfo *file_info)
244 {
245 	CPlaylist *of = (CPlaylist *)cbk;
246 	of->AddItem(name, 0);
247 	return 0;
248 }
249 
250 
ScanDirectory(const char * dir)251 void CPlaylist::ScanDirectory(const char *dir)
252 {
253 	ResetView();
254 
255 	if (!dir || !strlen(dir)) {
256 		RFs iFs;
257 		TDriveList aList;
258 		iFs.Connect();
259 		iFs.DriveList(aList);
260 		for (TInt i=0; i<KMaxDrives; i++) {
261 			if (aList[i]) {
262 				TChar aDrive;
263 				iFs.DriveToChar(i, aDrive);
264 				sprintf(szCurrentDir, "%c:", (TUint)aDrive);
265 				AddItem(szCurrentDir, 0);
266 			}
267 		}
268 		iFs.Close();
269 		FlushItemList();
270 		strcpy(szCurrentDir, "");
271 		return;
272 	} else {
273 		strcpy(szCurrentDir, dir);
274 		AddItem("..", 1);
275 	}
276 
277 #ifndef GPAC_GUI_ONLY
278 	gf_enum_directory((const char *) szCurrentDir, 1, enum_dirs, this, NULL);
279 	gf_enum_directory((char *) szCurrentDir, 0, enum_files, this, view_all_files ? NULL : ext_list);
280 #endif
281 	FlushItemList();
282 
283 	((COsmo4AppUi *) CEikonEnv::Static()->AppUi())->SetTitle(szCurrentDir, 0);
284 
285 }
286 
GetSelectionName(char * szName)287 void CPlaylist::GetSelectionName(char *szName)
288 {
289 	CDesCArray* array = static_cast<CDesCArray*>(iListBox->Model()->ItemTextArray());
290 	TInt idx = iListBox->CurrentItemIndex();
291 
292 #ifndef GPAC_GUI_ONLY
293 
294 #if defined(_UNICODE)
295 	size_t len;
296 	/*handle terminating zero !!*/
297 	u16 szNameUTF16[100];
298 	len = (*array)[idx].Size();
299 	memcpy(szNameUTF16, (*array)[idx].Ptr(), sizeof(u8)*len);
300 	szNameUTF16[len/2] = 0;
301 	const u16 *sptr = szNameUTF16;
302 
303 	/*skip initial '\t'*/
304 #ifdef USE_SKIN
305 	sptr += 1;
306 #endif
307 
308 	len = gf_utf8_wcstombs(szName, 512, &sptr);
309 	szName[len] = 0;
310 
311 
312 #else
313 
314 	char *src = (*array)[idx]).Ptr();
315 	/*skip initial '\t'*/
316 #ifdef USE_SKIN
317 	src += 1;
318 #endif
319 	strcpy(szName, (const char *) src) ;
320 #endif
321 
322 	/*remove trailing "\t\t"*/
323 #ifdef USE_SKIN
324 	len = strlen(szName);
325 	szName[len-2] = 0;
326 #endif
327 
328 #else
329 	szName[0] = 0;
330 #endif
331 
332 }
333 
HandleSelection()334 void CPlaylist::HandleSelection()
335 {
336 	char szName[100];
337 	GetSelectionName(szName);
338 
339 	/*sub-directory*/
340 	if ((szName[0] == '+') && (szName[1] == ' ')) {
341 		/*browse up*/
342 		if ((szName[2] == '.') && (szName[3] == '.')) {
343 			char *prev = strrchr(szCurrentDir, '\\');
344 			if (prev) {
345 				prev[0] = 0;
346 				ScanDirectory(szCurrentDir);
347 			} else {
348 				ScanDirectory(NULL);
349 			}
350 		} else {
351 			strcat(szCurrentDir, "\\");
352 			strcat(szCurrentDir, szName+2);
353 			ScanDirectory(szCurrentDir);
354 		}
355 	} else if (szName[1] == ':') {
356 		ScanDirectory(szName);
357 	} else {
358 		char szURL[1024];
359 		COsmo4AppUi *app = (COsmo4AppUi *) CEikonEnv::Static()->AppUi();
360 		if (playlist_mode) {
361 			TInt idx = iListBox->CurrentItemIndex();
362 #ifndef GPAC_GUI_ONLY
363 			const char *url = gf_cfg_get_key_name(m_user->config, "Playlist", idx);
364 			if (url) app->PlayURL(url);
365 #endif
366 		} else {
367 			gf_cfg_set_key(m_user->config, "General", "LastWorkingDir", (const char *) szCurrentDir);
368 			sprintf(szURL, "%s\\%s", szCurrentDir, szName);
369 			app->PlayURL(szURL);
370 		}
371 	}
372 }
373 
SelectionIsFile()374 Bool CPlaylist::SelectionIsFile()
375 {
376 	char szName[100];
377 	GetSelectionName(szName);
378 	if ((szName[0] == '+') && (szName[1] == ' ')) return 0;
379 	else if (szName[1] == ':') return 0;
380 	return 1;
381 }
382 
IsInPlaylist()383 Bool CPlaylist::IsInPlaylist()
384 {
385 	char szURL[1024];
386 	char szName[100];
387 	GetSelectionName(szName);
388 	if ((szName[0] == '+') && (szName[1] == ' ')) return 0;
389 	else if (szName[1] == ':') return 0;
390 
391 	/*remove from playlist*/
392 	sprintf(szURL, "%s\\%s", szCurrentDir, szName);
393 #ifndef GPAC_GUI_ONLY
394 	const char *opt = gf_cfg_get_key(m_user->config, "Playlist", szURL);
395 	if (opt) return 1;
396 #endif
397 	return 0;
398 }
399 
dir_add_files(void * cbk,char * name,char * path,GF_FileEnumInfo * file_info)400 static Bool dir_add_files(void *cbk, char *name, char *path, GF_FileEnumInfo *file_info)
401 {
402 	CPlaylist *pl = (CPlaylist *)cbk;
403 
404 #if 0
405 	if (!bViewUnknownTypes && extension_list) {
406 		char *ext = strrchr(name, '.');
407 		if (!ext || !strstr(extension_list, ext+1)) return 0;
408 	}
409 #endif
410 
411 #ifndef GPAC_GUI_ONLY
412 	gf_cfg_set_key(pl->m_user->config, "Playlist", path, "");
413 #endif
414 
415 	return 0;
416 }
417 
418 
RefreshPlaylist()419 void CPlaylist::RefreshPlaylist()
420 {
421 	if (playlist_mode) {
422 #ifndef GPAC_GUI_ONLY
423 		u32 count = gf_cfg_get_key_count(m_user->config, "Playlist");
424 		ResetView();
425 		for (u32 i=0; i<count; i++) {
426 			const char *opt = gf_cfg_get_key_name(m_user->config, "Playlist", i);
427 			const char *sep = strrchr(opt, '\\');
428 			if (!sep) sep = strrchr(opt, '/');
429 			AddItem(sep ? (sep+1) : opt, 0);
430 		}
431 		if (!count) AddItem("[empty]", 0);
432 #endif
433 		FlushItemList();
434 
435 		((COsmo4AppUi *) CEikonEnv::Static()->AppUi())->SetTitle("Playlist", 0);
436 	} else {
437 		ScanDirectory(szCurrentDir);
438 	}
439 }
440 
441 
PlaylistAct(Osmo4_PLActions act)442 void CPlaylist::PlaylistAct(Osmo4_PLActions act)
443 {
444 	char szURL[1024];
445 	char szName[100];
446 	CDesCArray*array;
447 	TInt idx;
448 	TInt count;
449 
450 	if (act==Osmo4PLClear) {
451 		while (1) {
452 #ifndef GPAC_GUI_ONLY
453 			const char *opt = gf_cfg_get_key_name(m_user->config, "Playlist", 0);
454 			if (!opt) break;
455 			gf_cfg_set_key(m_user->config, "Playlist", opt, NULL);
456 #endif
457 		}
458 		RefreshPlaylist();
459 		return;
460 	} else if (act == Osmo4PLToggleMode) {
461 		playlist_mode = !playlist_mode;
462 		RefreshPlaylist();
463 		return;
464 	} else if (act == Osmo4PLToggleAllFiles) {
465 		view_all_files = !view_all_files;
466 		RefreshPlaylist();
467 		return;
468 	} else if (act == Osmo4PLAdd) {
469 #ifndef GPAC_GUI_ONLY
470 		GetSelectionName(szName);
471 		if ((szName[0] == '+') && (szName[1] == ' ')) {
472 			if ((szName[2] != '.') && (szName[3] != '.')) {
473 				sprintf(szURL, "%s\\%s", szCurrentDir, szName+2);
474 				gf_enum_directory(szURL, 0, dir_add_files, this, view_all_files ? NULL : ext_list);
475 			}
476 		} else if (szName[1] == ':') {
477 			gf_enum_directory(szName, 0, dir_add_files, this, view_all_files ? NULL : ext_list);
478 		} else {
479 			sprintf(szURL, "%s\\%s", szCurrentDir, szName);
480 			gf_cfg_set_key(m_user->config, "Playlist", szURL, "");
481 		}
482 #endif
483 		return;
484 	}
485 
486 	GetSelectionName(szName);
487 	if ((szName[0] == '+') && (szName[1] == ' ')) return;
488 	else if (szName[1] == ':') return;
489 
490 	switch (act) {
491 	/*remove from playlist*/
492 	case Osmo4PLRem:
493 #ifndef GPAC_GUI_ONLY
494 		sprintf(szURL, "%s\\%s", szCurrentDir, szName);
495 		gf_cfg_set_key(m_user->config, "Playlist", szURL, NULL);
496 #endif
497 		RefreshPlaylist();
498 		break;
499 	/*move up*/
500 	case Osmo4PLMoveUp:
501 		array = static_cast<CDesCArray*>(iListBox->Model()->ItemTextArray());
502 		count = array->Count();
503 		idx = iListBox->CurrentItemIndex();
504 		sprintf(szURL, "%s\\%s", szCurrentDir, szName);
505 #ifndef GPAC_GUI_ONLY
506 		gf_cfg_set_key(m_user->config, "Playlist", szURL, NULL);
507 		gf_cfg_insert_key(m_user->config, "Playlist", szURL, "", idx-1);
508 #endif
509 		RefreshPlaylist();
510 		if (idx>1) iListBox->SetCurrentItemIndexAndDraw(idx-1);
511 		break;
512 	/*move down*/
513 	case Osmo4PLMoveDown:
514 		array = static_cast<CDesCArray*>(iListBox->Model()->ItemTextArray());
515 		count = array->Count();
516 		idx = iListBox->CurrentItemIndex();
517 		sprintf(szURL, "%s\\%s", szCurrentDir, szName);
518 #ifndef GPAC_GUI_ONLY
519 		gf_cfg_set_key(m_user->config, "Playlist", szURL, NULL);
520 		gf_cfg_insert_key(m_user->config, "Playlist", szURL, "", idx+1);
521 #endif
522 		RefreshPlaylist();
523 		if (idx<count-1) iListBox->SetCurrentItemIndexAndDraw(idx+1);
524 		break;
525 	default:
526 		break;
527 	}
528 }
529 
530