00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include <iostream>
00011 #include <cstdlib>
00012 using namespace std;
00013
00014 #include <qapplication.h>
00015 #include <qdir.h>
00016 #include <qmutex.h>
00017 #include <qregexp.h>
00018 #include <unistd.h>
00019 #include <netdb.h>
00020 #include <netinet/in.h>
00021 #include <net/if.h>
00022 #include <linux/videodev.h>
00023 #include <mythtv/mythcontext.h>
00024 #include <mythtv/mythdbcon.h>
00025 #include <mythtv/mythplugin.h>
00026 #include <mythtv/dialogbox.h>
00027 #include <mythtv/util.h>
00028 #include <mythtv/mythpluginapi.h>
00029
00030 #include "config.h"
00031 #include "dbcheck.h"
00032 #include "PhoneSettings.h"
00033 #include "webcam.h"
00034
00035 #include "sipfsm.h"
00036 #include "phoneui.h"
00037
00038 SipContainer *sipStack;
00039
00040
00041 void PhoneUI(void)
00042 {
00043 PhoneUIBox *puib;
00044
00045 puib = new PhoneUIBox(gContext->GetMainWindow(),
00046 "phone_ui", "phone-");
00047 qApp->unlock();
00048 puib->exec();
00049 qApp->lock();
00050 qApp->processEvents();
00051
00052 delete puib;
00053 }
00054
00055
00056 #if 0 // Removed web-cam settings screen and pushed all config into one set of screens. Leave here in case I change my mind
00057 void startWebcamSettings(void)
00058 {
00059 WebcamSettingsBox *wsb;
00060
00061 wsb = new WebcamSettingsBox(gContext->GetMainWindow(),
00062 "webcam_settings", "webcam-");
00063 qApp->unlock();
00064 wsb->exec();
00065 qApp->lock();
00066 qApp->processEvents();
00067
00068 delete wsb;
00069 }
00070
00071 void PhoneCallback(void *data, QString &selection)
00072 {
00073 (void)data;
00074 QString sel = selection.lower();
00075
00076 if (sel == "phone_settings_general")
00077 {
00078 MythPhoneSettings settings;
00079 settings.exec();
00080 }
00081 else if (sel == "webcam_settings")
00082 {
00083 startWebcamSettings();
00084 }
00085
00086 }
00087
00088 void runMenu(QString which_menu)
00089 {
00090 QString themedir = gContext->GetThemeDir();
00091
00092 ThemedMenu *diag = new ThemedMenu(themedir.ascii(), which_menu,
00093 gContext->GetMainWindow(), "phone menu");
00094
00095 diag->setCallback(PhoneCallback, NULL);
00096 diag->setKillable();
00097
00098 if (diag->foundTheme())
00099 {
00100 gContext->GetLCDDevice()->switchToTime();
00101 diag->exec();
00102 }
00103 else
00104 {
00105 cerr << "Couldn't find theme " << themedir << endl;
00106 }
00107
00108 delete diag;
00109 }
00110 #endif
00111
00112 void initKeys(void)
00113 {
00114 REG_KEY("Phone", "0", "0", "0");
00115 REG_KEY("Phone", "1", "1", "1");
00116 REG_KEY("Phone", "2", "2", "2");
00117 REG_KEY("Phone", "3", "3", "3");
00118 REG_KEY("Phone", "4", "4", "4");
00119 REG_KEY("Phone", "5", "5", "5");
00120 REG_KEY("Phone", "6", "6", "6");
00121 REG_KEY("Phone", "7", "7", "7");
00122 REG_KEY("Phone", "8", "8", "8");
00123 REG_KEY("Phone", "9", "9", "9");
00124 REG_KEY("Phone", "HASH", "HASH", "#");
00125 REG_KEY("Phone", "STAR", "STAR", "*");
00126 REG_KEY("Phone", "Up", "Up", "Up");
00127 REG_KEY("Phone", "Down", "Down", "Down");
00128 REG_KEY("Phone", "Left", "Left", "Left");
00129 REG_KEY("Phone", "Right", "Right", "Right");
00130 REG_KEY("Phone", "VOLUMEDOWN", "Volume down", "[,{,F10,Volume Down");
00131 REG_KEY("Phone", "VOLUMEUP", "Volume up", "],},F11,Volume Up");
00132 REG_KEY("Phone", "MUTE", "Mute", "|,\\,F9,Volume Mute");
00133 REG_KEY("Phone", "ZOOMIN", "Zoom the video window in", ">,.,Z,End");
00134 REG_KEY("Phone", "ZOOMOUT", "Zoom the video window out", ",,<,Q,Home");
00135 REG_KEY("Phone", "FULLSCRN", "Show received video full-screen", "P");
00136 REG_KEY("Phone", "HANGUP", "Hangup an active call", "O");
00137 REG_KEY("Phone", "LOOPBACK", "Loopback Video", "L");
00138 }
00139
00140 QString GetMySipIp()
00141 {
00142 QSocketDevice *tempSocket = new QSocketDevice (QSocketDevice::Datagram);
00143 QString ifName = gContext->GetSetting("SipBindInterface");
00144 struct ifreq ifreq;
00145 strcpy(ifreq.ifr_name, ifName);
00146 if (ioctl(tempSocket->socket(), SIOCGIFADDR, &ifreq) != 0)
00147 {
00148 cerr << "Failed to find network interface " << ifName << endl;
00149 delete tempSocket;
00150 tempSocket = 0;
00151 return "";
00152 }
00153 delete tempSocket;
00154 tempSocket = 0;
00155 struct sockaddr_in * sptr = (struct sockaddr_in *)&ifreq.ifr_addr;
00156 QHostAddress myIP;
00157 myIP.setAddress(htonl(sptr->sin_addr.s_addr));
00158 return myIP.toString();
00159 }
00160
00161 void addMyselfToDirectory()
00162 {
00163 QString thequery;
00164 char myHostname[64];
00165
00166
00167
00168
00169 if (gethostname(myHostname, sizeof(myHostname)) == -1)
00170 myHostname[0] = 0;
00171 QString Dir = "My MythTVs";
00172 QString Surname = myHostname;
00173 QString FirstName = QString("Local Myth Host");
00174 QString NickName = gContext->GetSetting("MySipName") + "(" + myHostname + ")";
00175 QString Uri;
00176 if (gContext->GetNumSetting("SipRegisterWithProxy", 1))
00177 Uri = gContext->GetSetting("SipProxyAuthName");
00178 else
00179 {
00180 Uri = "MythPhone@" + GetMySipIp();
00181 int myPort = atoi((const char *)gContext->GetSetting("SipLocalPort"));
00182 if (myPort != 5060)
00183 Uri += ":" + QString::number(myPort);
00184 }
00185
00186
00187
00188 MSqlQuery query(MSqlQuery::InitCon());
00189 thequery = QString("SELECT intid,nickname,url "
00190 "FROM phonedirectory "
00191 "WHERE directory = \"%1\" and "
00192 "firstname = \"%2\" and "
00193 "surname = \"%3\";")
00194 .arg(Dir.latin1()).arg(FirstName.latin1()).arg(myHostname);
00195 query.exec(thequery);
00196
00197 if(query.isActive() && query.size() > 0)
00198 {
00199 while(query.next())
00200 {
00201
00202 if ((query.value(1).toString() != NickName) ||
00203 (query.value(2).toString() != Uri))
00204 {
00205 cout << "SIP: Updating out-of-date autogen directory entry; " << query.value(1).toString() << ", " << query.value(2).toString() << endl;
00206
00207 MSqlQuery query2(MSqlQuery::InitCon());
00208 thequery = QString("UPDATE phonedirectory "
00209 "SET nickname=\"%1\", "
00210 "url=\"%2\" "
00211 "WHERE intid=%3 ;")
00212 .arg(NickName.latin1()).arg(Uri.latin1()).arg(query.value(0).toInt());
00213 query2.exec(thequery);
00214 }
00215 }
00216 }
00217 else
00218 {
00219 cout << "SIP: Creating autogen directory entry for this host\n";
00220 thequery = QString("INSERT INTO phonedirectory (nickname,firstname,surname,"
00221 "url,directory,photofile,speeddial,onhomelan) VALUES "
00222 "(\"%1\",\"%2\",\"%3\",\"%4\",\"%5\",\"\",1,1);")
00223 .arg(NickName.latin1()).arg(FirstName.latin1())
00224 .arg(Surname.latin1()).arg(Uri.latin1())
00225 .arg(Dir.latin1())
00226 ;
00227 query.exec(thequery);
00228 }
00229 }
00230
00231 int mythplugin_init(const char *libversion)
00232 {
00233 if (!gContext->TestPopupVersion("mythphone", libversion,
00234 MYTH_BINARY_VERSION))
00235 {
00236 cerr << "Test Popup Version Failed " << endl;
00237 return -1;
00238 }
00239
00240 gContext->ActivateSettingsCache(false);
00241 if (!UpgradePhoneDatabaseSchema())
00242 {
00243 VERBOSE(VB_IMPORTANT,
00244 "Couldn't upgrade database to new schema, exiting.");
00245 return -1;
00246 }
00247 gContext->ActivateSettingsCache(true);
00248
00249 MythPhoneSettings mpSettings;
00250 mpSettings.load();
00251 mpSettings.save();
00252
00253
00254 QString dirName = MythContext::GetConfDir();
00255 QDir dir(dirName);
00256 if (!dir.exists())
00257 dir.mkdir(dirName);
00258 dirName += "/MythPhone";
00259 dir = QDir(dirName);
00260 if (!dir.exists())
00261 dir.mkdir(dirName);
00262 QString vmName = dirName + "/Voicemail";
00263 dir = QDir(vmName);
00264 if (!dir.exists())
00265 dir.mkdir(vmName);
00266 QString phName = dirName + "/Photos";
00267 dir = QDir(phName);
00268 if (!dir.exists())
00269 dir.mkdir(phName);
00270
00271 initKeys();
00272
00273 addMyselfToDirectory();
00274
00275 sipStack = new SipContainer();
00276
00277 return 0;
00278 }
00279
00280 int mythplugin_run(void)
00281 {
00282 PhoneUI();
00283
00284 return 0;
00285 }
00286
00287 int mythplugin_config(void)
00288 {
00289
00290
00291 MythPhoneSettings settings;
00292 settings.exec();
00293
00294 return 0;
00295 }
00296
00297 void mythplugin_destroy(void)
00298 {
00299 delete sipStack;
00300 sipStack = NULL;
00301 }
00302