00001 #include <qapplication.h>
00002 #include <qsqldatabase.h>
00003 #include <qsqlquery.h>
00004 #include <qstring.h>
00005 #include <qdir.h>
00006 #include <qfile.h>
00007 #include <qstringlist.h>
00008 #include <qregexp.h>
00009 #include <qmap.h>
00010
00011 #include <unistd.h>
00012 #include <cstdio>
00013 #include <fcntl.h>
00014 #include <cstdlib>
00015 #include <sys/types.h>
00016
00017 #include <iostream>
00018
00019 #include "libmyth/mythconfig.h"
00020 #include "libmyth/mythcontext.h"
00021 #include "libmyth/mythdbcon.h"
00022 #include "libmyth/langsettings.h"
00023 #include "libmyth/dialogbox.h"
00024 #include "libmyth/exitcodes.h"
00025 #include "libmyth/util.h"
00026 #include "libmyth/storagegroup.h"
00027 #include "libmythui/myththemedmenu.h"
00028 #include "libmythui/myththemebase.h"
00029
00030 #include "libmythtv/dbcheck.h"
00031 #include "libmythtv/videosource.h"
00032 #include "libmythtv/channeleditor.h"
00033 #include "libmythtv/remoteutil.h"
00034 #include "backendsettings.h"
00035 #include "checksetup.h"
00036
00037 using namespace std;
00038
00039 void SetupMenuCallback ( void* data, QString& selection )
00040 {
00041 (void)data;
00042
00043 QString sel = selection.lower();
00044
00045 if ( sel == "general" )
00046 {
00047 BackendSettings be;
00048 be.exec();
00049 }
00050 else if ( sel == "capture cards" )
00051 {
00052 CaptureCardEditor cce;
00053 cce.exec();
00054 }
00055 else if ( sel == "video sources" )
00056 {
00057 VideoSourceEditor vse;
00058 vse.exec();
00059 }
00060 else if ( sel == "card inputs" )
00061 {
00062 CardInputEditor cie;
00063 cie.exec();
00064 }
00065 else if ( sel == "channel editor" )
00066 {
00067 ChannelEditor ce;
00068 ce.exec();
00069 }
00070 else if ( sel == "storage groups" )
00071 {
00072 StorageGroupListEditor sge;
00073 sge.exec();
00074 }
00075 }
00076
00077 void SetupMenu(MythMainWindow *win)
00078 {
00079 QString theme = gContext->GetSetting("Theme", "blue");
00080
00081 MythThemedMenu* menu = new MythThemedMenu(gContext->FindThemeDir(theme),
00082 "setup.xml", win->GetMainStack(),
00083 "mainmenu", false);
00084
00085 menu->setCallback(SetupMenuCallback, gContext);
00086 menu->setKillable();
00087
00088 if ( menu->foundTheme() )
00089 {
00090 win->GetMainStack()->AddScreen(menu);
00091 qApp->setMainWidget(win);
00092 qApp->exec();
00093 }
00094 else
00095 {
00096 cerr << "Couldn't find theme " << theme << endl;
00097 }
00098 }
00099
00100 int main(int argc, char *argv[])
00101 {
00102 QString geometry = QString::null;
00103 QString display = QString::null;
00104 QString verboseString = QString(" important general");
00105
00106 #ifdef USING_X11
00107
00108
00109 for(int argpos = 1; argpos + 1 < argc; ++argpos)
00110 {
00111 if (!strcmp(argv[argpos],"-geometry"))
00112 geometry = argv[argpos+1];
00113 else if (!strcmp(argv[argpos],"-display"))
00114 display = argv[argpos+1];
00115 }
00116 #endif
00117
00118 #ifdef Q_WS_MACX
00119
00120
00121 QApplication::setDesktopSettingsAware(FALSE);
00122 #endif
00123 QApplication a(argc, argv);
00124
00125 QMap<QString, QString> settingsOverride;
00126
00127 for(int argpos = 1; argpos < a.argc(); ++argpos)
00128 {
00129 if (!strcmp(a.argv()[argpos],"-display") ||
00130 !strcmp(a.argv()[argpos],"--display"))
00131 {
00132 if (a.argc()-1 > argpos)
00133 {
00134 display = a.argv()[argpos+1];
00135 if (display.startsWith("-"))
00136 {
00137 cerr << "Invalid or missing argument to -display option\n";
00138 return BACKEND_EXIT_INVALID_CMDLINE;
00139 }
00140 else
00141 ++argpos;
00142 }
00143 else
00144 {
00145 cerr << "Missing argument to -display option\n";
00146 return BACKEND_EXIT_INVALID_CMDLINE;
00147 }
00148 }
00149 else if (!strcmp(a.argv()[argpos],"-geometry") ||
00150 !strcmp(a.argv()[argpos],"--geometry"))
00151 {
00152 if (a.argc()-1 > argpos)
00153 {
00154 geometry = a.argv()[argpos+1];
00155 if (geometry.startsWith("-"))
00156 {
00157 cerr << "Invalid or missing argument to "
00158 "-geometry option\n";
00159 return BACKEND_EXIT_INVALID_CMDLINE;
00160 }
00161 else
00162 ++argpos;
00163 }
00164 else
00165 {
00166 cerr << "Missing argument to -geometry option\n";
00167 return BACKEND_EXIT_INVALID_CMDLINE;
00168 }
00169 }
00170 else if (!strcmp(a.argv()[argpos],"-v") ||
00171 !strcmp(a.argv()[argpos],"--verbose"))
00172 {
00173 if (a.argc()-1 > argpos)
00174 {
00175 if (parse_verbose_arg(a.argv()[argpos+1]) ==
00176 GENERIC_EXIT_INVALID_CMDLINE)
00177 return BACKEND_EXIT_INVALID_CMDLINE;
00178 ++argpos;
00179 }
00180 else
00181 {
00182 cerr << "Missing argument to -v/--verbose option\n";
00183 return BACKEND_EXIT_INVALID_CMDLINE;
00184 }
00185 }
00186 else if (!strcmp(a.argv()[argpos],"-O") ||
00187 !strcmp(a.argv()[argpos],"--override-setting"))
00188 {
00189 if (a.argc()-1 > argpos)
00190 {
00191 QString tmpArg = a.argv()[argpos+1];
00192 if (tmpArg.startsWith("-"))
00193 {
00194 cerr << "Invalid or missing argument to -O/--override-setting option\n";
00195 return BACKEND_EXIT_INVALID_CMDLINE;
00196 }
00197
00198 QStringList pairs = QStringList::split(",", tmpArg);
00199 for (unsigned int index = 0; index < pairs.size(); ++index)
00200 {
00201 QStringList tokens = QStringList::split("=", pairs[index]);
00202 tokens[0].replace(QRegExp("^[\"']"), "");
00203 tokens[0].replace(QRegExp("[\"']$"), "");
00204 tokens[1].replace(QRegExp("^[\"']"), "");
00205 tokens[1].replace(QRegExp("[\"']$"), "");
00206 settingsOverride[tokens[0]] = tokens[1];
00207 }
00208 }
00209 else
00210 {
00211 cerr << "Invalid or missing argument to -O/--override-setting option\n";
00212 return BACKEND_EXIT_INVALID_CMDLINE;
00213 }
00214
00215 ++argpos;
00216 }
00217 else
00218 {
00219 if (!(!strcmp(a.argv()[argpos],"-h") ||
00220 !strcmp(a.argv()[argpos],"--help") ||
00221 !strcmp(a.argv()[argpos],"--usage")))
00222 cerr << "Invalid argument: " << a.argv()[argpos] << endl;
00223
00224 cerr << "Valid options are: "<<endl
00225 #ifdef USING_X11
00226 <<"-display X-server Create GUI on X-server, not localhost"<<endl
00227 #endif
00228 <<"-geometry or --geometry WxH Override window size settings"<<endl
00229 <<"-geometry WxH+X+Y Override window size and position"<<endl
00230 <<"-O or "<<endl
00231 <<" --override-setting KEY=VALUE Force the setting named 'KEY' to value 'VALUE'"<<endl
00232 <<"-v or --verbose debug-level Use '-v help' for level info"<<endl
00233 <<endl;
00234 return -1;
00235 }
00236 }
00237
00238 if (!display.isEmpty())
00239 {
00240 MythContext::SetX11Display(display);
00241 }
00242
00243 gContext = NULL;
00244 gContext = new MythContext(MYTH_BINARY_VERSION);
00245
00246 if (!gContext->Init(true))
00247 {
00248 VERBOSE(VB_IMPORTANT, "Failed to init MythContext, exiting.");
00249 return -1;
00250 }
00251
00252 if (geometry != "")
00253 if (!gContext->ParseGeometryOverride(geometry))
00254 cerr << "Illegal -geometry argument '"
00255 << geometry << "' (ignored)\n";
00256
00257 if (settingsOverride.size())
00258 {
00259 QMap<QString, QString>::iterator it;
00260 for (it = settingsOverride.begin(); it != settingsOverride.end(); ++it)
00261 {
00262 VERBOSE(VB_IMPORTANT, QString("Setting '%1' being forced to '%2'")
00263 .arg(it.key()).arg(it.data()));
00264 gContext->OverrideSettingForSession(it.key(), it.data());
00265 }
00266 }
00267
00268 if (!MSqlQuery::testDBConnection())
00269 {
00270 cerr << "Unable to open database.\n";
00271
00272
00273
00274
00275
00276 return -1;
00277 }
00278
00279 if ((CompareTVDatabaseSchemaVersion() > 0) &&
00280
00281 (gContext->GetNumSetting("DBSchemaAutoUpgrade") != -1))
00282 {
00283 VERBOSE(VB_IMPORTANT, "The schema version of your existing database "
00284 "is newer than this version of MythTV understands. Please "
00285 "ensure that you have selected the proper database server or "
00286 "upgrade this and all other frontends and backends to the "
00287 "same MythTV version and revision.");
00288 return BACKEND_EXIT_DB_OUTOFDATE;
00289 }
00290 if (!UpgradeTVDatabaseSchema())
00291 {
00292 VERBOSE(VB_IMPORTANT, "Couldn't upgrade database to new schema.");
00293 return BACKEND_EXIT_DB_OUTOFDATE;
00294 }
00295
00296 gContext->SetSetting("Theme", "G.A.N.T");
00297 gContext->LoadQtConfig();
00298
00299 QString fileprefix = MythContext::GetConfDir();
00300
00301 QDir dir(fileprefix);
00302 if (!dir.exists())
00303 dir.mkdir(fileprefix);
00304
00305 MythMainWindow *mainWindow = GetMythMainWindow();
00306 mainWindow->Init();
00307 gContext->SetMainWindow(mainWindow);
00308
00309 gContext->UpdateImageCache();
00310 MythThemeBase *themeBase = new MythThemeBase();
00311 (void) themeBase;
00312
00313 LanguageSettings::prompt();
00314 LanguageSettings::load("mythfrontend");
00315
00316 QString warn =
00317 QObject::tr("WARNING") + ": " +
00318 QObject::tr("MythTV has detected that the backend is running.")+"\n\n"+
00319 QObject::tr("Changing existing card inputs, deleting anything, "
00320 "or scanning for channels may not work.");
00321
00322 bool backendIsRunning = gContext->BackendIsRunning();
00323
00324 if (backendIsRunning)
00325 {
00326 DialogCode val = MythPopupBox::Show2ButtonPopup(
00327 mainWindow, QObject::tr("WARNING"), warn,
00328 QObject::tr("Continue"),
00329 QObject::tr("Exit"), kDialogCodeButton0);
00330
00331 if (kDialogCodeButton1 == val)
00332 return 0;
00333 }
00334
00335 REG_KEY("qt", "DELETE", "Delete", "D");
00336 REG_KEY("qt", "EDIT", "Edit", "E");
00337
00338 DialogBox *dia = NULL;
00339 bool haveProblems = false;
00340 do
00341 {
00342
00343 SetupMenu(mainWindow);
00344
00345
00346 QString *problems = new QString("");
00347 haveProblems = CheckSetup(problems);
00348
00349 if (haveProblems)
00350 {
00351 QString prompt;
00352
00353 if (problems->contains("\n") > 1)
00354 prompt = QObject::tr("Do you want to fix these problems?");
00355 else
00356 prompt = QObject::tr("Do you want to fix this problem?");
00357
00358 dia = new DialogBox(mainWindow, problems->append("\n" + prompt));
00359 dia->AddButton(QObject::tr("Yes please"));
00360 dia->AddButton(QObject::tr("No, I know what I am doing"));
00361
00362 if (kDialogCodeButton1 == dia->exec())
00363 haveProblems = false;
00364 dia->deleteLater();
00365 }
00366
00367 delete problems;
00368
00369
00370 }
00371 while (haveProblems);
00372
00373 if (gContext->IsMasterHost())
00374 {
00375 dia = new DialogBox(mainWindow,
00376 QObject::tr("If this is the master backend server, "
00377 "please run 'mythfilldatabase' "
00378 "to populate the database "
00379 "with channel information."));
00380 dia->AddButton(QObject::tr("OK"));
00381 dia->exec();
00382 dia->deleteLater();
00383 }
00384
00385 if (backendIsRunning)
00386 RemoteSendMessage("CLEAR_SETTINGS_CACHE");
00387
00388 return 0;
00389 }
00390
00391