1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/menu.c Sat Dec 29 14:47:40 2007 +0100
1.3 @@ -0,0 +1,402 @@
1.4 +/*
1.5 + * MP3/MPlayer plugin to VDR (C++)
1.6 + *
1.7 + * (C) 2001-2007 Stefan Huelswitt <s.huelswitt@gmx.de>
1.8 + *
1.9 + * This code is free software; you can redistribute it and/or
1.10 + * modify it under the terms of the GNU General Public License
1.11 + * as published by the Free Software Foundation; either version 2
1.12 + * of the License, or (at your option) any later version.
1.13 + *
1.14 + * This code is distributed in the hope that it will be useful,
1.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1.17 + * GNU General Public License for more details.
1.18 + *
1.19 + * You should have received a copy of the GNU General Public License
1.20 + * along with this program; if not, write to the Free Software
1.21 + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
1.22 + * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
1.23 + */
1.24 +
1.25 +#include <ctype.h>
1.26 +#include <dirent.h>
1.27 +#include <stdlib.h>
1.28 +#include <stdio.h>
1.29 +#include <errno.h>
1.30 +#include <sys/stat.h>
1.31 +#include <sys/ioctl.h>
1.32 +#include <sys/types.h>
1.33 +#include <unistd.h>
1.34 +
1.35 +#include "common.h"
1.36 +#include "menu.h"
1.37 +#include "data.h"
1.38 +#include "data-src.h"
1.39 +#include "i18n.h"
1.40 +
1.41 +// -----------------------------------------------------------------------------
1.42 +
1.43 +void Status(const char *text)
1.44 +{
1.45 +#if APIVERSNUM >= 10307
1.46 + Skins.Message(mtStatus,text);
1.47 +#else
1.48 + if(text) {
1.49 + Interface->Status(text);
1.50 + Interface->Flush();
1.51 + }
1.52 +#endif
1.53 +}
1.54 +
1.55 +void Error(const char *text)
1.56 +{
1.57 +#if APIVERSNUM >= 10307
1.58 + Skins.Message(mtError,text);
1.59 +#else
1.60 + Interface->Error(text);
1.61 +#endif
1.62 +}
1.63 +
1.64 +void Info(const char *text)
1.65 +{
1.66 +#if APIVERSNUM >= 10307
1.67 + Skins.Message(mtInfo,text);
1.68 +#else
1.69 + Interface->Info(text);
1.70 +#endif
1.71 +}
1.72 +
1.73 +// --- cMenuBrowseItem ---------------------------------------------------------
1.74 +
1.75 +class cMenuBrowseItem : public cOsdItem {
1.76 + private:
1.77 + cFileObj *item;
1.78 + virtual void Set(void);
1.79 +public:
1.80 + cMenuBrowseItem(cFileObj *Item);
1.81 + cFileObj *Item(void) { return item; }
1.82 + };
1.83 +
1.84 +cMenuBrowseItem::cMenuBrowseItem(cFileObj *Item)
1.85 +{
1.86 + item = Item;
1.87 + Set();
1.88 +}
1.89 +
1.90 +void cMenuBrowseItem::Set(void)
1.91 +{
1.92 + char *buffer=0;
1.93 + asprintf(&buffer,item->Type()==otFile?"%s":"[%s]",item->Name());
1.94 + SetText(buffer,false);
1.95 +}
1.96 +
1.97 +// --- cMenuBrowse ------------------------------------------------------
1.98 +
1.99 +cFileObj *cMenuBrowse::lastselect=0;
1.100 +
1.101 +cMenuBrowse::cMenuBrowse(cFileSource *Source, bool Dirselect, bool WithID3, const char *title, const char * const *Excl)
1.102 +:cOsdMenu(title)
1.103 +{
1.104 + currentdir=parent=0;
1.105 + delete lastselect; lastselect=0;
1.106 + list=new cDirList;
1.107 +
1.108 + dirselectable=Dirselect;
1.109 + withID3=WithID3;
1.110 + excl=Excl;
1.111 +
1.112 + SetSource(Source);
1.113 + NewDir(currentdir);
1.114 +}
1.115 +
1.116 +cMenuBrowse::~cMenuBrowse()
1.117 +{
1.118 + free(parent);
1.119 + free(currentdir);
1.120 + delete list;
1.121 +}
1.122 +
1.123 +cFileObj *cMenuBrowse::CurrentItem(void)
1.124 +{
1.125 + cMenuBrowseItem *item = (cMenuBrowseItem *)Get(Current());
1.126 + return item ? item->Item():0;
1.127 +}
1.128 +
1.129 +void cMenuBrowse::SetButtons(void)
1.130 +{
1.131 + SetHelp(tr("Select"), currentdir?tr("Parent"):0, 0, withID3?tr("ID3 info"):0);
1.132 + Display();
1.133 +}
1.134 +
1.135 +void cMenuBrowse::SetSource(cFileSource *Source)
1.136 +{
1.137 + source=Source;
1.138 + free(currentdir); currentdir=0;
1.139 + free(parent); parent=0;
1.140 + source->GetRemember(currentdir,parent);
1.141 +}
1.142 +
1.143 +bool cMenuBrowse::LoadDir(const char *dir)
1.144 +{
1.145 + Clear();
1.146 + Status(tr("Scanning directory..."));
1.147 + bool res=list->Load(source,dir,excl);
1.148 + if(res) {
1.149 + cFileObj *item=list->First();
1.150 + while(item) {
1.151 + Add(new cMenuBrowseItem(item),(parent && !strcmp(item->Name(),parent)));
1.152 + item=list->Next(item);
1.153 + }
1.154 + }
1.155 + Status(0);
1.156 + return res;
1.157 +}
1.158 +
1.159 +bool cMenuBrowse::NewDir(const char *dir)
1.160 +{
1.161 + char *ncur=dir ? strdup(dir):0;
1.162 + bool r=LoadDir(ncur);
1.163 + if(!r && ncur) {
1.164 + free(ncur); ncur=0;
1.165 + r=LoadDir(ncur);
1.166 + }
1.167 + if(r) {
1.168 + free(currentdir); currentdir=ncur;
1.169 +
1.170 + cFileObj *item=CurrentItem();
1.171 + source->SetRemember(currentdir,item?item->Name():0);
1.172 +
1.173 + SetButtons();
1.174 + return true;
1.175 + }
1.176 + free(ncur);
1.177 + Error(tr("Error scanning directory!"));
1.178 + return false;
1.179 +}
1.180 +
1.181 +eOSState cMenuBrowse::Parent(void)
1.182 +{
1.183 + eOSState res=osContinue;
1.184 +
1.185 + if(currentdir) {
1.186 + free(parent);
1.187 + char *ss=strrchr(currentdir,'/');
1.188 + if(ss) {
1.189 + *ss++=0;
1.190 + parent=strdup(ss);
1.191 + ss=currentdir;
1.192 + }
1.193 + else parent=strdup(currentdir);
1.194 +
1.195 + if(!NewDir(ss)) res=osEnd;
1.196 + }
1.197 + return res;
1.198 +}
1.199 +
1.200 +eOSState cMenuBrowse::Select(bool isred)
1.201 +{
1.202 + eOSState res=osContinue;
1.203 + cFileObj *item;
1.204 +
1.205 + if((item=CurrentItem())) {
1.206 + switch(item->Type()) {
1.207 + case otParent:
1.208 + if(!isred || !dirselectable)
1.209 + res=Parent();
1.210 + break;
1.211 + case otDir:
1.212 + if(!isred || !dirselectable) {
1.213 + if(!NewDir(item->Path())) res=osEnd;
1.214 + break;
1.215 + }
1.216 + // fall through to otFile
1.217 + case otFile:
1.218 + lastselect=new cFileObj(item);
1.219 + res=osBack;
1.220 + break;
1.221 + default:
1.222 + break;
1.223 + }
1.224 + }
1.225 + return res;
1.226 +}
1.227 +
1.228 +eOSState cMenuBrowse::ID3Info(void)
1.229 +{
1.230 + return osContinue;
1.231 +}
1.232 +
1.233 +eOSState cMenuBrowse::ProcessStdKey(eKeys Key, eOSState state)
1.234 +{
1.235 + if(state==osUnknown) {
1.236 + switch (Key) {
1.237 + case kOk: state=Select(false); break;
1.238 + case kRed: state=Select(true); break;
1.239 + case kGreen: state=Parent(); break;
1.240 + case kBlue: if(withID3) state=ID3Info();
1.241 + break;
1.242 + //case kMenu: state=osEnd; break;
1.243 + default: break;
1.244 + }
1.245 + }
1.246 + if(state==osEnd || state==osBack) {
1.247 + cFileObj *item=CurrentItem();
1.248 + if(item) source->SetRemember(currentdir,item->Name());
1.249 + }
1.250 + return state;
1.251 +}
1.252 +
1.253 +// --- cMenuSourceItem ----------------------------------------------------------
1.254 +
1.255 +class cMenuSourceItem : public cOsdItem {
1.256 + private:
1.257 + cFileSource *source;
1.258 + virtual void Set(void);
1.259 +public:
1.260 + cMenuSourceItem(cFileSource *Source);
1.261 + cFileSource *Source(void) { return source; }
1.262 + };
1.263 +
1.264 +cMenuSourceItem::cMenuSourceItem(cFileSource *Source)
1.265 +{
1.266 + source=Source;
1.267 + Set();
1.268 +}
1.269 +
1.270 +void cMenuSourceItem::Set(void)
1.271 +{
1.272 + char *buffer=0;
1.273 + asprintf(&buffer, "%s\t%s\t%s", source->NeedsMount()?(source->Status()?"*":">"):"", source->Description(), source->BaseDir());
1.274 + SetText(buffer,false);
1.275 +}
1.276 +
1.277 +// --- cMenuSource --------------------------------------------------
1.278 +
1.279 +cFileSource *cMenuSource::selected=0;
1.280 +
1.281 +cMenuSource::cMenuSource(cFileSources *Sources, const char *title)
1.282 +:cOsdMenu(title,2,20)
1.283 +{
1.284 + selected=0;
1.285 + current=Sources->GetSource();
1.286 + cFileSource *source=Sources->First();
1.287 + while(source) {
1.288 + cOsdMenu::Add(new cMenuSourceItem(source),source==current);
1.289 + source=Sources->Next(source);
1.290 + }
1.291 +
1.292 + SetHelp(tr("Select"), tr("Mount"), tr("Unmount"), tr("Eject"));
1.293 + Display();
1.294 +}
1.295 +
1.296 +bool cMenuSource::DoMount(cFileSource *src)
1.297 +{
1.298 + bool res=src->Mount();
1.299 + RefreshCurrent();
1.300 + DisplayCurrent(true);
1.301 + return res;
1.302 +}
1.303 +
1.304 +bool cMenuSource::CheckMount(void)
1.305 +{
1.306 + cFileSource *src=selected ? selected:current;
1.307 + if(src->NeedsMount() && !src->Status()) {
1.308 + Error(tr("Selected source is not mounted!"));
1.309 + return false;
1.310 + }
1.311 + return true;
1.312 +}
1.313 +
1.314 +eOSState cMenuSource::Select(void)
1.315 +{
1.316 + if(HasSubMenu() || Count() == 0) return osContinue;
1.317 +
1.318 + cFileSource *src = ((cMenuSourceItem *)Get(Current()))->Source();
1.319 + if(src->NeedsMount() && !src->Status()) {
1.320 + if(!DoMount(src)) Error(tr("Mount failed!"));
1.321 + }
1.322 + if(!src->NeedsMount() || src->Status()) {
1.323 + selected=src;
1.324 + return osBack;
1.325 + }
1.326 + return osContinue;
1.327 +}
1.328 +
1.329 +eOSState cMenuSource::Mount(void)
1.330 +{
1.331 + if(HasSubMenu() || Count() == 0) return osContinue;
1.332 +
1.333 + cFileSource *src = ((cMenuSourceItem *)Get(Current()))->Source();
1.334 + if(src->NeedsMount() && !src->Status()) {
1.335 + if(DoMount(src)) Info(tr("Mount succeeded"));
1.336 + else Error(tr("Mount failed!"));
1.337 + }
1.338 + return osContinue;
1.339 +}
1.340 +
1.341 +eOSState cMenuSource::Unmount(void)
1.342 +{
1.343 + if(HasSubMenu() || Count() == 0) return osContinue;
1.344 +
1.345 + cFileSource *src = ((cMenuSourceItem *)Get(Current()))->Source();
1.346 + if(src->NeedsMount() && src->Status()) {
1.347 + bool res=src->Unmount();
1.348 + RefreshCurrent();
1.349 + DisplayCurrent(true);
1.350 + if(res) Info(tr("Unmount succeeded"));
1.351 + else Error(tr("Unmount failed!"));
1.352 + }
1.353 + return osContinue;
1.354 +}
1.355 +
1.356 +eOSState cMenuSource::Eject(void)
1.357 +{
1.358 + if(HasSubMenu() || Count() == 0) return osContinue;
1.359 +
1.360 + cFileSource *src = ((cMenuSourceItem *)Get(Current()))->Source();
1.361 + if(src->NeedsMount()) {
1.362 + bool res=src->Eject();
1.363 + RefreshCurrent();
1.364 + DisplayCurrent(true);
1.365 + if(!res) Error(tr("Eject failed!"));
1.366 + }
1.367 + return osContinue;
1.368 +}
1.369 +
1.370 +eOSState cMenuSource::ProcessKey(eKeys Key)
1.371 +{
1.372 + eOSState state = cOsdMenu::ProcessKey(Key);
1.373 +
1.374 + if(state==osBack && !CheckMount()) state=osContinue;
1.375 + if(state==osUnknown) {
1.376 + switch(Key) {
1.377 + case kOk:
1.378 + case kRed: return Select();
1.379 + case kGreen: return Mount();
1.380 + case kYellow: return Unmount();
1.381 + case kBlue: return Eject();
1.382 + case kMenu: CheckMount(); return osEnd;
1.383 + default: break;
1.384 + }
1.385 + }
1.386 + return state;
1.387 +}
1.388 +
1.389 +// --- cProgressBar ------------------------------------------------------------
1.390 +
1.391 +cProgressBar::cProgressBar(int Width, int Height, int Current, int Total)
1.392 +:cBitmap(Width, Height, 2)
1.393 +{
1.394 + if(Total > 0) {
1.395 + int p = Current * Width / Total;;
1.396 +#if APIVERSNUM >= 10307
1.397 + DrawRectangle(0, 0, p, Height - 1, clrGreen);
1.398 + DrawRectangle(p + 1, 0, Width - 1, Height - 1, clrWhite);
1.399 +#else
1.400 + Fill(0, 0, p, Height - 1, clrGreen);
1.401 + Fill(p + 1, 0, Width - 1, Height - 1, clrWhite);
1.402 +#endif
1.403 + }
1.404 +}
1.405 +