Subversion Repositories tpanel

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
3 andreas 1
/*
89 andreas 2
 * Copyright (C) 2020 to 2022 by Andreas Theofilu <andreas@theosys.at>
3 andreas 3
 *
4
 * This program is free software; you can redistribute it and/or modify
5
 * it under the terms of the GNU General Public License as published by
6
 * the Free Software Foundation; either version 3 of the License, or
7
 * (at your option) any later version.
8
 *
9
 * This program is distributed in the hope that it will be useful,
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 * GNU General Public License for more details.
13
 *
14
 * You should have received a copy of the GNU General Public License
15
 * along with this program; if not, write to the Free Software Foundation,
16
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
17
 */
18
 
19
#include <vector>
14 andreas 20
#include <thread>
21
#include <mutex>
186 andreas 22
 
36 andreas 23
#ifdef __ANDROID__
183 andreas 24
#   ifdef QT5_LINUX
25
#       include <QtAndroidExtras/QAndroidJniObject>
26
#       include <QtAndroidExtras/QtAndroid>
216 andreas 27
#   else
28
#       include <QJniObject>
29
#       include <QCoreApplication>
183 andreas 30
#   endif
31
#   include <android/log.h>
182 andreas 32
#endif
134 andreas 33
#include <unistd.h>
34
#ifndef __ANDROID__
183 andreas 35
#   include <fstab.h>
134 andreas 36
#endif
14 andreas 37
 
186 andreas 38
#if __cplusplus < 201402L
39
#   error "This module requires at least C++14 standard!"
40
#else
41
#   if __cplusplus < 201703L
42
#       include <experimental/filesystem>
43
namespace fs = std::experimental::filesystem;
44
#       warning "Support for C++14 and experimental filesystem will be removed in a future version!"
45
#   else
46
#       include <filesystem>
47
#       ifdef __ANDROID__
48
namespace fs = std::__fs::filesystem;
49
#       else
50
namespace fs = std::filesystem;
51
#       endif
52
#   endif
53
#endif
54
 
235 andreas 55
#ifdef __APPLE__
56
#   include <unistd.h>
57
#   ifndef HOST_NAME_MAX
58
#       ifdef MAXHOSTNAMELEN
59
#           define HOST_NAME_MAX    MAXHOSTNAMELEN
60
#       else
61
#           define HOST_NAME_MAX    64
62
#       endif   // MAXHOSTNAMELEN
63
#   endif       // HOST_NAME_MAX
64
#endif          // __APPLE__
65
 
3 andreas 66
#include "tpagemanager.h"
4 andreas 67
#include "tcolor.h"
3 andreas 68
#include "terror.h"
8 andreas 69
#include "ticons.h"
14 andreas 70
#include "tbutton.h"
8 andreas 71
#include "tprjresources.h"
11 andreas 72
#include "tresources.h"
51 andreas 73
#include "tobject.h"
71 andreas 74
#include "tsystemsound.h"
75
#include "tvalidatefile.h"
122 andreas 76
#include "ttpinit.h"
211 andreas 77
#include "tconfig.h"
3 andreas 78
 
79
using std::vector;
80
using std::string;
11 andreas 81
using std::map;
82
using std::pair;
83
using std::to_string;
14 andreas 84
using std::thread;
85
using std::atomic;
86
using std::mutex;
21 andreas 87
using std::bind;
3 andreas 88
 
8 andreas 89
TIcons *gIcons = nullptr;
90
TPrjResources *gPrjResources = nullptr;
14 andreas 91
TPageManager *gPageManager = nullptr;
169 andreas 92
//std::vector<amx::ANET_COMMAND> TPageManager::mCommands;
93
 
14 andreas 94
extern amx::TAmxNet *gAmxNet;
90 andreas 95
extern std::atomic<bool> _netRunning;
92 andreas 96
extern bool _restart_;                          //!< If this is set to true then the whole program will start over.
8 andreas 97
 
14 andreas 98
mutex surface_mutex;
21 andreas 99
bool prg_stopped = false;
14 andreas 100
 
37 andreas 101
#ifdef __ANDROID__
38 andreas 102
JNIEXPORT void JNICALL Java_org_qtproject_theosys_BatteryState_informBatteryStatus(JNIEnv *, jclass, jint level, jboolean charging, jint chargeType)
103
{
61 andreas 104
    DECL_TRACER("JNICALL Java_org_qtproject_theosys_BatteryState_informBatteryStatus(JNIEnv *, jclass, jint level, jboolean charging, jint chargeType)");
105
 
38 andreas 106
    if (gPageManager)
107
        gPageManager->informBatteryStatus(level, charging, chargeType);
108
}
109
 
36 andreas 110
JNIEXPORT void JNICALL Java_org_qtproject_theosys_NetworkStatus_informTPanelNetwork(JNIEnv */*env*/, jclass /*clazz*/, jboolean conn, jint level, jint type)
111
{
61 andreas 112
    DECL_TRACER("JNICALL Java_org_qtproject_theosys_NetworkStatus_informTPanelNetwork(JNIEnv */*env*/, jclass /*clazz*/, jboolean conn, jint level, jint type)");
36 andreas 113
   //Call native side conterpart
114
   if (gPageManager)
115
        gPageManager->informTPanelNetwork(conn, level, type);
116
}
47 andreas 117
 
61 andreas 118
JNIEXPORT void JNICALL Java_org_qtproject_theosys_PhoneCallState_informPhoneState(JNIEnv *env, jclass, jboolean call, jstring pnumber)
47 andreas 119
{
61 andreas 120
    DECL_TRACER("JNICALL Java_org_qtproject_theosys_PhoneCallState_informPhoneState(JNIEnv *env, jclass, jboolean call, jstring pnumber)");
121
 
122
    string phoneNumber;
123
 
124
    if (pnumber)
125
    {
126
        const jclass stringClass = env->GetObjectClass(pnumber);
127
        const jmethodID getBytes = env->GetMethodID(stringClass, "getBytes", "(Ljava/lang/String;)[B");
128
        const jbyteArray stringJbytes = (jbyteArray) env->CallObjectMethod(pnumber, getBytes, env->NewStringUTF("UTF-8"));
129
 
130
        size_t length = (size_t) env->GetArrayLength(stringJbytes);
131
        jbyte* pBytes = env->GetByteArrayElements(stringJbytes, NULL);
132
 
133
        phoneNumber = string((char *)pBytes, length);
134
        env->ReleaseByteArrayElements(stringJbytes, pBytes, JNI_ABORT);
135
 
136
        env->DeleteLocalRef(stringJbytes);
137
        env->DeleteLocalRef(stringClass);
138
    }
139
 
140
    if (gPageManager)
141
        gPageManager->informPhoneState(call, phoneNumber);
47 andreas 142
}
143
 
61 andreas 144
JNIEXPORT void JNICALL Java_org_qtproject_theosys_Logger_logger(JNIEnv *env, jclass, jint mode, jstring msg)
47 andreas 145
{
61 andreas 146
    DECL_TRACER("JNICALL Java_org_qtproject_theosys_Logger_logger(JNIEnv *env, jclass cl, jint mode, jstring msg)");
147
 
47 andreas 148
    if (!msg)
149
        return;
150
 
151
    const jclass stringClass = env->GetObjectClass(msg);
152
    const jmethodID getBytes = env->GetMethodID(stringClass, "getBytes", "(Ljava/lang/String;)[B");
153
    const jbyteArray stringJbytes = (jbyteArray) env->CallObjectMethod(msg, getBytes, env->NewStringUTF("UTF-8"));
154
 
155
    size_t length = (size_t) env->GetArrayLength(stringJbytes);
156
    jbyte* pBytes = env->GetByteArrayElements(stringJbytes, NULL);
157
 
158
    string ret = std::string((char *)pBytes, length);
159
    env->ReleaseByteArrayElements(stringJbytes, pBytes, JNI_ABORT);
160
 
161
    env->DeleteLocalRef(stringJbytes);
162
    env->DeleteLocalRef(stringClass);
163
 
61 andreas 164
    try
165
    {
251 andreas 166
//        TError::lock();
47 andreas 167
 
61 andreas 168
        if (TStreamError::checkFilter(mode))
169
            TError::Current()->logMsg(TError::append(mode, *TStreamError::getStream()) << ret << std::endl);
47 andreas 170
 
251 andreas 171
//        TError::unlock();
61 andreas 172
    }
173
    catch (std::exception& e)
174
    {
175
        __android_log_print(ANDROID_LOG_ERROR, "tpanel", "%s", e.what());
176
    }
47 andreas 177
}
130 andreas 178
 
179
JNIEXPORT void JNICALL Java_org_qtproject_theosys_Orientation_informTPanelOrientation(JNIEnv */*env*/, jclass /*clazz*/, jint orientation)
180
{
181
    DECL_TRACER("Java_org_qtproject_theosys_Orientation_informTPanelOrientation(JNIEnv */*env*/, jclass /*clazz*/, jint orientation)");
182
 
183
    MSG_PROTOCOL("Received android orientation " << orientation);
184
 
134 andreas 185
    if (!gPageManager)
186
        return;
187
 
188
    if (gPageManager->onOrientationChange())
130 andreas 189
        gPageManager->onOrientationChange()(orientation);
134 andreas 190
 
191
    gPageManager->setOrientation(orientation);
192
 
193
    if (gPageManager->getInformOrientation())
194
        gPageManager->sendOrientation();
130 andreas 195
}
37 andreas 196
#endif
36 andreas 197
 
3 andreas 198
TPageManager::TPageManager()
199
{
14 andreas 200
    surface_mutex.lock();
3 andreas 201
    DECL_TRACER("TPageManager::TPageManager()");
202
 
14 andreas 203
    gPageManager = this;
122 andreas 204
    TTPInit *tinit = new TTPInit;
186 andreas 205
    string projectPath = TConfig::getProjectPath();
197 andreas 206
    string pp = projectPath + "/prj.xma";
186 andreas 207
 
208
    tinit->setPath(projectPath);
156 andreas 209
    bool haveSurface = false;
122 andreas 210
 
211
    if (tinit->isVirgin())
156 andreas 212
        haveSurface = tinit->loadSurfaceFromController();
213
    else
214
        haveSurface = true;
122 andreas 215
 
197 andreas 216
    if (!fs::exists(pp))
193 andreas 217
    {
197 andreas 218
        projectPath = TConfig::getSystemProjectPath();
219
        pp = projectPath + "/prj.xma";
193 andreas 220
        mSetupActive = true;
221
    }
186 andreas 222
 
156 andreas 223
    if (!haveSurface)
224
    {
197 andreas 225
        if (isValidFile(pp))
156 andreas 226
            haveSurface = true;
186 andreas 227
        else
156 andreas 228
            haveSurface = tinit->reinitialize();
229
    }
159 andreas 230
    else
231
        tinit->makeSystemFiles();
156 andreas 232
 
122 andreas 233
    delete tinit;
156 andreas 234
 
43 andreas 235
    // Read the AMX panel settings.
186 andreas 236
    mTSettings = new TSettings(projectPath);
3 andreas 237
 
238
    if (TError::isError())
14 andreas 239
    {
23 andreas 240
        MSG_ERROR("Settings were not read successfull!");
14 andreas 241
        surface_mutex.unlock();
3 andreas 242
        return;
14 andreas 243
    }
3 andreas 244
 
193 andreas 245
    if (!mSetupActive)
246
    {
197 andreas 247
        mSystemSettings = new TSettings(TConfig::getSystemProjectPath());
193 andreas 248
 
249
        if (TError::isError())
250
        {
251
            MSG_ERROR("System settings were not read successfull!");
252
            delete mTSettings;
253
            mTSettings = nullptr;
254
            surface_mutex.unlock();
255
            return;
256
        }
257
    }
258
    else
259
        mSystemSettings = mTSettings;
260
 
178 andreas 261
    // Set the panel type from the project information
193 andreas 262
    if (!mSetupActive)
263
        TConfig::savePanelType(mTSettings->getPanelType());
178 andreas 264
 
122 andreas 265
    readMap();  // Start the initialisation of the AMX part.
266
 
8 andreas 267
    gPrjResources = new TPrjResources(mTSettings->getResourcesList());
4 andreas 268
    mPalette = new TPalette();
269
    vector<PALETTE_SETUP> pal = mTSettings->getSettings().palettes;
270
 
83 andreas 271
    if (pal.size() > 0)
272
    {
273
        vector<PALETTE_SETUP>::iterator iterPal;
4 andreas 274
 
118 andreas 275
        for (iterPal = pal.begin(); iterPal != pal.end(); ++iterPal)
83 andreas 276
            mPalette->initialize(iterPal->file);
277
    }
278
 
4 andreas 279
    if (!TError::isError())
280
        TColor::setPalette(mPalette);
281
 
7 andreas 282
    mFonts = new TFont();
283
 
284
    if (TError::isError())
285
    {
286
        MSG_ERROR("Initializing fonts was not successfull!");
287
    }
288
 
8 andreas 289
    gIcons = new TIcons();
290
 
291
    if (TError::isError())
292
    {
293
        MSG_ERROR("Initializing icons was not successfull!");
294
    }
295
 
3 andreas 296
    mPageList = new TPageList();
32 andreas 297
    mExternal = new TExternal();
4 andreas 298
    PAGELIST_T page;
299
 
194 andreas 300
    if (!mSetupActive)
3 andreas 301
    {
194 andreas 302
        if (!mTSettings->getSettings().powerUpPage.empty())
14 andreas 303
        {
194 andreas 304
            if (readPage(mTSettings->getSettings().powerUpPage))
305
            {
306
                MSG_TRACE("Found power up page " << mTSettings->getSettings().powerUpPage);
307
                page = findPage(mTSettings->getSettings().powerUpPage);
308
                mActualPage = page.pageID;
309
            }
14 andreas 310
        }
194 andreas 311
        else
312
        {
313
            MSG_WARNING("No power up page defined! Setting default page to 1.");
314
            mActualPage = 1;
315
        }
3 andreas 316
    }
23 andreas 317
    else
318
    {
194 andreas 319
        if (!mSystemSettings->getSettings().powerUpPage.empty())
320
        {
321
            if (readPage(mSystemSettings->getSettings().powerUpPage))
322
            {
323
                MSG_TRACE("Found power up page " << mSystemSettings->getSettings().powerUpPage);
324
                page = findPage(mSystemSettings->getSettings().powerUpPage);
325
                mActualPage = page.pageID;
326
            }
327
        }
328
        else
329
        {
330
            MSG_WARNING("No power up page defined! Setting default page to 5001.");
331
            mActualPage = 5001;
332
        }
23 andreas 333
    }
3 andreas 334
 
4 andreas 335
    TPage *pg = getPage(mActualPage);
336
 
194 andreas 337
    vector<string> popups;
3 andreas 338
 
194 andreas 339
    if (!mSetupActive)
340
        popups = mTSettings->getSettings().powerUpPopup;
341
    else
342
        popups = mSystemSettings->getSettings().powerUpPopup;
343
 
83 andreas 344
    if (popups.size() > 0)
3 andreas 345
    {
83 andreas 346
        vector<string>::iterator iter;
347
 
118 andreas 348
        for (iter = popups.begin(); iter != popups.end(); ++iter)
14 andreas 349
        {
88 andreas 350
            if (readSubPage(*iter))
83 andreas 351
            {
88 andreas 352
                MSG_TRACE("Found power up popup " << *iter);
3 andreas 353
 
88 andreas 354
                if (pg)
355
                {
356
                    TSubPage *spage = getSubPage(*iter);
357
                    pg->addSubPage(spage);
358
                }
83 andreas 359
            }
4 andreas 360
        }
3 andreas 361
    }
11 andreas 362
 
73 andreas 363
    // Here we initialize the system resources like borders, cursors, sliders, ...
364
    mSystemDraw = new TSystemDraw(TConfig::getSystemPath(TConfig::BASE));
365
 
366
    // Here are the commands supported by this emulation.
13 andreas 367
    MSG_INFO("Registering commands ...");
147 andreas 368
    REG_CMD(doAFP, "@AFP");     // Flips to a page with the specified page name using an animated transition.
369
    REG_CMD(doAFP, "^AFP");     // Flips to a page with the specified page name using an animated transition.
38 andreas 370
    REG_CMD(doAPG, "@APG");     // Add a specific popup page to a specified popup group.
371
    REG_CMD(doCPG, "@CPG");     // Clear all popup pages from specified popup group.
372
    REG_CMD(doDPG, "@DPG");     // Delete a specific popup page from specified popup group if it exists
373
//    REG_CMD(doPDR, "@PDR");     // Set the popup location reset flag.
374
    REG_CMD(doPHE, "@PHE");     // Set the hide effect for the specified popup page to the named hide effect.
375
    REG_CMD(doPHP, "@PHP");     // Set the hide effect position.
376
    REG_CMD(doPHT, "@PHT");     // Set the hide effect time for the specified popup page.
377
    REG_CMD(doPPA, "@PPA");     // Close all popups on a specified page.
104 andreas 378
    REG_CMD(doPPA, "^PPA");     // G5: Close all popups on a specified page.
38 andreas 379
    REG_CMD(doPPF, "@PPF");     // Deactivate a specific popup page on either a specified page or the current page.
104 andreas 380
    REG_CMD(doPPF, "^PPF");     // G5: Deactivate a specific popup page on either a specified page or the current page.
38 andreas 381
    REG_CMD(doPPF, "PPOF");     // Deactivate a specific popup page on either a specified page or the current page
382
    REG_CMD(doPPG, "@PPG");     // Toggle a specific popup page on either a specified page or the current page.
104 andreas 383
    REG_CMD(doPPG, "^PPG");     // G5: Toggle a specific popup page on either a specified page or the current page.
38 andreas 384
    REG_CMD(doPPG, "PPOG");     // Toggle a specific popup page on either a specified page or the current page.
385
    REG_CMD(doPPK, "@PPK");     // Kill a specific popup page from all pages.
104 andreas 386
    REG_CMD(doPPK, "^PPK");     // G5: Kill a specific popup page from all pages.
38 andreas 387
    REG_CMD(doPPM, "@PPM");     // Set the modality of a specific popup page to Modal or NonModal.
104 andreas 388
    REG_CMD(doPPM, "^PPM");     // G5: Set the modality of a specific popup page to Modal or NonModal.
38 andreas 389
    REG_CMD(doPPN, "@PPN");     // Activate a specific popup page to launch on either a specified page or the current page.
104 andreas 390
    REG_CMD(doPPN, "^PPN");     // G5: Activate a specific popup page to launch on either a specified page or the current page.
38 andreas 391
    REG_CMD(doPPN, "PPON");     // Activate a specific popup page to launch on either a specified page or the current page.
392
    REG_CMD(doPPT, "@PPT");     // Set a specific popup page to timeout within a specified time.
104 andreas 393
    REG_CMD(doPPT, "^PPT");     // G5: Set a specific popup page to timeout within a specified time.
38 andreas 394
    REG_CMD(doPPX, "@PPX");     // Close all popups on all pages.
104 andreas 395
    REG_CMD(doPPX, "^PPX");     // G5: Close all popups on all pages.
38 andreas 396
    REG_CMD(doPSE, "@PSE");     // Set the show effect for the specified popup page to the named show effect.
397
    REG_CMD(doPSP, "@PSP");     // Set the show effect position.
398
    REG_CMD(doPST, "@PST");     // Set the show effect time for the specified popup page.
399
    REG_CMD(doPAGE, "PAGE");    // Flip to a specified page.
104 andreas 400
    REG_CMD(doPAGE, "^PGE");    // G5: Flip to a specified page.
11 andreas 401
 
38 andreas 402
    REG_CMD(doANI, "^ANI");     // Run a button animation (in 1/10 second).
403
    REG_CMD(doAPF, "^APF");     // Add page flip action to a button if it does not already exist.
43 andreas 404
    REG_CMD(doBAT, "^BAT");     // Append non-unicode text.
60 andreas 405
    REG_CMD(doBAU, "^BAU");     // Append unicode text. Same format as ^UNI.
43 andreas 406
    REG_CMD(doBCB, "^BCB");     // Set the border color.
82 andreas 407
    REG_CMD(getBCB, "?BCB");    // Get the current border color.
60 andreas 408
    REG_CMD(doBCF, "^BCF");     // Set the fill color to the specified color.
82 andreas 409
    REG_CMD(getBCF, "?BCF");    // Get the current fill color.
60 andreas 410
    REG_CMD(doBCT, "^BCT");     // Set the text color to the specified color.
82 andreas 411
    REG_CMD(getBCT, "?BCT");    // Get the current text color.
60 andreas 412
    REG_CMD(doBDO, "^BDO");     // Set the button draw order
413
    REG_CMD(doBFB, "^BFB");     // Set the feedback type of the button.
224 andreas 414
    REG_CMD(doBIM, "^BIM");     // Set the input mask for the specified address
149 andreas 415
    REG_CMD(doBMC, "^BMC");     // Button copy command.
416
    REG_CMD(doBMF, "^BMF");     // Button Modify Command - Set any/all button parameters by sending embedded codes and data.
106 andreas 417
//    REG_CMD(doBMI, "^BMI");    // Set the button mask image.
149 andreas 418
    REG_CMD(doBML, "^BML");     // Set the maximum length of the text area button.
38 andreas 419
    REG_CMD(doBMP, "^BMP");     // Assign a picture to those buttons with a defined addressrange.
82 andreas 420
    REG_CMD(getBMP, "?BMP");    // Get the current bitmap name.
38 andreas 421
    REG_CMD(doBOP, "^BOP");     // Set the button opacity.
106 andreas 422
    REG_CMD(getBOP, "?BOP");    // Get the button opacity.
60 andreas 423
    REG_CMD(doBOR, "^BOR");     // Set a border to a specific border style.
107 andreas 424
    REG_CMD(doBOS, "^BOS");     // Set the button to display either a Video or Non-Video window.
60 andreas 425
    REG_CMD(doBRD, "^BRD");     // Set the border of a button state/states.
107 andreas 426
    REG_CMD(getBRD, "?BRD");    // Get the border of a button state/states.
103 andreas 427
//    REG_CMD(doBSF, "^BSF");     // Set the focus to the text area.
38 andreas 428
    REG_CMD(doBSP, "^BSP");     // Set the button size and position.
107 andreas 429
    REG_CMD(doBSM, "^BSM");     // Submit text for text area buttons.
430
    REG_CMD(doBSO, "^BSO");     // Set the sound played when a button is pressed.
38 andreas 431
    REG_CMD(doBWW, "^BWW");     // Set the button word wrap feature to those buttons with a defined address range.
108 andreas 432
    REG_CMD(getBWW, "?BWW");    // Get the button word wrap feature to those buttons with a defined address range.
38 andreas 433
    REG_CMD(doCPF, "^CPF");     // Clear all page flips from a button.
434
    REG_CMD(doDPF, "^DPF");     // Delete page flips from button if it already exists.
435
    REG_CMD(doENA, "^ENA");     // Enable or disable buttons with a set variable text range.
436
    REG_CMD(doFON, "^FON");     // Set a font to a specific Font ID value for those buttons with a range.
108 andreas 437
    REG_CMD(getFON, "?FON");    // Get the current font index.
103 andreas 438
//    REG_CMD(doGDI, "^GDI");     // Change the bargraph drag increment.
439
//    REG_CMD(doGDV, "^GDV");     // Invert the joystick axis to move the origin to another corner.
60 andreas 440
    REG_CMD(doGLH, "^GLH");     // Change the bargraph upper limit.
441
    REG_CMD(doGLL, "^GLL");     // Change the bargraph lower limit.
108 andreas 442
    REG_CMD(doGSC, "^GSC");     // Change the bargraph slider color or joystick cursor color.
38 andreas 443
    REG_CMD(doICO, "^ICO");     // Set the icon to a button.
108 andreas 444
    REG_CMD(getICO, "?ICO");    // Get the current icon index.
445
    REG_CMD(doJSB, "^JSB");     // Set bitmap/picture alignment using a numeric keypad layout for those buttons with a defined address range.
446
    REG_CMD(getJSB, "?JSB");    // Get the current bitmap justification.
447
    REG_CMD(doJSI, "^JSI");     // Set icon alignment using a numeric keypad layout for those buttons with a defined address range.
448
    REG_CMD(getJSI, "?JSI");    // Get the current icon justification.
449
    REG_CMD(doJST, "^JST");     // Set text alignment using a numeric keypad layout for those buttons with a defined address range.
450
    REG_CMD(getJST, "?JST");    // Get the current text justification.
38 andreas 451
    REG_CMD(doSHO, "^SHO");     // Show or hide a button with a set variable text range.
108 andreas 452
    REG_CMD(doTEC, "^TEC");     // Set the text effect color for the specified addresses/states to the specified color.
453
    REG_CMD(getTEC, "?TEC");    // Get the current text effect color.
110 andreas 454
    REG_CMD(doTEF, "^TEF");     // Set the text effect. The Text Effect is specified by name and can be found in TPD4.
455
    REG_CMD(getTEF, "?TEF");    // Get the current text effect name.
103 andreas 456
//    REG_CMD(doTOP, "^TOP");     // Send events to the Master as string events.
38 andreas 457
    REG_CMD(doTXT, "^TXT");     // Assign a text string to those buttons with a defined address range.
110 andreas 458
    REG_CMD(getTXT, "?TXT");    // Get the current text information.
104 andreas 459
    REG_CMD(doUNI, "^UNI");     // Set Unicode text.
460
    REG_CMD(doUTF, "^UTF");     // G5: Set button state text using UTF-8 text command.
148 andreas 461
    REG_CMD(doVTP, "^VTP");     // Simulates a touch/release/pulse at the given coordinate
14 andreas 462
 
103 andreas 463
//    REG_CMD(doLPC, "^LPC");     // Clear all users from the User Access Passwords list on the Password Setup page.
464
//    REG_CMD(doLPR, "^LPR");     // Remove a given user from the User Access Passwords list on the Password Setup page.
465
//    REG_CMD(doLPS, "^LPS");     // Set the user name and password.
466
 
111 andreas 467
    REG_CMD(doKPS, "^KPS");     // Set the keyboard passthru.
468
    REG_CMD(doVKS, "^VKS");     // Send one or more virtual key strokes to the G4 application.
103 andreas 469
 
470
//    REG_CMD(doPWD, "@PWD");     // Set the page flip password.
471
//    REG_CMD(doPWD, "^PWD");     // Set the page flip password.
472
 
38 andreas 473
    REG_CMD(doBBR, "^BBR");     // Set the bitmap of a button to use a particular resource.
97 andreas 474
    REG_CMD(doRAF, "^RAF");     // Add new resources
475
    REG_CMD(doRFR, "^RFR");     // Force a refresh for a given resource.
38 andreas 476
    REG_CMD(doRMF, "^RMF");     // Modify an existing resource.
111 andreas 477
    REG_CMD(doRSR, "^RSR");     // Change the refresh rate for a given resource.
21 andreas 478
 
108 andreas 479
    REG_CMD(doABEEP, "ABEEP");  // Output a single beep even if beep is Off.
480
    REG_CMD(doADBEEP, "ADBEEP");// Output a double beep even if beep is Off.
62 andreas 481
    REG_CMD(doAKB, "@AKB");     // Pop up the keyboard icon and initialize the text string to that specified.
482
    REG_CMD(doAKEYB, "AKEYB");  // Pop up the keyboard icon and initialize the text string to that specified.
483
    REG_CMD(doAKP, "@AKP");     // Pop up the keypad icon and initialize the text string to that specified.
484
    REG_CMD(doAKEYP, "AKEYP");  // Pop up the keypad icon and initialize the text string to that specified.
63 andreas 485
    REG_CMD(doAKEYR, "AKEYR");  // Remove the Keyboard/Keypad.
486
    REG_CMD(doAKR, "@AKR");     // Remove the Keyboard/Keypad.
71 andreas 487
    REG_CMD(doBEEP, "BEEP");    // Play a single beep.
104 andreas 488
    REG_CMD(doBEEP, "^ABP");    // G5: Play a single beep.
71 andreas 489
    REG_CMD(doDBEEP, "DBEEP");  // Play a double beep.
104 andreas 490
    REG_CMD(doDBEEP, "^ADB");   // G5: Play a double beep.
62 andreas 491
    REG_CMD(doEKP, "@EKP");     // Pop up the keypad icon and initialize the text string to that specified.
63 andreas 492
    REG_CMD(doPKP, "@PKB");     // Present a private keyboard.
493
    REG_CMD(doPKP, "PKEYP");    // Present a private keypad.
494
    REG_CMD(doPKP, "@PKP");     // Present a private keypad.
64 andreas 495
    REG_CMD(doSetup, "SETUP");  // Send panel to SETUP page.
104 andreas 496
    REG_CMD(doSetup, "^STP");   // G5: Open setup page.
64 andreas 497
    REG_CMD(doShutdown, "SHUTDOWN");// Shut down the App
82 andreas 498
    REG_CMD(doSOU, "@SOU");     // Play a sound file.
104 andreas 499
    REG_CMD(doSOU, "^SOU");     // G5: Play a sound file.
63 andreas 500
    REG_CMD(doTKP, "@TKP");     // Present a telephone keypad.
104 andreas 501
    REG_CMD(doTKP, "^TKP");     // G5: Bring up a telephone keypad.
63 andreas 502
    REG_CMD(doTKP, "@VKB");     // Present a virtual keyboard
104 andreas 503
    REG_CMD(doTKP, "^VKB");     // G5: Bring up a virtual keyboard.
129 andreas 504
#ifndef _NOSIP_
103 andreas 505
    // Here the SIP commands will take place
123 andreas 506
    REG_CMD(doPHN, "^PHN");     // SIP commands
127 andreas 507
    REG_CMD(getPHN, "?PHN");    // SIP state commands
129 andreas 508
#endif
225 andreas 509
    // ListView commands (G5)
510
    REG_CMD(doLVD, "^LVD");     // G5: Set Listview Data Source
230 andreas 511
    REG_CMD(doLVE, "^LVE");     // G5: Set ListView custom event number
227 andreas 512
    REG_CMD(doLVF, "^LVF");     // G5: Listview Filter
230 andreas 513
    REG_CMD(doLVL, "^LVL");     // G5: ListView layout
233 andreas 514
    REG_CMD(doLVM, "^LVM");     // G5: ListView map fields
515
    REG_CMD(doLVN, "^LVN");     // G5: ListView navigate
516
    REG_CMD(doLVR, "^LVR");     // G5: ListView refresh data
517
    REG_CMD(doLVS, "^LVS");     // G5: ListView sort data
225 andreas 518
 
103 andreas 519
    // State commands
14 andreas 520
    REG_CMD(doON, "ON");
521
    REG_CMD(doOFF, "OFF");
15 andreas 522
    REG_CMD(doLEVEL, "LEVEL");
523
    REG_CMD(doBLINK, "BLINK");
127 andreas 524
    REG_CMD(doVER, "^VER?");    // Return version string to master
525
    REG_CMD(doWCN, "^WCN?");    // Return SIP phone number
134 andreas 526
    // TPControl commands
527
    REG_CMD(doTPCCMD, "TPCCMD");    // Profile related options
528
    REG_CMD(doTPCACC, "TPCACC");    // Device orientation
153 andreas 529
    REG_CMD(doTPCSIP, "TPCSIP");    // Show the built in SIP phone
134 andreas 530
    // Virtual internal commands
26 andreas 531
    REG_CMD(doFTR, "#FTR");     // File transfer (virtual internal command)
23 andreas 532
 
123 andreas 533
    // At least we must add the SIP client
129 andreas 534
#ifndef _NOSIP_
127 andreas 535
    mSIPClient = new TSIPClient;
123 andreas 536
 
537
    if (TError::isError())
538
    {
539
        MSG_ERROR("Error initializing the SIP client!");
540
        TConfig::setSIPstatus(false);
541
    }
129 andreas 542
#endif
88 andreas 543
    TError::clear();
14 andreas 544
    surface_mutex.unlock();
3 andreas 545
}
546
 
547
TPageManager::~TPageManager()
548
{
549
    DECL_TRACER("TPageManager::~TPageManager()");
129 andreas 550
#ifndef _NOSIP_
127 andreas 551
    if (mSIPClient)
552
    {
553
        delete mSIPClient;
554
        mSIPClient = nullptr;
555
    }
129 andreas 556
#endif
3 andreas 557
    PCHAIN_T *p = mPchain;
558
    PCHAIN_T *next = nullptr;
37 andreas 559
#ifdef __ANDROID__
36 andreas 560
    stopNetworkState();
37 andreas 561
#endif
3 andreas 562
    try
563
    {
564
        while (p)
565
        {
566
            next = p->next;
567
 
568
            if (p->page)
569
                delete p->page;
570
 
571
            delete p;
572
            p = next;
573
        }
574
 
575
        SPCHAIN_T *sp = mSPchain;
576
        SPCHAIN_T *snext = nullptr;
577
 
578
        while (sp)
579
        {
580
            snext = sp->next;
581
 
582
            if (sp->page)
583
                delete sp->page;
584
 
585
            delete sp;
5 andreas 586
            sp = snext;
3 andreas 587
        }
588
 
589
        mPchain = nullptr;
590
        mSPchain = nullptr;
14 andreas 591
        setPChain(mPchain);
592
        setSPChain(mSPchain);
3 andreas 593
 
13 andreas 594
        if (mAmxNet)
595
        {
596
            delete mAmxNet;
597
            mAmxNet = nullptr;
598
        }
599
 
3 andreas 600
        if (mTSettings)
601
        {
602
            delete mTSettings;
603
            mTSettings = nullptr;
604
        }
605
 
606
        if (mPageList)
607
        {
608
            delete mPageList;
609
            mPageList = nullptr;
610
        }
5 andreas 611
 
612
        if (mPalette)
613
        {
614
            delete mPalette;
615
            mPalette = nullptr;
616
        }
7 andreas 617
 
618
        if (mFonts)
619
        {
620
            delete mFonts;
621
            mFonts = nullptr;
622
        }
8 andreas 623
 
624
        if (gIcons)
625
        {
626
            delete gIcons;
627
            gIcons = nullptr;
628
        }
629
 
630
        if (gPrjResources)
631
        {
632
            delete gPrjResources;
633
            gPrjResources = nullptr;
634
        }
40 andreas 635
 
33 andreas 636
        if (mExternal)
637
        {
638
            delete mExternal;
639
            mExternal = nullptr;
640
        }
3 andreas 641
    }
642
    catch (std::exception& e)
643
    {
644
        MSG_ERROR("Memory error: " << e.what());
645
    }
90 andreas 646
 
647
    gPageManager = nullptr;
3 andreas 648
}
649
 
11 andreas 650
void TPageManager::initialize()
651
{
652
    DECL_TRACER("TPageManager::initialize()");
653
 
14 andreas 654
    surface_mutex.lock();
11 andreas 655
    dropAllSubPages();
656
    dropAllPages();
657
 
186 andreas 658
    string projectPath = TConfig::getProjectPath();
659
 
660
    if (!fs::exists(projectPath + "/prj.xma"))
661
        projectPath += "/__system";
662
 
90 andreas 663
    if (mAmxNet && mAmxNet->isConnected())
664
        mAmxNet->close();
88 andreas 665
 
11 andreas 666
    if (mTSettings)
667
        mTSettings->loadSettings();
668
    else
186 andreas 669
        mTSettings = new TSettings(projectPath);
11 andreas 670
 
671
    if (TError::isError())
14 andreas 672
    {
673
        surface_mutex.unlock();
11 andreas 674
        return;
14 andreas 675
    }
11 andreas 676
 
178 andreas 677
    // Set the panel type from the project information
678
    TConfig::savePanelType(mTSettings->getPanelType());
679
 
88 andreas 680
    if (gPrjResources)
681
        delete gPrjResources;
11 andreas 682
 
88 andreas 683
    gPrjResources = new TPrjResources(mTSettings->getResourcesList());
11 andreas 684
 
88 andreas 685
    if (mPalette)
686
        delete mPalette;
687
 
688
    mPalette = new TPalette();
689
 
11 andreas 690
    vector<PALETTE_SETUP> pal = mTSettings->getSettings().palettes;
691
 
83 andreas 692
    if (pal.size() > 0)
693
    {
694
        vector<PALETTE_SETUP>::iterator iterPal;
11 andreas 695
 
118 andreas 696
        for (iterPal = pal.begin(); iterPal != pal.end(); ++iterPal)
83 andreas 697
            mPalette->initialize(iterPal->file);
698
    }
699
 
11 andreas 700
    if (!TError::isError())
701
        TColor::setPalette(mPalette);
702
 
88 andreas 703
    if (mFonts)
704
        delete mFonts;
11 andreas 705
 
88 andreas 706
    mFonts = new TFont();
707
 
11 andreas 708
    if (TError::isError())
709
    {
710
        MSG_ERROR("Initializing fonts was not successfull!");
14 andreas 711
        surface_mutex.unlock();
11 andreas 712
        return;
713
    }
714
 
88 andreas 715
    if (gIcons)
716
        delete gIcons;
11 andreas 717
 
88 andreas 718
    gIcons = new TIcons();
719
 
11 andreas 720
    if (TError::isError())
721
    {
722
        MSG_ERROR("Initializing icons was not successfull!");
14 andreas 723
        surface_mutex.unlock();
11 andreas 724
        return;
725
    }
726
 
88 andreas 727
    if (mPageList)
728
        delete mPageList;
11 andreas 729
 
88 andreas 730
    mPageList = new TPageList();
11 andreas 731
 
88 andreas 732
    if (mExternal)
733
        delete mExternal;
734
 
735
    mExternal = new TExternal();
736
 
11 andreas 737
    PAGELIST_T page;
738
 
739
    if (!mTSettings->getSettings().powerUpPage.empty())
740
    {
88 andreas 741
        if (readPage(mTSettings->getSettings().powerUpPage))
14 andreas 742
        {
88 andreas 743
            MSG_TRACE("Found power up page " << mTSettings->getSettings().powerUpPage);
744
            page = findPage(mTSettings->getSettings().powerUpPage);
745
            mActualPage = page.pageID;
14 andreas 746
        }
11 andreas 747
    }
748
 
749
    TPage *pg = getPage(mActualPage);
750
 
751
    vector<string> popups = mTSettings->getSettings().powerUpPopup;
752
 
83 andreas 753
    if (popups.size() > 0)
11 andreas 754
    {
83 andreas 755
        vector<string>::iterator iter;
756
 
118 andreas 757
        for (iter = popups.begin(); iter != popups.end(); ++iter)
14 andreas 758
        {
88 andreas 759
            if (readSubPage(*iter))
83 andreas 760
            {
88 andreas 761
                MSG_TRACE("Found power up popup " << *iter);
11 andreas 762
 
88 andreas 763
                if (pg)
764
                {
765
                    TSubPage *spage = getSubPage(*iter);
766
                    pg->addSubPage(spage);
767
                }
83 andreas 768
            }
11 andreas 769
        }
770
    }
771
 
88 andreas 772
    // Here we initialize the system resources like borders, cursors, sliders, ...
773
    if (mSystemDraw)
774
        delete mSystemDraw;
775
 
776
    mSystemDraw = new TSystemDraw(TConfig::getSystemPath(TConfig::BASE));
777
 
778
    TError::clear();        // Clear all errors who may be occured until here
779
 
11 andreas 780
    // Start the thread
92 andreas 781
    startComm();
782
 
783
    surface_mutex.unlock();
784
}
785
 
786
bool TPageManager::startComm()
787
{
788
    DECL_TRACER("TPageManager::startComm()");
789
 
790
    if (mAmxNet && mAmxNet->isNetRun())
791
        return true;
792
 
793
    try
11 andreas 794
    {
92 andreas 795
        if (!mAmxNet)
13 andreas 796
        {
92 andreas 797
            if (_netRunning)
13 andreas 798
            {
92 andreas 799
                // Wait until previous connection thread ended
800
                while (_netRunning)
801
                    std::this_thread::sleep_for(std::chrono::milliseconds(100));
13 andreas 802
            }
14 andreas 803
 
92 andreas 804
            mAmxNet = new amx::TAmxNet();
805
            mAmxNet->setCallback(bind(&TPageManager::doCommand, this, std::placeholders::_1));
806
            mAmxNet->setPanelID(TConfig::getChannel());
134 andreas 807
            mAmxNet->setSerialNum(V_SERIAL);
13 andreas 808
        }
90 andreas 809
 
810
        if (!mAmxNet->isNetRun())
811
            mAmxNet->Run();
85 andreas 812
    }
92 andreas 813
    catch (std::exception& e)
814
    {
815
        MSG_ERROR("Error starting the AmxNet thread: " << e.what());
816
        return false;
817
    }
14 andreas 818
 
92 andreas 819
    return true;
11 andreas 820
}
821
 
38 andreas 822
void TPageManager::startUp()
823
{
824
    DECL_TRACER("TPageManager::startUp()");
825
 
44 andreas 826
    if (mAmxNet)
90 andreas 827
    {
828
        MSG_WARNING("Communication with controller already initialized!");
44 andreas 829
        return;
90 andreas 830
    }
44 andreas 831
 
92 andreas 832
    if (!startComm())
833
        return;
90 andreas 834
 
38 andreas 835
#ifdef __ANDROID__
130 andreas 836
    initOrientation();
38 andreas 837
    initNetworkState();
838
#endif
839
}
89 andreas 840
 
841
void TPageManager::reset()
842
{
843
    DECL_TRACER("TPageManager::reset()");
844
 
100 andreas 845
    // Freshly initialize everything.
89 andreas 846
    initialize();
847
}
848
 
169 andreas 849
void TPageManager::runCommands()
850
{
851
    DECL_TRACER("TPageManager::runCommands()");
852
 
853
    if (mBusy || cmdLoop_busy)
854
        return;
855
 
856
    try
857
    {
858
        mThreadCommand = std::thread([=] { this->commandLoop(); });
859
        mThreadCommand.detach();
860
    }
861
    catch (std::exception& e)
862
    {
863
        MSG_ERROR("Error starting thread for command loop: " << e.what());
864
        _netRunning = false;
865
    }
866
}
867
 
197 andreas 868
void TPageManager::showSetup()
869
{
870
    DECL_TRACER("TPageManager::showSetup()");
251 andreas 871
#ifdef Q_OS_ANDROID
197 andreas 872
    if (mSetupActive)
873
        return;
874
 
875
    mSetupActive = true;
876
    mSavedPage = mActualPage;
877
 
198 andreas 878
    TPage *pg = getPage(mActualPage);
197 andreas 879
 
198 andreas 880
    if (pg)
881
    {
882
        TSubPage *spage = pg->getFirstSubPage();
883
        mSavedSubpages.clear();
197 andreas 884
 
198 andreas 885
        while (spage)
197 andreas 886
        {
198 andreas 887
            if (spage->isVisible())
888
                mSavedSubpages.push_back(spage->getNumber());
889
 
890
            spage = pg->getNextSubPage();
197 andreas 891
        }
892
    }
893
 
209 andreas 894
    setPage(SYSTEM_PAGE_CONTROLLER, true);    // Call the page "Controller" (NetLinx settings)
250 andreas 895
#else
896
        if (_callShowSetup)
897
            _callShowSetup();
898
#endif
197 andreas 899
}
900
 
901
void TPageManager::hideSetup()
902
{
903
    DECL_TRACER("TPageManager::hideSetup()");
904
 
206 andreas 905
    if (!mSetupActive || mSavedPage >= SYSTEM_PAGE_START)
197 andreas 906
        return;
907
 
198 andreas 908
    mSetupActive = false;
197 andreas 909
 
198 andreas 910
    if (!mSavedPage)
911
    {
912
        string sPage = mTSettings->getPowerUpPage();
197 andreas 913
 
198 andreas 914
        if (!setPage(sPage, true))
915
            setPage(1, true);
197 andreas 916
 
917
        return;
918
    }
919
 
198 andreas 920
    setPage(mSavedPage, true);
213 andreas 921
    MSG_PROTOCOL("Activated page: " << mSavedPage);
197 andreas 922
 
198 andreas 923
    if (mSavedSubpages.size() > 0)
197 andreas 924
    {
198 andreas 925
        vector<int>::iterator iter;
197 andreas 926
 
198 andreas 927
        for (iter = mSavedSubpages.begin(); iter != mSavedSubpages.end(); ++iter)
928
        {
929
            showSubPage(*iter);
213 andreas 930
            MSG_PROTOCOL("Activated subpage: " << *iter);
198 andreas 931
        }
217 andreas 932
 
933
        mSavedSubpages.clear();
197 andreas 934
    }
935
}
936
 
205 andreas 937
int TPageManager::getSelectedRow(ulong handle)
938
{
939
    DECL_TRACER("TPageManager::getSelectedRow(ulong handle)");
940
 
941
    ulong nPage = (handle >> 16) & 0x0000ffff;
942
 
206 andreas 943
    if ((nPage && TPage::isRegularPage(nPage)) || TPage::isSystemPage(nPage)) // Do we have a page?
205 andreas 944
    {                                                   // Yes, then look on page
945
        TPage *pg = getPage(nPage);
946
 
947
        if (!pg)
948
            return -1;
949
 
950
        return pg->getSelectedRow(handle);
951
    }
206 andreas 952
    else if (TPage::isRegularSubPage(nPage) || TPage::isSystemSubPage(nPage))
205 andreas 953
    {
954
        TSubPage *subPg = getSubPage(nPage);
955
 
956
        if (!subPg)
957
            return -1;
958
 
959
        return subPg->getSelectedRow(handle);
960
    }
961
 
962
    MSG_WARNING("Invalid handle " << TObject::handleToString(handle) << " detected!");
963
    return -1;
964
}
965
 
966
string TPageManager::getSelectedItem(ulong handle)
967
{
968
    DECL_TRACER("TPageManager::getSelectedItem(ulong handle)");
969
 
970
    ulong nPage = (handle >> 16) & 0x0000ffff;
971
 
206 andreas 972
    if ((nPage && TPage::isRegularPage(nPage)) || TPage::isSystemPage(nPage)) // Do we have a page?
205 andreas 973
    {                                                   // Yes, then look on page
974
        TPage *pg = getPage(nPage);
975
 
976
        if (!pg)
977
            return string();
978
 
979
        return pg->getSelectedItem(handle);
980
    }
206 andreas 981
    else if (TPage::isRegularSubPage(nPage) || TPage::isSystemSubPage(nPage))
205 andreas 982
    {
983
        TSubPage *subPg = getSubPage(nPage);
984
 
985
        if (!subPg)
986
            return string();
987
 
988
        return subPg->getSelectedItem(handle);
989
    }
990
 
991
    MSG_WARNING("Invalid handle " << TObject::handleToString(handle) << " detected!");
992
    return string();
993
}
994
 
206 andreas 995
void TPageManager::setSelectedRow(ulong handle, int row, const std::string& text)
205 andreas 996
{
997
    DECL_TRACER("TPageManager::setSelectedRow(ulong handle, int row)");
998
 
999
    ulong nPage = (handle >> 16) & 0x0000ffff;
1000
 
206 andreas 1001
    if (TPage::isRegularPage(nPage) || TPage::isSystemPage(nPage)) // Do we have a page?
205 andreas 1002
    {                                                   // Yes, then look on page
1003
        TPage *pg = getPage(nPage);
1004
 
1005
        if (!pg)
1006
            return;
1007
 
1008
        pg->setSelectedRow(handle, row);
1009
    }
206 andreas 1010
    else if (TPage::isRegularSubPage(nPage) || TPage::isSystemSubPage(nPage))   // Do we have a subpage?
1011
    {                                                   // Yes, then look on subpage
205 andreas 1012
        TSubPage *subPg = getSubPage(nPage);
1013
 
1014
        if (!subPg)
1015
            return;
1016
 
1017
        subPg->setSelectedRow(handle, row);
206 andreas 1018
        // Check if this is a system list. If so we must set the selected
1019
        // text to the input line or "label".
1020
        TPage *mainPage = nullptr;
1021
 
1022
        if (nPage >= SYSTEM_SUBPAGE_START)  // System subpage?
1023
        {
1024
            switch(nPage)
1025
            {
1026
                case SYSTEM_SUBPAGE_SYSTEMSOUND:
1027
                case SYSTEM_SUBPAGE_SINGLEBEEP:
1028
                case SYSTEM_SUBPAGE_DOUBLEBEEP:
1029
                    mainPage = getPage(SYSTEM_PAGE_SOUND);
1030
                break;
1031
 
1032
                case SYSTEM_SUBPAGE_SURFACE:
1033
                    mainPage = getPage(SYSTEM_PAGE_CONTROLLER);
1034
                break;
1035
            }
1036
        }
1037
 
1038
        if (mainPage)
1039
        {
1040
            if (nPage == SYSTEM_SUBPAGE_SYSTEMSOUND)  // System sound beep
1041
            {
1042
                Button::TButton *bt = mainPage->getButton(SYSTEM_PAGE_SOUND_TXSYSSOUND);
1043
 
1044
                if (bt)
1045
                {
1046
                    bt->setText(text, -1);
1047
                    TConfig::setTemporary(true);
1048
                    TConfig::saveSystemSoundFile(text);
1049
                }
1050
            }
1051
            else if (nPage == SYSTEM_SUBPAGE_SINGLEBEEP) // System sound single beep
1052
            {
1053
                Button::TButton *bt = mainPage->getButton(SYSTEM_PAGE_SOUND_TXSINGLEBEEP);
1054
 
1055
                if (bt)
1056
                {
1057
                    bt->setText(text, -1);
1058
                    TConfig::setTemporary(true);
1059
                    TConfig::saveSingleBeepFile(text);
1060
                }
1061
            }
1062
            else if (nPage == SYSTEM_SUBPAGE_DOUBLEBEEP) // System sound double beep
1063
            {
1064
                Button::TButton *bt = mainPage->getButton(SYSTEM_PAGE_SOUND_TXDOUBLEBEEP);
1065
 
1066
                if (bt)
1067
                {
1068
                    bt->setText(text, -1);
1069
                    TConfig::setTemporary(true);
1070
                    TConfig::saveDoubleBeepFile(text);
1071
                }
1072
            }
1073
            else if (nPage == SYSTEM_SUBPAGE_SURFACE)   // System TP4 files (surface files)
1074
            {
1075
                Button::TButton *bt = mainPage->getButton(SYSTEM_PAGE_CTRL_SURFACE);
1076
 
1077
                if (bt)
1078
                {
1079
                    MSG_DEBUG("Setting text: " << text);
1080
                    bt->setText(text, -1);
1081
                    TConfig::setTemporary(true);
1082
                    TConfig::saveFtpSurface(text);
1083
                }
1084
            }
1085
 
1086
            // Close the list subpage
1087
            subPg->drop();
1088
        }
205 andreas 1089
    }
1090
}
1091
 
198 andreas 1092
#ifdef _SCALE_SKIA_
197 andreas 1093
void TPageManager::setSetupScaleFactor(double scale, double sw, double sh)
1094
{
1095
    DECL_TRACER("TPageManager::setSetupScaleFactor(double scale, double sw, double sh)");
1096
 
1097
    mScaleSystem = scale;
1098
    mScaleSystemWidth = sw;
1099
    mScaleSystemHeight = sh;
1100
}
198 andreas 1101
#endif
197 andreas 1102
 
11 andreas 1103
/*
1104
 * The following method is called by the class TAmxNet whenever an event from
169 andreas 1105
 * the Netlinx occured.
11 andreas 1106
 */
1107
void TPageManager::doCommand(const amx::ANET_COMMAND& cmd)
1108
{
1109
    DECL_TRACER("TPageManager::doCommand(const amx::ANET_COMMAND& cmd)");
1110
 
169 andreas 1111
    if (!cmdLoop_busy)
1112
        runCommands();
1113
 
11 andreas 1114
    mCommands.push_back(cmd);
169 andreas 1115
}
11 andreas 1116
 
169 andreas 1117
void TPageManager::commandLoop()
1118
{
1119
    DECL_TRACER("TPageManager::commandLoop()");
1120
 
1121
    if (mBusy || cmdLoop_busy)
11 andreas 1122
        return;
1123
 
169 andreas 1124
    mBusy = cmdLoop_busy = true;
11 andreas 1125
    string com;
1126
 
169 andreas 1127
    while (cmdLoop_busy && !killed && !_restart_)
11 andreas 1128
    {
169 andreas 1129
        while (mCommands.size() > 0)
11 andreas 1130
        {
169 andreas 1131
            amx::ANET_COMMAND bef = mCommands.at(0);
1132
            mCommands.erase(mCommands.begin());
11 andreas 1133
 
169 andreas 1134
            switch (bef.MC)
1135
            {
1136
                case 0x0006:
1137
                case 0x0018:	// feedback channel on
1138
                    com.assign("ON-");
1139
                    com.append(to_string(bef.data.chan_state.channel));
1140
                    parseCommand(bef.device1, bef.data.chan_state.port, com);
1141
                break;
11 andreas 1142
 
169 andreas 1143
                case 0x0007:
1144
                case 0x0019:	// feedback channel off
1145
                    com.assign("OFF-");
1146
                    com.append(to_string(bef.data.chan_state.channel));
1147
                    parseCommand(bef.device1, bef.data.chan_state.port, com);
1148
                break;
11 andreas 1149
 
169 andreas 1150
                case 0x000a:	// level value change
1151
                    com = "LEVEL-";
1152
                    com += to_string(bef.data.message_value.value);
1153
                    com += ",";
11 andreas 1154
 
169 andreas 1155
                    switch (bef.data.message_value.type)
1156
                    {
1157
                        case 0x10: com += to_string(bef.data.message_value.content.byte); break;
1158
                        case 0x11: com += to_string(bef.data.message_value.content.ch); break;
1159
                        case 0x20: com += to_string(bef.data.message_value.content.integer); break;
1160
                        case 0x21: com += to_string(bef.data.message_value.content.sinteger); break;
1161
                        case 0x40: com += to_string(bef.data.message_value.content.dword); break;
1162
                        case 0x41: com += to_string(bef.data.message_value.content.sdword); break;
1163
                        case 0x4f: com += to_string(bef.data.message_value.content.fvalue); break;
1164
                        case 0x8f: com += to_string(bef.data.message_value.content.dvalue); break;
1165
                    }
11 andreas 1166
 
169 andreas 1167
                    parseCommand(bef.device1, bef.data.message_value.port, com);
1168
                break;
11 andreas 1169
 
169 andreas 1170
                case 0x000c:	// Command string
11 andreas 1171
                {
169 andreas 1172
                    amx::ANET_MSG_STRING msg = bef.data.message_string;
11 andreas 1173
 
169 andreas 1174
                    if (msg.length < strlen((char *)&msg.content))
1175
                    {
1176
                        mCmdBuffer.append((char *)&msg.content);
1177
                        break;
1178
                    }
1179
                    else if (mCmdBuffer.length() > 0)
1180
                    {
1181
                        mCmdBuffer.append((char *)&msg.content);
1182
                        size_t len = (mCmdBuffer.length() >= sizeof(msg.content)) ? (sizeof(msg.content)-1) : mCmdBuffer.length();
1183
                        strncpy((char *)&msg.content, mCmdBuffer.c_str(), len);
1184
                        msg.content[len] = 0;
1185
                    }
104 andreas 1186
 
169 andreas 1187
                    if (getCommand((char *)msg.content) == "^UTF")  // This is already UTF8!
1188
                        com.assign((char *)msg.content);
1189
                    else
1190
                        com.assign(cp1250ToUTF8((char *)&msg.content));
11 andreas 1191
 
169 andreas 1192
                    parseCommand(bef.device1, msg.port, com);
1193
                    mCmdBuffer.clear();
1194
                }
1195
                break;
15 andreas 1196
 
169 andreas 1197
                case 0x0502:    // Blink message (contains date and time)
1198
                    com = "BLINK-" + to_string(bef.data.blinkMessage.hour) + ":";
1199
                    com += to_string(bef.data.blinkMessage.minute) + ":";
1200
                    com += to_string(bef.data.blinkMessage.second) + ",";
1201
                    com += to_string(bef.data.blinkMessage.year) + "-";
1202
                    com += to_string(bef.data.blinkMessage.month) + "-";
1203
                    com += to_string(bef.data.blinkMessage.day) + ",";
1204
                    com += to_string(bef.data.blinkMessage.weekday) + ",";
1205
                    com += ((bef.data.blinkMessage.LED & 0x0001) ? "ON" : "OFF");
1206
                    parseCommand(0, 0, com);
1207
                break;
11 andreas 1208
 
169 andreas 1209
                case 0x1000:	// Filetransfer
11 andreas 1210
                {
169 andreas 1211
                    amx::ANET_FILETRANSFER ftr = bef.data.filetransfer;
1212
 
1213
                    if (ftr.ftype == 0)
11 andreas 1214
                    {
169 andreas 1215
                        switch(ftr.function)
1216
                        {
1217
                            case 0x0100:	// Syncing directory
1218
                                com = "#FTR-SYNC:0:";
1219
                                com.append((char*)&ftr.data[0]);
1220
                                parseCommand(bef.device1, bef.port1, com);
1221
                            break;
11 andreas 1222
 
169 andreas 1223
                            case 0x0104:	// Delete file
1224
                                com = "#FTR-SYNC:"+to_string(bef.count)+":Deleting files ... ("+to_string(bef.count)+"%)";
1225
                                parseCommand(bef.device1, bef.port1, com);
1226
                            break;
11 andreas 1227
 
169 andreas 1228
                            case 0x0105:	// start filetransfer
1229
                                com = "#FTR-START";
1230
                                parseCommand(bef.device1, bef.port1, com);
1231
                            break;
1232
                        }
11 andreas 1233
                    }
169 andreas 1234
                    else
11 andreas 1235
                    {
169 andreas 1236
                        switch(ftr.function)
1237
                        {
1238
                            case 0x0003:	// Received part of file
1239
                            case 0x0004:	// End of file
1240
                                com = "#FTR-FTRPART:"+to_string(bef.count)+":"+to_string(ftr.info1);
1241
                                parseCommand(bef.device1, bef.port1, com);
1242
                            break;
11 andreas 1243
 
169 andreas 1244
                            case 0x0007:	// End of file transfer
1245
                            {
1246
                                com = "#FTR-END";
1247
                                parseCommand(bef.device1, bef.port1, com);
1248
                            }
1249
                            break;
1250
 
1251
                            case 0x0102:	// Receiving file
1252
                                com = "#FTR-FTRSTART:"+to_string(bef.count)+":"+to_string(ftr.info1)+":";
1253
                                com.append((char*)&ftr.data[0]);
1254
                                parseCommand(bef.device1, bef.port1, com);
1255
                            break;
11 andreas 1256
                        }
1257
                    }
1258
                }
169 andreas 1259
                break;
11 andreas 1260
            }
1261
        }
169 andreas 1262
 
1263
        std::this_thread::sleep_for(std::chrono::milliseconds(50));
11 andreas 1264
    }
1265
 
1266
    mBusy = false;
169 andreas 1267
    cmdLoop_busy = false;
11 andreas 1268
}
1269
 
26 andreas 1270
void TPageManager::deployCallbacks()
1271
{
1272
    DECL_TRACER("TPageManager::deployCallbacks()");
1273
 
1274
    PCHAIN_T *p = mPchain;
1275
 
1276
    while (p)
1277
    {
1278
        if (p->page)
1279
        {
1280
            if (_setBackground)
1281
                p->page->registerCallback(_setBackground);
1282
 
1283
            if (_callPlayVideo)
1284
                p->page->regCallPlayVideo(_callPlayVideo);
1285
        }
1286
 
1287
        p = p->next;
1288
    }
1289
 
1290
    SPCHAIN_T *sp = mSPchain;
1291
 
1292
    while (sp)
1293
    {
1294
        if (sp->page)
1295
        {
1296
            if (_setBackground)
1297
                sp->page->registerCallback(_setBackground);
1298
 
1299
            if (_callPlayVideo)
1300
                sp->page->regCallPlayVideo(_callPlayVideo);
1301
        }
1302
 
1303
        sp = sp->next;
1304
    }
1305
}
36 andreas 1306
 
1307
void TPageManager::regCallbackNetState(std::function<void (int)> callNetState, ulong handle)
1308
{
1309
    DECL_TRACER("TPageManager::regCallbackNetState(std::function<void (int)> callNetState, ulong handle)");
1310
 
1311
    if (handle == 0)
1312
        return;
1313
 
1314
    mNetCalls.insert(std::pair<int, std::function<void (int)> >(handle, callNetState));
1315
}
1316
 
1317
void TPageManager::unregCallbackNetState(ulong handle)
1318
{
1319
    DECL_TRACER("TPageManager::unregCallbackNetState(ulong handle)");
1320
 
83 andreas 1321
    if (mNetCalls.size() == 0)
1322
        return;
1323
 
36 andreas 1324
    std::map<int, std::function<void (int)> >::iterator iter = mNetCalls.find(handle);
1325
 
1326
    if (iter != mNetCalls.end())
1327
        mNetCalls.erase(iter);
1328
}
247 andreas 1329
#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS)
251 andreas 1330
#ifdef Q_OS_ANDROID
38 andreas 1331
void TPageManager::regCallbackBatteryState(std::function<void (int, bool, int)> callBatteryState, ulong handle)
1332
{
1333
    DECL_TRACER("TPageManager::regCallbackBatteryState(std::function<void (int, bool, int)> callBatteryState, ulong handle)");
1334
 
1335
    if (handle == 0)
1336
        return;
1337
 
1338
    mBatteryCalls.insert(std::pair<int, std::function<void (int, bool, int)> >(handle, callBatteryState));
1339
}
247 andreas 1340
#endif
1341
#ifdef Q_OS_IOS
1342
void TPageManager::regCallbackBatteryState(std::function<void (int, int)> callBatteryState, ulong handle)
1343
{
1344
    DECL_TRACER("TPageManager::regCallbackBatteryState(std::function<void (int, int)> callBatteryState, ulong handle)");
38 andreas 1345
 
247 andreas 1346
    if (handle == 0)
1347
        return;
1348
 
1349
    mBatteryCalls.insert(std::pair<int, std::function<void (int, int)> >(handle, callBatteryState));
1350
 
1351
    if (mLastBatteryLevel > 0 || mLastBatteryState > 0)
1352
        informBatteryStatus(mLastBatteryLevel, mLastBatteryState);
1353
}
1354
#endif
38 andreas 1355
void TPageManager::unregCallbackBatteryState(ulong handle)
1356
{
1357
    DECL_TRACER("TPageManager::unregCallbackBatteryState(ulong handle)");
1358
 
83 andreas 1359
    if (mBatteryCalls.size() == 0)
1360
        return;
247 andreas 1361
#ifdef Q_OS_ANDROID
38 andreas 1362
    std::map<int, std::function<void (int, bool, int)> >::iterator iter = mBatteryCalls.find(handle);
247 andreas 1363
#endif
1364
#ifdef Q_OS_IOS
1365
    std::map<int, std::function<void (int, int)> >::iterator iter = mBatteryCalls.find(handle);
1366
#endif
38 andreas 1367
    if (iter != mBatteryCalls.end())
1368
        mBatteryCalls.erase(iter);
1369
}
247 andreas 1370
#endif  // defined(Q_OS_ANDROID) || defined(Q_OS_IOS)
11 andreas 1371
/*
1372
 * The following function must be called to start the "panel".
1373
 */
5 andreas 1374
bool TPageManager::run()
1375
{
1376
    DECL_TRACER("TPageManager::run()");
1377
 
1378
    if (mActualPage <= 0)
1379
        return false;
1380
 
154 andreas 1381
    TPage *pg = getPage(mActualPage);
1382
 
1383
    if (!pg || !_setPage || !mTSettings)
1384
        return false;
1385
 
14 andreas 1386
    surface_mutex.lock();
7 andreas 1387
    pg->setFonts(mFonts);
5 andreas 1388
    pg->registerCallback(_setBackground);
21 andreas 1389
    pg->regCallPlayVideo(_callPlayVideo);
5 andreas 1390
 
26 andreas 1391
    int width, height;
217 andreas 1392
    width = mTSettings->getWidth();
26 andreas 1393
    height = mTSettings->getHeight();
43 andreas 1394
#ifdef _SCALE_SKIA_
26 andreas 1395
    if (mScaleFactor != 1.0)
1396
    {
1397
        width = (int)((double)width * mScaleFactor);
1398
        height = (int)((double)height * mScaleFactor);
1399
    }
43 andreas 1400
#endif
26 andreas 1401
    _setPage((pg->getNumber() << 16) & 0xffff0000, width, height);
5 andreas 1402
    pg->show();
1403
 
1404
    TSubPage *subPg = pg->getFirstSubPage();
1405
 
1406
    while (subPg)
1407
    {
7 andreas 1408
        subPg->setFonts(mFonts);
1409
        subPg->registerCallback(_setBackground);
1410
        subPg->registerCallbackDB(_displayButton);
11 andreas 1411
        subPg->regCallDropSubPage(_callDropSubPage);
21 andreas 1412
        subPg->regCallPlayVideo(_callPlayVideo);
7 andreas 1413
 
5 andreas 1414
        if (_setSubPage)
6 andreas 1415
        {
1416
            MSG_DEBUG("Drawing page " << subPg->getNumber() << ": " << subPg->getName() << "...");
26 andreas 1417
            width = subPg->getWidth();
1418
            height = subPg->getHeight();
1419
            int left = subPg->getLeft();
1420
            int top = subPg->getTop();
43 andreas 1421
#ifdef _SCALE_SKIA_
26 andreas 1422
            if (mScaleFactor != 1.0)
1423
            {
1424
                width = (int)((double)width * mScaleFactor);
1425
                height = (int)((double)height * mScaleFactor);
1426
                left = (int)((double)left * mScaleFactor);
1427
                top = (int)((double)top * mScaleFactor);
1428
            }
43 andreas 1429
#endif
41 andreas 1430
            ANIMATION_t ani;
1431
            ani.showEffect = subPg->getShowEffect();
1432
            ani.showTime = subPg->getShowTime();
42 andreas 1433
            ani.hideEffect = subPg->getHideEffect();
1434
            ani.hideTime = subPg->getHideTime();
162 andreas 1435
 
1436
            subPg->setZOrder(pg->getNextZOrder());
217 andreas 1437
            _setSubPage(subPg->getHandle(), pg->getHandle(), left, top, width, height, ani);
6 andreas 1438
            subPg->show();
1439
        }
5 andreas 1440
 
1441
        subPg = pg->getNextSubPage();
1442
    }
1443
 
14 andreas 1444
    surface_mutex.unlock();
5 andreas 1445
    return true;
1446
}
1447
 
4 andreas 1448
TPage *TPageManager::getPage(int pageID)
1449
{
1450
    DECL_TRACER("TPageManager::getPage(int pageID)");
1451
 
209 andreas 1452
    if (pageID <= 0)
1453
        return nullptr;
1454
 
4 andreas 1455
    PCHAIN_T *p = mPchain;
1456
 
1457
    while (p)
1458
    {
1459
        if (p->page->getNumber() == pageID)
1460
            return p->page;
1461
 
1462
        p = p->next;
1463
    }
1464
 
14 andreas 1465
    MSG_DEBUG("Page " << pageID << " not found!");
4 andreas 1466
    return nullptr;
1467
}
1468
 
1469
TPage *TPageManager::getPage(const string& name)
1470
{
1471
    DECL_TRACER("TPageManager::getPage(const string& name)");
1472
 
1473
    PCHAIN_T *p = mPchain;
1474
 
1475
    while (p)
1476
    {
1477
        if (p->page->getName().compare(name) == 0)
1478
            return p->page;
1479
 
1480
        p = p->next;
1481
    }
1482
 
14 andreas 1483
    MSG_DEBUG("Page " << name << " not found!");
4 andreas 1484
    return nullptr;
1485
}
1486
 
209 andreas 1487
TPage *TPageManager::loadPage(PAGELIST_T& pl, bool *refresh)
15 andreas 1488
{
209 andreas 1489
    DECL_TRACER("TPageManager::loadPage(PAGELIST_T& pl, bool *refresh)");
15 andreas 1490
 
209 andreas 1491
    if (refresh)
1492
        *refresh = false;
1493
 
15 andreas 1494
    if (!pl.isValid)
1495
        return nullptr;
1496
 
1497
    TPage *pg = getPage(pl.pageID);
1498
 
1499
    if (!pg)
1500
    {
1501
        if (!readPage(pl.pageID))
1502
            return nullptr;
1503
 
1504
        pg = getPage(pl.pageID);
1505
 
1506
        if (!pg)
1507
        {
1508
            MSG_ERROR("Error loading page " << pl.pageID << ", " << pl.name << " from file " << pl.file << "!");
1509
            return nullptr;
1510
        }
209 andreas 1511
 
1512
        if (refresh)
213 andreas 1513
            *refresh = true;        // Indicate that the page was freshly loaded
15 andreas 1514
    }
1515
 
1516
    return pg;
1517
}
1518
 
209 andreas 1519
void TPageManager::reloadSystemPage(TPage *page)
1520
{
1521
    DECL_TRACER("TPageManager::reloadSystemPage(TPage *page)");
1522
 
1523
    if (!page)
1524
        return;
1525
 
1526
    vector<Button::TButton *> buttons = page->getAllButtons();
1527
    vector<Button::TButton *>::iterator iter;
210 andreas 1528
    TConfig::setTemporary(false);
209 andreas 1529
 
1530
    for (iter = buttons.begin(); iter != buttons.end(); ++iter)
1531
    {
1532
        Button::TButton *bt = *iter;
1533
 
1534
        if (bt->getAddressPort() == 0 && bt->getAddressChannel() > 0)
1535
        {
1536
            switch(bt->getAddressChannel())
1537
            {
1538
                case SYSTEM_ITEM_LOGLOGFILE:        bt->setTextOnly(TConfig::getLogFile(), -1); break;
1539
 
1540
                case SYSTEM_ITEM_NETLINX_IP:        bt->setTextOnly(TConfig::getController(), -1); break;
1541
                case SYSTEM_ITEM_NETLINX_PORT:      bt->setTextOnly(std::to_string(TConfig::getPort()), -1); break;
1542
                case SYSTEM_ITEM_NETLINX_CHANNEL:   bt->setTextOnly(std::to_string(TConfig::getChannel()), -1); break;
1543
                case SYSTEM_ITEM_NETLINX_PTYPE:     bt->setTextOnly(TConfig::getPanelType(), -1); break;
1544
                case SYSTEM_ITEM_FTPUSER:           bt->setTextOnly(TConfig::getFtpUser(), -1); break;
1545
                case SYSTEM_ITEM_FTPPASSWORD:       bt->setTextOnly(TConfig::getFtpPassword(), -1); break;
1546
                case SYSTEM_ITEM_FTPSURFACE:        bt->setTextOnly(TConfig::getFtpSurface(), -1); break;
210 andreas 1547
 
1548
                case SYSTEM_ITEM_SIPPROXY:          bt->setTextOnly(TConfig::getSIPproxy(), -1); break;
1549
                case SYSTEM_ITEM_SIPPORT:           bt->setTextOnly(std::to_string(TConfig::getSIPport()), -1); break;
1550
                case SYSTEM_ITEM_SIPSTUN:           bt->setTextOnly(TConfig::getSIPstun(), -1); break;
1551
                case SYSTEM_ITEM_SIPDOMAIN:         bt->setTextOnly(TConfig::getSIPdomain(), -1); break;
1552
                case SYSTEM_ITEM_SIPUSER:           bt->setTextOnly(TConfig::getSIPuser(), -1); break;
1553
                case SYSTEM_ITEM_SIPPASSWORD:       bt->setTextOnly(TConfig::getSIPpassword(), -1); break;
1554
 
1555
                case SYSTEM_ITEM_SYSTEMSOUND:       bt->setTextOnly(TConfig::getSystemSound(), -1); break;
1556
                case SYSTEM_ITEM_SINGLEBEEP:        bt->setTextOnly(TConfig::getSingleBeepSound(), -1); break;
1557
                case SYSTEM_ITEM_DOUBLEBEEP:        bt->setTextOnly(TConfig::getDoubleBeepSound(), -1); break;
209 andreas 1558
            }
1559
        }
210 andreas 1560
        else if (bt->getChannelPort() == 0 && bt->getChannelNumber() > 0)
1561
        {
1562
            switch(bt->getChannelNumber())
1563
            {
1564
                case SYSTEM_ITEM_DEBUGINFO:         bt->setActiveInstance(IS_LOG_INFO() ? 1 : 0); break;
1565
                case SYSTEM_ITEM_DEBUGWARNING:      bt->setActiveInstance(IS_LOG_WARNING() ? 1 : 0); break;
1566
                case SYSTEM_ITEM_DEBUGERROR:        bt->setActiveInstance(IS_LOG_ERROR() ? 1 : 0); break;
1567
                case SYSTEM_ITEM_DEBUGTRACE:        bt->setActiveInstance(IS_LOG_TRACE() ? 1 : 0); break;
1568
                case SYSTEM_ITEM_DEBUGDEBUG:        bt->setActiveInstance(IS_LOG_DEBUG() ? 1 : 0); break;
1569
                case SYSTEM_ITEM_DEBUGPROTOCOL:     bt->setActiveInstance(IS_LOG_PROTOCOL() ? 1 : 0); break;
1570
                case SYSTEM_ITEM_DEBUGALL:          bt->setActiveInstance(IS_LOG_ALL() ? 1 : 0); break;
1571
                case SYSTEM_ITEM_DEBUGLONG:         bt->setActiveInstance(TConfig::isLongFormat() ? 1 : 0); break;
1572
                case SYSTEM_ITEM_DEBUGPROFILE:      bt->setActiveInstance(TConfig::getProfiling() ? 1 : 0); break;
1573
 
1574
                case SYSTEM_ITEM_FTPPASSIVE:        bt->setActiveInstance(TConfig::getFtpPassive() ? 1 : 0); break;
1575
 
1576
                case SYSTEM_ITEM_SIPIPV4:           bt->setActiveInstance(TConfig::getSIPnetworkIPv4() ? 1 : 0); break;
1577
                case SYSTEM_ITEM_SIPIPV6:           bt->setActiveInstance(TConfig::getSIPnetworkIPv6() ? 1 : 0); break;
1578
                case SYSTEM_ITEM_SIPENABLE:         bt->setActiveInstance(TConfig::getSIPstatus() ? 1 : 0); break;
1579
                case SYSTEM_ITEM_SIPIPHONE:         bt->setActiveInstance(TConfig::getSIPiphone() ? 1 : 0); break;
1580
 
1581
                case SYSTEM_ITEM_SOUNDSWITCH:       bt->setActiveInstance(TConfig::getSystemSoundState() ? 1 : 0); break;
1582
 
1583
                case SYSTEM_ITEM_VIEWSCALEFIT:      bt->setActiveInstance(TConfig::getScale() ? 1 : 0); break;
1584
                case SYSTEM_ITEM_VIEWBANNER:        bt->setActiveInstance(TConfig::showBanner() ? 1 : 0); break;
1585
                case SYSTEM_ITEM_VIEWNOTOOLBAR:     bt->setActiveInstance(TConfig::getToolbarSuppress() ? 1 : 0); break;
1586
                case SYSTEM_ITEM_VIEWTOOLBAR:       bt->setActiveInstance(TConfig::getToolbarForce() ? 1 : 0); break;
1587
                case SYSTEM_ITEM_VIEWROTATE:        bt->setActiveInstance(TConfig::getRotationFixed() ? 1 : 0); break;
1588
            }
1589
        }
1590
        else if (bt->getLevelPort() == 0 && bt->getLevelValue() > 0)
1591
        {
1592
            switch(bt->getLevelValue())
1593
            {
1594
                case SYSTEM_ITEM_SYSVOLUME:         bt->drawBargraph(0, TConfig::getSystemVolume(), false); break;
1595
                case SYSTEM_ITEM_SYSGAIN:           bt->drawBargraph(0, TConfig::getSystemGain(), false); break;
1596
            }
1597
        }
209 andreas 1598
    }
1599
}
1600
 
198 andreas 1601
bool TPageManager::setPage(int PageID, bool forget)
15 andreas 1602
{
198 andreas 1603
    DECL_TRACER("TPageManager::setPage(int PageID, bool forget)");
15 andreas 1604
 
1605
    if (mActualPage == PageID)
1606
        return true;
1607
 
1608
    TPage *pg = getPage(mActualPage);
43 andreas 1609
    // FIXME: Make this a vector array to hold a larger history!
198 andreas 1610
    if (!forget)
1611
        mPreviousPage = mActualPage;
15 andreas 1612
 
1613
    if (pg)
1614
        pg->drop();
1615
 
1616
    mActualPage = 0;
1617
    PAGELIST_T listPg = findPage(PageID);
209 andreas 1618
    bool refresh = false;
15 andreas 1619
 
209 andreas 1620
    if ((pg = loadPage(listPg, &refresh)) == nullptr)
15 andreas 1621
        return false;
1622
 
1623
    mActualPage = PageID;
147 andreas 1624
 
209 andreas 1625
    if (PageID >= SYSTEM_PAGE_START && !refresh)
1626
        reloadSystemPage(pg);
1627
 
217 andreas 1628
    int width = (PageID >= SYSTEM_PAGE_START ? mSystemSettings->getWidth() : mTSettings->getWidth());
1629
    int height = (PageID >= SYSTEM_PAGE_START ? mSystemSettings->getHeight() : mTSettings->getHeight());
215 andreas 1630
 
147 andreas 1631
    if (_setPage)
215 andreas 1632
        _setPage((mActualPage << 16) & 0xffff0000, width, height);
147 andreas 1633
 
15 andreas 1634
    pg->show();
1635
    return true;
1636
}
1637
 
168 andreas 1638
bool TPageManager::setPage(const string& name, bool forget)
15 andreas 1639
{
190 andreas 1640
    DECL_TRACER("TPageManager::setPage(const string& name, bool forget)");
15 andreas 1641
 
1642
    TPage *pg = getPage(mActualPage);
1643
 
1644
    if (pg && pg->getName().compare(name) == 0)
1645
        return true;
1646
 
43 andreas 1647
    // FIXME: Make this a vector array to hold a larger history!
168 andreas 1648
    if (!forget)
1649
        mPreviousPage = mActualPage;    // Necessary to be able to jump back to at least the last previous page
15 andreas 1650
 
1651
    if (pg)
1652
        pg->drop();
1653
 
1654
    mActualPage = 0;
1655
    PAGELIST_T listPg = findPage(name);
210 andreas 1656
    bool refresh = false;
15 andreas 1657
 
210 andreas 1658
    if ((pg = loadPage(listPg, &refresh)) == nullptr)
15 andreas 1659
        return false;
1660
 
1661
    mActualPage = pg->getNumber();
147 andreas 1662
 
210 andreas 1663
    if (mActualPage >= SYSTEM_PAGE_START && !refresh)
1664
        reloadSystemPage(pg);
1665
 
147 andreas 1666
    if (_setPage)
1667
        _setPage((mActualPage << 16) & 0xffff0000, pg->getWidth(), pg->getHeight());
1668
 
15 andreas 1669
    pg->show();
1670
    return true;
1671
}
1672
 
4 andreas 1673
TSubPage *TPageManager::getSubPage(int pageID)
1674
{
1675
    DECL_TRACER("TPageManager::getSubPage(int pageID)");
1676
 
1677
    SPCHAIN_T *p = mSPchain;
1678
 
1679
    while(p)
1680
    {
1681
        if (p->page->getNumber() == pageID)
1682
            return p->page;
1683
 
1684
        p = p->next;
1685
    }
1686
 
1687
    return nullptr;
1688
}
1689
 
1690
TSubPage *TPageManager::getSubPage(const std::string& name)
1691
{
1692
    DECL_TRACER("TPageManager::getSubPage(const std::string& name)");
1693
 
1694
    SPCHAIN_T *p = mSPchain;
1695
 
1696
    while (p)
1697
    {
1698
        if (p->page->getName().compare(name) == 0)
1699
            return p->page;
1700
 
1701
        p = p->next;
1702
    }
1703
 
146 andreas 1704
    MSG_DEBUG("Page " << name << " not found in cache.");
4 andreas 1705
    return nullptr;
1706
}
1707
 
96 andreas 1708
TSubPage *TPageManager::deliverSubPage(const string& name, TPage **pg)
1709
{
198 andreas 1710
    DECL_TRACER("TPageManager::deliverSubPage(const string& name, TPage **pg)");
96 andreas 1711
 
1712
    TPage *page = getActualPage();
1713
 
1714
    if (!page)
1715
    {
1716
        MSG_ERROR("No actual page loaded!");
1717
        return nullptr;
1718
    }
1719
 
1720
    if (pg)
1721
        *pg = page;
1722
 
1723
    TSubPage *subPage = getSubPage(name);
1724
 
1725
    if (!subPage)
1726
    {
1727
        if (!readSubPage(name))
1728
        {
1729
            MSG_ERROR("Error reading subpage " << name);
1730
            return nullptr;
1731
        }
1732
 
1733
        subPage = getSubPage(name);
1734
 
1735
        if (!subPage)
1736
        {
1737
            MSG_ERROR("Fatal: A page with name " << name << " does not exist!");
1738
            return nullptr;
1739
        }
1740
    }
1741
 
1742
    return subPage;
1743
}
1744
 
198 andreas 1745
TSubPage *TPageManager::deliverSubPage(int number, TPage **pg)
1746
{
1747
    DECL_TRACER("TPageManager::deliverSubPage(int number, TPage **pg)");
1748
 
1749
    TPage *page = getActualPage();
1750
 
1751
    if (!page)
1752
    {
1753
        MSG_ERROR("No actual page loaded!");
1754
        return nullptr;
1755
    }
1756
 
1757
    if (pg)
1758
        *pg = page;
1759
 
1760
    TSubPage *subPage = getSubPage(number);
1761
 
1762
    if (!subPage)
1763
    {
1764
        if (!readSubPage(number))
1765
        {
1766
            MSG_ERROR("Error reading subpage " << number);
1767
            return nullptr;
1768
        }
1769
 
1770
        subPage = getSubPage(number);
1771
 
1772
        if (!subPage)
1773
        {
1774
            MSG_ERROR("Fatal: A page with name " << number << " does not exist!");
1775
            return nullptr;
1776
        }
1777
    }
1778
 
1779
    return subPage;
1780
}
1781
 
3 andreas 1782
bool TPageManager::readPages()
1783
{
1784
    DECL_TRACER("TPageManager::readPages()");
1785
 
1786
    if (!mPageList)
1787
    {
1788
        MSG_ERROR("Page list is not initialized!");
1789
        TError::setError();
1790
        return false;
1791
    }
1792
 
1793
    // Read all pages
1794
    vector<PAGELIST_T> pageList = mPageList->getPagelist();
1795
 
83 andreas 1796
    if (pageList.size() > 0)
3 andreas 1797
    {
83 andreas 1798
        vector<PAGELIST_T>::iterator pgIter;
14 andreas 1799
 
118 andreas 1800
        for (pgIter = pageList.begin(); pgIter != pageList.end(); ++pgIter)
14 andreas 1801
        {
83 andreas 1802
            TPage *page = new TPage(pgIter->name+".xml");
14 andreas 1803
 
83 andreas 1804
            if (TError::isError())
1805
            {
1806
                delete page;
1807
                return false;
1808
            }
3 andreas 1809
 
83 andreas 1810
            page->setPalette(mPalette);
1811
            page->setFonts(mFonts);
1812
            page->registerCallback(_setBackground);
1813
            page->registerCallbackDB(_displayButton);
1814
            page->regCallPlayVideo(_callPlayVideo);
1815
 
1816
            if (!addPage(page))
1817
                return false;
1818
        }
3 andreas 1819
    }
1820
 
1821
    vector<SUBPAGELIST_T> subPageList = mPageList->getSupPageList();
1822
 
83 andreas 1823
    if (subPageList.size() > 0)
3 andreas 1824
    {
83 andreas 1825
        vector<SUBPAGELIST_T>::iterator spgIter;
14 andreas 1826
 
118 andreas 1827
        for (spgIter = subPageList.begin(); spgIter != subPageList.end(); ++spgIter)
14 andreas 1828
        {
83 andreas 1829
            TSubPage *page = new TSubPage(spgIter->name+".xml");
14 andreas 1830
 
83 andreas 1831
            if (TError::isError())
1832
            {
1833
                delete page;
1834
                return false;
1835
            }
3 andreas 1836
 
83 andreas 1837
            page->setPalette(mPalette);
1838
            page->setFonts(mFonts);
1839
            page->registerCallback(_setBackground);
1840
            page->registerCallbackDB(_displayButton);
1841
            page->regCallDropSubPage(_callDropSubPage);
1842
            page->regCallPlayVideo(_callPlayVideo);
1843
            page->setGroup(spgIter->group);
1844
 
1845
            if (!addSubPage(page))
1846
                return false;
1847
        }
3 andreas 1848
    }
1849
 
1850
    return true;
1851
}
1852
 
1853
bool TPageManager::readPage(const std::string& name)
1854
{
1855
    DECL_TRACER("TPageManager::readPage(const std::string& name)");
1856
 
1857
    PAGELIST_T page = findPage(name);
1858
 
206 andreas 1859
    if ((page.pageID <= 0 || page.pageID >= MAX_PAGE_ID) && page.pageID < SYSTEM_PAGE_START && page.pageID >= SYSTEM_SUBPAGE_START)
3 andreas 1860
    {
1861
        MSG_ERROR("Page " << name << " not found!");
1862
        return false;
1863
    }
1864
 
43 andreas 1865
    TPage *pg;
14 andreas 1866
 
43 andreas 1867
    if (name.compare("_progress") == 0)
1868
        pg = new TPage(name);
1869
    else
1870
        pg = new TPage(page.name+".xml");
1871
 
14 andreas 1872
    if (TError::isError())
1873
    {
1874
        delete pg;
1875
        return false;
1876
    }
1877
 
4 andreas 1878
    pg->setPalette(mPalette);
7 andreas 1879
    pg->setFonts(mFonts);
1880
    pg->registerCallback(_setBackground);
1881
    pg->registerCallbackDB(_displayButton);
21 andreas 1882
    pg->regCallPlayVideo(_callPlayVideo);
3 andreas 1883
 
1884
    if (!addPage(pg))
1885
        return false;
1886
 
1887
    return true;
1888
}
1889
 
1890
bool TPageManager::readPage(int ID)
1891
{
1892
    DECL_TRACER("TPageManager::readPage(int ID)");
1893
 
16 andreas 1894
    TError::clear();
3 andreas 1895
    PAGELIST_T page = findPage(ID);
1896
 
1897
    if (page.pageID <= 0)
1898
    {
1899
        MSG_ERROR("Page with ID " << ID << " not found!");
1900
        return false;
1901
    }
1902
 
43 andreas 1903
    TPage *pg;
14 andreas 1904
 
43 andreas 1905
    if (ID == 300)      // Progress page of system?
1906
        pg = new TPage("_progress");
1907
    else
1908
        pg = new TPage(page.name+".xml");
1909
 
14 andreas 1910
    if (TError::isError())
1911
    {
1912
        delete pg;
1913
        return false;
1914
    }
1915
 
4 andreas 1916
    pg->setPalette(mPalette);
7 andreas 1917
    pg->setFonts(mFonts);
1918
    pg->registerCallback(_setBackground);
1919
    pg->registerCallbackDB(_displayButton);
21 andreas 1920
    pg->regCallPlayVideo(_callPlayVideo);
3 andreas 1921
 
1922
    if (!addPage(pg))
1923
        return false;
1924
 
1925
    return true;
1926
}
1927
 
1928
bool TPageManager::readSubPage(const std::string& name)
1929
{
1930
    DECL_TRACER("TPageManager::readSubPage(const std::string& name)");
1931
 
16 andreas 1932
    TError::clear();
3 andreas 1933
    SUBPAGELIST_T page = findSubPage(name);
1934
 
206 andreas 1935
    if (page.pageID < MAX_PAGE_ID || (page.pageID >= SYSTEM_PAGE_START && page.pageID < SYSTEM_SUBPAGE_START))
3 andreas 1936
    {
1937
        MSG_ERROR("Subpage " << name << " not found!");
1938
        return false;
1939
    }
1940
 
14 andreas 1941
    if (haveSubPage(name))
1942
        return true;
1943
 
3 andreas 1944
    TSubPage *pg = new TSubPage(page.name+".xml");
14 andreas 1945
 
1946
    if (TError::isError())
1947
    {
1948
        delete pg;
1949
        return false;
1950
    }
1951
 
4 andreas 1952
    pg->setPalette(mPalette);
7 andreas 1953
    pg->setFonts(mFonts);
1954
    pg->registerCallback(_setBackground);
1955
    pg->registerCallbackDB(_displayButton);
11 andreas 1956
    pg->regCallDropSubPage(_callDropSubPage);
21 andreas 1957
    pg->regCallPlayVideo(_callPlayVideo);
11 andreas 1958
    pg->setGroup(page.group);
3 andreas 1959
 
1960
    if (!addSubPage(pg))
14 andreas 1961
    {
1962
        delete pg;
3 andreas 1963
        return false;
14 andreas 1964
    }
3 andreas 1965
 
1966
    return true;
1967
}
1968
 
1969
bool TPageManager::readSubPage(int ID)
1970
{
1971
    DECL_TRACER("TPageManager::readSubPage(int ID)");
1972
 
16 andreas 1973
    TError::clear();
3 andreas 1974
    SUBPAGELIST_T page = findSubPage(ID);
1975
 
154 andreas 1976
    if (page.pageID <= MAX_PAGE_ID)
3 andreas 1977
    {
1978
        MSG_ERROR("Subpage with ID " << ID << " not found!");
1979
        return false;
1980
    }
1981
 
1982
    TSubPage *pg = new TSubPage(page.name+".xml");
14 andreas 1983
 
1984
    if (TError::isError())
1985
    {
1986
        delete pg;
1987
        return false;
1988
    }
1989
 
4 andreas 1990
    pg->setPalette(mPalette);
7 andreas 1991
    pg->setFonts(mFonts);
1992
    pg->registerCallback(_setBackground);
1993
    pg->registerCallbackDB(_displayButton);
11 andreas 1994
    pg->regCallDropSubPage(_callDropSubPage);
21 andreas 1995
    pg->regCallPlayVideo(_callPlayVideo);
11 andreas 1996
    pg->setGroup(page.group);
3 andreas 1997
 
1998
    if (!addSubPage(pg))
1999
        return false;
2000
 
2001
    return true;
2002
}
2003
 
192 andreas 2004
void TPageManager::updateActualPage()
2005
{
2006
    DECL_TRACER("TPageManager::updateActualPage()");
2007
 
2008
    if (!mActualPage)
2009
        return;
2010
 
2011
    TPage *pg = getPage(mActualPage);
2012
    Button::TButton *bt = pg->getFirstButton();
2013
 
2014
    while (bt)
2015
    {
2016
        bt->refresh();
2017
        bt = pg->getNextButton();
2018
    }
2019
}
2020
 
2021
void TPageManager::updateSubpage(int ID)
2022
{
2023
    DECL_TRACER("TPageManager::updateSubpage(int ID)");
2024
 
2025
    TSubPage *pg = getSubPage(ID);
2026
 
2027
    if (!pg)
2028
        return;
2029
 
2030
    vector<Button::TButton *> blist = pg->getAllButtons();
2031
    vector<Button::TButton *>::iterator iter;
2032
 
2033
    if (blist.empty())
2034
        return;
2035
 
2036
    for (iter = blist.begin(); iter != blist.end(); ++iter)
2037
    {
2038
        Button::TButton *bt = *iter;
2039
        bt->refresh();
2040
    }
2041
}
2042
 
2043
void TPageManager::updateSubpage(const std::string &name)
2044
{
2045
    DECL_TRACER("TPageManager::updateSubpage(const std::string &name)");
2046
 
2047
    TSubPage *pg = getSubPage(name);
2048
 
2049
    if (!pg)
2050
        return;
2051
 
2052
    vector<Button::TButton *> blist = pg->getAllButtons();
2053
    vector<Button::TButton *>::iterator iter;
2054
 
2055
    if (blist.empty())
2056
        return;
2057
 
2058
    for (iter = blist.begin(); iter != blist.end(); ++iter)
2059
    {
2060
        Button::TButton *bt = *iter;
2061
        bt->refresh();
2062
    }
2063
}
2064
 
3 andreas 2065
/******************** Internal private methods *********************/
2066
 
2067
PAGELIST_T TPageManager::findPage(const std::string& name)
2068
{
2069
    DECL_TRACER("TPageManager::findPage(const std::string& name)");
2070
 
194 andreas 2071
    vector<PAGELIST_T> pageList;
3 andreas 2072
 
194 andreas 2073
    if (!mSetupActive)
2074
        pageList = mPageList->getPagelist();
2075
    else
2076
        pageList = mPageList->getSystemPagelist();
2077
 
83 andreas 2078
    if (pageList.size() > 0)
3 andreas 2079
    {
83 andreas 2080
        vector<PAGELIST_T>::iterator pgIter;
2081
 
118 andreas 2082
        for (pgIter = pageList.begin(); pgIter != pageList.end(); ++pgIter)
83 andreas 2083
        {
2084
            if (pgIter->name.compare(name) == 0)
2085
                return *pgIter;
2086
        }
3 andreas 2087
    }
2088
 
194 andreas 2089
    MSG_WARNING("Page " << name << " not found!");
3 andreas 2090
    return PAGELIST_T();
2091
}
2092
 
2093
PAGELIST_T TPageManager::findPage(int ID)
2094
{
2095
    DECL_TRACER("TPageManager::findPage(int ID)");
2096
 
206 andreas 2097
    vector<PAGELIST_T> pageList = (ID < SYSTEM_PAGE_START ? mPageList->getPagelist() : mPageList->getSystemPagelist());
3 andreas 2098
 
83 andreas 2099
    if (pageList.size() > 0)
3 andreas 2100
    {
83 andreas 2101
        vector<PAGELIST_T>::iterator pgIter;
2102
 
118 andreas 2103
        for (pgIter = pageList.begin(); pgIter != pageList.end(); ++pgIter)
83 andreas 2104
        {
2105
            if (pgIter->pageID == ID)
2106
                return *pgIter;
2107
        }
3 andreas 2108
    }
2109
 
2110
    return PAGELIST_T();
2111
}
2112
 
2113
SUBPAGELIST_T TPageManager::findSubPage(const std::string& name)
2114
{
2115
    DECL_TRACER("TPageManager::findSubPage(const std::string& name)");
2116
 
194 andreas 2117
    vector<SUBPAGELIST_T> pageList = (mSetupActive ? mPageList->getSystemSupPageList() : mPageList->getSupPageList());
3 andreas 2118
 
83 andreas 2119
    if (pageList.size() > 0)
3 andreas 2120
    {
83 andreas 2121
        vector<SUBPAGELIST_T>::iterator pgIter;
2122
 
118 andreas 2123
        for (pgIter = pageList.begin(); pgIter != pageList.end(); ++pgIter)
83 andreas 2124
        {
2125
            if (pgIter->name.compare(name) == 0)
2126
                return *pgIter;
2127
        }
3 andreas 2128
    }
2129
 
2130
    return SUBPAGELIST_T();
2131
}
2132
 
2133
SUBPAGELIST_T TPageManager::findSubPage(int ID)
2134
{
2135
    DECL_TRACER("TPageManager::findSubPage(int ID)");
2136
 
206 andreas 2137
    vector<SUBPAGELIST_T> pageList = (ID < SYSTEM_PAGE_START ? mPageList->getSupPageList() : mPageList->getSystemSupPageList());
3 andreas 2138
 
83 andreas 2139
    if (pageList.size() > 0)
3 andreas 2140
    {
83 andreas 2141
        vector<SUBPAGELIST_T>::iterator pgIter;
2142
 
118 andreas 2143
        for (pgIter = pageList.begin(); pgIter != pageList.end(); ++pgIter)
83 andreas 2144
        {
2145
            if (pgIter->pageID == ID)
2146
                return *pgIter;
2147
        }
3 andreas 2148
    }
2149
 
2150
    return SUBPAGELIST_T();
2151
}
2152
 
2153
bool TPageManager::addPage(TPage* pg)
2154
{
2155
    DECL_TRACER("TPageManager::addPage(TPage* pg)");
2156
 
2157
    if (!pg)
2158
    {
2159
        MSG_ERROR("Parameter is NULL!");
2160
        TError::setError();
2161
        return false;
2162
    }
2163
 
2164
    PCHAIN_T *chain = new PCHAIN_T;
2165
    chain->page = pg;
5 andreas 2166
    chain->next = nullptr;
3 andreas 2167
 
2168
    if (mPchain)
2169
    {
2170
        PCHAIN_T *p = mPchain;
2171
 
2172
        while (p->next)
2173
            p = p->next;
2174
 
2175
        p->next = chain;
2176
    }
2177
    else
14 andreas 2178
    {
3 andreas 2179
        mPchain = chain;
14 andreas 2180
        setPChain(mPchain);
2181
    }
3 andreas 2182
 
156 andreas 2183
//    MSG_DEBUG("Added page " << chain->page->getName());
3 andreas 2184
    return true;
2185
}
2186
 
2187
bool TPageManager::addSubPage(TSubPage* pg)
2188
{
2189
    DECL_TRACER("TPageManager::addSubPage(TSubPage* pg)");
2190
 
2191
    if (!pg)
2192
    {
2193
        MSG_ERROR("Parameter is NULL!");
2194
        TError::setError();
2195
        return false;
2196
    }
2197
 
14 andreas 2198
    if (haveSubPage(pg->getNumber()))
2199
    {
2200
        MSG_ERROR("Subpage " << pg->getNumber() << ", " << pg->getName() << " is already in chain!");
2201
        return false;
2202
    }
2203
 
3 andreas 2204
    SPCHAIN_T *chain = new SPCHAIN_T;
2205
    chain->page = pg;
5 andreas 2206
    chain->next = nullptr;
3 andreas 2207
 
2208
    if (mSPchain)
2209
    {
2210
        SPCHAIN_T *p = mSPchain;
2211
 
2212
        while (p->next)
2213
            p = p->next;
2214
 
2215
        p->next = chain;
2216
    }
2217
    else
14 andreas 2218
    {
3 andreas 2219
        mSPchain = chain;
14 andreas 2220
        setSPChain(mSPchain);
2221
    }
3 andreas 2222
 
2223
    return true;
2224
}
4 andreas 2225
 
11 andreas 2226
void TPageManager::dropAllPages()
2227
{
2228
    DECL_TRACER("TPageManager::dropAllPages()");
2229
 
2230
    PCHAIN_T *pg = mPchain;
2231
    PCHAIN_T *next = nullptr;
2232
 
2233
    while (pg)
2234
    {
2235
        next = pg->next;
2236
 
2237
        if (pg->page)
2238
        {
2239
            if (_callDropPage)
2240
                _callDropPage((pg->page->getNumber() << 16) & 0xffff0000);
2241
 
2242
            delete pg->page;
2243
        }
2244
 
2245
        delete pg;
2246
        pg = next;
2247
    }
14 andreas 2248
 
2249
    mPchain = nullptr;
2250
    setPChain(mPchain);
11 andreas 2251
}
2252
 
2253
void TPageManager::dropAllSubPages()
2254
{
2255
    DECL_TRACER("TPageManager::dropAllSubPages()");
2256
 
2257
    SPCHAIN_T *spg = mSPchain;
2258
    SPCHAIN_T *next;
2259
 
2260
    while (spg)
2261
    {
2262
        next = spg->next;
2263
 
2264
        if (spg->page)
2265
        {
2266
            if (_callDropSubPage)
2267
                _callDropSubPage((spg->page->getNumber() << 16) & 0xffff0000);
2268
 
2269
            delete spg->page;
2270
        }
2271
 
2272
        delete spg;
2273
        spg = next;
2274
    }
14 andreas 2275
 
2276
    mSPchain = nullptr;
2277
    setSPChain(mSPchain);
11 andreas 2278
}
2279
 
44 andreas 2280
bool TPageManager::destroyAll()
2281
{
2282
    DECL_TRACER("TPageManager::destroyAll()");
2283
 
2284
    dropAllSubPages();
2285
    dropAllPages();
2286
    mActualPage = 0;
2287
    mPreviousPage = 0;
2288
    mActualGroupName.clear();
2289
 
2290
    if (mPageList)
2291
    {
2292
        delete mPageList;
2293
        mPageList = nullptr;
2294
    }
2295
 
2296
    if (mTSettings)
2297
    {
2298
        delete mTSettings;
2299
        mTSettings = nullptr;
2300
    }
2301
 
194 andreas 2302
    if (mSystemSettings)
2303
    {
2304
        delete mSystemSettings;
2305
        mSystemSettings = nullptr;
2306
    }
2307
 
44 andreas 2308
    if (mPalette)
2309
    {
2310
        delete mPalette;
2311
        mPalette = nullptr;
2312
    }
2313
 
2314
    if (mFonts)
2315
    {
2316
        delete mFonts;
2317
        mFonts = nullptr;
2318
    }
2319
 
2320
    if (mExternal)
2321
    {
2322
        delete mExternal;
2323
        mExternal = nullptr;
2324
    }
2325
 
2326
    if (gPrjResources)
2327
    {
2328
        delete gPrjResources;
2329
        gPrjResources = nullptr;
2330
    }
2331
 
2332
    if (gIcons)
2333
    {
2334
        delete gIcons;
2335
        gIcons = nullptr;
2336
    }
2337
 
2338
    if (TError::isError())
2339
        return false;
2340
 
2341
    return true;
2342
}
2343
 
150 andreas 2344
bool TPageManager::overlap(int x1, int y1, int w1, int h1, int x2, int y2, int w2, int h2)
2345
{
2346
    DECL_TRACER("TPageManager::overlap(int x1, int y1, int w1, int h1, int x2, int y2, int w2, int h2)");
2347
 
2348
    struct point
2349
    {
2350
        int x;
2351
        int y;
2352
    };
2353
 
2354
    struct point l1, r1, l2, r2;
2355
 
2356
    l1.x = x1;
2357
    l1.y = y1;
2358
    r1.x = x1 + w1;
2359
    r1.y = y1 + h1;
2360
 
2361
    l2.x = x2;
2362
    l2.y = y2;
2363
    r2.x = x2 + w2;
2364
    r2.y = y2 + h2;
2365
 
2366
    if (l1.x == r1.x || l1.y == r1.y || l2.x == r2.x || l2.y == r2.y)
2367
    {
2368
        // the line cannot have positive overlap
2369
        return false;
2370
    }
2371
 
183 andreas 2372
    return std::max(l1.x, l2.x) < std::min(r1.x, r2.x) &&
150 andreas 2373
           std::max(l1.y, l2.y) < std::min(r1.y, r2.y);
2374
}
2375
 
51 andreas 2376
Button::TButton *TPageManager::findButton(ulong handle)
2377
{
2378
    DECL_TRACER("TPageManager::findButton(ulong handle)");
2379
 
209 andreas 2380
    if (!handle)
2381
        return nullptr;
2382
 
51 andreas 2383
    TPage *pg = getPage(mActualPage);
2384
 
2385
    if (!pg)
2386
        return nullptr;
2387
 
2388
    vector<Button::TButton *> pgBtList = pg->getAllButtons();
2389
    vector<Button::TButton *>::iterator iter;
83 andreas 2390
 
2391
    if (pgBtList.size() > 0)
51 andreas 2392
    {
83 andreas 2393
        // First we look into the elements of the page
2394
        for (iter = pgBtList.begin(); iter != pgBtList.end(); ++iter)
2395
        {
2396
            Button::TButton *bt = *iter;
51 andreas 2397
 
83 andreas 2398
            if (bt->getHandle() == handle)
2399
                return bt;
2400
        }
51 andreas 2401
    }
2402
 
2403
    // We've not found the wanted element in the elements of the page. So
2404
    // we're looking at the elements of the subpages.
2405
    TSubPage *sp = pg->getFirstSubPage();
2406
 
2407
    if (!sp)
2408
        return nullptr;
2409
 
2410
    while (sp)
2411
    {
2412
        vector<Button::TButton *> spBtList = sp->getAllButtons();
2413
 
83 andreas 2414
        if (spBtList.size() > 0)
51 andreas 2415
        {
83 andreas 2416
            for (iter = spBtList.begin(); iter != spBtList.end(); ++iter)
2417
            {
2418
                Button::TButton *bt = *iter;
51 andreas 2419
 
83 andreas 2420
                if (bt->getHandle() == handle)
2421
                    return bt;
2422
            }
51 andreas 2423
        }
2424
 
2425
        sp = pg->getNextSubPage();
2426
    }
2427
 
2428
    return nullptr;
2429
}
2430
 
4 andreas 2431
TPage *TPageManager::getActualPage()
2432
{
168 andreas 2433
    DECL_TRACER("TPageManager::getActualPage()");
2434
 
4 andreas 2435
    return getPage(mActualPage);
2436
}
2437
 
2438
TSubPage *TPageManager::getFirstSubPage()
2439
{
2440
    DECL_TRACER("TPageManager::getFirstSubPage()");
168 andreas 2441
 
4 andreas 2442
    TPage *pg = getPage(mActualPage);
2443
 
2444
    if (!pg)
2445
        return nullptr;
2446
 
2447
    return pg->getFirstSubPage();
2448
}
2449
 
2450
TSubPage *TPageManager::getNextSubPage()
2451
{
2452
    DECL_TRACER("TPageManager::getNextSubPage()");
2453
 
2454
    TPage *pg = getPage(mActualPage);
2455
 
2456
    if (pg)
2457
        return pg->getNextSubPage();
2458
 
2459
    return nullptr;
2460
}
10 andreas 2461
 
154 andreas 2462
TSubPage *TPageManager::getPrevSubPage()
2463
{
2464
    DECL_TRACER("TPageManager::getPrevSubPage()");
2465
 
2466
    TPage *pg = getPage(mActualPage);
2467
 
2468
    if (pg)
2469
        return pg->getPrevSubPage();
2470
 
2471
    return nullptr;
2472
}
2473
 
2474
TSubPage *TPageManager::getLastSubPage()
2475
{
2476
    DECL_TRACER("TPageManager::getLastSubPage()");
2477
 
2478
    TPage *pg = getPage(mActualPage);
2479
 
2480
    if (pg)
2481
    {
2482
        pg->sortSubpages();
2483
        return pg->getLastSubPage();
2484
    }
2485
    else
2486
    {
2487
        MSG_WARNING("Actual page " << mActualPage << " not found!");
2488
    }
2489
 
2490
    return nullptr;
2491
}
2492
 
11 andreas 2493
TSubPage *TPageManager::getFirstSubPageGroup(const string& group)
2494
{
2495
    DECL_TRACER("TPageManager::getFirstSubPageGroup(const string& group)");
2496
 
14 andreas 2497
    if (group.empty())
2498
    {
2499
        MSG_WARNING("Empty group name is invalid. Ignoring it!");
2500
        mActualGroupName.clear();
2501
        mActualGroupPage = nullptr;
2502
        return nullptr;
2503
    }
2504
 
11 andreas 2505
    mActualGroupName = group;
2506
    TSubPage *pg = getFirstSubPage();
2507
 
2508
    while (pg)
2509
    {
14 andreas 2510
        MSG_DEBUG("Evaluating group " << pg->getGroupName() << " with " << group);
2511
 
11 andreas 2512
        if (pg->getGroupName().compare(group) == 0)
2513
        {
2514
            mActualGroupPage = pg;
2515
            return pg;
2516
        }
2517
 
2518
        pg = getNextSubPage();
2519
    }
2520
 
2521
    mActualGroupName.clear();
2522
    mActualGroupPage = nullptr;
2523
    return nullptr;
2524
}
2525
 
2526
TSubPage *TPageManager::getNextSubPageGroup()
2527
{
2528
    DECL_TRACER("TPageManager::getNextSubPageGroup()");
2529
 
2530
    if (mActualGroupName.empty())
2531
        return nullptr;
2532
 
2533
    TSubPage *pg = getFirstSubPage();
2534
    bool found = false;
2535
 
2536
    while (pg)
2537
    {
14 andreas 2538
        MSG_DEBUG("Evaluating group " << pg->getGroupName() << " with " << mActualGroupName);
2539
 
2540
        if (!found && pg == mActualGroupPage)
11 andreas 2541
        {
2542
            pg = getNextSubPage();
14 andreas 2543
            found = true;
11 andreas 2544
            continue;
2545
        }
2546
 
14 andreas 2547
        if (found && pg->getGroupName().compare(mActualGroupName) == 0)
11 andreas 2548
        {
2549
            mActualGroupPage = pg;
2550
            return pg;
2551
        }
2552
 
2553
        pg = getNextSubPage();
2554
    }
2555
 
2556
    mActualGroupName.clear();
2557
    mActualGroupPage = nullptr;
2558
    return nullptr;
2559
}
2560
 
2561
TSubPage *TPageManager::getNextSubPageGroup(const string& group, TSubPage* pg)
2562
{
2563
    DECL_TRACER("TPageManager::getNextSubPageGroup(const string& group, TSubPage* pg)");
2564
 
2565
    if (group.empty() || !pg)
2566
        return nullptr;
2567
 
2568
    TSubPage *page = getFirstSubPage();
2569
    bool found = false;
2570
 
2571
    while (page)
2572
    {
14 andreas 2573
        MSG_DEBUG("Evaluating group " << pg->getGroupName() << " with " << group);
2574
 
2575
        if (!found && pg == page)
11 andreas 2576
        {
2577
            page = getNextSubPage();
14 andreas 2578
            found = true;
11 andreas 2579
            continue;
2580
        }
2581
 
14 andreas 2582
        if (found && page->getGroupName().compare(group) == 0)
11 andreas 2583
            return page;
2584
 
2585
        page = getNextSubPage();
2586
    }
2587
 
2588
    return nullptr;
2589
}
2590
 
2591
TSubPage *TPageManager::getTopPage()
2592
{
2593
    DECL_TRACER("TPageManager::getTopPage()");
2594
 
2595
    // Scan for all occupied regions
2596
    vector<RECT_T> regions;
2597
 
2598
    TSubPage *pg = getFirstSubPage();
2599
 
2600
    while (pg)
2601
    {
2602
        RECT_T r = pg->getRegion();
2603
        regions.push_back(r);
2604
        pg = getNextSubPage();
2605
    }
2606
 
2607
    // Now scan all pages against all regions to find the top most
2608
    pg = getFirstSubPage();
2609
    TSubPage *top = nullptr;
2610
    int zPos = 0;
2611
 
2612
    while (pg)
2613
    {
2614
        RECT_T r = pg->getRegion();
2615
 
83 andreas 2616
        if (regions.size() > 0)
11 andreas 2617
        {
83 andreas 2618
            vector<RECT_T>::iterator iter;
2619
            int zo = 0;
11 andreas 2620
 
118 andreas 2621
            for (iter = regions.begin(); iter != regions.end(); ++iter)
83 andreas 2622
            {
2623
                if (doOverlap(*iter, r) && zPos > zo)
2624
                    top = pg;
2625
 
2626
                zo++;
2627
            }
11 andreas 2628
        }
2629
 
2630
        pg = getNextSubPage();
2631
        zPos++;
2632
    }
2633
 
2634
    return top;
2635
}
2636
 
2637
TSubPage *TPageManager::getCoordMatch(int x, int y)
2638
{
2639
    DECL_TRACER("TPageManager::getCoordMatch(int x, int y)");
2640
 
26 andreas 2641
    int realX = x;
2642
    int realY = y;
2643
 
11 andreas 2644
    // Reverse order of pages
154 andreas 2645
    TSubPage *pg = getLastSubPage();
11 andreas 2646
 
154 andreas 2647
    // Iterate in reverse order through array
11 andreas 2648
    while (pg)
2649
    {
154 andreas 2650
        if (!pg->isVisible() || pg->getZOrder() == ZORDER_INVALID)
151 andreas 2651
        {
154 andreas 2652
            pg = getPrevSubPage();
2653
            continue;
151 andreas 2654
        }
14 andreas 2655
 
154 andreas 2656
        MSG_DEBUG("Scanning subpage (Z: " << pg->getZOrder() << "): " << pg->getNumber() << ", " << pg->getName());
2657
        RECT_T r = pg->getRegion();
11 andreas 2658
 
154 andreas 2659
        if (r.left <= realX && (r.left + r.width) >= realX &&
2660
            r.top <= realY && (r.top + r.height) >= realY)
11 andreas 2661
        {
154 andreas 2662
            MSG_DEBUG("Click matches subpage " << pg->getNumber() << " (" << pg->getName() << ")");
2663
            return pg;
2664
        }
83 andreas 2665
 
154 andreas 2666
        pg = getPrevSubPage();
11 andreas 2667
    }
2668
 
2669
    return nullptr;
2670
}
2671
 
40 andreas 2672
Button::TButton *TPageManager::getCoordMatchPage(int x, int y)
2673
{
2674
    DECL_TRACER("TPageManager::getCoordMatchPage(int x, int y)");
2675
 
2676
    TPage *page = getActualPage();
2677
 
2678
    if (page)
2679
    {
150 andreas 2680
        Button::TButton *bt = page->getLastButton();
40 andreas 2681
 
2682
        while (bt)
2683
        {
150 andreas 2684
            bool clickable = bt->isClickable();
2685
            MSG_DEBUG("Button: " << bt->getButtonIndex() << ", l: " << bt->getLeftPosition() << ", t: " << bt->getTopPosition() << ", r: " << (bt->getLeftPosition() + bt->getWidth()) << ", b: " << (bt->getTopPosition() + bt->getHeight()) << ", x: " << x << ", y: " << y << ", " << (clickable ? "CLICKABLE" : "NOT CLICKABLE"));
40 andreas 2686
 
150 andreas 2687
            if (!clickable)
146 andreas 2688
            {
150 andreas 2689
                bt = page->getPreviousButton();
146 andreas 2690
                continue;
2691
            }
2692
 
40 andreas 2693
            if (bt->getLeftPosition() <= x && (bt->getLeftPosition() + bt->getWidth()) >= x &&
2694
                bt->getTopPosition() <= y && (bt->getTopPosition() + bt->getHeight()) >= y)
2695
            {
154 andreas 2696
                if (!bt->isClickable(x - bt->getLeftPosition(), y - bt->getTopPosition()))
2697
                {
2698
                    bt = page->getPreviousButton();
2699
                    continue;
2700
                }
2701
 
40 andreas 2702
                MSG_DEBUG("Click matches button " << bt->getButtonIndex() << " (" << bt->getButtonName() << ")");
2703
                return bt;
2704
            }
2705
 
150 andreas 2706
            bt = page->getPreviousButton();
40 andreas 2707
        }
2708
    }
2709
 
2710
    return nullptr;
2711
}
2712
 
11 andreas 2713
bool TPageManager::doOverlap(RECT_T r1, RECT_T r2)
2714
{
2715
    DECL_TRACER("TPageManager::doOverlap(RECT_T r1, RECT_T r2)");
2716
 
2717
    // If one rectangle is on left side of other
2718
    if (r1.left >= r2.left || r2.left >= r1.left)
2719
        return false;
2720
 
2721
    // If one rectangle is above other
2722
    if (r1.top <= r2.top || r2.top <= r1.top)
2723
        return false;
2724
 
2725
    return true;
2726
}
2727
 
14 andreas 2728
bool TPageManager::havePage(const string& name)
11 andreas 2729
{
14 andreas 2730
    DECL_TRACER("TPageManager::havePage(const string& name)");
11 andreas 2731
 
14 andreas 2732
    if (name.empty())
2733
        return false;
2734
 
2735
    PCHAIN_T *pg = mPchain;
2736
 
2737
    while (pg)
2738
    {
2739
        if (pg->page && pg->page->getName().compare(name) == 0)
2740
            return true;
2741
 
2742
        pg = pg->next;
2743
    }
2744
 
2745
    return false;
2746
}
2747
 
2748
bool TPageManager::haveSubPage(const string& name)
2749
{
2750
    DECL_TRACER("TPageManager::haveSubPage(const string& name)");
2751
 
2752
    if (name.empty())
2753
        return false;
2754
 
11 andreas 2755
    SPCHAIN_T *pg = mSPchain;
2756
 
2757
    while (pg)
2758
    {
14 andreas 2759
        if (pg->page && pg->page->getName().compare(name) == 0)
2760
        {
2761
            MSG_DEBUG("Subpage " << pg->page->getNumber() << ", " << name << " found.");
2762
            return true;
2763
        }
2764
 
2765
        pg = pg->next;
2766
    }
2767
 
2768
    MSG_DEBUG("Subpage " << name << " not found.");
2769
    return false;
2770
}
2771
 
2772
bool TPageManager::haveSubPage(int id)
2773
{
2774
    DECL_TRACER("TPageManager::haveSubPage(int id)");
2775
 
2776
    SPCHAIN_T *pg = mSPchain;
2777
 
2778
    while (pg)
2779
    {
2780
        if (pg->page && pg->page->getNumber() == id)
2781
        {
2782
            MSG_DEBUG("Subpage " << pg->page->getNumber() << ", " << pg->page->getName() << " found.");
2783
            return true;
2784
        }
2785
 
2786
        pg = pg->next;
2787
    }
2788
 
2789
    MSG_DEBUG("Subpage " << id << " not found.");
2790
    return false;
2791
}
2792
 
2793
bool TPageManager::haveSubPage(const string& page, const string& name)
2794
{
2795
    DECL_TRACER("TPageManager::haveSubPage(const string& page, const string& name)");
2796
 
2797
    TPage *pg = getPage(page);
2798
 
2799
    if (!pg)
2800
        return false;
2801
 
2802
    TSubPage *spg = pg->getFirstSubPage();
2803
 
2804
    while (spg)
2805
    {
2806
        if (spg->getName().compare(name) == 0)
2807
        {
2808
            MSG_DEBUG("Subpage " << spg->getNumber() << ", " << name << " found.");
2809
            return true;
2810
        }
2811
 
2812
        spg = pg->getNextSubPage();
2813
    }
2814
 
2815
    MSG_DEBUG("Subpage " << name << " not found on page " << page << ".");
2816
    return false;
2817
}
2818
 
2819
bool TPageManager::haveSubPage(const string& page, int id)
2820
{
2821
    DECL_TRACER("TPageManager::haveSubPage(const string& page, int id)");
2822
 
2823
    TPage *pg = getPage(page);
2824
 
2825
    if (!pg)
2826
        return false;
2827
 
2828
    TSubPage *spg = pg->getFirstSubPage();
2829
 
2830
    while (spg)
2831
    {
2832
        if (spg->getNumber() == id)
2833
        {
2834
            MSG_DEBUG("Subpage " << spg->getNumber() << ", " << spg->getName() << " found.");
2835
            return true;
2836
        }
2837
 
2838
        spg = pg->getNextSubPage();
2839
    }
2840
 
2841
    MSG_DEBUG("Subpage " << id << " on page " << page << " not found.");
2842
    return false;
2843
}
2844
 
2845
void TPageManager::closeGroup(const string& group)
2846
{
2847
    DECL_TRACER("TPageManager::closeGroup(const string& group)");
2848
 
2849
    SPCHAIN_T *pg = mSPchain;
2850
 
2851
    while (pg)
2852
    {
11 andreas 2853
        if (pg->page->getGroupName().compare(group) == 0 && pg->page->isVisible())
2854
        {
2855
            pg->page->regCallDropSubPage(_callDropSubPage);
2856
            pg->page->drop();
2857
            break;
2858
        }
2859
 
2860
        pg = pg->next;
2861
    }
2862
}
2863
 
14 andreas 2864
void TPageManager::showSubPage(const string& name)
2865
{
2866
    DECL_TRACER("TPageManager::showSubPage(const string& name)");
2867
 
2868
    if (name.empty())
2869
        return;
2870
 
152 andreas 2871
    TPage *page = nullptr;
2872
    TSubPage *pg = deliverSubPage(name, &page);
14 andreas 2873
 
96 andreas 2874
    if (!pg)
14 andreas 2875
        return;
2876
 
152 andreas 2877
    if (page)
2878
        page->addSubPage(pg);
2879
 
14 andreas 2880
    string group = pg->getGroupName();
2881
 
2882
    if (!group.empty())
2883
    {
2884
        TSubPage *sub = getFirstSubPageGroup(group);
2885
 
2886
        while(sub)
2887
        {
2888
            if (sub->isVisible() && sub->getNumber() != pg->getNumber())
2889
                sub->drop();
2890
 
2891
            sub = getNextSubPageGroup(group, sub);
2892
        }
2893
    }
2894
 
150 andreas 2895
    if (pg->isVisible())
2896
    {
152 andreas 2897
        MSG_DEBUG("Page " << pg->getName() << " is already visible but maybe not on top.");
150 andreas 2898
 
2899
        TSubPage *sub = getFirstSubPage();
2900
        bool redraw = false;
2901
 
2902
        while (sub)
2903
        {
151 andreas 2904
            if (sub->isVisible() && pg->getZOrder() < sub->getZOrder() &&
2905
                overlap(sub->getLeft(), sub->getTop(), sub->getWidth(), sub->getHeight(),
150 andreas 2906
                pg->getLeft(), pg->getTop(), pg->getWidth(), pg->getHeight()))
2907
            {
2908
                MSG_DEBUG("Page " << sub->getName() << " is overlapping page " << pg->getName());
2909
                redraw = true;
2910
                break;
2911
            }
2912
 
2913
            sub = getNextSubPage();
2914
        }
2915
 
151 andreas 2916
        if (redraw && _toFront)
2917
        {
154 andreas 2918
            _toFront(pg->getHandle());
151 andreas 2919
            pg->setZOrder(page->getNextZOrder());
2920
            page->sortSubpages();
154 andreas 2921
            MSG_DEBUG("Setting new Z-order " << page->getActZOrder() << " on subpage " << pg->getName());
151 andreas 2922
        }
154 andreas 2923
        else if (redraw && !_toFront)
150 andreas 2924
            pg->drop();
2925
    }
2926
 
14 andreas 2927
    if (!pg->isVisible())
2928
    {
2929
        if (!page)
2930
        {
198 andreas 2931
            page = getPage(mActualPage);
2932
 
2933
            if (!page)
2934
            {
2935
                MSG_ERROR("No active page found! Internal error.");
2936
                return;
2937
            }
14 andreas 2938
        }
2939
 
2940
        if (!haveSubPage(pg->getNumber()) && !page->addSubPage(pg))
2941
            return;
2942
 
2943
        pg->setZOrder(page->getNextZOrder());
2944
 
2945
        if (_setSubPage)
26 andreas 2946
        {
2947
            int left = pg->getLeft();
2948
            int top = pg->getTop();
2949
            int width = pg->getWidth();
2950
            int height = pg->getHeight();
43 andreas 2951
#ifdef _SCALE_SKIA_
26 andreas 2952
            if (mScaleFactor != 1.0)
2953
            {
2954
                left = (int)((double)left * mScaleFactor);
2955
                top = (int)((double)top * mScaleFactor);
2956
                width = (int)((double)width * mScaleFactor);
2957
                height = (int)((double)height * mScaleFactor);
28 andreas 2958
                MSG_DEBUG("Scaled subpage: left=" << left << ", top=" << top << ", width=" << width << ", height=" << height);
26 andreas 2959
            }
43 andreas 2960
#endif
41 andreas 2961
            ANIMATION_t ani;
2962
            ani.showEffect = pg->getShowEffect();
2963
            ani.showTime = pg->getShowTime();
42 andreas 2964
            ani.hideEffect = pg->getHideEffect();
2965
            ani.hideTime = pg->getHideTime();
54 andreas 2966
            // Test for a timer on the page
2967
            if (pg->getTimeout() > 0)
2968
                pg->startTimer();
2969
 
217 andreas 2970
            _setSubPage(pg->getHandle(), page->getHandle(), left, top, width, height, ani);
26 andreas 2971
        }
14 andreas 2972
    }
2973
 
2974
    pg->show();
2975
}
2976
 
198 andreas 2977
void TPageManager::showSubPage(int number, bool force)
2978
{
2979
    DECL_TRACER("TPageManager::showSubPage(int number, bool force)");
2980
 
2981
    if (number <= 0)
2982
        return;
2983
 
2984
    TPage *page = nullptr;
2985
    TSubPage *pg = deliverSubPage(number, &page);
2986
 
2987
    if (!pg)
2988
        return;
2989
 
2990
    if (page)
2991
        page->addSubPage(pg);
2992
 
2993
    string group = pg->getGroupName();
2994
 
2995
    if (!group.empty())
2996
    {
2997
        TSubPage *sub = getFirstSubPageGroup(group);
2998
 
2999
        while(sub)
3000
        {
3001
            if (sub->isVisible() && sub->getNumber() != pg->getNumber())
3002
                sub->drop();
3003
 
3004
            sub = getNextSubPageGroup(group, sub);
3005
        }
3006
    }
3007
 
3008
    if (pg->isVisible() && !force)
3009
    {
3010
        MSG_DEBUG("Page " << pg->getName() << " is already visible but maybe not on top.");
3011
 
3012
        TSubPage *sub = getFirstSubPage();
3013
        bool redraw = false;
3014
 
3015
        while (sub)
3016
        {
3017
            if (sub->isVisible() && pg->getZOrder() < sub->getZOrder() &&
3018
                overlap(sub->getLeft(), sub->getTop(), sub->getWidth(), sub->getHeight(),
3019
                        pg->getLeft(), pg->getTop(), pg->getWidth(), pg->getHeight()))
3020
            {
3021
                MSG_DEBUG("Page " << sub->getName() << " is overlapping page " << pg->getName());
3022
                redraw = true;
3023
                break;
3024
            }
3025
 
3026
            sub = getNextSubPage();
3027
        }
3028
 
3029
        if (redraw && _toFront)
3030
        {
3031
            _toFront(pg->getHandle());
3032
            pg->setZOrder(page->getNextZOrder());
3033
            page->sortSubpages();
3034
            MSG_DEBUG("Setting new Z-order " << page->getActZOrder() << " on subpage " << pg->getName());
3035
        }
3036
        else if (redraw && !_toFront)
3037
            pg->drop();
3038
    }
3039
 
3040
    if (!pg->isVisible() || force)
3041
    {
3042
        if (!page)
3043
        {
3044
            MSG_ERROR("No active page found! Internal error.");
3045
            return;
3046
        }
3047
 
3048
        if (!haveSubPage(pg->getNumber()) && !page->addSubPage(pg))
3049
            return;
3050
 
3051
        if (!pg->isVisible())
3052
            pg->setZOrder(page->getNextZOrder());
3053
 
3054
        if (_setSubPage)
3055
        {
3056
            int left = pg->getLeft();
3057
            int top = pg->getTop();
3058
            int width = pg->getWidth();
3059
            int height = pg->getHeight();
3060
            #ifdef _SCALE_SKIA_
3061
            if (mScaleFactor != 1.0)
3062
            {
3063
                left = (int)((double)left * mScaleFactor);
3064
                top = (int)((double)top * mScaleFactor);
3065
                width = (int)((double)width * mScaleFactor);
3066
                height = (int)((double)height * mScaleFactor);
3067
                MSG_DEBUG("Scaled subpage: left=" << left << ", top=" << top << ", width=" << width << ", height=" << height);
3068
            }
3069
            #endif
3070
            ANIMATION_t ani;
3071
            ani.showEffect = pg->getShowEffect();
3072
            ani.showTime = pg->getShowTime();
3073
            ani.hideEffect = pg->getHideEffect();
3074
            ani.hideTime = pg->getHideTime();
3075
            // Test for a timer on the page
3076
            if (pg->getTimeout() > 0)
3077
                pg->startTimer();
3078
 
217 andreas 3079
            _setSubPage(pg->getHandle(), page->getHandle(), left, top, width, height, ani);
198 andreas 3080
        }
3081
    }
3082
 
3083
    pg->show();
3084
}
3085
 
14 andreas 3086
void TPageManager::hideSubPage(const string& name)
3087
{
3088
    DECL_TRACER("TPageManager::hideSubPage(const string& name)");
3089
 
3090
    if (name.empty())
3091
        return;
3092
 
3093
    TPage *page = getPage(mActualPage);
3094
 
3095
    if (!page)
3096
    {
3097
        MSG_ERROR("No active page found! Internal error.");
3098
        return;
3099
    }
3100
 
3101
    TSubPage *pg = getSubPage(name);
3102
 
3103
    if (pg)
3104
    {
3105
        pg->drop();
154 andreas 3106
        page->decZOrder();
14 andreas 3107
    }
3108
}
3109
 
11 andreas 3110
/*
3111
 * Catch the mouse presses and scan all pages and subpages for an element to
3112
 * receive the klick.
3113
 */
10 andreas 3114
void TPageManager::mouseEvent(int x, int y, bool pressed)
3115
{
3116
    DECL_TRACER("TPageManager::mouseEvent(int x, int y, bool pressed)");
3117
 
16 andreas 3118
    TError::clear();
11 andreas 3119
    int realX = x - mFirstLeftPixel;
3120
    int realY = y - mFirstTopPixel;
31 andreas 3121
    MSG_DEBUG("Mouse at " << realX << ", " << realY << ", state " << ((pressed) ? "PRESSED" : "RELEASED") << ", [ " << x << " | " << y << " ]");
43 andreas 3122
#ifdef _SCALE_SKIA_
100 andreas 3123
    if (mScaleFactor != 1.0 && mScaleFactor > 0.0)
26 andreas 3124
    {
3125
        realX = (int)((double)realX / mScaleFactor);
3126
        realY = (int)((double)realY / mScaleFactor);
31 andreas 3127
        MSG_DEBUG("Scaled coordinates: x=" << realX << ", y=" << realY);
26 andreas 3128
    }
43 andreas 3129
#endif
70 andreas 3130
 
154 andreas 3131
    TSubPage *subPage = nullptr;
11 andreas 3132
 
154 andreas 3133
    if (pressed)
3134
        subPage = getCoordMatch(realX, realY);
3135
    else if (!pressed && mLastPagePush)
3136
        subPage = getSubPage(mLastPagePush);
3137
    else
3138
        subPage = getCoordMatch(realX, realY);
3139
 
11 andreas 3140
    if (!subPage)
14 andreas 3141
    {
146 andreas 3142
        Button::TButton *bt = getCoordMatchPage(realX, realY);
40 andreas 3143
 
3144
        if (bt)
3145
        {
3146
            MSG_DEBUG("Button on page " << bt->getButtonIndex() << ": size: left=" << bt->getLeftPosition() << ", top=" << bt->getTopPosition() << ", width=" << bt->getWidth() << ", height=" << bt->getHeight());
71 andreas 3147
 
150 andreas 3148
            if (TConfig::getSystemSoundState())
3149
            {
3150
                TSystemSound sysSound(TConfig::getSystemPath(TConfig::SOUNDS));
71 andreas 3151
 
150 andreas 3152
                if (pressed && _playSound && sysSound.getSystemSoundState())
3153
                    _playSound(sysSound.getTouchFeedbackSound());
3154
            }
3155
 
40 andreas 3156
            bt->doClick(x - bt->getLeftPosition(), y - bt->getTopPosition(), pressed);
3157
        }
3158
 
11 andreas 3159
        return;
14 andreas 3160
    }
11 andreas 3161
 
154 andreas 3162
    MSG_DEBUG("Subpage " << subPage->getNumber() << " [" << subPage->getName() << "]: size: left=" << subPage->getLeft() << ", top=" << subPage->getTop() << ", width=" << subPage->getWidth() << ", height=" << subPage->getHeight());
3163
 
3164
    if (pressed)
3165
        mLastPagePush = subPage->getNumber();
3166
    else
3167
        mLastPagePush = 0;
3168
 
11 andreas 3169
    subPage->doClick(realX - subPage->getLeft(), realY - subPage->getTop(), pressed);
10 andreas 3170
}
11 andreas 3171
 
192 andreas 3172
void TPageManager::inputButtonFinished(ulong handle, const std::string &content)
3173
{
3174
    DECL_TRACER("TPageManager::inputButtonFinished(ulong handle, const std::string &content)");
3175
 
3176
    Button::TButton *bt = findButton(handle);
3177
 
3178
    if (!bt)
3179
    {
3180
        MSG_WARNING("Invalid button handle " << TObject::handleToString(handle));
3181
        return;
3182
    }
3183
 
3184
    bt->setTextOnly(content, -1);
3185
}
3186
 
208 andreas 3187
void TPageManager::setTextToButton(ulong handle, const string& txt, bool redraw)
51 andreas 3188
{
208 andreas 3189
    DECL_TRACER("TPageManager::setTextToButton(ulong handle, const string& txt, bool redraw)");
51 andreas 3190
 
3191
    // First we search for the button the handle points to
3192
    Button::TButton *button = findButton(handle);
3193
 
3194
    if (!button)
3195
    {
3196
        MSG_ERROR("No button with handle " << TObject::handleToString(handle) << " found!");
3197
        return;
3198
    }
3199
 
3200
    // Now we search for all buttons with the same channel and port number
3201
    vector<int> channels;
3202
    channels.push_back(button->getAddressChannel());
193 andreas 3203
    vector<TMap::MAP_T> map = findButtons(button->getAddressPort(), channels);
51 andreas 3204
 
3205
    if (TError::isError() || map.empty())
3206
        return;
3207
 
3208
    // Here we load all buttons found.
3209
    vector<Button::TButton *> buttons = collectButtons(map);
83 andreas 3210
 
3211
    if (buttons.size() > 0)
51 andreas 3212
    {
83 andreas 3213
        vector<Button::TButton *>::iterator mapIter;
3214
        // Finaly we iterate through all found buttons and set the text
118 andreas 3215
        for (mapIter = buttons.begin(); mapIter != buttons.end(); ++mapIter)
83 andreas 3216
        {
3217
            Button::TButton *bt = *mapIter;
51 andreas 3218
 
208 andreas 3219
            if (redraw)
3220
                bt->setText(txt, -1);
3221
            else
3222
                bt->setTextOnly(txt, -1);
83 andreas 3223
        }
51 andreas 3224
    }
3225
}
3226
 
193 andreas 3227
vector<Button::TButton *> TPageManager::collectButtons(vector<TMap::MAP_T>& map)
14 andreas 3228
{
193 andreas 3229
    DECL_TRACER("TPageManager::collectButtons(vector<TMap::MAP_T>& map)");
14 andreas 3230
 
3231
    vector<Button::TButton *> buttons;
83 andreas 3232
 
3233
    if (map.size() == 0)
3234
        return buttons;
3235
 
193 andreas 3236
    vector<TMap::MAP_T>::iterator iter;
14 andreas 3237
 
118 andreas 3238
    for (iter = map.begin(); iter != map.end(); ++iter)
14 andreas 3239
    {
209 andreas 3240
        if (iter->pg < REGULAR_SUBPAGE_START || (iter->pg >= SYSTEM_PAGE_START && iter->pg < SYSTEM_SUBPAGE_START))     // Main page?
14 andreas 3241
        {
3242
            TPage *page;
3243
 
3244
            if ((page = getPage(iter->pg)) == nullptr)
3245
            {
3246
                MSG_TRACE("Page " << iter->pg << ", " << iter->pn << " not found in memory. Reading it ...");
3247
 
3248
                if (!readPage(iter->pg))
3249
                    return buttons;
3250
 
3251
                page = getPage(iter->pg);
3252
            }
3253
 
3254
            Button::TButton *bt = page->getButton(iter->bt);
3255
 
3256
            if (bt)
3257
                buttons.push_back(bt);
3258
        }
3259
        else
3260
        {
3261
            TSubPage *subpage;
3262
 
3263
            if ((subpage = getSubPage(iter->pg)) == nullptr)
3264
            {
3265
                MSG_TRACE("Subpage " << iter->pg << ", " << iter->pn << " not found in memory. Reading it ...");
3266
 
3267
                if (!readSubPage(iter->pg))
3268
                    return buttons;
3269
 
3270
                subpage = getSubPage(iter->pg);
3271
                TPage *page = getActualPage();
3272
 
3273
                if (!page)
3274
                {
3275
                    MSG_ERROR("No actual page loaded!");
3276
                    return buttons;
3277
                }
3278
            }
3279
 
3280
            Button::TButton *bt = subpage->getButton(iter->bt);
3281
 
3282
            if (bt)
3283
                buttons.push_back(bt);
3284
        }
3285
    }
3286
 
3287
    return buttons;
3288
}
3289
 
11 andreas 3290
/****************************************************************************
36 andreas 3291
 * Calls from a Java activity. This is only available for Android OS.
3292
 ****************************************************************************/
182 andreas 3293
#ifdef Q_OS_ANDROID
36 andreas 3294
void TPageManager::initNetworkState()
3295
{
3296
    DECL_TRACER("TPageManager::initNetworkState()");
183 andreas 3297
#ifdef QT5_LINUX
36 andreas 3298
    QAndroidJniObject activity = QtAndroid::androidActivity();
3299
    QAndroidJniObject::callStaticMethod<void>("org/qtproject/theosys/NetworkStatus", "Init", "(Landroid/app/Activity;)V", activity.object());
3300
    activity.callStaticMethod<void>("org/qtproject/theosys/NetworkStatus", "InstallNetworkListener", "()V");
182 andreas 3301
#else
3302
    QJniObject activity = QNativeInterface::QAndroidApplication::context();
3303
    QJniObject::callStaticMethod<void>("org/qtproject/theosys/NetworkStatus", "Init", "(Landroid/app/Activity;)V", activity.object());
3304
    activity.callStaticMethod<void>("org/qtproject/theosys/NetworkStatus", "InstallNetworkListener", "()V");
3305
#endif
36 andreas 3306
}
3307
 
3308
void TPageManager::stopNetworkState()
3309
{
3310
    DECL_TRACER("TPageManager::stopNetworkState()");
183 andreas 3311
#ifdef QT5_LINUX
36 andreas 3312
    QAndroidJniObject::callStaticMethod<void>("org/qtproject/theosys/NetworkStatus", "destroyNetworkListener", "()V");
182 andreas 3313
#else
3314
    QJniObject::callStaticMethod<void>("org/qtproject/theosys/NetworkStatus", "destroyNetworkListener", "()V");
3315
#endif
36 andreas 3316
}
38 andreas 3317
 
3318
void TPageManager::initBatteryState()
3319
{
3320
    DECL_TRACER("TPageManager::initBatteryState()");
183 andreas 3321
#ifdef QT5_LINUX
38 andreas 3322
    QAndroidJniObject activity = QtAndroid::androidActivity();
3323
    QAndroidJniObject::callStaticMethod<void>("org/qtproject/theosys/BatteryState", "Init", "(Landroid/app/Activity;)V", activity.object());
182 andreas 3324
#else
3325
    QJniObject activity = QNativeInterface::QAndroidApplication::context();
3326
    QJniObject::callStaticMethod<void>("org/qtproject/theosys/BatteryState", "Init", "(Landroid/app/Activity;)V", activity.object());
3327
#endif
38 andreas 3328
    activity.callStaticMethod<void>("org/qtproject/theosys/BatteryState", "InstallBatteryListener", "()V");
3329
}
3330
 
61 andreas 3331
void TPageManager::initPhoneState()
3332
{
3333
    DECL_TRACER("TPageManager::initPhoneState()");
183 andreas 3334
#ifdef QT5_LINUX
61 andreas 3335
    QAndroidJniObject activity = QtAndroid::androidActivity();
3336
    QAndroidJniObject::callStaticMethod<void>("org/qtproject/theosys/PhoneCallState", "Init", "(Landroid/app/Activity;)V", activity.object());
182 andreas 3337
#else
3338
    QJniObject activity = QNativeInterface::QAndroidApplication::context();
3339
    QJniObject::callStaticMethod<void>("org/qtproject/theosys/PhoneCallState", "Init", "(Landroid/app/Activity;)V", activity.object());
3340
#endif
61 andreas 3341
    activity.callStaticMethod<void>("org/qtproject/theosys/PhoneCallState", "InstallPhoneListener", "()V");
3342
}
3343
 
38 andreas 3344
void TPageManager::stopBatteryState()
3345
{
3346
    DECL_TRACER("TPageManager::stopBatteryState()");
183 andreas 3347
#ifdef QT5_LINUX
38 andreas 3348
    QAndroidJniObject::callStaticMethod<void>("org/qtproject/theosys/BatteryState", "destroyBatteryListener", "()V");
182 andreas 3349
#else
3350
    QJniObject::callStaticMethod<void>("org/qtproject/theosys/BatteryState", "destroyBatteryListener", "()V");
3351
#endif
38 andreas 3352
}
3353
 
36 andreas 3354
void TPageManager::informTPanelNetwork(jboolean conn, jint level, jint type)
3355
{
250 andreas 3356
    DECL_TRACER("TPageManager::informTPanelNetwork(jboolean conn, jint level, jint type)");
36 andreas 3357
 
3358
    int l = 0;
3359
    string sType;
3360
 
3361
    switch (type)
3362
    {
3363
        case 1: sType = "Wifi"; break;
3364
        case 2: sType = "Mobile"; break;
3365
 
3366
        default:
3367
            sType = "Unknown"; break;
3368
    }
3369
 
3370
    if (conn)
3371
        l = level;
3372
 
93 andreas 3373
    if (mNetState && mNetState != type)     // Has the connection type changed?
3374
    {
3375
        if (gAmxNet)
3376
            gAmxNet->reconnect();
3377
    }
3378
 
3379
    mNetState = type;
3380
 
36 andreas 3381
    MSG_INFO("Connection status: " << (conn ? "Connected" : "Disconnected") << ", level: " << level << ", type: " << sType);
3382
 
83 andreas 3383
    if (mNetCalls.size() > 0)
36 andreas 3384
    {
83 andreas 3385
        std::map<int, std::function<void (int level)> >::iterator iter;
3386
 
3387
        for (iter = mNetCalls.begin(); iter != mNetCalls.end(); ++iter)
3388
            iter->second(l);
36 andreas 3389
    }
3390
}
38 andreas 3391
 
3392
void TPageManager::informBatteryStatus(jint level, jboolean charging, jint chargeType)
3393
{
3394
    DECL_TRACER("TPageManager::informBatteryStatus(jint level, jboolean charging, jint chargeType)");
3395
 
59 andreas 3396
    MSG_INFO("Battery status: level: " << level << ", " << (charging ? "Charging" : "not charging") << ", type: " << chargeType << ", Elements: " << mBatteryCalls.size());
38 andreas 3397
 
83 andreas 3398
    if (mBatteryCalls.size() > 0)
38 andreas 3399
    {
83 andreas 3400
        std::map<int, std::function<void (int, bool, int)> >::iterator iter;
3401
 
3402
        for (iter = mBatteryCalls.begin(); iter != mBatteryCalls.end(); ++iter)
3403
            iter->second(level, charging, chargeType);
38 andreas 3404
    }
3405
}
61 andreas 3406
 
3407
void TPageManager::informPhoneState(bool call, const string &pnumber)
3408
{
3409
    DECL_TRACER("TPageManager::informPhoneState(bool call, const string &pnumber)");
3410
 
3411
    MSG_INFO("Call state: " << (call ? "Call in progress" : "No call") << ", phone number: " << pnumber);
3412
 
3413
    if (!gAmxNet)
3414
    {
3415
        MSG_WARNING("The network manager for the AMX controller is not initialized!");
3416
        return;
3417
    }
3418
}
130 andreas 3419
 
3420
void TPageManager::initOrientation()
3421
{
3422
    DECL_TRACER("TPageManager::initOrientation()");
3423
 
131 andreas 3424
    int rotate = getSettings()->getRotate();
183 andreas 3425
#ifdef QT5_LINUX
130 andreas 3426
    QAndroidJniObject activity = QtAndroid::androidActivity();
131 andreas 3427
    QAndroidJniObject::callStaticMethod<void>("org/qtproject/theosys/Orientation", "Init", "(Landroid/app/Activity;I)V", activity.object(), rotate);
182 andreas 3428
#else
3429
    QJniObject activity = QNativeInterface::QAndroidApplication::context();
3430
    QJniObject::callStaticMethod<void>("org/qtproject/theosys/Orientation", "Init", "(Landroid/app/Activity;I)V", activity.object(), rotate);
3431
#endif
130 andreas 3432
    activity.callStaticMethod<void>("org/qtproject/theosys/Orientation", "InstallOrientationListener", "()V");
3433
}
59 andreas 3434
#endif  // __ANDROID__
247 andreas 3435
#ifdef Q_OS_IOS
3436
void TPageManager::informBatteryStatus(int level, int state)
3437
{
3438
    DECL_TRACER("TPageManager::informBatteryStatus(int level, int state)");
36 andreas 3439
 
247 andreas 3440
    MSG_INFO("Battery status: level: " << level << ", " << state);
3441
 
3442
    if (mBatteryCalls.size() > 0)
3443
    {
3444
        std::map<int, std::function<void (int, int)> >::iterator iter;
3445
 
3446
        for (iter = mBatteryCalls.begin(); iter != mBatteryCalls.end(); ++iter)
3447
            iter->second(level, state);
3448
    }
3449
}
250 andreas 3450
 
3451
void TPageManager::informTPanelNetwork(bool conn, int level, int type)
3452
{
3453
    DECL_TRACER("TPageManager::informTPanelNetwork(bool conn, int level, int type)");
3454
 
3455
    int l = 0;
3456
    string sType;
3457
 
3458
    switch (type)
3459
    {
3460
        case 1: sType = "Ethernet"; break;
3461
        case 2: sType = "Mobile"; break;
3462
        case 3: sType = "WiFi"; break;
3463
        case 4: sType = "Bluetooth"; break;
3464
 
3465
        default:
3466
            sType = "Unknown"; break;
3467
    }
3468
 
3469
    if (conn)
3470
        l = level;
3471
 
3472
    if (mNetState && mNetState != type)     // Has the connection type changed?
3473
    {
3474
        if (gAmxNet)
3475
            gAmxNet->reconnect();
3476
    }
3477
 
3478
    mNetState = type;
3479
 
3480
    MSG_INFO("Connection status: " << (conn ? "Connected" : "Disconnected") << ", level: " << level << ", type: " << sType);
3481
 
3482
    if (mNetCalls.size() > 0)
3483
    {
3484
        std::map<int, std::function<void (int level)> >::iterator iter;
3485
 
3486
        for (iter = mNetCalls.begin(); iter != mNetCalls.end(); ++iter)
3487
            iter->second(l);
3488
    }
3489
}
3490
 
247 andreas 3491
#endif
3492
 
60 andreas 3493
void TPageManager::setButtonCallbacks(Button::TButton *bt)
3494
{
227 andreas 3495
    DECL_TRACER("TPageManager::setButtonCallbacks(Button::TButton *bt)");
3496
 
162 andreas 3497
    if (!bt)
3498
        return;
3499
 
60 andreas 3500
    bt->registerCallback(_displayButton);
3501
    bt->regCallPlayVideo(_callPlayVideo);
3502
    bt->setFonts(mFonts);
3503
    bt->setPalette(mPalette);
3504
}
3505
 
3506
void TPageManager::externalButton(extButtons_t bt, bool checked)
3507
{
3508
    DECL_TRACER("TPageManager::externalButton(extButtons_t bt)");
3509
 
3510
    if (!mExternal)
3511
        return;
3512
 
3513
    EXTBUTTON_t button = mExternal->getButton(bt);
3514
 
3515
    if (button.type == EXT_NOBUTTON)
3516
        return;
3517
 
3518
    if (button.cp && button.ch)
3519
    {
3520
        amx::ANET_SEND scmd;
3521
 
3522
        scmd.device = TConfig::getChannel();
3523
        scmd.port = button.cp;
3524
        scmd.channel = button.ch;
3525
 
3526
        if (checked)
3527
            scmd.MC = 0x0084;   // push button
134 andreas 3528
        else
3529
            scmd.MC = 0x0085;   // release button
60 andreas 3530
 
134 andreas 3531
        MSG_DEBUG("Sending to device <" << scmd.device << ":" << scmd.port << ":0> channel " << scmd.channel << " value 0x" << std::setw(2) << std::setfill('0') << std::hex << scmd.MC << " (" << (checked?"PUSH":"RELEASE") << ")");
60 andreas 3532
 
134 andreas 3533
        if (gAmxNet)
3534
            gAmxNet->sendCommand(scmd);
3535
        else
3536
        {
3537
            MSG_WARNING("Missing global class TAmxNet. Can't send a message!");
3538
        }
60 andreas 3539
    }
3540
}
3541
 
62 andreas 3542
void TPageManager::sendKeyboard(const std::string& text)
3543
{
3544
    DECL_TRACER("TPageManager::sendKeyboard(const std::string& text)");
3545
 
3546
    amx::ANET_SEND scmd;
3547
    scmd.port = 1;
3548
    scmd.channel = 0;
3549
    scmd.msg = UTF8ToCp1250(text);
3550
    scmd.MC = 0x008b;
3551
 
3552
    if (gAmxNet)
3553
        gAmxNet->sendCommand(scmd);
3554
    else
3555
        MSG_WARNING("Missing global class TAmxNet. Can't send message!");
3556
}
3557
 
3558
void TPageManager::sendKeypad(const std::string& text)
3559
{
3560
    DECL_TRACER("TPageManager::sendKeypad(const std::string& text)");
3561
 
3562
    amx::ANET_SEND scmd;
3563
    scmd.port = 1;
3564
    scmd.channel = 0;
3565
    scmd.msg = UTF8ToCp1250(text);
3566
    scmd.MC = 0x008b;
3567
 
3568
    if (gAmxNet)
3569
        gAmxNet->sendCommand(scmd);
3570
    else
3571
        MSG_WARNING("Missing global class TAmxNet. Can't send message!");
3572
}
3573
 
3574
void TPageManager::sendString(uint handle, const std::string& text)
3575
{
3576
    DECL_TRACER("TPageManager::sendString(uint handle, const std::string& text)");
3577
 
3578
    Button::TButton *bt = findButton(handle);
3579
 
3580
    if (!bt)
3581
    {
3582
        MSG_WARNING("Button " << TObject::handleToString(handle) << " not found!");
3583
        return;
3584
    }
3585
 
3586
    amx::ANET_SEND scmd;
3587
    scmd.port = bt->getAddressPort();
3588
    scmd.channel = bt->getAddressChannel();
3589
    scmd.msg = UTF8ToCp1250(text);
3590
    scmd.MC = 0x008b;
3591
 
3592
    if (gAmxNet)
3593
        gAmxNet->sendCommand(scmd);
3594
    else
3595
        MSG_WARNING("Missing global class TAmxNet. Can't send message!");
3596
}
3597
 
134 andreas 3598
void TPageManager::sendGlobalString(const string& text)
3599
{
3600
    DECL_TRACER("TPageManager::sendGlobalString(const string& text)");
3601
 
3602
    if (text.empty() || text.find("-") == string::npos)
3603
        return;
3604
 
3605
    amx::ANET_SEND scmd;
3606
    scmd.port = 1;
3607
    scmd.channel = 0;
3608
    scmd.msg = text;
3609
    scmd.MC = 0x008b;
3610
 
3611
    if (gAmxNet)
3612
        gAmxNet->sendCommand(scmd);
3613
    else
3614
        MSG_WARNING("Missing global class TAmxNet. Can't send message!");
3615
}
3616
 
147 andreas 3617
void TPageManager::sendCommandString(int port, const string& cmd)
3618
{
3619
    DECL_TRACER("TPageManager::sendGlobalString(const string& text)");
3620
 
3621
    if (cmd.empty())
3622
        return;
3623
 
3624
    amx::ANET_SEND scmd;
3625
    scmd.port = port;
3626
    scmd.channel = 0;
3627
    scmd.msg = cmd;
3628
    scmd.MC = 0x008c;
3629
 
3630
    if (gAmxNet)
3631
        gAmxNet->sendCommand(scmd);
3632
    else
3633
        MSG_WARNING("Missing global class TAmxNet. Can't send message!");
3634
}
3635
 
123 andreas 3636
void TPageManager::sendPHNcommand(const std::string& cmd)
3637
{
3638
    DECL_TRACER("TPageManager::sendPHNcommand(const std::string& cmd)");
3639
 
3640
    amx::ANET_SEND scmd;
144 andreas 3641
    scmd.port = mTSettings->getSettings().voipCommandPort;
123 andreas 3642
    scmd.channel = TConfig::getChannel();
3643
    scmd.msg = "^PHN-" + cmd;
127 andreas 3644
    scmd.MC = 0x008c;
3645
    MSG_DEBUG("Sending PHN command: ^PHN-" << cmd);
123 andreas 3646
 
3647
    if (gAmxNet)
3648
        gAmxNet->sendCommand(scmd);
3649
    else
3650
        MSG_WARNING("Missing global class TAmxNet. Can't send ^PHN command!");
3651
}
3652
 
111 andreas 3653
void TPageManager::sendKeyStroke(char key)
3654
{
3655
    DECL_TRACER("TPageManager::sendKeyStroke(char key)");
3656
 
3657
    if (!key)
3658
        return;
3659
 
3660
    char msg[2];
3661
    msg[0] = key;
3662
    msg[1] = 0;
3663
 
3664
    amx::ANET_SEND scmd;
3665
    scmd.port = 1;
3666
    scmd.channel = 0;
3667
    scmd.msg.assign(msg);
127 andreas 3668
    scmd.MC = 0x008c;
111 andreas 3669
 
3670
    if (gAmxNet)
3671
        gAmxNet->sendCommand(scmd);
3672
    else
3673
        MSG_WARNING("Missing global class TAmxNet. Can't send message!");
3674
}
3675
 
110 andreas 3676
/**
3677
 * Sending a custom event is identical in all cases. Because of this I
3678
 * implemented this method to send a custom event. This is called in all cases
3679
 * where a ?XXX command is received.
3680
 *
3681
 * @param value1    The instance of the button.
3682
 * @param value2    The value of a numeric request or the length of the string.
3683
 * @param value3    Always 0
3684
 * @param msg       In case of a string this contains the string.
3685
 * @param evType    This is the event type, a number between 1001 and 1099.
3686
 * @param cp        Channel port of button.
3687
 * @param cn        Channel number. of button.
3688
 *
3689
 * @return If all parameters are valid it returns TRUE.
3690
 */
3691
bool TPageManager::sendCustomEvent(int value1, int value2, int value3, const string& msg, int evType, int cp, int cn)
3692
{
3693
    DECL_TRACER("TPageManager::sendCustomEvent(int value1, int value2, int value3, const string& msg, int evType)");
3694
 
3695
    if (value1 < 1)
3696
        return false;
3697
 
3698
    amx::ANET_SEND scmd;
3699
    scmd.port = cp;
3700
    scmd.channel = cn;
3701
    scmd.ID = scmd.channel;
3702
    scmd.flag = 0;
3703
    scmd.type = evType;
3704
    scmd.value1 = value1;   // instance
3705
    scmd.value2 = value2;
3706
    scmd.value3 = value3;
3707
    scmd.msg = msg;
3708
 
3709
    if (!msg.empty())
3710
        scmd.dtype = 0x0001;// Char array
3711
 
3712
    scmd.MC = 0x008d;       // custom event
3713
 
3714
    if (gAmxNet)
3715
        gAmxNet->sendCommand(scmd);
3716
    else
3717
        MSG_WARNING("Missing global class TAmxNet. Can't send message!");
3718
 
3719
    return true;
3720
}
129 andreas 3721
#ifndef _NOSIP_
127 andreas 3722
string TPageManager::sipStateToString(TSIPClient::SIP_STATE_t s)
3723
{
3724
    DECL_TRACER("TPageManager::sipStateToString(TSIPClient::SIP_STATE_t s)");
3725
 
3726
    switch(s)
3727
    {
3728
        case TSIPClient::SIP_CONNECTED:     return "CONNECTED";
3729
        case TSIPClient::SIP_DISCONNECTED:  return "DISCONNECTED";
3730
        case TSIPClient::SIP_HOLD:          return "HOLD";
3731
        case TSIPClient::SIP_RINGING:       return "RINGING";
3732
        case TSIPClient::SIP_TRYING:        return "TRYING";
3733
 
3734
        default:
3735
            return "IDLE";
3736
    }
3737
 
3738
    return "IDLE";
3739
}
129 andreas 3740
#endif
134 andreas 3741
void TPageManager::sendOrientation()
3742
{
3743
    string ori;
3744
 
3745
    switch(mOrientation)
3746
    {
3747
        case O_PORTRAIT:            ori = "DeviceOrientationPortrait"; break;
3748
        case O_REVERSE_PORTRAIT:    ori = "DeviceOrientationPortraitUpsideDown"; break;
3749
        case O_LANDSCAPE:           ori = "DeviceOrientationLandscapeLeft"; break;
3750
        case O_REVERSE_LANDSCAPE:   ori = "DeviceOrientationLandscapeRight"; break;
3751
        case O_FACE_UP:             ori = "DeviceOrientationFaceUp"; break;
3752
        case O_FACE_DOWN:           ori = "DeviceOrientationFaceDown"; break;
3753
        default:
3754
            return;
3755
    }
3756
 
3757
    sendGlobalString("TPCACC-" + ori);
3758
}
3759
 
153 andreas 3760
void TPageManager::onSwipeEvent(TPageManager::SWIPES sw)
3761
{
3762
    DECL_TRACER("TPageManager::onSwipeEvent(TPageManager::SWIPES sw)");
3763
 
3764
    // Swipes are defined in "external".
3765
    if (!mExternal)
3766
        return;
3767
 
3768
    extButtons_t eBt;
3769
    string dbg;
3770
 
3771
    switch(sw)
3772
    {
3773
        case SW_LEFT:   eBt = EXT_GESTURE_LEFT; dbg.assign("LEFT"); break;
3774
        case SW_RIGHT:  eBt = EXT_GESTURE_RIGHT; dbg.assign("RIGHT"); break;
3775
        case SW_UP:     eBt = EXT_GESTURE_UP; dbg.assign("UP"); break;
3776
        case SW_DOWN:   eBt = EXT_GESTURE_DOWN; dbg.assign("DOWN"); break;
3777
 
3778
        default:
3779
            return;
3780
    }
3781
 
3782
    int pgNum = getActualPageNumber();
3783
    EXTBUTTON_t bt = mExternal->getButton(pgNum, eBt);
3784
 
3785
    if (bt.bi == 0)
3786
        return;
3787
 
3788
    MSG_DEBUG("Received swipe " << dbg << " event for page " << pgNum << " on button " << bt.bi << " \"" << bt.na << "\"");
3789
 
3790
    if (!bt.cm.empty() && bt.co == 0)           // Feed command to ourself?
3791
    {                                           // Yes, then feed it into command queue.
3792
        MSG_DEBUG("Button has a self feed command");
3793
 
3794
        int channel = TConfig::getChannel();
3795
        int system = TConfig::getSystem();
3796
 
3797
        amx::ANET_COMMAND cmd;
3798
        cmd.MC = 0x000c;
3799
        cmd.device1 = channel;
3800
        cmd.port1 = bt.ap;
3801
        cmd.system = system;
3802
        cmd.data.message_string.device = channel;
3803
        cmd.data.message_string.port = bt.ap;  // Must be the address port of button
3804
        cmd.data.message_string.system = system;
3805
        cmd.data.message_string.type = 1;   // 8 bit char string
3806
 
3807
        vector<string>::iterator iter;
3808
 
3809
        for (iter = bt.cm.begin(); iter != bt.cm.end(); ++iter)
3810
        {
3811
            cmd.data.message_string.length = iter->length();
3812
            memset(&cmd.data.message_string.content, 0, sizeof(cmd.data.message_string.content));
3813
            strncpy((char *)&cmd.data.message_string.content, iter->c_str(), sizeof(cmd.data.message_string.content));
3814
            doCommand(cmd);
3815
        }
3816
    }
3817
    else if (!bt.cm.empty())
3818
    {
3819
        MSG_DEBUG("Button sends a command on port " << bt.co);
3820
 
3821
        vector<string>::iterator iter;
3822
 
3823
        for (iter = bt.cm.begin(); iter != bt.cm.end(); ++iter)
3824
            sendCommandString(bt.co, *iter);
3825
    }
3826
}
3827
 
36 andreas 3828
/****************************************************************************
11 andreas 3829
 * The following functions implements one of the commands the panel accepts.
3830
 ****************************************************************************/
43 andreas 3831
 
3832
/**
3833
 * This is a special function handling the progress bars when the files of the
3834
 * panel are updated. Instead of simply displaying a ready page, it fakes one
3835
 * with the actual dimensions of the main page. This is possible, because we've
3836
 * always a main page even if the panel is started for the first time.
3837
 */
3838
void TPageManager::doFTR(int port, vector<int>& channels, vector<string>& pars)
23 andreas 3839
{
43 andreas 3840
    DECL_TRACER("TPageManager::doFTR(int, vector<int>&, vector<string>& pars)");
14 andreas 3841
 
23 andreas 3842
    if (pars.empty())
3843
    {
3844
        MSG_WARNING("Command #FTR needs at least 1 parameter! Ignoring command.");
3845
        return;
3846
    }
3847
 
96 andreas 3848
    if (TStreamError::checkFilter(HLOG_DEBUG))
23 andreas 3849
    {
96 andreas 3850
        for (size_t i = 0; i < pars.size(); i++)
3851
        {
3852
            MSG_DEBUG("[" << i << "]: " << pars.at(i));
3853
        }
23 andreas 3854
    }
43 andreas 3855
 
3856
    if (pars.at(0).compare("START") == 0)
3857
    {
3858
        // Here we have to drop all pages and subpages first and then display
3859
        // the faked page with the progress bars.
3860
        MSG_DEBUG("Starting file transfer ...");
3861
        doPPX(port, channels, pars);
3862
        TPage *pg = getPage("_progress");
3863
 
3864
        if (!pg)
3865
        {
3866
            if (!readPage("_progress"))
3867
            {
3868
                MSG_ERROR("Error creating the system page _progress!");
3869
                return;
3870
            }
3871
 
3872
            pg = getPage("_progress");
3873
 
3874
            if (!pg)
3875
            {
3876
                MSG_ERROR("Error getting system page _progress!");
3877
                return;
3878
            }
3879
        }
3880
 
3881
        pg->setFonts(mFonts);
3882
        pg->registerCallback(_setBackground);
3883
        pg->regCallPlayVideo(_callPlayVideo);
3884
 
3885
        if (!pg || !_setPage || !mTSettings)
3886
            return;
3887
 
3888
        int width, height;
217 andreas 3889
        width = mTSettings->getWidth();
43 andreas 3890
        height = mTSettings->getHeight();
3891
#ifdef _SCALE_SKIA_
3892
        if (mScaleFactor != 1.0)
3893
        {
3894
            width = (int)((double)width * mScaleFactor);
3895
            height = (int)((double)height * mScaleFactor);
3896
        }
3897
#endif
3898
        _setPage((pg->getNumber() << 16) & 0xffff0000, width, height);
3899
        pg->show();
3900
        MSG_DEBUG("Page _progress on screen");
3901
    }
3902
    else if (pars.at(0).compare("SYNC") == 0)
3903
    {
3904
        TPage *pg = getPage("_progress");
3905
 
3906
        if (!pg)
3907
        {
3908
            MSG_ERROR("Page _progress not found!");
3909
            return;
3910
        }
3911
 
3912
        Button::TButton *bt = pg->getButton(1);   // Line 1
3913
 
3914
        if (!bt)
3915
        {
3916
            MSG_ERROR("Button 160 of page _progress not found!");
3917
            return;
3918
        }
3919
 
3920
        bt->setText(pars.at(2), 0);
3921
        bt->show();
3922
    }
3923
    else if (pars.at(0).compare("FTRSTART") == 0)
3924
    {
3925
        TPage *pg = getPage("_progress");
3926
 
3927
        if (!pg)
3928
        {
3929
            MSG_ERROR("Page _progress not found!");
3930
            return;
3931
        }
3932
 
3933
        Button::TButton *bt1 = pg->getButton(1);   // Line 1
3934
        Button::TButton *bt2 = pg->getButton(2);   // Line 2
3935
        Button::TButton *bt3 = pg->getButton(3);   // Bargraph 1
3936
        Button::TButton *bt4 = pg->getButton(4);   // Bargraph 2
3937
 
3938
        if (!bt1 || !bt2 || !bt3 || !bt4)
3939
        {
3940
            MSG_ERROR("Buttons of page _progress not found!");
3941
            return;
3942
        }
3943
 
3944
        bt1->setText("Transfering files ...", 0);
3945
        bt1->show();
3946
        bt2->setText(pars.at(3), 0);
3947
        bt2->show();
3948
        bt3->drawBargraph(0, atoi(pars.at(1).c_str()), true);
3949
        bt4->drawBargraph(0, atoi(pars.at(2).c_str()), true);
3950
    }
3951
    else if (pars.at(0).compare("FTRPART") == 0)
3952
    {
3953
        TPage *pg = getPage("_progress");
3954
 
3955
        if (!pg)
3956
        {
3957
            MSG_ERROR("Page _progress not found!");
3958
            return;
3959
        }
3960
 
3961
        Button::TButton *bt = pg->getButton(4);   // Bargraph 2
3962
 
3963
        if (!bt)
3964
        {
3965
            MSG_ERROR("Buttons of page _progress not found!");
3966
            return;
3967
        }
3968
 
3969
        bt->drawBargraph(0, atoi(pars.at(2).c_str()), true);
3970
    }
3971
    else if (pars.at(0).compare("END") == 0)
3972
    {
3973
        MSG_TRACE("End of file transfer reached.");
44 andreas 3974
 
155 andreas 3975
        // To make sure the new surface will not be deleted and replaced by the
3976
        // default build in surface, we must delete the "virgin" marker first.
3977
        // This is a file called <project path>/.system.
3978
        string virgin = TConfig::getProjectPath() + "/.system";
3979
        remove(virgin.c_str());     // Because this file may not exist we don't care about the result code.
3980
 
44 andreas 3981
        if (_resetSurface)
3982
            _resetSurface();
3983
        else
3984
        {
3985
            MSG_WARNING("Missing callback function \"resetSurface\"!");
3986
        }
43 andreas 3987
    }
23 andreas 3988
}
3989
 
22 andreas 3990
void TPageManager::doON(int port, vector<int>&, vector<string>& pars)
14 andreas 3991
{
3992
    DECL_TRACER("TPageManager::doON(int port, vector<int>& channels, vector<string>& pars)");
3993
 
3994
    if (pars.empty())
3995
    {
3996
        MSG_WARNING("Command ON needs 1 parameter! Ignoring command.");
3997
        return;
3998
    }
3999
 
16 andreas 4000
    TError::clear();
14 andreas 4001
    int c = atoi(pars[0].c_str());
4002
 
4003
    if (c <= 0)
4004
    {
4005
        MSG_WARNING("Invalid channel " << c << "! Ignoring command.");
4006
        return;
4007
    }
4008
 
4009
    vector<int> chans = { c };
193 andreas 4010
    vector<TMap::MAP_T> map = findButtons(port, chans, TMap::TYPE_CM);
14 andreas 4011
 
4012
    if (TError::isError() || map.empty())
4013
        return;
4014
 
4015
    vector<Button::TButton *> buttons = collectButtons(map);
4016
 
83 andreas 4017
    if (buttons.size() > 0)
14 andreas 4018
    {
83 andreas 4019
        vector<Button::TButton *>::iterator mapIter;
14 andreas 4020
 
118 andreas 4021
        for (mapIter = buttons.begin(); mapIter != buttons.end(); ++mapIter)
83 andreas 4022
        {
4023
            Button::TButton *bt = *mapIter;
4024
 
195 andreas 4025
            if (bt->getButtonType() == GENERAL)
83 andreas 4026
                bt->setActive(1);
4027
        }
14 andreas 4028
    }
4029
}
4030
 
22 andreas 4031
void TPageManager::doOFF(int port, vector<int>&, vector<string>& pars)
14 andreas 4032
{
4033
    DECL_TRACER("TPageManager::doOFF(int port, vector<int>& channels, vector<string>& pars)");
4034
 
4035
    if (pars.empty())
4036
    {
4037
        MSG_WARNING("Command OFF needs 1 parameter! Ignoring command.");
4038
        return;
4039
    }
4040
 
16 andreas 4041
    TError::clear();
14 andreas 4042
    int c = atoi(pars[0].c_str());
4043
 
4044
    if (c <= 0)
4045
    {
4046
        MSG_WARNING("Invalid channel " << c << "! Ignoring command.");
4047
        return;
4048
    }
4049
 
4050
    vector<int> chans = { c };
193 andreas 4051
    vector<TMap::MAP_T> map = findButtons(port, chans, TMap::TYPE_CM);
14 andreas 4052
 
4053
    if (TError::isError() || map.empty())
4054
        return;
4055
 
4056
    vector<Button::TButton *> buttons = collectButtons(map);
4057
 
83 andreas 4058
    if (buttons.size() > 0)
14 andreas 4059
    {
83 andreas 4060
        vector<Button::TButton *>::iterator mapIter;
14 andreas 4061
 
118 andreas 4062
        for (mapIter = buttons.begin(); mapIter != buttons.end(); ++mapIter)
83 andreas 4063
        {
4064
            Button::TButton *bt = *mapIter;
4065
 
195 andreas 4066
            if (bt->getButtonType() == GENERAL)
83 andreas 4067
                bt->setActive(0);
4068
        }
14 andreas 4069
    }
4070
}
4071
 
22 andreas 4072
void TPageManager::doLEVEL(int port, vector<int>&, vector<string>& pars)
15 andreas 4073
{
4074
    DECL_TRACER("TPageManager::doLEVEL(int port, vector<int>& channels, vector<string>& pars)");
4075
 
4076
    if (pars.size() < 2)
4077
    {
4078
        MSG_WARNING("Command LEVEL needs 2 parameters! Ignoring command.");
4079
        return;
4080
    }
4081
 
16 andreas 4082
    TError::clear();
15 andreas 4083
    int c = atoi(pars[0].c_str());
4084
    int level = atoi(pars[1].c_str());
4085
 
4086
    if (c <= 0)
4087
    {
4088
        MSG_WARNING("Invalid channel " << c << "! Ignoring command.");
4089
        return;
4090
    }
4091
 
4092
    vector<int> chans = { c };
193 andreas 4093
    vector<TMap::MAP_T> map = findBargraphs(port, chans);
15 andreas 4094
 
4095
    if (TError::isError() || map.empty())
4096
    {
4097
        MSG_WARNING("No bargraphs found!");
4098
        return;
4099
    }
4100
 
4101
    vector<Button::TButton *> buttons = collectButtons(map);
4102
 
83 andreas 4103
    if (buttons.size() > 0)
15 andreas 4104
    {
83 andreas 4105
        vector<Button::TButton *>::iterator mapIter;
15 andreas 4106
 
118 andreas 4107
        for (mapIter = buttons.begin(); mapIter != buttons.end(); ++mapIter)
15 andreas 4108
        {
83 andreas 4109
            Button::TButton *bt = *mapIter;
4110
 
195 andreas 4111
            if (bt->getButtonType() == BARGRAPH)
83 andreas 4112
                bt->drawBargraph(bt->getActiveInstance(), level);
195 andreas 4113
            else if (bt->getButtonType() == MULTISTATE_BARGRAPH)
83 andreas 4114
            {
4115
                int state = (int)((double)bt->getStateCount() / (double)(bt->getRangeHigh() - bt->getRangeLow()) * (double)level);
4116
                bt->setActive(state);
4117
            }
15 andreas 4118
        }
4119
    }
4120
}
4121
 
22 andreas 4122
void TPageManager::doBLINK(int, vector<int>&, vector<string>& pars)
15 andreas 4123
{
4124
    DECL_TRACER("TPageManager::doBLINK(int port, vector<int>& channels, vector<string>& pars)");
4125
 
4126
    if (pars.size() < 4)
4127
    {
4128
        MSG_WARNING("Command BLINK expects 4 parameters! Command ignored.");
4129
        return;
4130
    }
4131
 
16 andreas 4132
    TError::clear();
15 andreas 4133
    vector<int> sysButtons = { 141, 142, 143, 151, 152, 153, 154, 155, 156, 157, 158 };
193 andreas 4134
    vector<TMap::MAP_T> map = findButtons(0, sysButtons);
15 andreas 4135
 
4136
    if (TError::isError() || map.empty())
4137
    {
4138
        MSG_WARNING("No system buttons found.");
4139
        return;
4140
    }
4141
 
4142
    vector<Button::TButton *> buttons = collectButtons(map);
4143
    vector<Button::TButton *>::iterator mapIter;
4144
 
4145
    for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
4146
    {
4147
        Button::TButton *bt = *mapIter;
4148
        bt->setActive(0);
4149
    }
4150
}
4151
 
162 andreas 4152
/**
4153
 * Send the version of the panel to the NetLinx. This is the real application
4154
 * version.
4155
 */
127 andreas 4156
void TPageManager::doVER(int, vector<int>&, vector<string>&)
4157
{
4158
    DECL_TRACER("TPageManager::doVER(int, vector<int>&, vector<string>&)");
4159
 
4160
    amx::ANET_SEND scmd;
4161
    scmd.port = 1;
4162
    scmd.channel = 0;
4163
    scmd.msg.assign(string("^VER-")+VERSION_STRING());
4164
    scmd.MC = 0x008c;
4165
 
4166
    if (gAmxNet)
4167
        gAmxNet->sendCommand(scmd);
4168
    else
4169
        MSG_WARNING("Missing global class TAmxNet. Can't send message!");
4170
}
4171
 
162 andreas 4172
/**
4173
 * Returns the user name used to connect to a SIP server. An empty string is
4174
 * returned if there is no user defined.
4175
 */
127 andreas 4176
void TPageManager::doWCN(int, vector<int>&, vector<string>&)
4177
{
4178
    DECL_TRACER("TPageManager::doWCN(int, vector<int>&, vector<string>&)");
4179
 
4180
    if (!TConfig::getSIPstatus())
4181
        return;
4182
 
4183
    amx::ANET_SEND scmd;
4184
    scmd.port = 1;
4185
    scmd.channel = 0;
4186
    scmd.msg.assign("^WCN-" + TConfig::getSIPuser());
4187
    scmd.MC = 0x008c;
4188
 
4189
    if (gAmxNet)
4190
        gAmxNet->sendCommand(scmd);
4191
    else
4192
        MSG_WARNING("Missing global class TAmxNet. Can't send message!");
4193
}
4194
 
14 andreas 4195
/**
147 andreas 4196
 * Flip to specified page using the named animation.
4197
 * FIXME: Implement animation for pages.
4198
 */
4199
void TPageManager::doAFP(int, vector<int>&, vector<string>& pars)
4200
{
4201
    DECL_TRACER("TPageManager::doAFP(int, vector<int>&, vector<string>& pars)");
4202
 
4203
    if (pars.size() < 4)
4204
    {
4205
        MSG_ERROR("Less than 4 parameters!");
4206
        return;
4207
    }
4208
 
4209
    TError::clear();
4210
    string pname = pars[0];
4211
//    string ani = pars[1];
4212
//    int origin = atoi(pars[2].c_str());
4213
//    int duration = atoi(pars[3].c_str());
4214
 
4215
    // FIXME: Animation of pages is currently not implemented.
4216
 
4217
    if (!pname.empty())
4218
        setPage(pname);
4219
    else if (mPreviousPage)
4220
        setPage(mPreviousPage);
4221
}
4222
 
4223
/**
14 andreas 4224
 * Add a specific popup page to a specified popup group if it does not already
4225
 * exist. If the new popup is added to a group which has a popup displayed on
4226
 * the current page along with the new pop-up, the displayed popup will be
4227
 * hidden and the new popup will be displayed.
4228
 */
22 andreas 4229
void TPageManager::doAPG(int, std::vector<int>&, std::vector<std::string>& pars)
11 andreas 4230
{
4231
    DECL_TRACER("TPageManager::doAPG(int port, std::vector<int>& channels, std::vector<std::string>& pars)");
4232
 
4233
    if (pars.size() < 2)
4234
    {
4235
        MSG_ERROR("Less than 2 parameters!");
4236
        return;
4237
    }
4238
 
16 andreas 4239
    TError::clear();
11 andreas 4240
    closeGroup(pars[1]);
14 andreas 4241
 
96 andreas 4242
    TPage *page = nullptr;
4243
    TSubPage *subPage = deliverSubPage(pars[0], &page);
14 andreas 4244
 
11 andreas 4245
    if (!subPage)
4246
    {
4247
        MSG_ERROR("Subpage " << pars[0] << " couldn't either found or created!");
4248
        return;
4249
    }
4250
 
162 andreas 4251
    if (!page)
4252
    {
4253
        MSG_ERROR("There seems to be no page for subpage " << pars[0]);
4254
        return;
4255
    }
4256
 
152 andreas 4257
    page->addSubPage(subPage);
11 andreas 4258
    subPage->setGroup(pars[1]);
14 andreas 4259
    subPage->setZOrder(page->getNextZOrder());
152 andreas 4260
    MSG_DEBUG("Setting new Z-order " << page->getActZOrder() << " on page " << page->getName());
11 andreas 4261
    subPage->show();
4262
}
4263
 
14 andreas 4264
/**
4265
 * Clear all popup pages from specified popup group.
4266
 */
22 andreas 4267
void TPageManager::doCPG(int, std::vector<int>&, std::vector<std::string>& pars)
11 andreas 4268
{
4269
    DECL_TRACER("TPageManager::doCPG(int port, std::vector<int>& channels, std::vector<std::string>& pars)");
4270
 
4271
    if (pars.size() < 1)
4272
    {
4273
        MSG_ERROR("Expecting 1 parameter but got only 1!");
4274
        return;
4275
    }
4276
 
16 andreas 4277
    TError::clear();
11 andreas 4278
    vector<SUBPAGELIST_T> pageList = mPageList->getSupPageList();
4279
 
83 andreas 4280
    if (pageList.size() > 0)
11 andreas 4281
    {
83 andreas 4282
        vector<SUBPAGELIST_T>::iterator pgIter;
4283
 
4284
        for (pgIter = pageList.begin(); pgIter != pageList.end(); pgIter++)
11 andreas 4285
        {
83 andreas 4286
            if (pgIter->group.compare(pars[0]) == 0)
4287
            {
4288
                pgIter->group.clear();
4289
                TSubPage *pg = getSubPage(pgIter->pageID);
11 andreas 4290
 
83 andreas 4291
                if (pg)
4292
                    pg->setGroup(pgIter->group);
4293
            }
11 andreas 4294
        }
4295
    }
4296
}
4297
 
14 andreas 4298
/**
4299
 * Delete a specific popup page from specified popup group if it exists.
4300
 */
22 andreas 4301
void TPageManager::doDPG(int, std::vector<int>&, std::vector<std::string>& pars)
11 andreas 4302
{
4303
    DECL_TRACER("TPageManager::doDPG(int port, std::vector<int>& channels, std::vector<std::string>& pars)");
4304
 
4305
    if (pars.size() < 2)
4306
    {
4307
        MSG_ERROR("Less than 2 parameters!");
4308
        return;
4309
    }
4310
 
16 andreas 4311
    TError::clear();
11 andreas 4312
    SUBPAGELIST_T listPg = findSubPage(pars[0]);
4313
 
4314
    if (!listPg.isValid)
4315
        return;
4316
 
4317
    if (listPg.group.compare(pars[1]) == 0)
4318
    {
4319
        listPg.group.clear();
4320
        TSubPage *pg = getSubPage(listPg.pageID);
4321
 
4322
        if (pg)
4323
            pg->setGroup(listPg.group);
4324
    }
4325
}
4326
 
14 andreas 4327
/**
15 andreas 4328
 * Set the hide effect for the specified popup page to the named hide effect.
4329
 */
22 andreas 4330
void TPageManager::doPHE(int, vector<int>&, vector<string>& pars)
15 andreas 4331
{
4332
    DECL_TRACER("TPageManager::doPHE(int port, vector<int>& channels, vector<string>& pars)");
4333
 
4334
    if (pars.size() < 2)
4335
    {
4336
        MSG_ERROR("Less than 2 parameters!");
4337
        return;
4338
    }
4339
 
16 andreas 4340
    TError::clear();
96 andreas 4341
    TSubPage *pg = deliverSubPage(pars[0]);
15 andreas 4342
 
4343
    if (!pg)
96 andreas 4344
        return;
15 andreas 4345
 
162 andreas 4346
    if (strCaseCompare(pars[1], "fade") == 0)
15 andreas 4347
        pg->setHideEffect(SE_FADE);
162 andreas 4348
    else if (strCaseCompare(pars[1], "slide to left") == 0)
15 andreas 4349
        pg->setHideEffect(SE_SLIDE_LEFT);
162 andreas 4350
    else if (strCaseCompare(pars[1], "slide to right") == 0)
15 andreas 4351
        pg->setHideEffect(SE_SLIDE_RIGHT);
162 andreas 4352
    else if (strCaseCompare(pars[1], "slide to top") == 0)
15 andreas 4353
        pg->setHideEffect(SE_SLIDE_TOP);
162 andreas 4354
    else if (strCaseCompare(pars[1], "slide to bottom") == 0)
15 andreas 4355
        pg->setHideEffect(SE_SLIDE_BOTTOM);
162 andreas 4356
    else if (strCaseCompare(pars[1], "slide to left fade") == 0)
15 andreas 4357
        pg->setHideEffect(SE_SLIDE_LEFT_FADE);
162 andreas 4358
    else if (strCaseCompare(pars[1], "slide to right fade") == 0)
15 andreas 4359
        pg->setHideEffect(SE_SLIDE_RIGHT_FADE);
162 andreas 4360
    else if (strCaseCompare(pars[1], "slide to top fade") == 0)
15 andreas 4361
        pg->setHideEffect(SE_SLIDE_TOP_FADE);
162 andreas 4362
    else if (strCaseCompare(pars[1], "slide to bottom fade") == 0)
15 andreas 4363
        pg->setHideEffect(SE_SLIDE_BOTTOM_FADE);
4364
    else
4365
        pg->setHideEffect(SE_NONE);
4366
}
4367
 
4368
/**
4369
 * Set the hide effect position. Only 1 coordinate is ever needed for an effect;
4370
 * however, the command will specify both. This command sets the location at
4371
 * which the effect will end at.
4372
 */
22 andreas 4373
void TPageManager::doPHP(int, vector<int>&, vector<string>& pars)
15 andreas 4374
{
4375
    DECL_TRACER("TPageManager::doPHP(int port, vector<int>& channels, vector<string>& pars)");
4376
 
4377
    if (pars.size() < 2)
4378
    {
4379
        MSG_ERROR("Less than 2 parameters!");
4380
        return;
4381
    }
4382
 
16 andreas 4383
    TError::clear();
15 andreas 4384
    size_t pos = pars[1].find(",");
4385
    int x, y;
4386
 
4387
    if (pos == string::npos)
4388
    {
4389
        x = atoi(pars[1].c_str());
4390
        y = 0;
4391
    }
4392
    else
4393
    {
4394
        x = atoi(pars[1].substr(0, pos).c_str());
4395
        y = atoi(pars[1].substr(pos+1).c_str());
4396
    }
4397
 
96 andreas 4398
    TSubPage *pg = deliverSubPage(pars[0]);
15 andreas 4399
 
4400
    if (!pg)
96 andreas 4401
        return;
15 andreas 4402
 
4403
    pg->setHideEndPosition(x, y);
4404
}
4405
 
4406
/**
4407
 * Set the hide effect time for the specified popup page.
4408
 */
22 andreas 4409
void TPageManager::doPHT(int, vector<int>&, vector<string>& pars)
15 andreas 4410
{
4411
    DECL_TRACER("TPageManager::doPHT(int port, vector<int>& channels, vector<string>& pars)");
4412
 
4413
    if (pars.size() < 2)
4414
    {
4415
        MSG_ERROR("Less than 2 parameters!");
4416
        return;
4417
    }
4418
 
16 andreas 4419
    TError::clear();
96 andreas 4420
    TSubPage *pg = deliverSubPage(pars[0]);
15 andreas 4421
 
4422
    if (!pg)
96 andreas 4423
        return;
15 andreas 4424
 
4425
    pg->setHideTime(atoi(pars[1].c_str()));
4426
}
4427
 
4428
/**
14 andreas 4429
 * Close all popups on a specified page. If the page name is empty, the current
4430
 * page is used. Same as the ’Clear Page’ command in TPDesign4.
4431
 */
22 andreas 4432
void TPageManager::doPPA(int, std::vector<int>&, std::vector<std::string>& pars)
11 andreas 4433
{
4434
    DECL_TRACER("TPageManager::doPPA(int port, std::vector<int>& channels, std::vector<std::string>& pars)");
4435
 
16 andreas 4436
    TError::clear();
11 andreas 4437
    TPage *pg;
4438
 
4439
    if (pars.size() == 0)
4440
        pg = getPage(mActualPage);
4441
    else
4442
        pg = getPage(pars[0]);
4443
 
4444
    if (!pg)
4445
        return;
4446
 
12 andreas 4447
    pg->drop();
14 andreas 4448
    pg->resetZOrder();
11 andreas 4449
}
4450
 
14 andreas 4451
/**
4452
 * Deactivate a specific popup page on either a specified page or the current
4453
 * page. If the page name is empty, the current page is used. If the popup page
4454
 * is part of a group, the whole group is deactivated. This command works in
4455
 * the same way as the ’Hide Popup’ command in TPDesign4.
4456
 */
22 andreas 4457
void TPageManager::doPPF(int, std::vector<int>&, std::vector<std::string>& pars)
12 andreas 4458
{
4459
    DECL_TRACER("TPageManager::doPPF(int port, std::vector<int>& channels, std::vector<std::string>& pars)");
4460
 
4461
    if (pars.size() < 1)
4462
    {
4463
        MSG_ERROR("At least 1 parameter is expected!");
4464
        return;
4465
    }
4466
 
16 andreas 4467
    TError::clear();
14 andreas 4468
    hideSubPage(pars[0]);
12 andreas 4469
}
4470
 
14 andreas 4471
/**
4472
 * Toggle a specific popup page on either a specified page or the current page.
4473
 * If the page name is empty, the current page is used. Toggling refers to the
4474
 * activating/deactivating (On/Off) of a popup page. This command works in the
4475
 * same way as the ’Toggle Popup’ command in TPDesign4.
4476
 */
22 andreas 4477
void TPageManager::doPPG(int, std::vector<int>&, std::vector<std::string>& pars)
12 andreas 4478
{
4479
    DECL_TRACER("TPageManager::doPPG(int port, std::vector<int>& channels, std::vector<std::string>& pars)");
14 andreas 4480
 
12 andreas 4481
    if (pars.size() < 1)
4482
    {
4483
        MSG_ERROR("At least 1 parameter is expected!");
4484
        return;
4485
    }
4486
 
16 andreas 4487
    TError::clear();
14 andreas 4488
    TPage *page = getPage(mActualPage);
4489
 
4490
    if (!page)
4491
    {
4492
        MSG_ERROR("No active page found! Internal error.");
4493
        return;
4494
    }
4495
 
12 andreas 4496
    TSubPage *pg = getSubPage(pars[0]);
14 andreas 4497
 
12 andreas 4498
    if (!pg)
4499
        return;
14 andreas 4500
 
12 andreas 4501
    if (pg->isVisible())
4502
    {
4503
        pg->drop();
162 andreas 4504
        page->decZOrder();
12 andreas 4505
        return;
4506
    }
4507
 
4508
    TSubPage *sub = getFirstSubPageGroup(pg->getGroupName());
14 andreas 4509
 
12 andreas 4510
    while(sub)
4511
    {
4512
        if (sub->getGroupName().compare(pg->getGroupName()) == 0 && sub->isVisible())
4513
            sub->drop();
14 andreas 4514
 
12 andreas 4515
        sub = getNextSubPageGroup(pg->getGroupName(), sub);
4516
    }
4517
 
152 andreas 4518
    pg->setZOrder(page->getNextZOrder());
4519
    MSG_DEBUG("Setting new Z-order " << page->getActZOrder() << " on page " << page->getName());
12 andreas 4520
    pg->show();
4521
}
4522
 
14 andreas 4523
/**
4524
 * Kill refers to the deactivating (Off) of a popup window from all pages. If
4525
 * the pop-up page is part of a group, the whole group is deactivated. This
4526
 * command works in the same way as the 'Clear Group' command in TPDesign 4.
4527
 */
22 andreas 4528
void TPageManager::doPPK(int, std::vector<int>&, std::vector<std::string>& pars)
12 andreas 4529
{
4530
    DECL_TRACER("TPageManager::doPPK(int port, std::vector<int>& channels, std::vector<std::string>& pars)");
14 andreas 4531
 
12 andreas 4532
    if (pars.size() < 1)
4533
    {
4534
        MSG_ERROR("At least 1 parameter is expected!");
4535
        return;
4536
    }
4537
 
16 andreas 4538
    TError::clear();
14 andreas 4539
    TPage *page = getPage(mActualPage);
4540
 
4541
    if (!page)
4542
    {
4543
        MSG_ERROR("No active page found! Internal error.");
4544
        return;
4545
    }
4546
 
12 andreas 4547
    TSubPage *pg = getSubPage(pars[0]);
14 andreas 4548
 
12 andreas 4549
    if (pg)
14 andreas 4550
    {
4551
        pg->drop();
162 andreas 4552
        page->decZOrder();
14 andreas 4553
    }
12 andreas 4554
}
4555
 
14 andreas 4556
/**
4557
 * Set the modality of a specific popup page to Modal or NonModal.
4558
 * A Modal popup page, when active, only allows you to use the buttons and
4559
 * features on that popup page. All other buttons on the panel page are
4560
 * inactivated.
4561
 */
22 andreas 4562
void TPageManager::doPPM(int, std::vector<int>&, std::vector<std::string>& pars)
12 andreas 4563
{
4564
    DECL_TRACER("TPageManager::doPPM(int port, std::vector<int>& channels, std::vector<std::string>& pars)");
14 andreas 4565
 
12 andreas 4566
    if (pars.size() < 2)
4567
    {
4568
        MSG_ERROR("Expecting 2 parameters!");
4569
        return;
4570
    }
14 andreas 4571
 
16 andreas 4572
    TError::clear();
12 andreas 4573
    TSubPage *pg = getSubPage(pars[0]);
14 andreas 4574
 
12 andreas 4575
    if (pg)
4576
    {
162 andreas 4577
        if (pars[1] == "1" || strCaseCompare(pars[1], "modal") == 0)
12 andreas 4578
            pg->setModal(1);
4579
        else
4580
            pg->setModal(0);
4581
    }
4582
}
4583
 
14 andreas 4584
/**
4585
 * Activate a specific popup page to launch on either a specified page or the
4586
 * current page. If the page name is empty, the current page is used. If the
4587
 * popup page is already on, do not re-draw it. This command works in the same
4588
 * way as the ’Show Popup’ command in TPDesign4.
4589
 */
22 andreas 4590
void TPageManager::doPPN(int, std::vector<int>&, std::vector<std::string>& pars)
12 andreas 4591
{
4592
    DECL_TRACER("TPageManager::doPPN(int port, std::vector<int>& channels, std::vector<std::string>& pars)");
4593
 
4594
    if (pars.size() < 1)
4595
    {
4596
        MSG_ERROR("At least 1 parameter is expected!");
4597
        return;
4598
    }
4599
 
16 andreas 4600
    TError::clear();
14 andreas 4601
    showSubPage(pars[0]);
12 andreas 4602
}
4603
 
14 andreas 4604
/**
15 andreas 4605
 * Set a specific popup page to timeout within a specified time. If timeout is
4606
 * empty, popup page will clear the timeout.
4607
 */
22 andreas 4608
void TPageManager::doPPT(int, vector<int>&, vector<string>& pars)
15 andreas 4609
{
4610
    DECL_TRACER("TPageManager::doPPT(int port, vector<int>& channels, vector<string>& pars)");
4611
 
4612
    if (pars.size() < 2)
4613
    {
4614
        MSG_ERROR("Expecting 2 parameters!");
4615
        return;
4616
    }
4617
 
16 andreas 4618
    TError::clear();
96 andreas 4619
    TSubPage *pg = deliverSubPage(pars[0]);
15 andreas 4620
 
4621
    if (!pg)
96 andreas 4622
        return;
15 andreas 4623
 
4624
    pg->setTimeout(atoi(pars[1].c_str()));
4625
}
4626
 
4627
/**
14 andreas 4628
 * Close all popups on all pages. This command works in the same way as the
4629
 * 'Clear All' command in TPDesign 4.
4630
 */
22 andreas 4631
void TPageManager::doPPX(int, std::vector<int>&, std::vector<std::string>&)
12 andreas 4632
{
4633
    DECL_TRACER("TPageManager::doPPX(int port, std::vector<int>& channels, std::vector<std::string>& pars)");
4634
 
16 andreas 4635
    TError::clear();
12 andreas 4636
    PCHAIN_T *chain = mPchain;
14 andreas 4637
 
12 andreas 4638
    while(chain)
4639
    {
4640
        TSubPage *sub = chain->page->getFirstSubPage();
14 andreas 4641
 
12 andreas 4642
        while (sub)
4643
        {
14 andreas 4644
            MSG_DEBUG("Dopping subpage " << sub->getNumber() << ", \"" << sub->getName() << "\".");
12 andreas 4645
            sub->drop();
4646
            sub = chain->page->getNextSubPage();
4647
        }
14 andreas 4648
 
12 andreas 4649
        chain = chain->next;
4650
    }
14 andreas 4651
 
4652
    TPage *page = getPage(mActualPage);
4653
 
4654
    if (!page)
4655
    {
4656
        MSG_ERROR("No active page found! Internal error.");
4657
        return;
4658
    }
4659
 
4660
    page->resetZOrder();
12 andreas 4661
}
4662
 
14 andreas 4663
/**
15 andreas 4664
 * Set the show effect for the specified popup page to the named show effect.
4665
 */
22 andreas 4666
void TPageManager::doPSE(int, vector<int>&, vector<string>& pars)
15 andreas 4667
{
4668
    DECL_TRACER("TPageManager::doPSE(int port, vector<int>& channels, vector<string>& pars)");
4669
 
4670
    if (pars.size() < 2)
4671
    {
4672
        MSG_ERROR("Less than 2 parameters!");
4673
        return;
4674
    }
4675
 
16 andreas 4676
    TError::clear();
96 andreas 4677
    TSubPage *pg = deliverSubPage(pars[0]);
15 andreas 4678
 
4679
    if (!pg)
96 andreas 4680
        return;
15 andreas 4681
 
162 andreas 4682
    if (strCaseCompare(pars[1], "fade") == 0)
15 andreas 4683
        pg->setShowEffect(SE_FADE);
162 andreas 4684
    else if (strCaseCompare(pars[1], "slide to left") == 0)
15 andreas 4685
        pg->setShowEffect(SE_SLIDE_LEFT);
162 andreas 4686
    else if (strCaseCompare(pars[1], "slide to right") == 0)
15 andreas 4687
        pg->setShowEffect(SE_SLIDE_RIGHT);
162 andreas 4688
    else if (strCaseCompare(pars[1], "slide to top") == 0)
15 andreas 4689
        pg->setShowEffect(SE_SLIDE_TOP);
162 andreas 4690
    else if (strCaseCompare(pars[1], "slide to bottom") == 0)
15 andreas 4691
        pg->setShowEffect(SE_SLIDE_BOTTOM);
162 andreas 4692
    else if (strCaseCompare(pars[1], "slide to left fade") == 0)
15 andreas 4693
        pg->setShowEffect(SE_SLIDE_LEFT_FADE);
162 andreas 4694
    else if (strCaseCompare(pars[1], "slide to right fade") == 0)
15 andreas 4695
        pg->setShowEffect(SE_SLIDE_RIGHT_FADE);
162 andreas 4696
    else if (strCaseCompare(pars[1], "slide to top fade") == 0)
15 andreas 4697
        pg->setShowEffect(SE_SLIDE_TOP_FADE);
162 andreas 4698
    else if (strCaseCompare(pars[1], "slide to bottom fade") == 0)
15 andreas 4699
        pg->setShowEffect(SE_SLIDE_BOTTOM_FADE);
4700
    else
4701
        pg->setShowEffect(SE_NONE);
4702
}
4703
 
162 andreas 4704
/**
4705
 * Set the show effect position. Only 1 coordinate is ever needed for an effect;
4706
 * however, the command will specify both. This command sets the location at
4707
 * which the effect will begin.
4708
 */
22 andreas 4709
void TPageManager::doPSP(int, vector<int>&, vector<string>& pars)
15 andreas 4710
{
4711
    DECL_TRACER("TPageManager::doPSP(int port, vector<int>& channels, vector<string>& pars)");
4712
 
4713
    if (pars.size() < 2)
4714
    {
4715
        MSG_ERROR("Less than 2 parameters!");
4716
        return;
4717
    }
4718
 
16 andreas 4719
    TError::clear();
15 andreas 4720
    size_t pos = pars[1].find(",");
4721
    int x, y;
4722
 
4723
    if (pos == string::npos)
4724
    {
4725
        x = atoi(pars[1].c_str());
4726
        y = 0;
4727
    }
4728
    else
4729
    {
4730
        x = atoi(pars[1].substr(0, pos).c_str());
4731
        y = atoi(pars[1].substr(pos+1).c_str());
4732
    }
4733
 
96 andreas 4734
    TSubPage *pg = deliverSubPage(pars[0]);
15 andreas 4735
 
4736
    if (!pg)
96 andreas 4737
        return;
15 andreas 4738
 
4739
    pg->setShowEndPosition(x, y);
4740
}
4741
 
4742
/**
4743
 * Set the show effect time for the specified popup page.
4744
 */
22 andreas 4745
void TPageManager::doPST(int, vector<int>&, vector<string>& pars)
15 andreas 4746
{
4747
    DECL_TRACER("TPageManager::doPST(int port, vector<int>& channels, vector<string>& pars)");
4748
 
4749
    if (pars.size() < 2)
4750
    {
4751
        MSG_ERROR("Less than 2 parameters!");
4752
        return;
4753
    }
4754
 
16 andreas 4755
    TError::clear();
96 andreas 4756
    TSubPage *pg = deliverSubPage(pars[0]);
15 andreas 4757
 
4758
    if (!pg)
96 andreas 4759
        return;
15 andreas 4760
 
4761
    pg->setShowTime(atoi(pars[1].c_str()));
4762
}
4763
 
4764
/**
14 andreas 4765
 * Flips to a page with a specified page name. If the page is currently active,
4766
 * it will not redraw the page.
4767
 */
22 andreas 4768
void TPageManager::doPAGE(int, std::vector<int>&, std::vector<std::string>& pars)
12 andreas 4769
{
4770
    DECL_TRACER("TPageManager::doPAGE(int port, std::vector<int>& channels, std::vector<std::string>& pars)");
14 andreas 4771
 
15 andreas 4772
    if (pars.empty())
4773
    {
4774
        MSG_WARNING("Got no page parameter!");
4775
        return;
4776
    }
14 andreas 4777
 
16 andreas 4778
    TError::clear();
15 andreas 4779
    setPage(pars[0]);
4780
}
4781
 
4782
/**
38 andreas 4783
 * @brief TPageManager::doANI Run a button animation (in 1/10 second).
4784
 * Syntax:
4785
 *      ^ANI-<vt addr range>,<start state>,<end state>,<time>
4786
 * Variable:
4787
 *      variable text address range = 1 - 4000.
4788
 *      start state = Beginning of button state (0= current state).
4789
 *      end state = End of button state.
4790
 *      time = In 1/10 second intervals.
4791
 * Example:
4792
 *      SEND_COMMAND Panel,"'^ANI-500,1,25,100'"
4793
 * Runs a button animation at text range 500 from state 1 to state 25 for 10 seconds.
4794
 *
4795
 * @param port      The port number
4796
 * @param channels  The channels of the buttons
4797
 * @param pars      The parameters
4798
 */
4799
void TPageManager::doANI(int port, std::vector<int> &channels, std::vector<std::string> &pars)
4800
{
4801
    DECL_TRACER("TPageManager::doANI(int port, std::vector<int> &channels, std::vector<std::string> &pars)");
4802
 
4803
    if (pars.size() < 3)
4804
    {
4805
        MSG_ERROR("Expecting 3 parameters but got " << pars.size() << "! Ignoring command.");
4806
        return;
4807
    }
4808
 
4809
    TError::clear();
4810
    int stateStart = atoi(pars[0].c_str());
4811
    int endState = atoi(pars[1].c_str());
4812
    int runTime = atoi(pars[2].c_str());
4813
 
193 andreas 4814
    vector<TMap::MAP_T> map = findButtons(port, channels);
38 andreas 4815
 
4816
    if (TError::isError() || map.empty())
4817
        return;
4818
 
4819
    vector<Button::TButton *> buttons = collectButtons(map);
4820
 
83 andreas 4821
    if (buttons.size() > 0)
38 andreas 4822
    {
83 andreas 4823
        vector<Button::TButton *>::iterator mapIter;
4824
 
4825
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
4826
        {
4827
            Button::TButton *bt = *mapIter;
4828
            bt->startAnimation(stateStart, endState, runTime);
4829
        }
38 andreas 4830
    }
4831
}
4832
 
4833
/**
15 andreas 4834
 * Add page flip action to a button if it does not already exist.
4835
 */
4836
void TPageManager::doAPF(int port, vector<int>& channels, vector<string>& pars)
4837
{
4838
    DECL_TRACER("TPageManager::doAPF(int port, vector<int>& channels, vector<string>& pars)");
4839
 
4840
    if (pars.size() < 2)
4841
    {
4842
        MSG_ERROR("Expecting 2 parameters but got " << pars.size() << "! Ignoring command.");
14 andreas 4843
        return;
15 andreas 4844
    }
14 andreas 4845
 
16 andreas 4846
    TError::clear();
15 andreas 4847
    string action = pars[0];
4848
    string pname = pars[1];
14 andreas 4849
 
193 andreas 4850
    vector<TMap::MAP_T> map = findButtons(port, channels);
14 andreas 4851
 
15 andreas 4852
    if (TError::isError() || map.empty())
4853
        return;
4854
 
4855
    vector<Button::TButton *> buttons = collectButtons(map);
4856
 
83 andreas 4857
    if (buttons.size() > 0)
12 andreas 4858
    {
83 andreas 4859
        vector<Button::TButton *>::iterator mapIter;
4860
 
4861
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
4862
        {
4863
            Button::TButton *bt = *mapIter;
4864
            setButtonCallbacks(bt);
4865
            bt->addPushFunction(action, pname);
4866
        }
15 andreas 4867
    }
4868
}
12 andreas 4869
 
15 andreas 4870
/**
43 andreas 4871
 * Append non-unicode text.
4872
 */
4873
void TPageManager::doBAT(int port, vector<int> &channels, vector<string> &pars)
4874
{
4875
    DECL_TRACER("TPageManager::doBAT(int port, vector<int> &channels, vector<string> &pars)");
4876
 
4877
    if (pars.size() < 1)
4878
    {
4879
        MSG_ERROR("Expecting 1 parameters but got none! Ignoring command.");
4880
        return;
4881
    }
4882
 
4883
    TError::clear();
4884
    int btState = atoi(pars[0].c_str());
4885
    string text;
4886
 
4887
    if (pars.size() > 1)
4888
        text = pars[1];
4889
 
193 andreas 4890
    vector<TMap::MAP_T> map = findButtons(port, channels);
43 andreas 4891
 
4892
    if (TError::isError() || map.empty())
4893
        return;
4894
 
4895
    vector<Button::TButton *> buttons = collectButtons(map);
4896
 
162 andreas 4897
    if (buttons.empty())
4898
        return;
4899
 
4900
    vector<Button::TButton *>::iterator mapIter;
4901
 
4902
    for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
43 andreas 4903
    {
162 andreas 4904
        Button::TButton *bt = *mapIter;
4905
        setButtonCallbacks(bt);
43 andreas 4906
 
162 andreas 4907
        if (btState == 0)       // All instances?
43 andreas 4908
        {
162 andreas 4909
            int bst = bt->getNumberInstances();
43 andreas 4910
 
162 andreas 4911
            for (int i = 0; i < bst; i++)
4912
                bt->appendText(text, i);
43 andreas 4913
        }
162 andreas 4914
        else
4915
            bt->appendText(text, btState - 1);
43 andreas 4916
    }
4917
}
4918
 
4919
/**
60 andreas 4920
 * @brief Append unicode text. Same format as ^UNI.
4921
 * This command allows to set up to 50 characters of ASCII code. The unicode
4922
 * characters must be set as hex numbers.
4923
 */
4924
void TPageManager::doBAU(int port, vector<int>& channels, vector<string>& pars)
4925
{
4926
    DECL_TRACER("TPageManager::doBAU(int port, vector<int>& channels, vector<string>& pars)");
4927
 
4928
    if (pars.size() < 1)
4929
    {
4930
        MSG_ERROR("Expecting 1 parameters but got none! Ignoring command.");
4931
        return;
4932
    }
4933
 
4934
    TError::clear();
4935
    int btState = atoi(pars[0].c_str());
4936
    string text;
4937
    char ch[3];
4938
 
162 andreas 4939
    if (pars.size() > 1 && (pars.size() % 2) == 0)
60 andreas 4940
    {
162 andreas 4941
        try
60 andreas 4942
        {
162 andreas 4943
            text = pars[1];
4944
            // Because the unicode characters are hex numbers, we scan the text
4945
            // and convert the hex numbers into real numbers.
4946
            size_t len = text.length();
4947
            bool inHex = false;
4948
            int lastChar = 0;
4949
            std::wstring uniText;
4950
            int uniPos = 0;
60 andreas 4951
 
162 andreas 4952
            for (size_t i = 0; i < len; i++)
60 andreas 4953
            {
162 andreas 4954
                int c = text.at(i);
60 andreas 4955
 
162 andreas 4956
                if (!inHex && isHex(c))
4957
                {
4958
                    inHex = true;
4959
                    lastChar = c;
4960
                    continue;
4961
                }
4962
 
4963
                if (inHex && !isHex(c))
4964
                {
4965
                    inHex = false;
4966
                    break;
4967
                }
4968
 
4969
                if (inHex && isHex(c))
4970
                {
4971
                    ch[0] = lastChar;
4972
                    ch[1] = c;
4973
                    ch[2] = 0;
4974
                    uint16_t num = (uint16_t)strtol(ch, NULL, 16);
4975
                    uniText += num;
4976
                    uniPos++;
4977
                    inHex = false;
4978
 
4979
                    if (uniPos >= 50)
4980
                        break;
4981
 
4982
                    continue;
4983
                }
60 andreas 4984
            }
4985
 
162 andreas 4986
            text = CharConvert::UtfConv<std::string>(uniText);
60 andreas 4987
        }
162 andreas 4988
        catch (std::exception const & e)
4989
        {
4990
            MSG_ERROR("Character conversion error: " << e.what());
4991
            return;
4992
        }
60 andreas 4993
    }
4994
 
193 andreas 4995
    vector<TMap::MAP_T> map = findButtons(port, channels);
60 andreas 4996
 
4997
    if (TError::isError() || map.empty())
4998
        return;
4999
 
5000
    vector<Button::TButton *> buttons = collectButtons(map);
5001
 
83 andreas 5002
    if (buttons.size() > 0)
60 andreas 5003
    {
83 andreas 5004
        vector<Button::TButton *>::iterator mapIter;
60 andreas 5005
 
83 andreas 5006
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
60 andreas 5007
        {
83 andreas 5008
            Button::TButton *bt = *mapIter;
5009
            setButtonCallbacks(bt);
60 andreas 5010
 
83 andreas 5011
            if (btState == 0)       // All instances?
5012
            {
5013
                int bst = bt->getNumberInstances();
5014
 
5015
                for (int i = 0; i < bst; i++)
5016
                    bt->appendText(text, i);
5017
            }
5018
            else
5019
                bt->appendText(text, btState - 1);
60 andreas 5020
        }
5021
    }
5022
}
5023
 
5024
/**
43 andreas 5025
 * @brief TPageManager::doBCB Set the border color.
5026
 * Set the border color to the specified color. Only if the specified border
5027
 * color is not the same as the current color.
5028
 * Note: Color can be assigned by color name (without spaces), number or
5029
 * R,G,B value (RRGGBB or RRGGBBAA).
5030
 */
5031
void TPageManager::doBCB(int port, vector<int> &channels, vector<string> &pars)
5032
{
5033
    DECL_TRACER("TPageManager::doBCB(int port, vector<int> &channels, vector<string> &pars)");
5034
 
5035
    if (pars.size() < 1)
5036
    {
5037
        MSG_ERROR("Expecting 1 parameters but got none! Ignoring command.");
5038
        return;
5039
    }
5040
 
5041
    TError::clear();
5042
    int btState = atoi(pars[0].c_str());
5043
    string color;
5044
 
5045
    if (pars.size() > 1)
5046
        color = pars[1];
5047
 
193 andreas 5048
    vector<TMap::MAP_T> map = findButtons(port, channels);
43 andreas 5049
 
5050
    if (TError::isError() || map.empty())
5051
        return;
5052
 
5053
    vector<Button::TButton *> buttons = collectButtons(map);
5054
 
83 andreas 5055
    if (buttons.size() > 0)
43 andreas 5056
    {
83 andreas 5057
        vector<Button::TButton *>::iterator mapIter;
43 andreas 5058
 
83 andreas 5059
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
43 andreas 5060
        {
83 andreas 5061
            Button::TButton *bt = *mapIter;
5062
            setButtonCallbacks(bt);
43 andreas 5063
 
83 andreas 5064
            if (btState == 0)       // All instances?
5065
            {
5066
                int bst = bt->getNumberInstances();
5067
 
5068
                for (int i = 0; i < bst; i++)
5069
                    bt->setBorderColor(color, i);
5070
            }
5071
            else
5072
                bt->setBorderColor(color, btState - 1);
43 andreas 5073
        }
5074
    }
5075
}
60 andreas 5076
 
82 andreas 5077
void TPageManager::getBCB(int port, vector<int> &channels, vector<string> &pars)
5078
{
5079
    DECL_TRACER("TPageManager::getBCB(int port, vector<int> &channels, vector<string> &pars)");
5080
 
5081
    if (pars.size() < 1)
5082
    {
5083
        MSG_ERROR("Expecting 1 parameters but got none! Ignoring command.");
5084
        return;
5085
    }
5086
 
5087
    TError::clear();
5088
    int btState = atoi(pars[0].c_str());
5089
    string color;
5090
 
193 andreas 5091
    vector<TMap::MAP_T> map = findButtons(port, channels);
82 andreas 5092
 
5093
    if (TError::isError() || map.empty())
5094
        return;
5095
 
5096
    vector<Button::TButton *> buttons = collectButtons(map);
5097
 
83 andreas 5098
    if (buttons.size() > 0)
82 andreas 5099
    {
110 andreas 5100
        Button::TButton *bt = buttons[0];
82 andreas 5101
 
110 andreas 5102
        if (btState == 0)       // All instances?
82 andreas 5103
        {
110 andreas 5104
            int bst = bt->getNumberInstances();
82 andreas 5105
 
110 andreas 5106
            for (int i = 0; i < bst; i++)
82 andreas 5107
            {
110 andreas 5108
                color = bt->getBorderColor(i);
82 andreas 5109
 
110 andreas 5110
                if (color.empty())
5111
                    continue;
83 andreas 5112
 
110 andreas 5113
                sendCustomEvent(i + 1, color.length(), 0, color, 1011, bt->getChannelPort(), bt->getChannelNumber());
83 andreas 5114
            }
110 andreas 5115
        }
5116
        else
5117
        {
5118
            color = bt->getBorderColor(btState - 1);
83 andreas 5119
 
110 andreas 5120
            if (color.empty())
5121
                return;
82 andreas 5122
 
110 andreas 5123
            sendCustomEvent(btState, color.length(), 0, color, 1011, bt->getChannelPort(), bt->getChannelNumber());
82 andreas 5124
        }
5125
    }
5126
}
5127
 
43 andreas 5128
/**
60 andreas 5129
 * @brief Set the fill color to the specified color.
5130
 * Only if the specified fill color is not the same as the current color.
5131
 * Note: Color can be assigned by color name (without spaces), number or R,G,B value (RRGGBB or RRGGBBAA).
15 andreas 5132
 */
60 andreas 5133
void TPageManager::doBCF(int port, vector<int>& channels, vector<std::string>& pars)
15 andreas 5134
{
60 andreas 5135
    DECL_TRACER("TPageManager::doBCF(int port, vector<int>& channels, vector<std::string>& pars)");
15 andreas 5136
 
60 andreas 5137
    if (pars.size() < 1)
15 andreas 5138
    {
60 andreas 5139
        MSG_ERROR("Expecting 1 parameters but got none! Ignoring command.");
12 andreas 5140
        return;
5141
    }
14 andreas 5142
 
16 andreas 5143
    TError::clear();
15 andreas 5144
    int btState = atoi(pars[0].c_str());
60 andreas 5145
    string color;
14 andreas 5146
 
60 andreas 5147
    if (pars.size() > 1)
5148
        color = pars[1];
5149
 
193 andreas 5150
    vector<TMap::MAP_T> map = findButtons(port, channels);
15 andreas 5151
 
5152
    if (TError::isError() || map.empty())
5153
        return;
5154
 
5155
    vector<Button::TButton *> buttons = collectButtons(map);
5156
 
83 andreas 5157
    if (buttons.size() > 0)
15 andreas 5158
    {
83 andreas 5159
        vector<Button::TButton *>::iterator mapIter;
15 andreas 5160
 
83 andreas 5161
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
15 andreas 5162
        {
83 andreas 5163
            Button::TButton *bt = *mapIter;
5164
            setButtonCallbacks(bt);
15 andreas 5165
 
83 andreas 5166
            if (btState == 0)       // All instances?
5167
            {
5168
                int bst = bt->getNumberInstances();
5169
 
5170
                for (int i = 0; i < bst; i++)
5171
                    bt->setFillColor(color, i);
5172
            }
5173
            else
5174
                bt->setFillColor(color, btState - 1);
15 andreas 5175
        }
5176
    }
12 andreas 5177
}
5178
 
82 andreas 5179
void TPageManager::getBCF(int port, vector<int> &channels, vector<string> &pars)
5180
{
5181
    DECL_TRACER("TPageManager::getBCF(int port, vector<int> &channels, vector<string> &pars)");
5182
 
5183
    if (pars.size() < 1)
5184
    {
5185
        MSG_ERROR("Expecting 1 parameters but got none! Ignoring command.");
5186
        return;
5187
    }
5188
 
5189
    TError::clear();
5190
    int btState = atoi(pars[0].c_str());
5191
    string color;
5192
 
193 andreas 5193
    vector<TMap::MAP_T> map = findButtons(port, channels);
82 andreas 5194
 
5195
    if (TError::isError() || map.empty())
5196
        return;
5197
 
5198
    vector<Button::TButton *> buttons = collectButtons(map);
5199
 
83 andreas 5200
    if (buttons.size() > 0)
82 andreas 5201
    {
110 andreas 5202
        Button::TButton *bt = buttons[0];
82 andreas 5203
 
110 andreas 5204
        if (btState == 0)       // All instances?
82 andreas 5205
        {
110 andreas 5206
            int bst = bt->getNumberInstances();
82 andreas 5207
 
110 andreas 5208
            for (int i = 0; i < bst; i++)
82 andreas 5209
            {
110 andreas 5210
                color = bt->getFillColor(i);
82 andreas 5211
 
110 andreas 5212
                if (color.empty())
5213
                    continue;
82 andreas 5214
 
110 andreas 5215
                sendCustomEvent(i + 1, color.length(), 0, color, 1012, bt->getChannelPort(), bt->getChannelNumber());
83 andreas 5216
            }
82 andreas 5217
        }
110 andreas 5218
        else
5219
        {
5220
            color = bt->getFillColor(btState-1);
5221
            sendCustomEvent(btState, color.length(), 0, color, 1012, bt->getChannelPort(), bt->getChannelNumber());
5222
        }
82 andreas 5223
    }
5224
}
5225
 
60 andreas 5226
/**
5227
 * @brief Set the text color to the specified color.
5228
 * Only if the specified text color is not the same as the current color.
5229
 * Note: Color can be assigned by color name (without spaces), number or R,G,B value (RRGGBB or RRGGBBAA).
5230
 */
5231
void TPageManager::doBCT(int port, vector<int>& channels, vector<string>& pars)
18 andreas 5232
{
60 andreas 5233
    DECL_TRACER("TPageManager::doBCT(int port, vector<int>& channels, vector<string>& pars)");
5234
 
5235
    if (pars.size() < 1)
5236
    {
5237
        MSG_ERROR("Expecting 1 parameters but got none! Ignoring command.");
5238
        return;
5239
    }
5240
 
5241
    TError::clear();
5242
    int btState = atoi(pars[0].c_str());
5243
    string color;
5244
 
5245
    if (pars.size() > 1)
5246
        color = pars[1];
5247
 
193 andreas 5248
    vector<TMap::MAP_T> map = findButtons(port, channels);
60 andreas 5249
 
5250
    if (TError::isError() || map.empty())
5251
        return;
5252
 
5253
    vector<Button::TButton *> buttons = collectButtons(map);
5254
 
83 andreas 5255
    if (buttons.size() > 0)
60 andreas 5256
    {
83 andreas 5257
        vector<Button::TButton *>::iterator mapIter;
60 andreas 5258
 
83 andreas 5259
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
60 andreas 5260
        {
83 andreas 5261
            Button::TButton *bt = *mapIter;
5262
            setButtonCallbacks(bt);
60 andreas 5263
 
83 andreas 5264
            if (btState == 0)       // All instances?
5265
            {
5266
                int bst = bt->getNumberInstances();
5267
 
5268
                for (int i = 0; i < bst; i++)
5269
                    bt->setTextColor(color, i);
5270
            }
5271
            else
5272
                bt->setTextColor(color, btState - 1);
60 andreas 5273
        }
5274
    }
18 andreas 5275
}
5276
 
82 andreas 5277
void TPageManager::getBCT(int port, vector<int> &channels, vector<string> &pars)
5278
{
5279
    DECL_TRACER("TPageManager::getBCT(int port, vector<int> &channels, vector<string> &pars)");
5280
 
5281
    if (pars.size() < 1)
5282
    {
5283
        MSG_ERROR("Expecting 1 parameters but got none! Ignoring command.");
5284
        return;
5285
    }
5286
 
5287
    TError::clear();
5288
    int btState = atoi(pars[0].c_str());
5289
    string color;
5290
 
193 andreas 5291
    vector<TMap::MAP_T> map = findButtons(port, channels);
82 andreas 5292
 
5293
    if (TError::isError() || map.empty())
5294
        return;
5295
 
5296
    vector<Button::TButton *> buttons = collectButtons(map);
5297
 
83 andreas 5298
    if (buttons.size() > 0)
82 andreas 5299
    {
110 andreas 5300
        Button::TButton *bt = buttons[0];
82 andreas 5301
 
110 andreas 5302
        if (btState == 0)       // All instances?
82 andreas 5303
        {
110 andreas 5304
            int bst = bt->getNumberInstances();
82 andreas 5305
 
110 andreas 5306
            for (int i = 0; i < bst; i++)
82 andreas 5307
            {
110 andreas 5308
                color = bt->getTextColor(i);
82 andreas 5309
 
110 andreas 5310
                if (color.empty())
5311
                    continue;
82 andreas 5312
 
110 andreas 5313
                sendCustomEvent(i + 1, color.length(), 0, color, 1013, bt->getChannelPort(), bt->getChannelNumber());
83 andreas 5314
            }
82 andreas 5315
        }
110 andreas 5316
        else
5317
        {
5318
            color = bt->getTextColor(btState - 1);
5319
            sendCustomEvent(btState, color.length(), 0, color, 1013, bt->getChannelPort(), bt->getChannelNumber());
5320
        }
82 andreas 5321
    }
5322
}
5323
 
60 andreas 5324
/**
5325
 * Set the button draw order
5326
 * Determines what order each layer of the button is drawn.
5327
 */
5328
void TPageManager::doBDO(int port, vector<int>& channels, vector<std::string>& pars)
32 andreas 5329
{
60 andreas 5330
    DECL_TRACER("TPageManager::doBDO(int port, vector<int>& channels, vector<std::string>& pars)");
32 andreas 5331
 
60 andreas 5332
    if (pars.size() < 1)
5333
    {
5334
        MSG_ERROR("Expecting 1 parameters but got none! Ignoring command.");
32 andreas 5335
        return;
60 andreas 5336
    }
32 andreas 5337
 
60 andreas 5338
    TError::clear();
5339
    int btState = atoi(pars[0].c_str());
5340
    string order;
32 andreas 5341
 
60 andreas 5342
    if (pars.size() > 1)
5343
    {
5344
        string ord = pars[1];
5345
        // Convert the numbers into the expected draw order
5346
        for (size_t i = 0; i < ord.length(); i++)
5347
        {
5348
            if (ord.at(i) >= '1' && ord.at(i) <= '5')
5349
            {
5350
                char hv0[32];
5351
                snprintf(hv0, sizeof(hv0), "%02d", (int)(ord.at(i) - '0'));
5352
                order.append(hv0);
5353
            }
5354
            else
5355
            {
5356
                MSG_ERROR("Illegal order number " << ord.substr(i, 1) << "!");
5357
                return;
5358
            }
5359
        }
5360
 
5361
        if (order.length() != 10)
5362
        {
5363
            MSG_ERROR("Expected 5 order numbers but got " << (order.length() / 2)<< "!");
5364
            return;
5365
        }
5366
    }
5367
 
193 andreas 5368
    vector<TMap::MAP_T> map = findButtons(port, channels);
60 andreas 5369
 
5370
    if (TError::isError() || map.empty())
32 andreas 5371
        return;
5372
 
60 andreas 5373
    vector<Button::TButton *> buttons = collectButtons(map);
5374
 
83 andreas 5375
    if (buttons.size() > 0)
32 andreas 5376
    {
83 andreas 5377
        vector<Button::TButton *>::iterator mapIter;
32 andreas 5378
 
83 andreas 5379
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
60 andreas 5380
        {
83 andreas 5381
            Button::TButton *bt = *mapIter;
5382
            setButtonCallbacks(bt);
32 andreas 5383
 
83 andreas 5384
            if (btState == 0)       // All instances?
5385
            {
5386
                int bst = bt->getNumberInstances();
5387
 
5388
                for (int i = 0; i < bst; i++)
5389
                    bt->setDrawOrder(order, i);
5390
            }
5391
            else
5392
                bt->setDrawOrder(order, btState - 1);
60 andreas 5393
        }
5394
    }
5395
}
32 andreas 5396
 
60 andreas 5397
/**
5398
 * Set the feedback type of the button.
5399
 * ONLY works on General-type buttons.
5400
 */
5401
void TPageManager::doBFB(int port, vector<int>& channels, vector<std::string>& pars)
5402
{
5403
    DECL_TRACER("TPageManager::doBFB(int port, vector<int>& channels, vector<std::string>& pars)");
32 andreas 5404
 
60 andreas 5405
    if (pars.size() < 1)
5406
    {
5407
        MSG_ERROR("Expecting 1 parameters but got none! Ignoring command.");
5408
        return;
5409
    }
5410
 
5411
    TError::clear();
5412
    Button::FEEDBACK type = Button::FB_NONE;
5413
    string stype = pars[0];
5414
    vector<string> stypes = { "None", "Channel", "Invert", "On", "Momentary", "Blink" };
5415
    vector<string>::iterator iter;
5416
    int i = 0;
5417
 
5418
    for (iter = stypes.begin(); iter != stypes.end(); ++iter)
5419
    {
5420
        if (strCaseCompare(stype, *iter) == 0)
33 andreas 5421
        {
60 andreas 5422
            type = (Button::FEEDBACK)i;
5423
            break;
32 andreas 5424
        }
60 andreas 5425
 
5426
        i++;
32 andreas 5427
    }
5428
 
193 andreas 5429
    vector<TMap::MAP_T> map = findButtons(port, channels);
60 andreas 5430
 
5431
    if (TError::isError() || map.empty())
5432
        return;
5433
 
5434
    vector<Button::TButton *> buttons = collectButtons(map);
5435
 
83 andreas 5436
    if (buttons.size() > 0)
60 andreas 5437
    {
83 andreas 5438
        vector<Button::TButton *>::iterator mapIter;
5439
 
5440
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
5441
        {
5442
            Button::TButton *bt = *mapIter;
5443
            setButtonCallbacks(bt);
5444
            bt->setFeedback(type);
5445
        }
60 andreas 5446
    }
32 andreas 5447
}
5448
 
224 andreas 5449
/*
5450
 * Set the input mask for the specified address.
5451
 */
5452
void TPageManager::doBIM(int port, vector<int>& channels, vector<std::string>& pars)
5453
{
5454
    DECL_TRACER("TPageManager::doBIM(int port, vector<int>& channels, vector<std::string>& pars)");
5455
 
5456
    if (pars.size() < 1)
5457
    {
5458
        MSG_ERROR("Expecting 1 parameters but got none! Ignoring command.");
5459
        return;
5460
    }
5461
 
5462
    TError::clear();
5463
    string mask = pars[0];
5464
    vector<TMap::MAP_T> map = findButtons(port, channels);
5465
 
5466
    if (TError::isError() || map.empty())
5467
        return;
5468
 
5469
    vector<Button::TButton *> buttons = collectButtons(map);
5470
 
5471
    if (buttons.size() > 0)
5472
    {
5473
        vector<Button::TButton *>::iterator mapIter;
5474
 
5475
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
5476
        {
5477
            Button::TButton *bt = *mapIter;
5478
            bt->setInputMask(mask);
5479
        }
5480
    }
5481
}
5482
 
106 andreas 5483
void TPageManager::doBMC(int port, vector<int>& channels, vector<std::string>& pars)
5484
{
5485
    DECL_TRACER("TPageManager::doBMC(int port, vector<int>& channels, vector<std::string>& pars)");
5486
 
5487
    if (pars.size() < 5)
5488
    {
5489
        MSG_ERROR("Expecting 5 parameters but got " << pars.size() << ". Ignoring command.");
5490
        return;
5491
    }
5492
 
5493
    TError::clear();
5494
    int btState = atoi(pars[0].c_str());
5495
    int src_port = atoi(pars[1].c_str());
5496
    int src_addr = atoi(pars[2].c_str());
5497
    int src_state = atoi(pars[3].c_str());
5498
    string src_codes = pars[4];
5499
    vector<int> src_channel;
5500
    src_channel.push_back(src_addr);
5501
 
193 andreas 5502
    vector<TMap::MAP_T> src_map = findButtons(src_port, src_channel);
106 andreas 5503
 
5504
    if (src_map.size() == 0)
5505
    {
5506
        MSG_WARNING("Button <" << TConfig::getChannel() << ":" << src_port << ":" << TConfig::getSystem() << ">:" << src_addr << " does not exist!");
5507
        return;
5508
    }
5509
 
5510
    vector<Button::TButton *>src_buttons = collectButtons(src_map);
5511
 
5512
    if (src_buttons.size() == 0)
5513
    {
5514
        MSG_WARNING("Button <" << TConfig::getChannel() << ":" << src_port << ":" << TConfig::getSystem() << ">:" << src_addr << " does not exist!");
5515
        return;
5516
    }
5517
 
5518
    if (src_buttons[0]->getNumberInstances() < src_state)
5519
    {
5520
        MSG_WARNING("Button <" << TConfig::getChannel() << ":" << src_port << ":" << TConfig::getSystem() << ">:" << src_addr << " has less then " << src_state << " elements.");
5521
        return;
5522
    }
5523
 
5524
    if (src_state < 1)
5525
    {
5526
        MSG_WARNING("Button <" << TConfig::getChannel() << ":" << src_port << ":" << TConfig::getSystem() << ">:" << src_addr << " has invalid source state " << src_state << ".");
5527
        return;
5528
    }
5529
 
5530
    src_state--;
5531
 
5532
    if (btState > 0)
5533
        btState--;
5534
 
193 andreas 5535
    vector<TMap::MAP_T> map = findButtons(port, channels);
106 andreas 5536
    vector<Button::TButton *> buttons = collectButtons(map);
5537
    //                        0     1     2     3     4     5     6     7
5538
    vector<string>codes = { "BM", "BR", "CB", "CF", "CT", "EC", "EF", "FT",
5539
                            "IC", "JB", "JI", "JT", "LN", "OP", "SO", "TX", // 8 - 15
5540
                            "VI", "WW" };   // 16, 17
5541
 
5542
    for (size_t ibuttons = 0; ibuttons < buttons.size(); ibuttons++)
5543
    {
5544
        vector<string>::iterator iter;
5545
        int idx = 0;
5546
 
5547
        for (iter = codes.begin(); iter != codes.end(); ++iter)
5548
        {
5549
            if (src_codes.find(*iter) != string::npos)
5550
            {
5551
                int j, x, y;
5552
 
5553
                switch(idx)
5554
                {
5555
                    case 0: buttons[ibuttons]->setBitmap(src_buttons[0]->getBitmapName(src_state), btState); break;
5556
                    case 1: buttons[ibuttons]->setBorderStyle(src_buttons[0]->getBorderStyle(src_state), btState); break;
5557
                    case 2: buttons[ibuttons]->setBorderColor(src_buttons[0]->getBorderColor(src_state), btState); break;
5558
                    case 3: buttons[ibuttons]->setFillColor(src_buttons[0]->getFillColor(src_state), btState); break;
5559
                    case 4: buttons[ibuttons]->setTextColor(src_buttons[0]->getTextColor(src_state), btState); break;
5560
                    case 5: buttons[ibuttons]->setTextEffectColor(src_buttons[0]->getTextEffectColor(src_state), btState); break;
5561
                    case 6: buttons[ibuttons]->setTextEffect(src_buttons[0]->getTextEffect(src_state), btState); break;
5562
                    case 7: buttons[ibuttons]->setFontIndex(src_buttons[0]->getFontIndex(src_state), btState); break;
110 andreas 5563
                    case 8: buttons[ibuttons]->setIcon(src_buttons[0]->getIconIndex(src_state), btState); break;
106 andreas 5564
 
5565
                    case 9:
5566
                        j = src_buttons[0]->getBitmapJustification(&x, &y, src_state);
5567
                        buttons[ibuttons]->setBitmapJustification(j, x, y, btState);
5568
                    break;
5569
 
5570
                    case 10:
5571
                        j = src_buttons[0]->getIconJustification(&x, &y, src_state);
5572
                        buttons[ibuttons]->setIconJustification(j, x, y, btState);
5573
                    break;
5574
 
5575
                    case 11:
5576
                        j = src_buttons[0]->getTextJustification(&x, &y, src_state);
5577
                        buttons[ibuttons]->setTextJustification(j, x, y, btState);
5578
                    break;
5579
 
5580
                    case 12: MSG_INFO("\"Lines of video removed\" not supported!"); break;
5581
                    case 13: buttons[ibuttons]->setOpacity(src_buttons[0]->getOpacity(src_state), btState); break;
5582
                    case 14: buttons[ibuttons]->setSound(src_buttons[0]->getSound(src_state), btState); break;
5583
                    case 15: buttons[ibuttons]->setText(src_buttons [0]->getText(src_state), btState); break;
5584
                    case 16: MSG_INFO("\"Video slot ID\" not supported!"); break;
5585
                    case 17: buttons[ibuttons]->setTextWordWrap(src_buttons[0]->getTextWordWrap(src_state), btState); break;
5586
                }
5587
            }
5588
 
5589
            idx++;
5590
        }
5591
    }
5592
}
5593
 
149 andreas 5594
void TPageManager::doBMF (int port, vector<int>& channels, vector<string>& pars)
5595
{
5596
    DECL_TRACER("TPageManager::doBMF (int port, vector<int>& channels, vector<string>& pars)");
5597
 
5598
    if (pars.size() < 2)
5599
        return;
5600
 
5601
    TError::clear();
5602
    int btState = atoi(pars[0].c_str()) - 1;
150 andreas 5603
    string commands;
149 andreas 5604
 
150 andreas 5605
    for (size_t i = 1; i < pars.size(); ++i)
5606
    {
5607
        if (i > 1)
5608
            commands += ",";
5609
 
5610
        commands += pars[i];
5611
    }
5612
 
193 andreas 5613
    vector<TMap::MAP_T> map = findButtons(port, channels);
149 andreas 5614
 
5615
    if (TError::isError() || map.empty())
5616
        return;
5617
 
5618
    // Start of parsing the command line
162 andreas 5619
    // We splitt the command line into parts by searching for a percent (%) sign.
149 andreas 5620
    vector<string> parts = StrSplit(commands, "%");
5621
 
162 andreas 5622
    if (parts.empty())
5623
        return;
5624
 
149 andreas 5625
    // Search for all buttons who need to be updated
5626
    vector<Button::TButton *> buttons = collectButtons(map);
5627
 
5628
    if (buttons.size() > 0)
5629
    {
5630
        vector<Button::TButton *>::iterator mapIter;
5631
 
5632
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
5633
        {
5634
            Button::TButton *bt = *mapIter;
162 andreas 5635
 
5636
            if (!bt)
5637
            {
5638
                MSG_WARNING("Command ^BMF found an invalid pointer to a button!")
5639
                continue;
5640
            }
5641
 
149 andreas 5642
            // Iterate through commands and apply them to button
5643
            vector<string>::iterator iter;
5644
 
5645
            for (iter = parts.begin(); iter != parts.end(); ++iter)
5646
            {
5647
                char cmd = iter->at(0);
5648
                char cmd2;
5649
                string content;
5650
 
5651
                switch(cmd)
5652
                {
5653
                    case 'B':   // Border style
5654
                        content = iter->substr(1);
5655
                        bt->setBorderStyle(content, btState);
5656
                    break;
5657
 
5658
                    case 'C':   // Colors
5659
                        cmd2 = iter->at(1);
5660
                        content = iter->substr(2);
5661
 
5662
                        switch(cmd2)
5663
                        {
5664
                            case 'B':   // Border color
5665
                                bt->setBorderColor(content, btState);
5666
                            break;
5667
 
5668
                            case 'F':   // Fill color
5669
                                bt->setFillColor(content, btState);
5670
                            break;
5671
 
5672
                            case 'T':   // Text color
5673
                                bt->setTextColor(content, btState);
5674
                            break;
5675
                        }
5676
                    break;
5677
 
150 andreas 5678
                    case 'D':   // Draw order
5679
                        cmd2 = iter->at(1);
5680
                        content = iter->substr(2);
5681
 
5682
                        if (cmd2 == 'O')
5683
                            bt->setDrawOrder(content, btState);
5684
                    break;
5685
 
149 andreas 5686
                    case 'E':   // Text effect
5687
                        cmd2 = iter->at(1);
5688
                        content = iter->substr(2);
5689
 
5690
                        switch(cmd2)
5691
                        {
5692
                            case 'C':   // Text effect color
5693
                                bt->setTextEffectColor(content, btState);
5694
                            break;
5695
 
5696
                            case 'F':   // Text effect name
5697
                                bt->setTextEffectName(content, btState);
5698
                            break;
5699
 
5700
                            case 'N':   // Enable/disable button
5701
                                bt->setEnable((content[0] == '1' ? true : false));
5702
                            break;
5703
                        }
5704
                    break;
5705
 
5706
                    case 'F':   // Set font file name
5707
                        content = iter->substr(1);
150 andreas 5708
 
5709
                        if (!isdigit(content[0]))
5710
                            bt->setFontFileName(content, -1, btState);
5711
                        else
5712
                            bt->setFontIndex(atoi(content.c_str()), btState);
149 andreas 5713
                    break;
5714
 
5715
                    case 'G':   // Bargraphs
5716
                        cmd2 = iter->at(1);
5717
                        content = iter->substr(2);
5718
 
5719
                        switch(cmd2)
5720
                        {
5721
                            case 'C':   // Bargraph slider color
5722
                                bt->setBargraphSliderColor(content);
5723
                            break;
5724
 
5725
                            case 'D':   // Ramp down time
5726
                                // FIXME: Add function to set ramp time
5727
                            break;
5728
 
5729
                            case 'G':   // Drag increment
5730
                                // FIXME: Add function to set drag increment
5731
                            break;
5732
 
5733
                            case 'H':   // Upper limit
5734
                                bt->setBargraphUpperLimit(atoi(content.c_str()));
5735
                            break;
5736
 
5737
                            case 'I':   // Invert/noninvert
5738
                                // FIXME: Add function to set inverting
5739
                            break;
5740
 
5741
                            case 'L':   // Lower limit
5742
                                bt->setBargraphLowerLimit(atoi(content.c_str()));
5743
                            break;
5744
 
5745
                            case 'N':   // Slider name
5746
                                // FIXME: Add function to set slider name
5747
                            break;
5748
 
5749
                            case 'R':   // Repeat interval
5750
                                // FIXME: Add function to set repeat interval
5751
                            break;
5752
 
5753
                            case 'U':   // Ramp up time
5754
                                // FIXME: Add function to set ramp up time
5755
                            break;
5756
 
5757
                            case 'V':   // Bargraph value
5758
                                // FIXME: Add function to set level value
5759
                            break;
5760
                        }
5761
                    break;
5762
 
152 andreas 5763
                    case 'I':   // Set the icon
5764
                        content = iter->substr(1);
5765
                        bt->setIcon(atoi(content.c_str()), btState);
5766
                    break;
5767
 
149 andreas 5768
                    case 'J':   // Set text justification
150 andreas 5769
                        cmd2 = iter->at(1);
5770
 
5771
                        if (cmd2 != 'T' && cmd2 != 'B' && cmd2 != 'I')
5772
                        {
5773
                            content = iter->substr(1);
152 andreas 5774
                            int just = atoi(content.c_str());
5775
                            int x = 0, y = 0;
5776
 
5777
                            if (just == 0)
5778
                            {
5779
                                vector<string> coords = StrSplit(content, ",");
5780
 
5781
                                if (coords.size() >= 3)
5782
                                {
5783
                                    x = atoi(coords[1].c_str());
5784
                                    y = atoi(coords[2].c_str());
5785
                                }
5786
                            }
5787
 
5788
                            bt->setTextJustification(atoi(content.c_str()), x, y, btState);
150 andreas 5789
                        }
5790
                        else
5791
                        {
5792
                            content = iter->substr(2);
152 andreas 5793
                            int x = 0, y = 0;
5794
                            int just = atoi(content.c_str());
150 andreas 5795
 
152 andreas 5796
                            if (just == 0)
5797
                            {
5798
                                vector<string> coords = StrSplit(content, ",");
5799
 
5800
                                if (coords.size() >= 3)
5801
                                {
5802
                                    x = atoi(coords[1].c_str());
5803
                                    y = atoi(coords[2].c_str());
5804
                                }
5805
                            }
5806
 
150 andreas 5807
                            switch(cmd2)
5808
                            {
5809
                                case 'B':   // Alignment of bitmap
152 andreas 5810
                                    bt->setBitmapJustification(atoi(content.c_str()), x, y, btState);
150 andreas 5811
                                break;
5812
 
5813
                                case 'I':   // Alignment of icon
152 andreas 5814
                                    bt->setIconJustification(atoi(content.c_str()), x, y, btState);
150 andreas 5815
                                break;
5816
 
5817
                                case 'T':   // Alignment of text
152 andreas 5818
                                    bt->setTextJustification(atoi(content.c_str()), x, y, btState);
150 andreas 5819
                                break;
5820
                            }
5821
                        }
5822
                    break;
5823
 
5824
                    case 'M':   // Text area
5825
                        cmd2 = iter->at(1);
5826
                        content = iter->substr(2);
5827
 
5828
                        switch(cmd2)
5829
                        {
152 andreas 5830
                            case 'I':   // Set mask image
5831
                                // FIXME: Add code for image mask
5832
                            break;
5833
 
150 andreas 5834
                            case 'K':   // Input mask of text area
5835
                                // FIXME: Add input mask
5836
                            break;
5837
 
5838
                            case 'L':   // Maximum length of text area
5839
                                // FIXME: Add code to set maximum length
5840
                            break;
5841
                        }
5842
                    break;
5843
 
5844
                    case 'O':   // Set feedback typ, opacity
5845
                        cmd2 = iter->at(1);
5846
 
5847
                        switch(cmd2)
5848
                        {
5849
                            case 'P':   // Set opacity
5850
                                bt->setOpacity(atoi(iter->substr(2).c_str()), btState);
5851
                            break;
5852
 
5853
                            case 'T':   // Set feedback type
5854
                                content = iter->substr(2);
5855
                                content = toUpper(content);
5856
 
5857
                                if (content == "NONE")
5858
                                    bt->setFeedback(Button::FB_NONE);
5859
                                else if (content == "CHANNEL")
5860
                                    bt->setFeedback(Button::FB_CHANNEL);
5861
                                else if (content == "INVERT")
5862
                                    bt->setFeedback(Button::FB_INV_CHANNEL);
5863
                                else if (content == "ON")
5864
                                    bt->setFeedback(Button::FB_ALWAYS_ON);
5865
                                else if (content == "MOMENTARY")
5866
                                    bt->setFeedback(Button::FB_MOMENTARY);
5867
                                else if (content == "BLINK")
5868
                                    bt->setFeedback(Button::FB_BLINK);
5869
                                else
5870
                                {
5871
                                    MSG_WARNING("Unknown feedback type " << content);
5872
                                }
5873
                            break;
5874
 
5875
                            default:
5876
                                content = iter->substr(1);
5877
                                // FIXME: Add code to set the feedback type
5878
                        }
5879
                    break;
5880
 
152 andreas 5881
                    case 'P':   // Set picture/bitmap file name
5882
                        content = iter->substr(1);
165 andreas 5883
 
5884
                        if (content.find(".") == string::npos)  // If the image has no extension ...
5885
                        {                                       // we must find the image in the map
5886
                            string iname = findImage(content);
5887
 
5888
                            if (!iname.empty())
5889
                                content = iname;
5890
                        }
5891
 
152 andreas 5892
                        bt->setBitmap(content, btState);
5893
                    break;
5894
 
5895
                    case 'R':   // Set rectangle
5896
                    {
5897
                        content = iter->substr(1);
5898
                        vector<string> corners = StrSplit(content, ",");
5899
 
5900
                        if (corners.size() > 0)
5901
                        {
5902
                            vector<string>::iterator itcorn;
5903
                            int pos = 0;
5904
                            int left, top, right, bottom;
5905
                            left = top = right = bottom = 0;
5906
 
5907
                            for (itcorn = corners.begin(); itcorn != corners.end(); ++itcorn)
5908
                            {
5909
                                switch(pos)
5910
                                {
5911
                                    case 0: left   = atoi(itcorn->c_str()); break;
5912
                                    case 1: top    = atoi(itcorn->c_str()); break;
5913
                                    case 2: right  = atoi(itcorn->c_str()); break;
5914
                                    case 3: bottom = atoi(itcorn->c_str()); break;
5915
                                }
5916
 
5917
                                pos++;
5918
                            }
5919
 
5920
                            if (pos >= 4)
5921
                                bt->setRectangle(left, top, right, bottom);
5922
                        }
5923
                    }
5924
                    break;
5925
 
150 andreas 5926
                    case 'S':   // show/hide, style, sound
5927
                        cmd2 = iter->at(1);
5928
                        content = iter->substr(2);
5929
 
5930
                        switch(cmd2)
5931
                        {
5932
                            case 'F':   // Set focus of text area button
5933
                                // FIXME: Add code to set the focus of text area button
5934
                            break;
5935
 
5936
                            case 'M':   // Submit text
169 andreas 5937
                                if (content.find("|"))  // To be replaced by LF (0x0a)?
5938
                                {
5939
                                    size_t pos = 0;
5940
 
5941
                                    while ((pos = content.find("|")) != string::npos)
5942
                                        content = content.replace(pos, 1, "\n");
5943
                                }
5944
 
150 andreas 5945
                                bt->setText(content, btState);
5946
                            break;
5947
 
5948
                            case 'O':   // Sound
5949
                                bt->setSound(content, btState);
5950
                            break;
5951
 
5952
                            case 'T':   // Button style
5953
                                // FIXME: Add code to set the button style
5954
                            break;
5955
 
5956
                            case 'W':   // Show / hide button
5957
                                if (content[0] == '0')
5958
                                    bt->hide();
5959
                                else
5960
                                    bt->show();
5961
                            break;
5962
                        }
5963
                    break;
5964
 
152 andreas 5965
                    case 'T':   // Set text
5966
                        content = iter->substr(1);
169 andreas 5967
 
5968
                        if (content.find("|"))  // To be replaced by LF (0x0a)?
5969
                        {
5970
                            size_t pos = 0;
5971
 
5972
                            while ((pos = content.find("|")) != string::npos)
5973
                                content = content.replace(pos, 1, "\n");
5974
                        }
5975
 
152 andreas 5976
                        bt->setText(content, btState);
5977
                    break;
5978
 
150 andreas 5979
                    case 'U':   // Set the unicode text
5980
                        if (iter->at(1) == 'N')
5981
                        {
5982
                            content = iter->substr(2);
152 andreas 5983
                            string byte, text;
5984
                            size_t pos = 0;
5985
 
5986
                            while (pos < content.length())
5987
                            {
5988
                                byte = content.substr(pos, 2);
5989
                                char ch = (char)strtol(byte.c_str(), NULL, 16);
5990
                                text += ch;
5991
                                pos += 2;
5992
                            }
5993
 
169 andreas 5994
                            if (text.find("|"))  // To be replaced by LF (0x0a)?
5995
                            {
5996
                                size_t pos = 0;
5997
 
5998
                                while ((pos = text.find("|")) != string::npos)
5999
                                    text = text.replace(pos, 1, "\n");
6000
                            }
6001
 
152 andreas 6002
                            bt->setText(text, btState);
150 andreas 6003
                        }
6004
                    break;
6005
 
6006
                    case 'V':   // Video on / off
6007
                        cmd2 = iter->at(1);
6008
                        // Controlling a computer remotely is not supported.
6009
                        if (cmd2 != 'L' && cmd2 != 'N' && cmd2 != 'P')
6010
                        {
6011
                            content = iter->substr(2);
6012
                            // FIXME: Add code to switch video on or off
6013
                        }
6014
                    break;
6015
 
6016
                    case 'W':   // Word wrap
152 andreas 6017
                        if (iter->at(1) == 'W')
6018
                        {
6019
                            content = iter->substr(2);
6020
                            bt->setTextWordWrap(content[0] == '1' ? true : false, btState);
6021
                        }
149 andreas 6022
                    break;
6023
                }
6024
            }
6025
        }
6026
    }
6027
}
6028
 
14 andreas 6029
/**
110 andreas 6030
 * Set the maximum length of the text area button. If this value is set to
6031
 * zero (0), the text area has no max length. The maximum length available is
6032
 * 2000. This is only for a Text area input button and not for a Text area input
6033
 * masking button.
6034
 */
6035
void TPageManager::doBML(int port, vector<int>& channels, vector<string>& pars)
6036
{
6037
    DECL_TRACER("TPageManager::doBML(int port, vector<int>& channels, vector<string>& pars)");
6038
 
6039
    if (pars.size() < 1)
6040
    {
6041
        MSG_ERROR("Expecting 1 parameter but got " << pars.size() << "! Ignoring command.");
6042
        return;
6043
    }
6044
 
6045
    TError::clear();
6046
    int maxLen = atoi(pars[0].c_str());
6047
 
6048
    if (maxLen < 0 || maxLen > 2000)
6049
    {
6050
        MSG_WARNING("Got illegal length of text area! [" << maxLen << "]");
6051
        return;
6052
    }
6053
 
193 andreas 6054
    vector<TMap::MAP_T> map = findButtons(port, channels);
110 andreas 6055
 
6056
    if (TError::isError() || map.empty())
6057
        return;
6058
 
6059
    vector<Button::TButton *> buttons = collectButtons(map);
6060
 
6061
    if (buttons.size() > 0)
6062
    {
6063
        vector<Button::TButton *>::iterator mapIter;
6064
 
6065
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
6066
        {
6067
            Button::TButton *bt = *mapIter;
6068
            bt->setTextMaxChars(maxLen);
6069
        }
6070
    }
6071
}
6072
 
6073
/**
60 andreas 6074
 * Assign a picture to those buttons with a defined address range.
6075
 */
6076
void TPageManager::doBMP(int port, vector<int>& channels, vector<string>& pars)
6077
{
6078
    DECL_TRACER("TPageManager::doBMP(int port, vector<int>& channels, vector<string>& pars)");
6079
 
6080
    if (pars.size() < 2)
6081
    {
6082
        MSG_ERROR("Expecting 2 parameters but got " << pars.size() << "! Ignoring command.");
6083
        return;
6084
    }
6085
 
6086
    TError::clear();
6087
    int btState = atoi(pars[0].c_str());
6088
    string bitmap = pars[1];
104 andreas 6089
    // If this is a G5 command, we may have up to 2 additional parameters.
6090
    int slot = -1, justify = -1, jx = 0, jy = 0;
60 andreas 6091
 
104 andreas 6092
    if (pars.size() > 2)
6093
    {
6094
        slot = atoi(pars[2].c_str());
6095
 
6096
        if (pars.size() >= 4)
6097
        {
6098
            justify = atoi(pars[4].c_str());
6099
 
6100
            if (justify == 0)
6101
            {
6102
                if (pars.size() >= 5)
6103
                    jx = atoi(pars[5].c_str());
6104
 
6105
                if (pars.size() >= 6)
6106
                    jy = atoi(pars[6].c_str());
6107
            }
6108
        }
6109
    }
6110
 
193 andreas 6111
    vector<TMap::MAP_T> map = findButtons(port, channels);
60 andreas 6112
 
6113
    if (TError::isError() || map.empty())
6114
        return;
6115
 
6116
    vector<Button::TButton *> buttons = collectButtons(map);
6117
 
83 andreas 6118
    if (buttons.size() > 0)
60 andreas 6119
    {
83 andreas 6120
        vector<Button::TButton *>::iterator mapIter;
60 andreas 6121
 
83 andreas 6122
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
60 andreas 6123
        {
83 andreas 6124
            Button::TButton *bt = *mapIter;
6125
            setButtonCallbacks(bt);
60 andreas 6126
 
83 andreas 6127
            if (btState == 0)       // All instances?
6128
            {
6129
                int bst = bt->getNumberInstances();
96 andreas 6130
                MSG_DEBUG("Setting bitmap " << bitmap << " on all " << bst << " instances...");
83 andreas 6131
 
6132
                for (int i = 0; i < bst; i++)
104 andreas 6133
                {
6134
                    if (justify >= 0)
6135
                    {
6136
                        if (slot == 2)
6137
                            bt->setIconJustification(justify, jx, jy, i);
6138
                        else
106 andreas 6139
                            bt->setBitmapJustification(justify, jx, jy, i);
104 andreas 6140
                    }
6141
 
6142
                    if (slot >= 0)
6143
                    {
6144
                        switch(slot)
6145
                        {
6146
                            case 0: bt->setCameleon(bitmap, i); break;
6147
                            case 2: bt->setIcon(bitmap, i); break;  // On G4 we have no bitmap layer. Therefor we use layer 2 as icon layer.
6148
                            default:
6149
                                bt->setBitmap(bitmap, i);
6150
                        }
6151
                    }
6152
                    else
6153
                        bt->setBitmap(bitmap, i);
6154
                }
83 andreas 6155
            }
6156
            else
104 andreas 6157
            {
6158
                if (justify >= 0)
6159
                {
6160
                    if (slot == 2)
6161
                        bt->setIconJustification(justify, jx, jy, btState);
6162
                    else
106 andreas 6163
                        bt->setBitmapJustification(justify, jx, jy, btState);
104 andreas 6164
                }
6165
 
6166
                if (slot >= 0)
6167
                {
6168
                    switch(slot)
6169
                    {
6170
                        case 0: bt->setCameleon(bitmap, btState); break;
6171
                        case 2: bt->setIcon(bitmap, btState); break;      // On G4 we have no bitmap layer. Therefor we use layer 2 as icon layer.
6172
                        default:
6173
                            bt->setBitmap(bitmap, btState);
6174
                    }
6175
                }
6176
                else
6177
                    bt->setBitmap(bitmap, btState);
6178
            }
60 andreas 6179
        }
6180
    }
6181
}
6182
 
82 andreas 6183
void TPageManager::getBMP(int port, vector<int> &channels, vector<string> &pars)
6184
{
6185
    DECL_TRACER("TPageManager::getBMP(int port, vector<int> &channels, vector<string> &pars)");
6186
 
6187
    if (pars.size() < 1)
6188
    {
6189
        MSG_ERROR("Expecting 1 parameters but got none! Ignoring command.");
6190
        return;
6191
    }
6192
 
6193
    TError::clear();
6194
    int btState = atoi(pars[0].c_str());
6195
    string bmp;
6196
 
193 andreas 6197
    vector<TMap::MAP_T> map = findButtons(port, channels);
82 andreas 6198
 
6199
    if (TError::isError() || map.empty())
6200
        return;
6201
 
6202
    vector<Button::TButton *> buttons = collectButtons(map);
6203
 
83 andreas 6204
    if (buttons.size() > 0)
82 andreas 6205
    {
110 andreas 6206
        Button::TButton *bt = buttons[0];
82 andreas 6207
 
110 andreas 6208
        if (btState == 0)       // All instances?
82 andreas 6209
        {
110 andreas 6210
            int bst = bt->getNumberInstances();
82 andreas 6211
 
110 andreas 6212
            for (int i = 0; i < bst; i++)
82 andreas 6213
            {
110 andreas 6214
                bmp = bt->getBitmapName(i);
82 andreas 6215
 
110 andreas 6216
                if (bmp.empty())
6217
                    continue;
82 andreas 6218
 
110 andreas 6219
                sendCustomEvent(i + 1, bmp.length(), 0, bmp, 1002, bt->getChannelPort(), bt->getChannelNumber());
83 andreas 6220
            }
82 andreas 6221
        }
110 andreas 6222
        else
6223
        {
6224
            bmp = bt->getTextColor(btState-1);
6225
            sendCustomEvent(btState, bmp.length(), 0, bmp, 1002, bt->getChannelPort(), bt->getChannelNumber());
6226
        }
82 andreas 6227
    }
6228
}
6229
 
60 andreas 6230
/**
16 andreas 6231
 * Set the button opacity. The button opacity can be specified as a decimal
6232
 * between 0 - 255, where zero (0) is invisible and 255 is opaque, or as a
6233
 * HEX code, as used in the color commands by preceding the HEX code with
6234
 * the # sign. In this case, #00 becomes invisible and #FF becomes opaque.
6235
 * If the opacity is set to zero (0), this does not make the button inactive,
6236
 * only invisible.
6237
 */
6238
void TPageManager::doBOP(int port, vector<int>& channels, vector<string>& pars)
6239
{
6240
    DECL_TRACER("TPageManager::doBOP(int port, vector<int>& channels, vector<string>& pars)");
6241
 
6242
    if (pars.size() < 2)
6243
    {
6244
        MSG_ERROR("Expecting 2 parameters but got " << pars.size() << "! Ignoring command.");
6245
        return;
6246
    }
6247
 
6248
    TError::clear();
6249
    int btState = atoi(pars[0].c_str());
6250
    int btOpacity = 0;
6251
 
6252
    if (pars[1].at(0) == '#')
6253
        btOpacity = (int)strtol(pars[1].substr(1).c_str(), NULL, 16);
6254
    else
6255
        btOpacity = atoi(pars[1].c_str());
6256
 
193 andreas 6257
    vector<TMap::MAP_T> map = findButtons(port, channels);
16 andreas 6258
 
6259
    if (TError::isError() || map.empty())
6260
        return;
6261
 
6262
    vector<Button::TButton *> buttons = collectButtons(map);
6263
 
83 andreas 6264
    if (buttons.size() > 0)
16 andreas 6265
    {
83 andreas 6266
        vector<Button::TButton *>::iterator mapIter;
16 andreas 6267
 
83 andreas 6268
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
16 andreas 6269
        {
83 andreas 6270
            Button::TButton *bt = *mapIter;
6271
            setButtonCallbacks(bt);
16 andreas 6272
 
83 andreas 6273
            if (btState == 0)       // All instances?
6274
            {
6275
                int bst = bt->getNumberInstances();
6276
                MSG_DEBUG("Setting opacity " << btOpacity << " on all " << bst << " instances...");
6277
 
6278
                for (int i = 0; i < bst; i++)
6279
                    bt->setOpacity(btOpacity, i);
6280
            }
6281
            else
6282
                bt->setOpacity(btOpacity, btState);
16 andreas 6283
        }
6284
    }
6285
}
6286
 
106 andreas 6287
void TPageManager::getBOP(int port, vector<int>& channels, vector<string>& pars)
6288
{
6289
    DECL_TRACER("TPageManager::getBOP(int port, vector<int>& channels, vector<string>& pars)");
6290
 
6291
    if (pars.size() < 1)
6292
    {
6293
        MSG_ERROR("Expecting 1 parameters but got none! Ignoring command.");
6294
        return;
6295
    }
6296
 
6297
    TError::clear();
6298
    int btState = atoi(pars[0].c_str());
6299
 
193 andreas 6300
    vector<TMap::MAP_T> map = findButtons(port, channels);
106 andreas 6301
 
6302
    if (TError::isError() || map.empty())
6303
        return;
6304
 
6305
    vector<Button::TButton *> buttons = collectButtons(map);
6306
 
6307
    if (buttons.size() > 0)
6308
    {
110 andreas 6309
        Button::TButton *bt = buttons[0];
106 andreas 6310
 
110 andreas 6311
        if (btState == 0)       // All instances?
106 andreas 6312
        {
110 andreas 6313
            int bst = bt->getNumberInstances();
106 andreas 6314
 
110 andreas 6315
            for (int i = 0; i < bst; i++)
106 andreas 6316
            {
110 andreas 6317
                int oo = bt->getOpacity(i);
6318
                sendCustomEvent(i + 1, oo, 0, "", 1015, bt->getChannelPort(), bt->getChannelNumber());
106 andreas 6319
            }
6320
        }
110 andreas 6321
        else
6322
        {
6323
            int oo = bt->getOpacity(btState-1);
6324
            sendCustomEvent(btState, oo, 0, "", 1015, bt->getChannelPort(), bt->getChannelNumber());
6325
        }
106 andreas 6326
    }
6327
}
6328
 
60 andreas 6329
void TPageManager::doBOR(int port, vector<int>& channels, vector<string>& pars)
6330
{
6331
    DECL_TRACER("TPageManager::doBOR(int port, vector<int>& channels, vector<string>& pars)");
6332
 
6333
    if (pars.size() < 1)
6334
    {
6335
        MSG_ERROR("Expecting at least 1 parameter but got " << pars.size() << "! Ignoring command.");
6336
        return;
6337
    }
6338
 
6339
    TError::clear();
6340
    // Numbers of styles from 0 to 41
6341
    vector<string> styles = { "No border", "No border", "Single line", "Double line", "Quad line",
6342
                              "Circle 15", "Circle 25", "Single line", "Double line",
6343
                              "Quad line", "Picture frame", "Picture frame", "Double line",
6344
                              "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A",
6345
                              "Bevel-S", "Bevel-M", "Circle 15", "Circle 25", "Neon inactive-S",
6346
                              "Neon inactive-M", "Neon inactive-L", "Neon inactive-L",
6347
                              "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A",
6348
                              "Diamond 55", "Diamond 56" };
6349
    string bor = pars[0];
6350
    string border = "None";
6351
    int ibor = -1;
6352
 
6353
    if (bor.at(0) >= '0' && bor.at(0) <= '9')
6354
        ibor = atoi(bor.c_str());
6355
    else
6356
    {
6357
        vector<string>::iterator iter;
6358
        int i = 0;
6359
 
6360
        for (iter = styles.begin(); iter != styles.end(); ++iter)
6361
        {
6362
            if (strCaseCompare(*iter, bor) == 0)
6363
            {
6364
                ibor = i;
6365
                break;
6366
            }
6367
 
6368
            i++;
6369
        }
6370
    }
6371
 
6372
    if (ibor < 0 || ibor > 41)
6373
    {
6374
        MSG_ERROR("Invalid border type " << bor << "!");
6375
        return;
6376
    }
6377
 
6378
    switch (ibor)
6379
    {
6380
        case 20: border = "Bevel Raised -S"; break;
6381
        case 21: border = "Bevel Raised -M"; break;
6382
        case 24: border = "AMX Elite Raised -S"; break;
6383
        case 25: border = "AMX Elite Inset -S"; break;
6384
        case 26: border = "AMX Elite Raised -M"; break;
6385
        case 27: border = "AMX Elite Inset -M"; break;
6386
        case 28: border = "AMX Elite Raised -L"; break;
6387
        case 29: border = "AMX Elite Inset -L"; break;
6388
        case 30: border = "Circle 35"; break;
6389
        case 31: border = "Circle 45"; break;
6390
        case 32: border = "Circle 55"; break;
6391
        case 33: border = "Circle 65"; break;
6392
        case 34: border = "Circle 75"; break;
6393
        case 35: border = "Circle 85"; break;
6394
        case 36: border = "Circle 95"; break;
6395
        case 37: border = "Circle 105"; break;
6396
        case 38: border = "Circle 115"; break;
6397
        case 39: border = "Circle 125"; break;
6398
        default:
6399
            border = styles[ibor];
6400
    }
6401
 
193 andreas 6402
    vector<TMap::MAP_T> map = findButtons(port, channels);
60 andreas 6403
 
6404
    if (TError::isError() || map.empty())
6405
        return;
6406
 
6407
    vector<Button::TButton *> buttons = collectButtons(map);
6408
 
83 andreas 6409
    if (buttons.size() > 0)
60 andreas 6410
    {
83 andreas 6411
        vector<Button::TButton *>::iterator mapIter;
6412
 
6413
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
6414
        {
6415
            Button::TButton *bt = *mapIter;
6416
            setButtonCallbacks(bt);
6417
            bt->setBorderStyle(border);
6418
        }
60 andreas 6419
    }
6420
}
6421
 
107 andreas 6422
void TPageManager::doBOS(int port, vector<int>& channels, vector<string>& pars)
6423
{
6424
    DECL_TRACER("TPageManager::doBOS(int port, vector<int>& channels, vector<string>& pars)");
6425
 
6426
    if (pars.size() < 2)
6427
    {
6428
        MSG_ERROR("Expecting at least 2 parameters but got " << pars.size() << "! Ignoring command.");
6429
        return;
6430
    }
6431
 
6432
    TError::clear();
6433
    int btState = atoi(pars[0].c_str());
6434
    int videoState = atoi(pars[1].c_str());
6435
 
193 andreas 6436
    vector<TMap::MAP_T> map = findButtons(port, channels);
107 andreas 6437
 
6438
    if (TError::isError() || map.empty())
6439
        return;
6440
 
6441
    vector<Button::TButton *> buttons = collectButtons(map);
6442
 
6443
    if (buttons.size() > 0)
6444
    {
6445
        vector<Button::TButton *>::iterator mapIter;
6446
 
6447
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
6448
        {
6449
            Button::TButton *bt = *mapIter;
6450
 
6451
            if (btState == 0)       // All instances?
6452
                bt->setDynamic(videoState);
6453
            else
6454
                bt->setDynamic(videoState, btState-1);
6455
        }
6456
    }
6457
}
6458
 
16 andreas 6459
/**
60 andreas 6460
 * Set the border of a button state/states.
6461
 * The border names are available through the TPDesign4 border-name drop-down
6462
 * list.
6463
 */
6464
void TPageManager::doBRD(int port, vector<int>& channels, vector<string>& pars)
6465
{
6466
    DECL_TRACER("TPageManager::doBRD(int port, vector<int>& channels, vector<string>& pars)");
6467
 
6468
    if (pars.size() < 1)
6469
    {
6470
        MSG_ERROR("Expecting at least 1 parameter but got " << pars.size() << "! Ignoring command.");
6471
        return;
6472
    }
6473
 
6474
    TError::clear();
6475
    int btState = atoi(pars[0].c_str());
6476
    string border = "None";
6477
 
6478
    if (pars.size() > 1)
6479
        border = pars[1];
6480
 
193 andreas 6481
    vector<TMap::MAP_T> map = findButtons(port, channels);
60 andreas 6482
 
6483
    if (TError::isError() || map.empty())
6484
        return;
6485
 
6486
    vector<Button::TButton *> buttons = collectButtons(map);
6487
 
83 andreas 6488
    if (buttons.size() > 0)
60 andreas 6489
    {
83 andreas 6490
        vector<Button::TButton *>::iterator mapIter;
60 andreas 6491
 
83 andreas 6492
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
60 andreas 6493
        {
83 andreas 6494
            Button::TButton *bt = *mapIter;
6495
            setButtonCallbacks(bt);
60 andreas 6496
 
83 andreas 6497
            if (btState == 0)       // All instances?
6498
            {
6499
                int bst = bt->getNumberInstances();
6500
 
6501
                for (int i = 0; i < bst; i++)
106 andreas 6502
                    bt->setBorderStyle(border, i+1);
83 andreas 6503
            }
6504
            else
106 andreas 6505
                bt->setBorderStyle(border, btState);
60 andreas 6506
        }
6507
    }
6508
}
6509
 
107 andreas 6510
void TPageManager::getBRD(int port, vector<int>& channels, vector<string>& pars)
6511
{
6512
    DECL_TRACER("TPageManager::getBRD(int port, vector<int>& channels, vector<string>& pars)");
6513
 
6514
    if (pars.size() < 1)
6515
    {
6516
        MSG_ERROR("Expecting at least 1 parameter but got " << pars.size() << "! Ignoring command.");
6517
        return;
6518
    }
6519
 
6520
    TError::clear();
6521
    int btState = atoi(pars[0].c_str());
6522
 
193 andreas 6523
    vector<TMap::MAP_T> map = findButtons(port, channels);
107 andreas 6524
 
6525
    if (TError::isError() || map.empty())
6526
        return;
6527
 
6528
    vector<Button::TButton *> buttons = collectButtons(map);
6529
 
6530
    if (buttons.size() > 0)
6531
    {
110 andreas 6532
        Button::TButton *bt = buttons[0];
107 andreas 6533
 
110 andreas 6534
        if (btState == 0)       // All instances?
107 andreas 6535
        {
110 andreas 6536
            int bst = bt->getNumberInstances();
107 andreas 6537
 
110 andreas 6538
            for (int i = 0; i < bst; i++)
107 andreas 6539
            {
110 andreas 6540
                string bname = bt->getBorderStyle(i);
6541
                sendCustomEvent(i + 1, bname.length(), 0, bname, 1014, bt->getChannelPort(), bt->getChannelNumber());
107 andreas 6542
            }
6543
        }
110 andreas 6544
        else
6545
        {
6546
            string bname = bt->getBorderStyle(btState-1);
6547
            sendCustomEvent(btState, bname.length(), 0, bname, 1014, bt->getChannelPort(), bt->getChannelNumber());
6548
        }
107 andreas 6549
    }
6550
}
6551
 
60 andreas 6552
/**
16 andreas 6553
 * Set the button size and its position on the page.
6554
 */
6555
void TPageManager::doBSP(int port, vector<int>& channels, vector<string>& pars)
6556
{
6557
    DECL_TRACER("TPageManager::doBSP(int port, vector<int>& channels, vector<string>& pars)");
6558
 
6559
    if (pars.size() < 1)
6560
    {
6561
        MSG_ERROR("Expecting at least 1 parameter but got " << pars.size() << "! Ignoring command.");
6562
        return;
6563
    }
6564
 
6565
    TError::clear();
6566
    bool bLeft = false, bTop = false, bRight = false, bBottom = false;
6567
    int x, y;
6568
 
83 andreas 6569
    if (pars.size() > 0)
16 andreas 6570
    {
83 andreas 6571
        vector<string>::iterator iter;
6572
 
6573
        for (iter = pars.begin(); iter != pars.end(); iter++)
6574
        {
6575
            if (iter->compare("left") == 0)
6576
                bLeft = true;
6577
            else if (iter->compare("top") == 0)
6578
                bTop = true;
6579
            else if (iter->compare("right") == 0)
6580
                bRight = true;
6581
            else if (iter->compare("bottom") == 0)
6582
                bBottom = true;
6583
        }
16 andreas 6584
    }
6585
 
193 andreas 6586
    vector<TMap::MAP_T> map = findButtons(port, channels);
16 andreas 6587
 
6588
    if (TError::isError() || map.empty())
6589
        return;
6590
 
6591
    vector<Button::TButton *> buttons = collectButtons(map);
6592
 
83 andreas 6593
    if (buttons.size() > 0)
16 andreas 6594
    {
83 andreas 6595
        vector<Button::TButton *>::iterator mapIter;
16 andreas 6596
 
83 andreas 6597
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
6598
        {
6599
            Button::TButton *bt = *mapIter;
6600
            setButtonCallbacks(bt);
16 andreas 6601
 
83 andreas 6602
            if (bLeft)
6603
                x = 0;
16 andreas 6604
 
83 andreas 6605
            if (bTop)
6606
                y = 0;
16 andreas 6607
 
83 andreas 6608
            if (bRight)
16 andreas 6609
            {
83 andreas 6610
                ulong handle = bt->getHandle();
6611
                int parentID = (handle >> 16) & 0x0000ffff;
6612
                int pwidth = 0;
16 andreas 6613
 
83 andreas 6614
                if (parentID < 500)
16 andreas 6615
                {
83 andreas 6616
                    TPage *pg = getPage(parentID);
6617
 
6618
                    if (!pg)
6619
                    {
6620
                        MSG_ERROR("Internal error: Page " << parentID << " not found!");
6621
                        return;
6622
                    }
6623
 
6624
                    pwidth = pg->getWidth();
16 andreas 6625
                }
83 andreas 6626
                else
6627
                {
6628
                    TSubPage *spg = getSubPage(parentID);
16 andreas 6629
 
83 andreas 6630
                    if (!spg)
6631
                    {
6632
                        MSG_ERROR("Internal error: Subpage " << parentID << " not found!");
6633
                        return;
6634
                    }
16 andreas 6635
 
83 andreas 6636
                    pwidth = spg->getWidth();
16 andreas 6637
                }
6638
 
83 andreas 6639
                x = pwidth - bt->getWidth();
16 andreas 6640
            }
6641
 
83 andreas 6642
            if (bBottom)
6643
            {
6644
                ulong handle = bt->getHandle();
6645
                int parentID = (handle >> 16) & 0x0000ffff;
6646
                int pheight = 0;
16 andreas 6647
 
83 andreas 6648
                if (parentID < 500)
6649
                {
6650
                    TPage *pg = getPage(parentID);
16 andreas 6651
 
83 andreas 6652
                    if (!pg)
6653
                    {
6654
                        MSG_ERROR("Internal error: Page " << parentID << " not found!");
6655
                        return;
6656
                    }
16 andreas 6657
 
83 andreas 6658
                    pheight = pg->getHeight();
6659
                }
6660
                else
16 andreas 6661
                {
83 andreas 6662
                    TSubPage *spg = getSubPage(parentID);
16 andreas 6663
 
83 andreas 6664
                    if (!spg)
6665
                    {
6666
                        MSG_ERROR("Internal error: Subpage " << parentID << " not found!");
6667
                        return;
6668
                    }
16 andreas 6669
 
83 andreas 6670
                    pheight = spg->getHeight();
16 andreas 6671
                }
6672
 
83 andreas 6673
                y = pheight - bt->getHeight();
16 andreas 6674
            }
6675
 
83 andreas 6676
            bt->setLeftTop(x, y);
16 andreas 6677
        }
6678
    }
6679
}
6680
 
6681
/**
107 andreas 6682
 * Submit text for text area buttons. This command causes the text areas to
6683
 * send their text as strings to the NetLinx Master.
6684
 */
6685
void TPageManager::doBSM(int port, vector<int>& channels, vector<string>&)
6686
{
6687
    DECL_TRACER("TPageManager::doBSM(int port, vector<int>& channels, vector<string>& pars)");
6688
 
6689
    TError::clear();
193 andreas 6690
    vector<TMap::MAP_T> map = findButtons(port, channels);
107 andreas 6691
 
6692
    if (TError::isError() || map.empty())
6693
        return;
6694
 
6695
    vector<Button::TButton *> buttons = collectButtons(map);
6696
 
6697
    if (buttons.size() > 0)
6698
    {
6699
        vector<Button::TButton *>::iterator mapIter;
6700
 
6701
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
6702
        {
6703
            Button::TButton *bt = *mapIter;
6704
 
195 andreas 6705
            if (bt->getButtonType() != TEXT_INPUT && bt->getButtonType() != GENERAL)
107 andreas 6706
                return;
6707
 
6708
            amx::ANET_SEND scmd;
6709
            scmd.port = bt->getChannelPort();
6710
            scmd.channel = bt->getChannelNumber();
6711
            scmd.ID = scmd.channel;
6712
            scmd.msg = bt->getText(0);
6713
            scmd.MC = 0x008b;       // string value
6714
 
6715
            if (gAmxNet)
6716
                gAmxNet->sendCommand(scmd);
6717
            else
6718
                MSG_WARNING("Missing global class TAmxNet. Can't send message!");
6719
 
6720
        }
6721
    }
6722
}
6723
 
6724
/**
6725
 * Set the sound played when a button is pressed. If the sound name is blank
6726
 * the sound is then cleared. If the sound name is not matched, the button
6727
 * sound is not changed.
6728
 */
6729
void TPageManager::doBSO(int port, vector<int>& channels, vector<string>& pars)
6730
{
6731
    DECL_TRACER("TPageManager::doBSO(int port, vector<int>& channels, vector<string>& pars)");
6732
 
6733
    if (pars.size() < 2)
6734
    {
6735
        MSG_ERROR("Expecting 2 parameters but got " << pars.size() << "! Ignoring command.");
6736
        return;
6737
    }
6738
 
6739
    if (!gPrjResources)
6740
        return;
6741
 
6742
    TError::clear();
6743
    int btState = atoi(pars[0].c_str());
6744
    string sound = pars[1];
6745
 
6746
    if (!soundExist(sound))
6747
        return;
6748
 
193 andreas 6749
    vector<TMap::MAP_T> map = findButtons(port, channels);
107 andreas 6750
 
6751
    if (TError::isError() || map.empty())
6752
        return;
6753
 
6754
    vector<Button::TButton *> buttons = collectButtons(map);
6755
 
6756
    if (buttons.size() > 0)
6757
    {
6758
        vector<Button::TButton *>::iterator mapIter;
6759
 
6760
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
6761
        {
6762
            Button::TButton *bt = *mapIter;
6763
 
6764
            if (btState == 0)
6765
            {
6766
                int bst = bt->getNumberInstances();
6767
 
6768
                for (int i = 0; i < bst; i++)
6769
                    bt->setSound(sound, i);
6770
            }
6771
            else
6772
                bt->setSound(sound, btState-1);
6773
        }
6774
    }
6775
}
6776
 
6777
/**
16 andreas 6778
 * Set the button word wrap feature to those buttons with a defined address
6779
 * range. By default, word-wrap is Off.
6780
 */
6781
void TPageManager::doBWW(int port, vector<int>& channels, vector<string>& pars)
6782
{
6783
    DECL_TRACER("TPageManager::doBWW(int port, vector<int>& channels, vector<string>& pars)");
6784
 
6785
    if (pars.size() < 1)
6786
    {
6787
        MSG_ERROR("Expecting 1 parameter but got " << pars.size() << "! Ignoring command.");
6788
        return;
6789
    }
6790
 
6791
    TError::clear();
6792
    int btState = atoi(pars[0].c_str());
6793
 
193 andreas 6794
    vector<TMap::MAP_T> map = findButtons(port, channels);
16 andreas 6795
 
6796
    if (TError::isError() || map.empty())
6797
        return;
6798
 
6799
    vector<Button::TButton *> buttons = collectButtons(map);
6800
 
83 andreas 6801
    if (buttons.size() > 0)
16 andreas 6802
    {
83 andreas 6803
        vector<Button::TButton *>::iterator mapIter;
16 andreas 6804
 
83 andreas 6805
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
16 andreas 6806
        {
83 andreas 6807
            Button::TButton *bt = *mapIter;
6808
            setButtonCallbacks(bt);
16 andreas 6809
 
83 andreas 6810
            if (btState == 0)       // All instances?
6811
            {
6812
                int bst = bt->getNumberInstances();
6813
                MSG_DEBUG("Setting word wrap on all " << bst << " instances...");
6814
 
6815
                for (int i = 0; i < bst; i++)
110 andreas 6816
                    bt->setTextWordWrap(true, i);
83 andreas 6817
            }
6818
            else
110 andreas 6819
                bt->setTextWordWrap(true, btState - 1);
16 andreas 6820
        }
6821
    }
6822
}
6823
 
108 andreas 6824
void TPageManager::getBWW(int port, vector<int>& channels, vector<string>& pars)
6825
{
6826
    DECL_TRACER("TPageManager::getBWW(int port, vector<int>& channels, vector<string>& pars)");
6827
 
6828
    if (pars.size() < 1)
6829
    {
6830
        MSG_ERROR("Expecting at least 1 parameter but got " << pars.size() << "! Ignoring command.");
6831
        return;
6832
    }
6833
 
6834
    TError::clear();
6835
    int btState = atoi(pars[0].c_str());
6836
 
193 andreas 6837
    vector<TMap::MAP_T> map = findButtons(port, channels);
108 andreas 6838
 
6839
    if (TError::isError() || map.empty())
6840
        return;
6841
 
6842
    vector<Button::TButton *> buttons = collectButtons(map);
6843
 
6844
    if (buttons.size() > 0)
6845
    {
110 andreas 6846
        Button::TButton *bt = buttons[0];
108 andreas 6847
 
110 andreas 6848
        if (btState == 0)       // All instances?
108 andreas 6849
        {
110 andreas 6850
            int bst = bt->getNumberInstances();
108 andreas 6851
 
110 andreas 6852
            for (int i = 0; i < bst; i++)
6853
                sendCustomEvent(i + 1, bt->getTextWordWrap(i), 0, "", 1010, bt->getChannelPort(), bt->getChannelNumber());
108 andreas 6854
        }
110 andreas 6855
        else
6856
            sendCustomEvent(btState, bt->getTextWordWrap(btState-1), 0, "", 1010, bt->getChannelPort(), bt->getChannelNumber());
108 andreas 6857
    }
6858
}
6859
 
16 andreas 6860
/**
6861
 * Clear all page flips from a button.
6862
 */
22 andreas 6863
void TPageManager::doCPF(int port, vector<int>& channels, vector<string>&)
16 andreas 6864
{
6865
    DECL_TRACER("TPageManager::doCPF(int port, vector<int>& channels, vector<string>& pars)");
6866
 
6867
    TError::clear();
193 andreas 6868
    vector<TMap::MAP_T> map = findButtons(port, channels);
16 andreas 6869
 
6870
    if (TError::isError() || map.empty())
6871
        return;
6872
 
6873
    vector<Button::TButton *> buttons = collectButtons(map);
6874
 
83 andreas 6875
    if (buttons.size() > 0)
16 andreas 6876
    {
83 andreas 6877
        vector<Button::TButton *>::iterator mapIter;
6878
 
6879
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
6880
        {
6881
            Button::TButton *bt = *mapIter;
6882
            setButtonCallbacks(bt);
6883
            bt->clearPushFunctions();
6884
        }
16 andreas 6885
    }
6886
}
6887
 
6888
/**
6889
 * Delete page flips from button if it already exists.
6890
 */
6891
void TPageManager::doDPF(int port, vector<int>& channels, vector<string>& pars)
6892
{
6893
    DECL_TRACER("TPageManager::doDPF(int port, vector<int>& channels, vector<string>& pars)");
6894
 
6895
    if (pars.size() < 1)
6896
    {
6897
        MSG_ERROR("Expecting at least 1 parameter but got " << pars.size() << "! Ignoring command.");
6898
        return;
6899
    }
6900
 
6901
    TError::clear();
6902
    string action = pars[0];
6903
    string pname;
6904
 
6905
    if (pars.size() >= 2)
6906
    {
6907
        pname = pars[1];
6908
        vector<Button::TButton *> list;
6909
        // First we search for a subpage because this is more likely
6910
        TSubPage *spg = getSubPage(pname);
6911
 
6912
        if (spg)
6913
            list = spg->getButtons(port, channels[0]);
6914
        else    // Then for a page
6915
        {
6916
            TPage *pg = getPage(pname);
6917
 
6918
            if (pg)
6919
                list = pg->getButtons(port, channels[0]);
6920
            else
6921
            {
6922
                MSG_WARNING("The name " << pname << " doesn't name either a page or a subpage!");
6923
                return;
6924
            }
6925
        }
6926
 
6927
        if (list.empty())
6928
            return;
6929
 
6930
        vector<Button::TButton *>::iterator it;
6931
 
6932
        for (it = list.begin(); it != list.end(); it++)
6933
        {
6934
            Button::TButton *bt = *it;
18 andreas 6935
            setButtonCallbacks(bt);
16 andreas 6936
            bt->clearPushFunction(action);
6937
        }
6938
 
6939
        return;
6940
    }
6941
 
6942
    // Here we don't have a page name
193 andreas 6943
    vector<TMap::MAP_T> map = findButtons(port, channels);
16 andreas 6944
 
6945
    if (TError::isError() || map.empty())
6946
        return;
6947
 
6948
    vector<Button::TButton *> buttons = collectButtons(map);
6949
 
83 andreas 6950
    if (buttons.size() > 0)
16 andreas 6951
    {
83 andreas 6952
        vector<Button::TButton *>::iterator mapIter;
6953
 
6954
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
6955
        {
6956
            Button::TButton *bt = *mapIter;
6957
            setButtonCallbacks(bt);
6958
            bt->clearPushFunction(action);
6959
        }
16 andreas 6960
    }
6961
}
6962
 
6963
/**
6964
 * Enable or disable buttons with a set variable text range.
6965
 */
6966
void TPageManager::doENA(int port, vector<int>& channels, vector<string>& pars)
6967
{
6968
    DECL_TRACER("TPageManager::doENA(int port, vector<int>& channels, vector<string>& pars)");
6969
 
6970
    if (pars.empty())
6971
    {
6972
        MSG_ERROR("Expecting 1 parameter but got none! Ignoring command.");
6973
        return;
6974
    }
6975
 
6976
    TError::clear();
6977
    int cvalue = atoi(pars[0].c_str());
6978
 
193 andreas 6979
    vector<TMap::MAP_T> map = findButtons(port, channels);
16 andreas 6980
 
6981
    if (TError::isError() || map.empty())
6982
        return;
6983
 
6984
    vector<Button::TButton *> buttons = collectButtons(map);
6985
 
83 andreas 6986
    if (buttons.size() > 0)
16 andreas 6987
    {
83 andreas 6988
        vector<Button::TButton *>::iterator mapIter;
6989
 
6990
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
6991
        {
6992
            Button::TButton *bt = *mapIter;
6993
            setButtonCallbacks(bt);
6994
            bt->setEnable(((cvalue)?true:false));
6995
        }
16 andreas 6996
    }
6997
}
6998
 
6999
/**
7000
 * Set a font to a specific Font ID value for those buttons with a defined
7001
 * address range. Font ID numbers are generated by the TPDesign4 programmers
7002
 * report.
7003
 */
7004
void TPageManager::doFON(int port, vector<int>& channels, vector<string>& pars)
7005
{
7006
    DECL_TRACER("TPageManager::doFON(int port, vector<int>& channels, vector<string>& pars)");
7007
 
7008
    if (pars.size() < 2)
7009
    {
7010
        MSG_ERROR("Expecting 2 parameters but got " << pars.size() << "! Ignoring command.");
7011
        return;
7012
    }
7013
 
7014
    TError::clear();
7015
    int btState = atoi(pars[0].c_str());
7016
    int fvalue = atoi(pars[1].c_str());
7017
 
193 andreas 7018
    vector<TMap::MAP_T> map = findButtons(port, channels);
16 andreas 7019
 
7020
    if (TError::isError() || map.empty())
7021
        return;
7022
 
7023
    vector<Button::TButton *> buttons = collectButtons(map);
7024
 
83 andreas 7025
    if (buttons.size() > 0)
16 andreas 7026
    {
83 andreas 7027
        vector<Button::TButton *>::iterator mapIter;
16 andreas 7028
 
83 andreas 7029
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
16 andreas 7030
        {
83 andreas 7031
            Button::TButton *bt = *mapIter;
7032
            setButtonCallbacks(bt);
16 andreas 7033
 
83 andreas 7034
            if (btState == 0)       // All instances?
7035
            {
7036
                int bst = bt->getNumberInstances();
7037
                MSG_DEBUG("Setting font " << fvalue << " on all " << bst << " instances...");
7038
 
7039
                for (int i = 0; i < bst; i++)
7040
                    bt->setFont(fvalue, i);
7041
            }
7042
            else
7043
                bt->setFont(fvalue, btState - 1);
16 andreas 7044
        }
7045
    }
7046
}
7047
 
108 andreas 7048
void TPageManager::getFON(int port, vector<int>& channels, vector<string>& pars)
7049
{
7050
    DECL_TRACER("TPageManager::getFON(int port, vector<int>& channels, vector<string>& pars)");
7051
 
7052
    if (pars.size() < 1)
7053
    {
7054
        MSG_ERROR("Expecting at least 1 parameter but got " << pars.size() << "! Ignoring command.");
7055
        return;
7056
    }
7057
 
7058
    TError::clear();
7059
    int btState = atoi(pars[0].c_str());
7060
 
193 andreas 7061
    vector<TMap::MAP_T> map = findButtons(port, channels);
108 andreas 7062
 
7063
    if (TError::isError() || map.empty())
7064
        return;
7065
 
7066
    vector<Button::TButton *> buttons = collectButtons(map);
7067
 
7068
    if (buttons.size() > 0)
7069
    {
110 andreas 7070
        Button::TButton *bt = buttons[0];
108 andreas 7071
 
110 andreas 7072
        if (btState == 0)       // All instances?
108 andreas 7073
        {
110 andreas 7074
            int bst = bt->getNumberInstances();
108 andreas 7075
 
110 andreas 7076
            for (int i = 0; i < bst; i++)
7077
                sendCustomEvent(i + 1, bt->getFontIndex(i), 0, "", 1007, bt->getChannelPort(), bt->getChannelNumber());
108 andreas 7078
        }
110 andreas 7079
        else
7080
            sendCustomEvent(btState, bt->getFontIndex(btState - 1), 0, "", 1007, bt->getChannelPort(), bt->getChannelNumber());
108 andreas 7081
    }
7082
}
7083
 
16 andreas 7084
/**
60 andreas 7085
 * Change the bargraph upper limit.
7086
 */
7087
void TPageManager::doGLH(int port, vector<int>& channels, vector<std::string>& pars)
7088
{
7089
    DECL_TRACER("TPageManager::doGLH(int port, vector<int>& channels, vector<std::string>& pars)");
7090
 
7091
    if (pars.size() < 1)
7092
    {
7093
        MSG_ERROR("Expecting 1 parameter but got " << pars.size() << "! Ignoring command.");
7094
        return;
7095
    }
7096
 
7097
    TError::clear();
7098
    int limit = atoi(pars[0].c_str());
7099
 
7100
    if (limit < 1)
7101
    {
7102
        MSG_ERROR("Invalid upper limit " << limit << "!");
7103
        return;
7104
    }
7105
 
193 andreas 7106
    vector<TMap::MAP_T> map = findButtons(port, channels);
60 andreas 7107
 
7108
    if (TError::isError() || map.empty())
7109
        return;
7110
 
7111
    vector<Button::TButton *> buttons = collectButtons(map);
7112
 
83 andreas 7113
    if (buttons.size() > 0)
60 andreas 7114
    {
83 andreas 7115
        vector<Button::TButton *>::iterator mapIter;
7116
 
7117
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
7118
        {
7119
            Button::TButton *bt = *mapIter;
7120
            setButtonCallbacks(bt);
7121
            bt->setBargraphUpperLimit(limit);
7122
        }
60 andreas 7123
    }
7124
}
7125
 
7126
/**
7127
 * Change the bargraph lower limit.
7128
 */
7129
void TPageManager::doGLL(int port, vector<int>& channels, vector<std::string>& pars)
7130
{
7131
    DECL_TRACER("TPageManager::doGLL(int port, vector<int>& channels, vector<std::string>& pars)");
7132
 
7133
    if (pars.size() < 1)
7134
    {
7135
        MSG_ERROR("Expecting 1 parameter but got " << pars.size() << "! Ignoring command.");
7136
        return;
7137
    }
7138
 
7139
    TError::clear();
7140
    int limit = atoi(pars[0].c_str());
7141
 
7142
    if (limit < 1)
7143
    {
7144
        MSG_ERROR("Invalid lower limit " << limit << "!");
7145
        return;
7146
    }
7147
 
193 andreas 7148
    vector<TMap::MAP_T> map = findButtons(port, channels);
60 andreas 7149
 
7150
    if (TError::isError() || map.empty())
7151
        return;
7152
 
7153
    vector<Button::TButton *> buttons = collectButtons(map);
7154
 
83 andreas 7155
    if (buttons.size() > 0)
60 andreas 7156
    {
83 andreas 7157
        vector<Button::TButton *>::iterator mapIter;
7158
 
7159
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
7160
        {
7161
            Button::TButton *bt = *mapIter;
7162
            setButtonCallbacks(bt);
7163
            bt->setBargraphLowerLimit(limit);
7164
        }
60 andreas 7165
    }
7166
}
7167
 
108 andreas 7168
void TPageManager::doGSC(int port, vector<int>& channels, vector<string>& pars)
7169
{
7170
    DECL_TRACER("TPageManager::doGSC(int port, vector<int>& channels, vector<string>& pars)");
7171
 
7172
    if (pars.size() < 1)
7173
    {
7174
        MSG_ERROR("Expecting 1 parameter but got " << pars.size() << "! Ignoring command.");
7175
        return;
7176
    }
7177
 
7178
    TError::clear();
7179
    string color = pars[0];
193 andreas 7180
    vector<TMap::MAP_T> map = findButtons(port, channels);
108 andreas 7181
 
7182
    if (TError::isError() || map.empty())
7183
        return;
7184
 
7185
    vector<Button::TButton *> buttons = collectButtons(map);
7186
 
7187
    if (buttons.size() > 0)
7188
    {
7189
        vector<Button::TButton *>::iterator mapIter;
7190
 
7191
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
7192
        {
7193
            Button::TButton *bt = *mapIter;
7194
            setButtonCallbacks(bt);
7195
            bt->setBargraphSliderColor(color);
7196
        }
7197
    }
7198
}
7199
 
60 andreas 7200
/**
14 andreas 7201
 * Set the icon to a button.
7202
 */
7203
void TPageManager::doICO(int port, vector<int>& channels, vector<string>& pars)
7204
{
7205
    DECL_TRACER("TPageManager::doICO(int port, vector<int>& channels, vector<string>& pars)");
7206
 
7207
    if (pars.size() < 2)
7208
    {
7209
        MSG_ERROR("Expecting 2 parameters but got " << pars.size() << "! Ignoring command.");
7210
        return;
7211
    }
7212
 
16 andreas 7213
    TError::clear();
14 andreas 7214
    int btState = atoi(pars[0].c_str());
7215
    int iconIdx = atoi(pars[1].c_str());
7216
 
193 andreas 7217
    vector<TMap::MAP_T> map = findButtons(port, channels);
14 andreas 7218
 
7219
    if (TError::isError() || map.empty())
7220
        return;
7221
 
7222
    vector<Button::TButton *> buttons = collectButtons(map);
7223
 
83 andreas 7224
    if (buttons.size() > 0)
14 andreas 7225
    {
83 andreas 7226
        vector<Button::TButton *>::iterator mapIter;
14 andreas 7227
 
83 andreas 7228
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
14 andreas 7229
        {
83 andreas 7230
            Button::TButton *bt = *mapIter;
7231
            setButtonCallbacks(bt);
14 andreas 7232
 
83 andreas 7233
            if (btState == 0)       // All instances?
14 andreas 7234
            {
83 andreas 7235
                int bst = bt->getNumberInstances();
7236
                MSG_DEBUG("Setting Icon on all " << bst << " instances...");
7237
 
7238
                for (int i = 0; i < bst; i++)
7239
                {
7240
                    if (iconIdx > 0)
7241
                        bt->setIcon(iconIdx, i);
7242
                    else
7243
                        bt->revokeIcon(i);
7244
                }
14 andreas 7245
            }
83 andreas 7246
            else if (iconIdx > 0)
7247
                bt->setIcon(iconIdx, btState - 1);
7248
            else
7249
                bt->revokeIcon(btState - 1);
14 andreas 7250
        }
7251
    }
7252
}
7253
 
108 andreas 7254
void TPageManager::getICO(int port, vector<int>& channels, vector<string>& pars)
7255
{
7256
    DECL_TRACER("TPageManager::getICO(int port, vector<int>& channels, vector<string>& pars)");
7257
 
7258
    if (pars.size() < 1)
7259
    {
7260
        MSG_ERROR("Expecting at least 1 parameter but got " << pars.size() << "! Ignoring command.");
7261
        return;
7262
    }
7263
 
7264
    TError::clear();
7265
    int btState = atoi(pars[0].c_str());
7266
 
193 andreas 7267
    vector<TMap::MAP_T> map = findButtons(port, channels);
108 andreas 7268
 
7269
    if (TError::isError() || map.empty())
7270
        return;
7271
 
7272
    vector<Button::TButton *> buttons = collectButtons(map);
7273
 
7274
    if (buttons.size() > 0)
7275
    {
110 andreas 7276
        Button::TButton *bt = buttons[0];
108 andreas 7277
 
110 andreas 7278
        if (btState == 0)       // All instances?
108 andreas 7279
        {
110 andreas 7280
            int bst = bt->getNumberInstances();
108 andreas 7281
 
110 andreas 7282
            for (int i = 0; i < bst; i++)
7283
                sendCustomEvent(i + 1, bt->getIconIndex(i), 0, "", 1003, bt->getChannelPort(), bt->getChannelNumber());
108 andreas 7284
        }
110 andreas 7285
        else
7286
            sendCustomEvent(btState, bt->getIconIndex(btState - 1), 0, "", 1003, bt->getChannelPort(), bt->getChannelNumber());
108 andreas 7287
    }
7288
}
7289
 
14 andreas 7290
/**
108 andreas 7291
 * Set bitmap/picture alignment using a numeric keypad layout for those buttons
7292
 * with a defined address range. The alignment of 0 is followed by
7293
 * ',<left>,<top>'. The left and top coordinates are relative to the upper left
7294
 * corner of the button.
7295
 */
7296
void TPageManager::doJSB(int port, vector<int>& channels, vector<string>& pars)
7297
{
7298
    DECL_TRACER("TPageManager::doJSB(int port, vector<int>& channels, vector<string>& pars)");
7299
 
7300
    if (pars.size() < 2)
7301
    {
7302
        MSG_ERROR("Expecting at least 2 parameters but got less! Ignoring command.");
7303
        return;
7304
    }
7305
 
7306
    TError::clear();
7307
    int btState = atoi(pars[0].c_str());
7308
    int align = atoi(pars[1].c_str());
7309
    int x = 0, y = 0;
7310
 
7311
    if (!align && pars.size() >= 3)
7312
    {
7313
        x = atoi(pars[2].c_str());
7314
 
7315
        if (pars.size() >= 4)
7316
            y = atoi(pars[3].c_str());
7317
    }
7318
 
193 andreas 7319
    vector<TMap::MAP_T> map = findButtons(port, channels);
108 andreas 7320
 
7321
    if (TError::isError() || map.empty())
7322
        return;
7323
 
7324
    vector<Button::TButton *> buttons = collectButtons(map);
7325
 
7326
    if (buttons.size() > 0)
7327
    {
7328
        vector<Button::TButton *>::iterator mapIter;
7329
 
7330
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
7331
        {
7332
            Button::TButton *bt = *mapIter;
7333
 
7334
            if (btState == 0)
7335
                bt->setBitmapJustification(align, x, y, -1);
7336
            else
7337
                bt->setBitmapJustification(align, x, y, btState-1);
7338
        }
7339
    }
7340
}
7341
 
7342
void TPageManager::getJSB(int port, vector<int>& channels, vector<string>& pars)
7343
{
7344
    DECL_TRACER("TPageManager::getJSB(int port, vector<int>& channels, vector<string>& pars)");
7345
 
7346
    if (pars.size() < 1)
7347
    {
7348
        MSG_ERROR("Expecting at least 1 parameter but got " << pars.size() << "! Ignoring command.");
7349
        return;
7350
    }
7351
 
7352
    TError::clear();
7353
    int btState = atoi(pars[0].c_str());
7354
    int j, x, y;
7355
 
193 andreas 7356
    vector<TMap::MAP_T> map = findButtons(port, channels);
108 andreas 7357
 
7358
    if (TError::isError() || map.empty())
7359
        return;
7360
 
7361
    vector<Button::TButton *> buttons = collectButtons(map);
7362
 
7363
    if (buttons.size() > 0)
7364
    {
110 andreas 7365
        Button::TButton *bt = buttons[0];
108 andreas 7366
 
110 andreas 7367
        if (btState == 0)       // All instances?
108 andreas 7368
        {
110 andreas 7369
            int bst = bt->getNumberInstances();
108 andreas 7370
 
110 andreas 7371
            for (int i = 0; i < bst; i++)
108 andreas 7372
            {
110 andreas 7373
                j = bt->getBitmapJustification(&x, &y, i);
7374
                sendCustomEvent(i + 1, j, 0, "", 1005, bt->getChannelPort(), bt->getChannelNumber());
108 andreas 7375
            }
7376
        }
110 andreas 7377
        else
7378
        {
7379
            j = bt->getBitmapJustification(&x, &y, btState-1);
7380
            sendCustomEvent(btState, j, 0, "", 1005, bt->getChannelPort(), bt->getChannelNumber());
7381
        }
108 andreas 7382
    }
7383
}
7384
 
7385
/**
7386
 * Set icon alignment using a numeric keypad layout for those buttons with a
7387
 * defined address range. The alignment of 0 is followed by ',<left>,<top>'.
7388
 * The left and top coordinates are relative to the upper left corner of the
7389
 * button.
7390
 */
7391
void TPageManager::doJSI(int port, vector<int>& channels, vector<string>& pars)
7392
{
7393
    DECL_TRACER("TPageManager::doJSB(int port, vector<int>& channels, vector<string>& pars)");
7394
 
7395
    if (pars.size() < 2)
7396
    {
7397
        MSG_ERROR("Expecting at least 2 parameters but got less! Ignoring command.");
7398
        return;
7399
    }
7400
 
7401
    TError::clear();
7402
    int btState = atoi(pars[0].c_str());
7403
    int align = atoi(pars[1].c_str());
7404
    int x = 0, y = 0;
7405
 
7406
    if (!align && pars.size() >= 3)
7407
    {
7408
        x = atoi(pars[2].c_str());
7409
 
7410
        if (pars.size() >= 4)
7411
            y = atoi(pars[3].c_str());
7412
    }
7413
 
193 andreas 7414
    vector<TMap::MAP_T> map = findButtons(port, channels);
108 andreas 7415
 
7416
    if (TError::isError() || map.empty())
7417
        return;
7418
 
7419
    vector<Button::TButton *> buttons = collectButtons(map);
7420
 
7421
    if (buttons.size() > 0)
7422
    {
7423
        vector<Button::TButton *>::iterator mapIter;
7424
 
7425
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
7426
        {
7427
            Button::TButton *bt = *mapIter;
7428
 
7429
            if (btState == 0)
7430
                bt->setIconJustification(align, x, y, -1);
7431
            else
7432
                bt->setIconJustification(align, x, y, btState-1);
7433
        }
7434
    }
7435
}
7436
 
7437
void TPageManager::getJSI(int port, vector<int>& channels, vector<string>& pars)
7438
{
7439
    DECL_TRACER("TPageManager::getJSB(int port, vector<int>& channels, vector<string>& pars)");
7440
 
7441
    if (pars.size() < 1)
7442
    {
7443
        MSG_ERROR("Expecting at least 1 parameter but got " << pars.size() << "! Ignoring command.");
7444
        return;
7445
    }
7446
 
7447
    TError::clear();
7448
    int btState = atoi(pars[0].c_str());
7449
    int j, x, y;
7450
 
193 andreas 7451
    vector<TMap::MAP_T> map = findButtons(port, channels);
108 andreas 7452
 
7453
    if (TError::isError() || map.empty())
7454
        return;
7455
 
7456
    vector<Button::TButton *> buttons = collectButtons(map);
7457
 
7458
    if (buttons.size() > 0)
7459
    {
110 andreas 7460
        Button::TButton *bt = buttons[0];
108 andreas 7461
 
110 andreas 7462
        if (btState == 0)       // All instances?
108 andreas 7463
        {
110 andreas 7464
            int bst = bt->getNumberInstances();
108 andreas 7465
 
110 andreas 7466
            for (int i = 0; i < bst; i++)
108 andreas 7467
            {
110 andreas 7468
                j = bt->getIconJustification(&x, &y, i);
7469
                sendCustomEvent(i + 1, j, 0, "", 1006, bt->getChannelPort(), bt->getChannelNumber());
108 andreas 7470
            }
7471
        }
110 andreas 7472
        else
7473
        {
7474
            j = bt->getIconJustification(&x, &y, btState-1);
7475
            sendCustomEvent(btState, j, 0, "", 1006, bt->getChannelPort(), bt->getChannelNumber());
7476
        }
108 andreas 7477
    }
7478
}
7479
 
7480
void TPageManager::doJST(int port, vector<int>& channels, vector<string>& pars)
7481
{
7482
    DECL_TRACER("TPageManager::doJSB(int port, vector<int>& channels, vector<string>& pars)");
7483
 
7484
    if (pars.size() < 2)
7485
    {
7486
        MSG_ERROR("Expecting at least 2 parameters but got less! Ignoring command.");
7487
        return;
7488
    }
7489
 
7490
    TError::clear();
7491
    int btState = atoi(pars[0].c_str());
7492
    int align = atoi(pars[1].c_str());
7493
    int x = 0, y = 0;
7494
 
7495
    if (!align && pars.size() >= 3)
7496
    {
7497
        x = atoi(pars[2].c_str());
7498
 
7499
        if (pars.size() >= 4)
7500
            y = atoi(pars[3].c_str());
7501
    }
7502
 
193 andreas 7503
    vector<TMap::MAP_T> map = findButtons(port, channels);
108 andreas 7504
 
7505
    if (TError::isError() || map.empty())
7506
        return;
7507
 
7508
    vector<Button::TButton *> buttons = collectButtons(map);
7509
 
7510
    if (buttons.size() > 0)
7511
    {
7512
        vector<Button::TButton *>::iterator mapIter;
7513
 
7514
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
7515
        {
7516
            Button::TButton *bt = *mapIter;
7517
 
7518
            if (btState == 0)
7519
                bt->setTextJustification(align, x, y, -1);
7520
            else
7521
                bt->setTextJustification(align, x, y, btState-1);
7522
        }
7523
    }
7524
}
7525
 
7526
void TPageManager::getJST(int port, vector<int>& channels, vector<string>& pars)
7527
{
7528
    DECL_TRACER("TPageManager::getJSB(int port, vector<int>& channels, vector<string>& pars)");
7529
 
7530
    if (pars.size() < 1)
7531
    {
7532
        MSG_ERROR("Expecting at least 1 parameter but got " << pars.size() << "! Ignoring command.");
7533
        return;
7534
    }
7535
 
7536
    TError::clear();
7537
    int btState = atoi(pars[0].c_str());
7538
    int j, x, y;
7539
 
193 andreas 7540
    vector<TMap::MAP_T> map = findButtons(port, channels);
108 andreas 7541
 
7542
    if (TError::isError() || map.empty())
7543
        return;
7544
 
7545
    vector<Button::TButton *> buttons = collectButtons(map);
7546
 
7547
    if (buttons.size() > 0)
7548
    {
110 andreas 7549
        Button::TButton *bt = buttons[0];
108 andreas 7550
 
110 andreas 7551
        if (btState == 0)       // All instances?
108 andreas 7552
        {
110 andreas 7553
            int bst = bt->getNumberInstances();
108 andreas 7554
 
110 andreas 7555
            for (int i = 0; i < bst; i++)
108 andreas 7556
            {
110 andreas 7557
                j = bt->getTextJustification(&x, &y, i);
7558
                sendCustomEvent(i + 1, j, 0, "", 1004, bt->getChannelPort(), bt->getChannelNumber());
108 andreas 7559
            }
7560
        }
110 andreas 7561
        else
7562
        {
7563
            j = bt->getTextJustification(&x, &y, btState-1);
7564
            sendCustomEvent(btState, j, 0, "", 1004, bt->getChannelPort(), bt->getChannelNumber());
7565
        }
108 andreas 7566
    }
7567
}
7568
 
7569
/**
16 andreas 7570
 * Show or hide a button with a set variable text range.
7571
 */
7572
void TPageManager::doSHO(int port, vector<int>& channels, vector<string>& pars)
7573
{
7574
    DECL_TRACER("TPageManager::doSHO(int port, vector<int>& channels, vector<string>& pars)");
7575
 
7576
    if (pars.empty())
7577
    {
7578
        MSG_ERROR("Expecting 1 parameter but got none! Ignoring command.");
7579
        return;
7580
    }
7581
 
7582
    TError::clear();
7583
    int cvalue = atoi(pars[0].c_str());
7584
 
193 andreas 7585
    vector<TMap::MAP_T> map = findButtons(port, channels);
16 andreas 7586
 
7587
    if (TError::isError() || map.empty())
7588
        return;
7589
 
7590
    vector<Button::TButton *> buttons = collectButtons(map);
7591
 
83 andreas 7592
    if (buttons.size() > 0)
16 andreas 7593
    {
83 andreas 7594
        vector<Button::TButton *>::iterator mapIter;
7595
 
7596
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
7597
        {
7598
            Button::TButton *bt = *mapIter;
100 andreas 7599
            int pgID = (bt->getParent() >> 16) & 0x0000ffff;
7600
            bool pVisible = false;
7601
 
7602
            if (pgID < 500)
7603
            {
7604
                TPage *pg = getPage(pgID);
7605
 
7606
                if (pg && pg->isVisilble())
7607
                    pVisible = true;
7608
            }
7609
            else
7610
            {
7611
                TSubPage *pg = getSubPage(pgID);
7612
 
7613
                if (pg && pg->isVisible())
7614
                    pVisible = true;
7615
            }
7616
 
151 andreas 7617
            bool oldV = bt->isVisible();
7618
            bool visible = cvalue ? true : false;
7619
            MSG_DEBUG("Button " << bt->getButtonIndex() << ", \"" << bt->getButtonName() << "\" set " << (visible ? "VISIBLE" : "HIDDEN") << " (Previous: " << (oldV ? "VISIBLE" : "HIDDEN") << ")");
98 andreas 7620
 
151 andreas 7621
            if (visible != oldV)
100 andreas 7622
            {
151 andreas 7623
                bt->setVisible(visible);
100 andreas 7624
 
151 andreas 7625
                if (pVisible)
7626
                {
7627
                    setButtonCallbacks(bt);
7628
 
7629
                    if (_setVisible)
7630
                        _setVisible(bt->getHandle(), visible);
7631
                    else
7632
                        bt->refresh();
7633
                }
100 andreas 7634
            }
83 andreas 7635
        }
16 andreas 7636
    }
7637
}
7638
 
108 andreas 7639
void TPageManager::doTEC(int port, vector<int>& channels, vector<string>& pars)
7640
{
7641
    DECL_TRACER("TPageManager::doTEC(int port, vector<int>& channels, vector<string>& pars)");
7642
 
7643
    if (pars.size() < 2)
7644
    {
7645
        MSG_ERROR("Expecting at least 2 parameters but got less! Ignoring command.");
7646
        return;
7647
    }
7648
 
7649
    TError::clear();
7650
    int btState = atoi(pars[0].c_str());
7651
    string color = pars[1];
7652
 
193 andreas 7653
    vector<TMap::MAP_T> map = findButtons(port, channels);
108 andreas 7654
 
7655
    if (TError::isError() || map.empty())
7656
        return;
7657
 
7658
    vector<Button::TButton *> buttons = collectButtons(map);
7659
 
7660
    if (buttons.size() > 0)
7661
    {
7662
        vector<Button::TButton *>::iterator mapIter;
7663
 
7664
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
7665
        {
7666
            Button::TButton *bt = *mapIter;
7667
 
7668
            if (btState == 0)
7669
                bt->setTextEffectColor(color);
7670
            else
7671
                bt->setTextEffectColor(color, btState-1);
7672
        }
7673
    }
7674
}
7675
 
7676
void TPageManager::getTEC(int port, vector<int>& channels, vector<string>& pars)
7677
{
7678
    DECL_TRACER("TPageManager::getTEC(int port, vector<int>& channels, vector<string>& pars)");
7679
 
7680
    if (pars.size() < 1)
7681
    {
7682
        MSG_ERROR("Expecting at least 1 parameter but got " << pars.size() << "! Ignoring command.");
7683
        return;
7684
    }
7685
 
7686
    TError::clear();
7687
    int btState = atoi(pars[0].c_str());
7688
 
193 andreas 7689
    vector<TMap::MAP_T> map = findButtons(port, channels);
108 andreas 7690
 
7691
    if (TError::isError() || map.empty())
7692
        return;
7693
 
7694
    vector<Button::TButton *> buttons = collectButtons(map);
7695
 
7696
    if (buttons.size() > 0)
7697
    {
110 andreas 7698
        Button::TButton *bt = buttons[0];
7699
 
7700
        if (btState == 0)       // All instances?
7701
        {
7702
            int bst = bt->getNumberInstances();
7703
 
7704
            for (int i = 0; i < bst; i++)
7705
            {
7706
                string c = bt->getTextEffectColor(i);
7707
                sendCustomEvent(i + 1, c.length(), 0, c, 1009, bt->getChannelPort(), bt->getChannelNumber());
7708
            }
7709
        }
7710
        else
7711
        {
7712
            string c = bt->getTextEffectColor(btState-1);
7713
            sendCustomEvent(btState, c.length(), 0, c, 1009, bt->getChannelPort(), bt->getChannelNumber());
7714
        }
7715
    }
7716
}
7717
 
7718
void TPageManager::doTEF(int port, vector<int>& channels, vector<string>& pars)
7719
{
7720
    DECL_TRACER("TPageManager::doTEF(int port, vector<int>& channels, vector<string>& pars)");
7721
 
7722
    if (pars.size() < 2)
7723
    {
7724
        MSG_ERROR("Expecting at least 2 parameters but got less! Ignoring command.");
7725
        return;
7726
    }
7727
 
7728
    TError::clear();
7729
    int btState = atoi(pars[0].c_str());
7730
    string tef = pars[1];
7731
 
193 andreas 7732
    vector<TMap::MAP_T> map = findButtons(port, channels);
110 andreas 7733
 
7734
    if (TError::isError() || map.empty())
7735
        return;
7736
 
7737
    vector<Button::TButton *> buttons = collectButtons(map);
7738
 
7739
    if (buttons.size() > 0)
7740
    {
108 andreas 7741
        vector<Button::TButton *>::iterator mapIter;
7742
 
7743
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
7744
        {
7745
            Button::TButton *bt = *mapIter;
7746
 
110 andreas 7747
            if (btState == 0)
7748
                bt->setTextEffectName(tef);
7749
            else
7750
                bt->setTextEffectName(tef, btState-1);
7751
        }
7752
    }
7753
}
108 andreas 7754
 
110 andreas 7755
void TPageManager::getTEF(int port, vector<int>& channels, vector<string>& pars)
7756
{
7757
    DECL_TRACER("TPageManager::getTEF(int port, vector<int>& channels, vector<string>& pars)");
108 andreas 7758
 
110 andreas 7759
    if (pars.size() < 1)
7760
    {
7761
        MSG_ERROR("Expecting at least 1 parameter but got " << pars.size() << "! Ignoring command.");
7762
        return;
7763
    }
108 andreas 7764
 
110 andreas 7765
    TError::clear();
7766
    int btState = atoi(pars[0].c_str());
7767
 
193 andreas 7768
    vector<TMap::MAP_T> map = findButtons(port, channels);
110 andreas 7769
 
7770
    if (TError::isError() || map.empty())
7771
        return;
7772
 
7773
    vector<Button::TButton *> buttons = collectButtons(map);
7774
 
7775
    if (buttons.size() > 0)
7776
    {
7777
        Button::TButton *bt = buttons[0];
7778
 
7779
        if (btState == 0)       // All instances?
7780
        {
7781
            int bst = bt->getNumberInstances();
7782
 
7783
            for (int i = 0; i < bst; i++)
108 andreas 7784
            {
110 andreas 7785
                string c = bt->getTextEffectName(i);
7786
                sendCustomEvent(i + 1, c.length(), 0, c, 1008, bt->getChannelPort(), bt->getChannelNumber());
108 andreas 7787
            }
7788
        }
110 andreas 7789
        else
7790
        {
7791
            string c = bt->getTextEffectName(btState-1);
7792
            sendCustomEvent(btState, c.length(), 0, c, 1008, bt->getChannelPort(), bt->getChannelNumber());
7793
        }
108 andreas 7794
    }
7795
}
7796
 
16 andreas 7797
/**
14 andreas 7798
 * Assign a text string to those buttons with a defined address range.
7799
 * Sets Non-Unicode text.
7800
 */
7801
void TPageManager::doTXT(int port, vector<int>& channels, vector<string>& pars)
7802
{
7803
    DECL_TRACER("TPageManager::doTXT(int port, vector<int>& channels, vector<string>& pars)");
7804
 
7805
    if (pars.size() < 1)
7806
    {
7807
        MSG_ERROR("Expecting 1 parameters but got none! Ignoring command.");
7808
        return;
7809
    }
7810
 
16 andreas 7811
    TError::clear();
14 andreas 7812
    int btState = atoi(pars[0].c_str());
7813
    string text;
7814
 
7815
    if (pars.size() > 1)
150 andreas 7816
    {
7817
        for (size_t i = 1; i < pars.size(); ++i)
7818
        {
7819
            if (i > 1)
7820
                text += ",";
14 andreas 7821
 
150 andreas 7822
            text += pars[i];
7823
        }
7824
    }
7825
 
193 andreas 7826
    vector<TMap::MAP_T> map = findButtons(port, channels);
14 andreas 7827
 
7828
    if (TError::isError() || map.empty())
7829
        return;
7830
 
7831
    vector<Button::TButton *> buttons = collectButtons(map);
7832
 
83 andreas 7833
    if (buttons.size() > 0)
14 andreas 7834
    {
83 andreas 7835
        vector<Button::TButton *>::iterator mapIter;
14 andreas 7836
 
83 andreas 7837
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
14 andreas 7838
        {
83 andreas 7839
            Button::TButton *bt = *mapIter;
7840
            setButtonCallbacks(bt);
14 andreas 7841
 
83 andreas 7842
            if (btState == 0)       // All instances?
7843
            {
7844
                int bst = bt->getNumberInstances();
7845
                MSG_DEBUG("Setting TXT on all " << bst << " instances...");
7846
 
7847
                for (int i = 0; i < bst; i++)
7848
                    bt->setText(text, i);
7849
            }
7850
            else
7851
                bt->setText(text, btState - 1);
14 andreas 7852
        }
7853
    }
7854
}
21 andreas 7855
 
110 andreas 7856
void TPageManager::getTXT(int port, vector<int>& channels, vector<string>& pars)
7857
{
7858
    DECL_TRACER("TPageManager::getTXT(int port, vector<int>& channels, vector<string>& pars)");
7859
 
7860
    if (pars.size() < 1)
7861
    {
7862
        MSG_ERROR("Expecting at least 1 parameter but got " << pars.size() << "! Ignoring command.");
7863
        return;
7864
    }
7865
 
7866
    TError::clear();
7867
    int btState = atoi(pars[0].c_str());
7868
 
193 andreas 7869
    vector<TMap::MAP_T> map = findButtons(port, channels);
110 andreas 7870
 
7871
    if (TError::isError() || map.empty())
7872
        return;
7873
 
7874
    vector<Button::TButton *> buttons = collectButtons(map);
7875
 
7876
    if (buttons.size() > 0)
7877
    {
7878
        Button::TButton *bt = buttons[0];
7879
 
7880
        if (btState == 0)       // All instances?
7881
        {
7882
            int bst = bt->getNumberInstances();
7883
 
7884
            for (int i = 0; i < bst; i++)
7885
            {
7886
                string c = bt->getText(i);
7887
                sendCustomEvent(i + 1, c.length(), 0, c, 1001, bt->getChannelPort(), bt->getChannelNumber());
7888
            }
7889
        }
7890
        else
7891
        {
7892
            string c = bt->getText(btState-1);
7893
            sendCustomEvent(btState, c.length(), 0, c, 1001, bt->getChannelPort(), bt->getChannelNumber());
7894
        }
7895
    }
7896
}
7897
 
97 andreas 7898
/*
104 andreas 7899
 * Set button state legacy unicode text command.
7900
 *
7901
 * Set Unicode text in the legacy G4 format. For the ^UNI command, the Unicode
7902
 * text is sent as ASCII-HEX nibbles.
7903
 */
7904
void TPageManager::doUNI(int port, vector<int>& channels, vector<string>& pars)
7905
{
7906
    DECL_TRACER("TPageManager::doUNI(int port, vector<int>& channels, vector<string>& pars)");
7907
 
7908
    if (pars.size() < 1)
7909
    {
7910
        MSG_ERROR("Expecting 1 parameters but got none! Ignoring command.");
7911
        return;
7912
    }
7913
 
7914
    TError::clear();
7915
    int btState = atoi(pars[0].c_str());
7916
    string text;
7917
 
7918
    // Because UTF8 is not supported out of the box from Windows and NetLinx
7919
    // Studio has no native support for it, any UTF8 text must be encoded in
7920
    // bytes. Because of this we must decode the bytes into real bytes here.
7921
    if (pars.size() > 1)
7922
    {
7923
        string byte;
7924
        size_t pos = 0;
7925
 
7926
        while (pos < pars[1].length())
7927
        {
7928
            byte = pars[1].substr(pos, 2);
7929
            char ch = (char)strtol(byte.c_str(), NULL, 16);
7930
            text += ch;
7931
            pos += 2;
7932
        }
7933
    }
7934
 
193 andreas 7935
    vector<TMap::MAP_T> map = findButtons(port, channels);
104 andreas 7936
 
7937
    if (TError::isError() || map.empty())
7938
        return;
7939
 
7940
    vector<Button::TButton *> buttons = collectButtons(map);
7941
 
7942
    if (buttons.size() > 0)
7943
    {
7944
        vector<Button::TButton *>::iterator mapIter;
7945
 
7946
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
7947
        {
7948
            Button::TButton *bt = *mapIter;
7949
            setButtonCallbacks(bt);
7950
 
7951
            if (btState == 0)       // All instances?
7952
            {
7953
                int bst = bt->getNumberInstances();
7954
                MSG_DEBUG("Setting UNI on all " << bst << " instances...");
7955
 
7956
                for (int i = 0; i < bst; i++)
7957
                    bt->setText(text, i);
7958
            }
7959
            else
7960
                bt->setText(text, btState - 1);
7961
        }
7962
    }
7963
}
7964
 
7965
void TPageManager::doUTF(int port, vector<int>& channels, vector<string>& pars)
7966
{
7967
    DECL_TRACER("TPageManager::doTXT(int port, vector<int>& channels, vector<string>& pars)");
7968
 
7969
    if (pars.size() < 1)
7970
    {
7971
        MSG_ERROR("Expecting 1 parameters but got none! Ignoring command.");
7972
        return;
7973
    }
7974
 
7975
    TError::clear();
7976
    int btState = atoi(pars[0].c_str());
7977
    string text;
7978
 
7979
    if (pars.size() > 1)
150 andreas 7980
    {
7981
        for (size_t i = 1; i < pars.size(); ++i)
7982
        {
7983
            if (i > 1)
7984
                text += ",";
104 andreas 7985
 
150 andreas 7986
            text += pars[i];
7987
        }
7988
    }
7989
 
193 andreas 7990
    vector<TMap::MAP_T> map = findButtons(port, channels);
104 andreas 7991
 
7992
    if (TError::isError() || map.empty())
7993
        return;
7994
 
7995
    vector<Button::TButton *> buttons = collectButtons(map);
7996
 
7997
    if (buttons.size() > 0)
7998
    {
7999
        vector<Button::TButton *>::iterator mapIter;
8000
 
8001
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
8002
        {
8003
            Button::TButton *bt = *mapIter;
8004
            setButtonCallbacks(bt);
8005
 
8006
            if (btState == 0)       // All instances?
8007
            {
8008
                int bst = bt->getNumberInstances();
8009
                MSG_DEBUG("Setting TXT on all " << bst << " instances...");
8010
 
8011
                for (int i = 0; i < bst; i++)
8012
                    bt->setText(text, i);
8013
            }
8014
            else
8015
                bt->setText(text, btState - 1);
8016
        }
8017
    }
8018
}
111 andreas 8019
 
148 andreas 8020
void TPageManager::doVTP (int, vector<int>&, vector<string>& pars)
8021
{
8022
    DECL_TRACER("TPageManager::doVTP (int, vector<int>&, vector<string>& pars)");
8023
 
8024
    if (pars.size() < 3)
8025
    {
8026
        MSG_ERROR("Expected 3 parameters but got only " << pars.size() << " parameters!");
8027
        return;
8028
    }
8029
 
8030
    int pushType = atoi(pars[0].c_str());
8031
    int x = atoi(pars[1].c_str());
8032
    int y = atoi(pars[2].c_str());
8033
 
8034
    if (pushType < 0 || pushType > 2)
8035
    {
8036
        MSG_ERROR("Invalid push type " << pushType << ". Ignoring command!");
8037
        return;
8038
    }
8039
 
217 andreas 8040
    if (x < 0 || x > mTSettings->getWidth() || y < 0 || y > mTSettings->getHeight())
148 andreas 8041
    {
8042
        MSG_ERROR("Illegal coordinates " << x << " x " << y << ". Ignoring command!");
8043
        return;
8044
    }
8045
 
8046
    if (pushType == 0 || pushType == 2)
8047
        mouseEvent(x, y, true);
8048
 
8049
    if (pushType == 1 || pushType == 2)
8050
        mouseEvent(x, y, false);
8051
}
8052
 
111 andreas 8053
/**
8054
 * Set the keyboard passthru.
8055
 */
8056
void TPageManager::doKPS(int, vector<int>&, vector<string>& pars)
8057
{
8058
    DECL_TRACER("TPageManager::doKPS(int, vector<int>&, vector<string>& pars)");
8059
 
8060
    if (pars.size() < 1)
8061
    {
8062
        MSG_ERROR("Got no parameter. Ignoring command!");
8063
        return;
8064
    }
8065
 
8066
    int state = atoi(pars[0].c_str());
8067
 
8068
    if (state == 0)
8069
        mPassThrough = false;
8070
    else if (state == 5)
8071
        mPassThrough = true;
8072
}
8073
 
8074
void TPageManager::doVKS(int, std::vector<int>&, vector<string>& pars)
8075
{
8076
    DECL_TRACER("TPageManager::doVKS(int, std::vector<int>&, vector<string>& pars)");
8077
 
8078
    if (pars.size() < 1)
8079
    {
8080
        MSG_ERROR("Got no parameter. Ignoring command!");
8081
        return;
8082
    }
8083
 
8084
    if (_sendVirtualKeys)
8085
        _sendVirtualKeys(pars[0]);
8086
}
8087
 
104 andreas 8088
/*
97 andreas 8089
 * Set the bitmap of a button to use a particular resource.
8090
 * Syntax:
8091
 *    "'^BBR-<vt addr range>,<button states range>,<resource name>'"
8092
 * Variable:
8093
 *    variable text address range = 1 - 4000.
8094
 *    button states range = 1 - 256 for multi-state buttons (0 = All states, for General buttons 1 = Off state and 2 = On state).
8095
 *    resource name = 1 - 50 ASCII characters.
8096
 * Example:
8097
 *    SEND_COMMAND Panel,"'^BBR-700,1,Sports_Image'"
8098
 *    Sets the resource name of the button to ’Sports_Image’.
8099
 */
21 andreas 8100
void TPageManager::doBBR(int port, vector<int>& channels, vector<string>& pars)
8101
{
8102
    DECL_TRACER("TPageManager::doBBR(int port, vector<int>& channels, vector<string>& pars)");
8103
 
8104
    if (pars.size() < 2)
8105
    {
8106
        MSG_ERROR("Expecting 2 parameters but got none! Ignoring command.");
8107
        return;
8108
    }
8109
 
8110
    TError::clear();
8111
    int btState = atoi(pars[0].c_str());
8112
    string resName = pars[1];
8113
 
193 andreas 8114
    vector<TMap::MAP_T> map = findButtons(port, channels);
21 andreas 8115
 
8116
    if (TError::isError() || map.empty())
8117
        return;
8118
 
8119
    vector<Button::TButton *> buttons = collectButtons(map);
8120
 
83 andreas 8121
    if (buttons.size() > 0)
21 andreas 8122
    {
83 andreas 8123
        vector<Button::TButton *>::iterator mapIter;
21 andreas 8124
 
83 andreas 8125
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
21 andreas 8126
        {
83 andreas 8127
            Button::TButton *bt = *mapIter;
8128
            setButtonCallbacks(bt);
21 andreas 8129
 
83 andreas 8130
            if (btState == 0)       // All instances?
8131
            {
8132
                int bst = bt->getNumberInstances();
8133
                MSG_DEBUG("Setting BBR on all " << bst << " instances...");
8134
 
8135
                for (int i = 0; i < bst; i++)
8136
                    bt->setResourceName(resName, i);
8137
            }
8138
            else
8139
                bt->setResourceName(resName, btState - 1);
97 andreas 8140
 
8141
            if (bt->isVisible())
8142
                bt->refresh();
99 andreas 8143
            else if (_setVisible)
8144
                _setVisible(bt->getHandle(), false);
21 andreas 8145
        }
8146
    }
8147
}
8148
 
97 andreas 8149
/*
8150
 * Add new resources
8151
 * Adds any and all resource parameters by sending embedded codes and data.
8152
 * Since the embedded codes are preceded by a '%' character, any '%' character
8153
 * contained in* the URL must be escaped with a second '%' character (see
8154
 * example).
8155
 * The file name field (indicated by a %F embedded code) may contain special
8156
 * escape sequences as shown in the ^RAF, ^RMF.
8157
 * Syntax:
8158
 *    "'^RAF-<resource name>,<data>'"
8159
 * Variables:
8160
 *    resource name = 1 - 50 ASCII characters.
8161
 *    data = Refers to the embedded codes, see the ^RAF, ^RMF.
8162
 * Example:
8163
 *    SEND_COMMAND Panel,"'^RAF-New Image,%P0%HAMX.COM%ALab/Test%%5Ffile%Ftest.jpg'"
8164
 *    Adds a new resource.
8165
 *    The resource name is ’New Image’
8166
 *    %P (protocol) is an HTTP
8167
 *    %H (host name) is AMX.COM
8168
 *    %A (file path) is Lab/Test_f ile
8169
 *    %F (file name) is test.jpg.
8170
 *    Note that the %%5F in the file path is actually encoded as %5F.
8171
 */
8172
void TPageManager::doRAF(int, vector<int>&, vector<string>& pars)
8173
{
8174
    DECL_TRACER("TPageManager::doRAF(int port, vector<int>& channels, vector<string>& pars)");
8175
 
8176
    if (pars.size() < 2)
8177
    {
8178
        MSG_ERROR("Expecting 2 parameters but got none! Ignoring command.");
8179
        return;
8180
    }
8181
 
8182
    string name = pars[0];
8183
    string data = pars[1];
8184
 
8185
    vector<string> parts = StrSplit(data, "%");
8186
    RESOURCE_T res;
8187
 
8188
    if (parts.size() > 0)
8189
    {
8190
        vector<string>::iterator sIter;
8191
 
8192
        for (sIter = parts.begin(); sIter != parts.end(); sIter++)
8193
        {
8194
            const char *s = sIter->c_str();
8195
            string ss = *sIter;
8196
            MSG_DEBUG("Parsing \"" << ss << "\" with token << " << ss[0]);
8197
 
8198
            switch(*s)
8199
            {
8200
                case 'P':
8201
                    if (*(s+1) == '0')
8202
                        res.protocol = "HTTP";
8203
                    else
8204
                        res.protocol = "FTP";
8205
                    break;
8206
 
8207
                case 'U': res.user = sIter->substr(1); break;
8208
                case 'S': res.password = sIter->substr(1); break;
8209
                case 'H': res.host = sIter->substr(1); break;
8210
                case 'F': res.file = sIter->substr(1); break;
8211
                case 'A': res.path = sIter->substr(1); break;
8212
                case 'R': res.refresh = atoi(sIter->substr(1).c_str()); break;
8213
 
8214
                default:
8215
                    MSG_WARNING("Option " << sIter->at(0) << " is currently not implemented!");
8216
            }
8217
        }
8218
 
8219
        if (gPrjResources)
8220
            gPrjResources->addResource(name, res.protocol, res.host, res.path, res.file, res.user, res.password, res.refresh);
8221
    }
8222
}
8223
 
111 andreas 8224
void TPageManager::doRFR(int, vector<int>&, vector<string>& pars)
97 andreas 8225
{
8226
    DECL_TRACER("TPageManager::doRFR(int port, vector<int>& channels, vector<string>& pars)");
8227
 
8228
    if (pars.size() < 1)
8229
    {
8230
        MSG_ERROR("Expecting 1 parameter but got none! Ignoring command.");
8231
        return;
8232
    }
8233
 
8234
    string name = pars[0];
193 andreas 8235
    vector<TMap::MAP_T> map = findButtonByName(name);
97 andreas 8236
 
8237
    if (TError::isError() || map.empty())
8238
        return;
8239
 
8240
    vector<Button::TButton *> buttons = collectButtons(map);
8241
 
8242
    if (buttons.size() > 0)
8243
    {
8244
        vector<Button::TButton *>::iterator mapIter;
8245
 
8246
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
8247
        {
8248
            Button::TButton *bt = *mapIter;
8249
 
8250
            if (bt->isVisible())
8251
            {
8252
                setButtonCallbacks(bt);
8253
                bt->refresh();
8254
            }
8255
        }
8256
    }
8257
}
8258
 
8259
/*
8260
 * Modify an existing resource
8261
 *
8262
 * Modifies any and all resource parameters by sending embedded codes and data.
8263
 * Since the embedded codes are preceded by a '%' character, any '%' character
8264
 * contained in the URL must be escaped with a second '%' character (see
8265
 * example).
8266
 * The file name field (indicated by a %F embedded code) may contain special
8267
 * escape sequences as shown in the ^RAF.
8268
 *
8269
 * Syntax:
8270
 * "'^RMF-<resource name>,<data>'"
8271
 * Variables:
8272
 *   • resource name = 1 - 50 ASCII characters
8273
 *   • data = Refers to the embedded codes, see the ^RAF, ^RMF.
8274
 * Example:
8275
 *   SEND_COMMAND Panel,"'^RMF-Sports_Image,%ALab%%5FTest/Images%Ftest.jpg'"
8276
 * Changes the resource ’Sports_Image’ file name to ’test.jpg’ and the path to
8277
 * ’Lab_Test/Images’.
8278
 * Note that the %%5F in the file path is actually encoded as %5F.
8279
 */
22 andreas 8280
void TPageManager::doRMF(int, vector<int>&, vector<string>& pars)
21 andreas 8281
{
8282
    DECL_TRACER("TPageManager::doRMF(int port, vector<int>& channels, vector<string>& pars)");
8283
 
8284
    if (pars.size() < 2)
8285
    {
8286
        MSG_ERROR("Expecting 2 parameters but got none! Ignoring command.");
8287
        return;
8288
    }
8289
 
8290
    string name = pars[0];
8291
    string data = pars[1];
8292
 
8293
    vector<string> parts = StrSplit(data, "%");
8294
    RESOURCE_T res;
8295
 
83 andreas 8296
    if (parts.size() > 0)
21 andreas 8297
    {
83 andreas 8298
        vector<string>::iterator sIter;
21 andreas 8299
 
83 andreas 8300
        for (sIter = parts.begin(); sIter != parts.end(); sIter++)
21 andreas 8301
        {
83 andreas 8302
            const char *s = sIter->c_str();
8303
            string ss = *sIter;
8304
            MSG_DEBUG("Parsing \"" << ss << "\" with token << " << ss[0]);
21 andreas 8305
 
83 andreas 8306
            switch(*s)
8307
            {
8308
                case 'P':
8309
                    if (*(s+1) == '0')
8310
                        res.protocol = "HTTP";
8311
                    else
8312
                        res.protocol = "FTP";
8313
                break;
21 andreas 8314
 
83 andreas 8315
                case 'U': res.user = sIter->substr(1); break;
8316
                case 'S': res.password = sIter->substr(1); break;
8317
                case 'H': res.host = sIter->substr(1); break;
8318
                case 'F': res.file = sIter->substr(1); break;
8319
                case 'A': res.path = sIter->substr(1); break;
8320
                case 'R': res.refresh = atoi(sIter->substr(1).c_str()); break;
8321
 
8322
                default:
8323
                    MSG_WARNING("Option " << sIter->at(0) << " is currently not implemented!");
8324
            }
21 andreas 8325
        }
83 andreas 8326
 
8327
        if (gPrjResources)
8328
            gPrjResources->setResource(name, res.protocol, res.host, res.path, res.file, res.user, res.password, res.refresh);
21 andreas 8329
    }
8330
}
62 andreas 8331
 
8332
/**
111 andreas 8333
 * Change the refresh rate for a given resource.
8334
 */
8335
void TPageManager::doRSR(int, vector<int>&, vector<string>& pars)
8336
{
8337
    DECL_TRACER("TPageManager::doRSR(int, vector<int>&, vector<string>& pars)");
8338
 
8339
    if (pars.size() < 2)
8340
    {
8341
        MSG_ERROR("Expecting 2 parameters but got none! Ignoring command.");
8342
        return;
8343
    }
8344
 
8345
    string resName = pars[0];
8346
    int resRefresh = atoi(pars[1].c_str());
8347
 
8348
    if (!gPrjResources)
8349
    {
8350
        MSG_ERROR("Missing the resource module. Ignoring command!");
8351
        return;
8352
    }
8353
 
8354
    RESOURCE_T res = gPrjResources->findResource(resName);
8355
 
8356
    if (res.name.empty() || res.refresh == resRefresh)
8357
        return;
8358
 
8359
    gPrjResources->setResource(resName, res.protocol, res.host, res.path, res.file, res.user, res.password, resRefresh);
8360
}
8361
 
8362
/**
62 andreas 8363
 * @brief TPageManager::doAKB - Pop up the keyboard icon
8364
 * Pop up the keyboard icon and initialize the text string to that specified.
8365
 * Keyboard string is set to null on power up and is stored until power is lost.
8366
 * The Prompt Text is optional.
8367
 */
8368
void TPageManager::doAKB(int, vector<int>&, vector<string> &pars)
8369
{
8370
    DECL_TRACER("TPageManager::doAKB(int, vector<int>&, vector<string> &pars)");
8371
 
8372
    if (pars.size() < 1)
8373
    {
8374
        MSG_ERROR("Expecting 2 parameters but got only " << pars.size() << "! Ignoring command.");
8375
        return;
8376
    }
8377
 
8378
    string initText = pars[0];
8379
    string promptText;
8380
 
8381
    if (pars.size() > 1)
8382
        promptText = pars[1];
8383
 
63 andreas 8384
    if (initText.empty())
8385
        initText = mAkbText;
8386
    else
8387
        mAkbText = initText;
62 andreas 8388
 
8389
    if (_callKeyboard)
63 andreas 8390
        _callKeyboard(initText, promptText, false);
62 andreas 8391
}
8392
 
63 andreas 8393
/**
8394
 * Pop up the keyboard icon and initialize the text string to that
8395
 * specified.
8396
 */
62 andreas 8397
void TPageManager::doAKEYB(int port, vector<int>& channels, vector<string>& pars)
8398
{
8399
    DECL_TRACER("TPageManager::doAKEYB(int port, vector<int>& channels, vector<string>& pars)");
8400
 
8401
    doAKB(port, channels, pars);
8402
}
8403
 
63 andreas 8404
void TPageManager::doAKEYP(int port, std::vector<int>& channels, std::vector<std::string>& pars)
8405
{
8406
    DECL_TRACER("TPageManager::doAKEYP(int port, std::vector<int>& channels, std::vector<std::string>& pars)");
8407
 
8408
    doAKP(port, channels, pars);
8409
}
8410
 
62 andreas 8411
/**
63 andreas 8412
 * Remove keyboard or keypad that was displayed using 'AKEYB', 'AKEYP', 'PKEYP',
8413
 * @AKB, @AKP, @PKP, @EKP, or @TKP commands.
8414
 */
8415
void TPageManager::doAKEYR(int, vector<int>&, vector<string>&)
8416
{
8417
    DECL_TRACER("TPageManager::doAKEYR(int, vector<int>&, vector<string>&)");
8418
 
8419
    if (_callResetKeyboard)
8420
        _callResetKeyboard();
8421
}
8422
 
8423
/**
62 andreas 8424
 * @brief TPageManager::doAKP - Pop up the keypad icon
8425
 * Pop up the keypad icon and initialize the text string to that specified.
8426
 * Keypad string is set to null on power up and is stored until power is lost.
8427
 * The Prompt Text is optional.
8428
 */
8429
void TPageManager::doAKP(int, std::vector<int>&, std::vector<std::string> &pars)
8430
{
8431
    DECL_TRACER("TPageManager::doAKP(int, vector<int>&, vector<string> &pars)");
8432
 
8433
    if (pars.size() < 1)
8434
    {
8435
        MSG_ERROR("Expecting 2 parameters but got only " << pars.size() << "! Ignoring command.");
8436
        return;
8437
    }
8438
 
8439
    string initText = pars[0];
8440
    string promptText;
8441
 
8442
    if (pars.size() > 1)
8443
        promptText = pars[1];
8444
 
63 andreas 8445
    if (initText.empty())
8446
        initText = mAkpText;
8447
    else
8448
        mAkpText = initText;
62 andreas 8449
 
8450
    if (_callKeypad)
63 andreas 8451
        _callKeypad(initText, promptText, false);
62 andreas 8452
}
8453
 
63 andreas 8454
/**
8455
 * Remove keyboard or keypad that was displayed using 'AKEYB', 'AKEYP', 'PKEYP',
8456
 * @AKB, @AKP, @PKP, @EKP, or @TKP commands.
8457
 */
8458
void TPageManager::doAKR(int port, vector<int>& channels, vector<string>& pars)
62 andreas 8459
{
63 andreas 8460
    DECL_TRACER("TPageManager::doAKR(int, vector<int>&, vector<string>&)");
62 andreas 8461
 
63 andreas 8462
    doAKEYR(port, channels, pars);
62 andreas 8463
}
8464
 
108 andreas 8465
void TPageManager::doABEEP(int, std::vector<int>&, vector<string>&)
8466
{
8467
    DECL_TRACER("TPageManager::doBEEP(int, std::vector<int>&, vector<string>&)");
8468
 
8469
    if (!_playSound)
8470
        return;
8471
 
8472
    string snd = TConfig::getSystemPath(TConfig::SOUNDS) + "/" + TConfig::getSingleBeepSound();
8473
    TValidateFile vf;
8474
 
8475
    if (_playSound && vf.isValidFile(snd))
8476
        _playSound(snd);
8477
}
8478
 
8479
void TPageManager::doADBEEP(int, std::vector<int>&, vector<string>&)
8480
{
8481
    DECL_TRACER("TPageManager::doDBEEP(int, std::vector<int>&, vector<string>&)");
8482
 
8483
    if (!_playSound)
8484
        return;
8485
 
8486
    string snd = TConfig::getSystemPath(TConfig::SOUNDS) + "/" + TConfig::getDoubleBeepSound();
8487
    TValidateFile vf;
8488
 
8489
    if (_playSound && vf.isValidFile(snd))
8490
        _playSound(snd);
8491
}
8492
 
71 andreas 8493
void TPageManager::doBEEP(int, std::vector<int>&, vector<string>&)
8494
{
8495
    DECL_TRACER("TPageManager::doBEEP(int, std::vector<int>&, vector<string>&)");
8496
 
8497
    if (!_playSound)
8498
        return;
8499
 
8500
    string snd = TConfig::getSystemPath(TConfig::SOUNDS) + "/" + TConfig::getSingleBeepSound();
8501
    TValidateFile vf;
108 andreas 8502
    TSystemSound sysSound(TConfig::getSystemPath(TConfig::SOUNDS));
71 andreas 8503
 
108 andreas 8504
    if (_playSound && sysSound.getSystemSoundState() && vf.isValidFile(snd))
71 andreas 8505
        _playSound(snd);
8506
}
8507
 
8508
void TPageManager::doDBEEP(int, std::vector<int>&, vector<string>&)
8509
{
8510
    DECL_TRACER("TPageManager::doDBEEP(int, std::vector<int>&, vector<string>&)");
8511
 
8512
    if (!_playSound)
8513
        return;
8514
 
8515
    string snd = TConfig::getSystemPath(TConfig::SOUNDS) + "/" + TConfig::getDoubleBeepSound();
8516
    TValidateFile vf;
108 andreas 8517
    TSystemSound sysSound(TConfig::getSystemPath(TConfig::SOUNDS));
71 andreas 8518
 
108 andreas 8519
    if (_playSound && sysSound.getSystemSoundState() && vf.isValidFile(snd))
71 andreas 8520
        _playSound(snd);
8521
}
8522
 
63 andreas 8523
/**
8524
 * @brief Pop up the keypad icon and initialize the text string to that specified.
8525
 * Keypad string is set to null on power up and is stored until power is lost.
8526
 * The Prompt Text is optional.
8527
 */
62 andreas 8528
void TPageManager::doEKP(int port, std::vector<int>& channels, std::vector<std::string>& pars)
8529
{
8530
    DECL_TRACER("TPageManager::doEKP(int port, std::vector<int>& channels, std::vector<std::string>& pars)");
8531
 
8532
    doAKP(port, channels, pars);
8533
}
63 andreas 8534
 
8535
/**
8536
 * @brief Present a private keyboard.
8537
 * Pops up the keyboard icon and initializes the text string to that specified.
8538
 * Keyboard displays a '*' instead of the letters typed. The Prompt Text is optional.
8539
 */
8540
void TPageManager::doPKB(int, vector<int>&, vector<string>& pars)
8541
{
8542
    DECL_TRACER("TPageManager::doPKB(int, vector<int>&, vector<string>& pars)");
8543
 
8544
    if (pars.size() < 1)
8545
    {
8546
        MSG_ERROR("Expecting 2 parameters but got only " << pars.size() << "! Ignoring command.");
8547
        return;
8548
    }
8549
 
8550
    string initText = pars[0];
8551
    string promptText;
8552
 
8553
    if (pars.size() > 1)
8554
        promptText = pars[1];
8555
 
8556
    if (_callKeyboard)
8557
        _callKeyboard(initText, promptText, true);
8558
}
8559
 
8560
/**
8561
 * @brief Present a private keypad.
8562
 * Pops up the keypad icon and initializes the text string to that specified.
8563
 * Keypad displays a '*' instead of the numbers typed. The Prompt Text is optional.
8564
 */
8565
void TPageManager::doPKP(int, vector<int>&, vector<string>& pars)
8566
{
8567
    DECL_TRACER("TPageManager::doPKP(int, vector<int>&, vector<string>& pars)");
8568
 
8569
    if (pars.size() < 1)
8570
    {
8571
        MSG_ERROR("Expecting 2 parameters but got only " << pars.size() << "! Ignoring command.");
8572
        return;
8573
    }
8574
 
8575
    string initText = pars[0];
8576
    string promptText;
8577
 
8578
    if (pars.size() > 1)
8579
        promptText = pars[1];
8580
 
8581
    if (_callKeypad)
8582
        _callKeypad(initText, promptText, true);
8583
}
8584
 
8585
/**
64 andreas 8586
 * Send panel to SETUP page.
8587
 */
8588
void TPageManager::doSetup(int, vector<int>&, vector<string>&)
8589
{
8590
    DECL_TRACER("TPageManager::doSetup(int, vector<int>&, vector<string>&)");
8591
 
8592
    if (_callShowSetup)
8593
        _callShowSetup();
8594
}
8595
 
8596
/**
8597
 * Shut down the App
8598
 */
8599
void TPageManager::doShutdown(int, vector<int>&, vector<string>&)
8600
{
8601
    DECL_TRACER("TPageManager::doShutdown(int, vector<int>&, vector<string>&)");
8602
 
97 andreas 8603
    MSG_PROTOCOL("Received shutdown ...");
64 andreas 8604
#ifdef __ANDROID__
8605
    stopNetworkState();
8606
#endif
8607
    prg_stopped = true;
8608
    killed = true;
8609
 
8610
    if (_shutdown)
8611
        _shutdown();
8612
}
8613
 
82 andreas 8614
void TPageManager::doSOU(int, vector<int>&, vector<string>& pars)
8615
{
8616
    DECL_TRACER("TPageManager::doSOU(int, vector<int>&, vector<string>& pars)");
8617
 
8618
    if (pars.size() < 1)
8619
    {
8620
        MSG_ERROR("@SOU: Expecting a sound file as parameter! Ignoring command.");
8621
        return;
8622
    }
8623
 
8624
    if (!_playSound)
8625
    {
8626
        MSG_ERROR("@SOU: Missing sound module!");
8627
        return;
8628
    }
8629
 
165 andreas 8630
    if (pars[0].empty() || strCaseCompare(pars[0], "None") == 0)
8631
        return;
8632
 
82 andreas 8633
    _playSound(pars[0]);
8634
}
8635
 
64 andreas 8636
/**
63 andreas 8637
 * @brief Present a telephone keypad.
8638
 * Pops up the keypad icon and initializes the text string to that specified.
8639
 * The Prompt Text is optional.
8640
 */
8641
void TPageManager::doTKP(int port, vector<int>& channels, vector<string>& pars)
8642
{
8643
    DECL_TRACER("TPageManager::doTKP(int port, vector<int>& channels, vector<string>& pars)");
8644
 
8645
    // TODO: Implement a real telefone keypad.
8646
    doAKP(port, channels, pars);
8647
}
8648
 
8649
/**
8650
 * Popup the virtual keyboard
8651
 */
123 andreas 8652
void TPageManager::doVKB(int port, vector<int>& channels, vector<string>& pars)
63 andreas 8653
{
123 andreas 8654
    DECL_TRACER("TPageManager::doVKB(int port, vector<int>& channels, vector<string>& pars)");
63 andreas 8655
 
8656
    doAKP(port, channels, pars);
8657
}
129 andreas 8658
#ifndef _NOSIP_
123 andreas 8659
void TPageManager::sendPHN(vector<string>& cmds)
8660
{
8661
    DECL_TRACER("TPageManager::sendPHN(const vector<string>& cmds)");
8662
 
8663
    vector<int> channels;
8664
    doPHN(-1, channels, cmds);
8665
}
8666
 
141 andreas 8667
void TPageManager::actPHN(vector<string>& cmds)
8668
{
8669
    DECL_TRACER("TPageManager::actPHN(const vector<string>& cmds)");
8670
 
8671
    vector<int> channels;
8672
    doPHN(1, channels, cmds);
8673
}
8674
 
140 andreas 8675
void TPageManager::phonePickup(int id)
8676
{
8677
    DECL_TRACER("TPageManager::phonePickup(int id)");
8678
 
8679
    if (id < 0 || id >= 4)
8680
        return;
8681
 
8682
    if (mSIPClient)
8683
        mSIPClient->pickup(id);
8684
}
8685
 
8686
void TPageManager::phoneHangup(int id)
8687
{
8688
    DECL_TRACER("TPageManager::phoneHangup(int id)");
8689
 
8690
    if (id < 0 || id >= 4)
8691
        return;
8692
 
8693
    if (mSIPClient)
8694
        mSIPClient->terminate(id);
8695
}
8696
 
123 andreas 8697
/**
8698
 * @brief Phone commands.
8699
 * The phone commands could come from the master or are send to the master.
8700
 * If the parameter \p port is less then 0 (zero) a command is send to the
8701
 * master. In any other case the command came from the mater.
125 andreas 8702
 *
8703
 * @param port  This is used to signal if the command was sent by the master
8704
 *              or generated from the panel. If ths is less then 0, then the
8705
 *              method was called because of an event happen in the panel.
8706
 *              If this is grater or equal 0, then the event is comming from
8707
 *              the master.
8708
 * @param pars  This are parameters. The first parameter defines the action
8709
 *              to be done. According to the command this parameter may have a
8710
 *              different number of arguments.
123 andreas 8711
 */
8712
void TPageManager::doPHN(int port, vector<int>&, vector<string>& pars)
8713
{
8714
    DECL_TRACER("TPageManager::doPHN(int port, vector<int>&, vector<string>& pars)");
8715
 
8716
    if (pars.size() < 1)
8717
    {
8718
        MSG_ERROR("Expecting at least 1 parameter but got none! Ignoring command.");
8719
        return;
8720
    }
8721
 
8722
    string sCommand;
8723
    string cmd = toUpper(pars[0]);
8724
 
8725
    // Master to panel
8726
    if (port >= 0)
8727
    {
8728
        if (!mSIPClient)
8729
        {
8730
            MSG_ERROR("SIP client class was not initialized!")
8731
            return;
8732
        }
8733
 
8734
        if (cmd == "ANSWER")
8735
        {
8736
            if (pars.size() >= 2)
8737
            {
124 andreas 8738
                int id = atoi(pars[1].c_str());
8739
 
8740
                if (mSIPClient->getSIPState(id) == TSIPClient::SIP_HOLD)
8741
                    mSIPClient->resume(id);
8742
                else
135 andreas 8743
                    mSIPClient->pickup(id);
123 andreas 8744
            }
8745
        }
8746
        else if (cmd == "AUTOANSWER")
8747
        {
8748
            if (pars.size() >= 2)
8749
            {
8750
                if (pars[1].at(0) == '0')
8751
                    mPHNautoanswer = false;
8752
                else
8753
                    mPHNautoanswer = true;
127 andreas 8754
 
8755
                vector<string> cmds;
8756
                cmds = { "AUTOANSWER", to_string(mPHNautoanswer ? 1 : 0) };
128 andreas 8757
                sendPHN(cmds);
123 andreas 8758
            }
8759
        }
8760
        else if (cmd == "CALL")     // Initiate a call
8761
        {
8762
            if (pars.size() >= 2)
127 andreas 8763
                mSIPClient->call(pars[1]);
123 andreas 8764
        }
8765
        else if (cmd == "DTMF")     // Send tone modified codes
8766
        {
127 andreas 8767
            if (pars.size() >= 2)
8768
                mSIPClient->sendDTMF(pars[1]);
123 andreas 8769
        }
8770
        else if (cmd == "HANGUP")   // terminate a call
8771
        {
124 andreas 8772
            if (pars.size() >= 2)
8773
            {
8774
                int id = atoi(pars[1].c_str());
8775
                mSIPClient->terminate(id);
8776
            }
123 andreas 8777
        }
8778
        else if (cmd == "HOLD")     // Hold the line
8779
        {
124 andreas 8780
            if (pars.size() >= 2)
8781
            {
8782
                int id = atoi(pars[1].c_str());
8783
                mSIPClient->hold(id);
8784
            }
123 andreas 8785
        }
128 andreas 8786
        else if (cmd == "LINESTATE") // State of all line
127 andreas 8787
        {
128 andreas 8788
            mSIPClient->sendLinestate();
127 andreas 8789
        }
123 andreas 8790
        else if (cmd == "PRIVACY")  // Set/unset "do not disturb"
8791
        {
128 andreas 8792
            if (pars.size() >= 2)
8793
            {
8794
                bool state = (pars[1].at(0) == '1' ? true : false);
8795
                mSIPClient->sendPrivate(state);
8796
            }
123 andreas 8797
        }
8798
        else if (cmd == "REDIAL")   // Redials the last number
8799
        {
128 andreas 8800
            mSIPClient->redial();
123 andreas 8801
        }
8802
        else if (cmd == "TRANSFER") // Transfer call to provided number
8803
        {
128 andreas 8804
            if (pars.size() >= 3)
8805
            {
8806
                int id = atoi(pars[1].c_str());
8807
                string num = pars[2];
8808
 
8809
                if (mSIPClient->transfer(id, num))
8810
                {
8811
                    vector<string> cmds;
8812
                    cmds.push_back("TRANSFERRED");
8813
                    sendPHN(cmds);
8814
                }
8815
            }
123 andreas 8816
        }
144 andreas 8817
        else if (cmd == "IM")
8818
        {
8819
            if (pars.size() < 3)
8820
                return;
8821
 
8822
            string to = pars[1];
8823
            string msg = pars[2];
8824
            string toUri;
8825
 
8826
            if (to.find("sip:") == string::npos)
8827
                toUri = "sip:";
8828
 
8829
            toUri += to;
8830
 
8831
            if (to.find("@") == string::npos)
8832
                toUri += "@" + TConfig::getSIPproxy();
8833
 
8834
            mSIPClient->sendIM(toUri, msg);
8835
        }
123 andreas 8836
        else if (cmd == "SETUP")    // Some temporary settings
8837
        {
8838
            if (pars.size() < 2)
8839
                return;
8840
 
8841
            if (pars[1] == "DOMAIN" && pars.size() >= 3)
8842
                TConfig::setSIPdomain(pars[2]);
8843
            else if (pars[1] == "DTMFDURATION")
8844
            {
138 andreas 8845
                unsigned int ms = atoi(pars[2].c_str());
8846
                mSIPClient->setDTMFduration(ms);
123 andreas 8847
            }
8848
            else if (pars[1] == "ENABLE")   // (re)register user
8849
            {
8850
                TConfig::setSIPstatus(true);
127 andreas 8851
                mSIPClient->cleanUp();
135 andreas 8852
                mSIPClient->init();
123 andreas 8853
            }
127 andreas 8854
            else if (pars[1] == "DOMAIN" && pars.size() >= 3)
8855
                TConfig::setSIPdomain(pars[2]);
123 andreas 8856
            else if (pars[1] == "PASSWORD" && pars.size() >= 3)
8857
                TConfig::setSIPpassword(pars[2]);
8858
            else if (pars[1] == "PORT" && pars.size() != 3)
8859
                TConfig::setSIPport(atoi(pars[2].c_str()));
8860
            else if (pars[1] == "PROXYADDR" && pars.size() >= 3)
8861
                TConfig::setSIPproxy(pars[2]);
8862
            else if (pars[1] == "STUNADDR" && pars.size() >= 3)
8863
                TConfig::setSIPstun(pars[2]);
8864
            else if (pars[1] == "USERNAME" && pars.size() >= 3)
8865
                TConfig::setSIPuser(pars[2]);
8866
        }
8867
        else
8868
        {
8869
            MSG_ERROR("Unknown command ^PHN-" << cmd << " ignored!");
8870
        }
8871
    }
8872
    else   // Panel to master
8873
    {
8874
        vector<string>::iterator iter;
8875
 
8876
        for (iter = pars.begin(); iter != pars.end(); ++iter)
8877
        {
8878
            if (!sCommand.empty())
8879
                sCommand += ",";
8880
 
8881
            sCommand += *iter;
8882
        }
8883
 
8884
        sendPHNcommand(sCommand);
8885
    }
8886
}
127 andreas 8887
 
8888
void TPageManager::getPHN(int, vector<int>&, vector<string>& pars)
8889
{
8890
    DECL_TRACER("TPageManager::getPHN(int, vector<int>&, vector<string>& pars)");
8891
 
8892
    if (pars.size() < 1)
8893
    {
8894
        MSG_ERROR("Invalid number of arguments!");
8895
        return;
8896
    }
8897
 
8898
    string cmd = pars[0];
8899
 
8900
    if (cmd == "AUTOANSWER")
8901
        sendPHNcommand(cmd + "," + (mPHNautoanswer ? "1" : "0"));
8902
    else if (cmd == "LINESTATE")
8903
    {
8904
        if (!mSIPClient)
8905
            return;
8906
 
138 andreas 8907
        mSIPClient->sendLinestate();
127 andreas 8908
    }
8909
    else if (cmd == "MSGWAITING")
8910
    {
144 andreas 8911
        size_t num = mSIPClient->getNumberMessages();
8912
        sendPHNcommand(cmd + "," + (num > 0 ? "1" : "0") + "," + std::to_string(num) + "0,0,0");
127 andreas 8913
    }
8914
    else if (cmd == "PRIVACY")
8915
    {
138 andreas 8916
        if (mSIPClient->getPrivate())
8917
            sendPHNcommand(cmd + ",1");
8918
        else
8919
            sendPHNcommand(cmd + ",0");
127 andreas 8920
    }
144 andreas 8921
    else if (cmd == "REDIAL")
8922
    {
8923
        if (pars.size() < 2)
8924
            return;
8925
 
8926
        sendPHNcommand(cmd + "," + pars[1]);
8927
    }
127 andreas 8928
    else
8929
    {
8930
        MSG_WARNING("Unknown command " << cmd << " found!");
8931
    }
8932
}
129 andreas 8933
#endif  // _NOSIP_
134 andreas 8934
 
227 andreas 8935
void TPageManager::doLVD(int port, vector<int> &channels, vector<string> &pars)
225 andreas 8936
{
227 andreas 8937
    DECL_TRACER("TPageManager::doLVD(int port, vector<int> &channels, vector<string> &pars)");
225 andreas 8938
 
8939
    if (pars.size() < 1)
8940
    {
8941
        MSG_ERROR("Expecting one parameter but got none! Ignoring command.");
8942
        return;
8943
    }
8944
 
8945
    TError::clear();
8946
    string source = pars[0];
8947
    vector<string> configs;
8948
 
8949
    if (pars.size() > 1)
8950
    {
8951
        for (size_t i = 1; i < pars.size(); ++i)
227 andreas 8952
        {
8953
            string low = toLower(pars[i]);
8954
 
8955
            if (low.find_first_of("user=") != string::npos ||
8956
                low.find_first_of("pass=") != string::npos ||
8957
                low.find_first_of("csv=")  != string::npos ||
8958
                low.find_first_of("has_headers=") != string::npos)
8959
            {
8960
                configs.push_back(pars[i]);
8961
            }
8962
        }
225 andreas 8963
    }
8964
 
8965
    vector<TMap::MAP_T> map = findButtons(port, channels);
8966
 
8967
    if (TError::isError() || map.empty())
8968
        return;
8969
 
8970
    vector<Button::TButton *> buttons = collectButtons(map);
8971
 
8972
    if (buttons.size() > 0)
8973
    {
8974
        vector<Button::TButton *>::iterator mapIter;
8975
 
8976
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
8977
        {
8978
            Button::TButton *bt = *mapIter;
8979
            bt->setListSource(source, configs);
8980
        }
8981
    }
8982
 
8983
}
8984
 
230 andreas 8985
void TPageManager::doLVE(int port, vector<int> &channels, vector<string> &pars)
8986
{
8987
    DECL_TRACER("TPageManager::doLVE(int port, vector<int> &channels, vector<string> &pars)");
8988
 
8989
    if (pars.size() < 1)
8990
    {
8991
        MSG_ERROR("Expecting one parameter but got none! Ignoring command.");
8992
        return;
8993
    }
8994
 
8995
    TError::clear();
8996
    int num = atoi(pars[0].c_str());
8997
 
8998
    vector<TMap::MAP_T> map = findButtons(port, channels);
8999
 
9000
    if (TError::isError() || map.empty())
9001
        return;
9002
 
9003
    vector<Button::TButton *> buttons = collectButtons(map);
9004
 
9005
    if (buttons.size() > 0)
9006
    {
9007
        vector<Button::TButton *>::iterator mapIter;
9008
 
9009
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
9010
        {
9011
            Button::TButton *bt = *mapIter;
9012
            bt->setListViewEventNumber(num);
9013
        }
9014
    }
9015
 
9016
}
9017
 
227 andreas 9018
void TPageManager::doLVF(int port, vector<int> &channels, vector<string> &pars)
9019
{
9020
    DECL_TRACER("TPageManager::doLVF(int port, vector<int> &channels, vector<string> &pars)");
9021
 
9022
    if (pars.size() < 1)
9023
    {
9024
        MSG_ERROR("Expecting one parameter but got none! Ignoring command.");
9025
        return;
9026
    }
9027
 
9028
    TError::clear();
9029
    string filter;
9030
 
9031
    vector<string>::iterator iter;
9032
 
9033
    for (iter = pars.begin(); iter != pars.end(); ++iter)
9034
    {
9035
        if (filter.length() > 0)
9036
            filter += ",";
9037
 
9038
        filter += *iter;
9039
    }
9040
 
9041
    vector<TMap::MAP_T> map = findButtons(port, channels);
9042
 
9043
    if (TError::isError() || map.empty())
9044
        return;
9045
 
9046
    vector<Button::TButton *> buttons = collectButtons(map);
9047
 
9048
    if (buttons.size() > 0)
9049
    {
9050
        vector<Button::TButton *>::iterator mapIter;
9051
 
9052
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
9053
        {
9054
            Button::TButton *bt = *mapIter;
9055
            bt->setListSourceFilter(filter);
9056
        }
9057
    }
9058
}
9059
 
230 andreas 9060
void TPageManager::doLVL(int port, vector<int> &channels, vector<string> &pars)
9061
{
9062
    DECL_TRACER("TPageManager::doLVL(int port, vector<int> &channels, vector<string> &pars)");
9063
 
9064
    if (pars.size() < 1)
9065
    {
9066
        MSG_ERROR("Expecting one parameter but got none! Ignoring command.");
9067
        return;
9068
    }
9069
 
9070
    TError::clear();
233 andreas 9071
    bool hasColumns = false;
230 andreas 9072
    int columns = 0;
233 andreas 9073
    bool hasLayout = false;
230 andreas 9074
    int layout = 0;
233 andreas 9075
    bool hasComponent = false;
9076
    int component = 0;
9077
    bool hasCellHeight = false;
9078
    bool cellHeightPercent = false;
9079
    int cellheight = 0;
9080
    bool hasP1 = false;
9081
    int p1 = 0;
9082
    bool hasP2 = false;
9083
    int p2 = 0;
9084
    bool hasFilter = false;
9085
    bool filter = false;
9086
    bool hasFilterHeight = false;
9087
    bool filterHeightPercent = false;
9088
    int filterheight = 0;
9089
    bool hasAlphaScroll = false;
9090
    bool alphascroll = false;
230 andreas 9091
 
9092
    vector<string>::iterator iter;
9093
 
9094
    for (iter = pars.begin(); iter != pars.end(); ++iter)
9095
    {
9096
        string low = toLower(*iter);
9097
 
9098
        if (low.find("columns=") != string::npos ||
9099
            low.find("nc=") != string::npos ||
9100
            low.find("numcol=") != string::npos)
9101
        {
9102
            size_t pos = low.find("=");
9103
            string sCols = low.substr(pos + 1);
9104
            columns = atoi(sCols.c_str());
233 andreas 9105
            hasColumns = true;
9106
        }
9107
        else if (low.find("c=") != string::npos || low.find("comp=") != string::npos)
9108
        {
9109
            size_t pos = low.find("=");
9110
            string sComp = low.substr(pos + 1);
9111
            component |= atoi(sComp.c_str());
9112
            hasComponent = true;
9113
        }
9114
        else if (low.find("l=") != string::npos || low.find("layout=") != string::npos)
9115
        {
9116
            size_t pos = low.find("=");
9117
            string sLay = low.substr(pos + 1);
9118
            layout = atoi(sLay.c_str());
9119
            hasLayout = true;
9120
        }
9121
        else if (low.find("ch=") != string::npos || low.find("cellheight=") != string::npos)
9122
        {
9123
            size_t pos = low.find("=");
9124
            string sCh = low.substr(pos + 1);
9125
            cellheight = atoi(sCh.c_str());
230 andreas 9126
 
233 andreas 9127
            if (low.find("%") != string::npos)
9128
                cellHeightPercent = true;
9129
 
9130
            hasCellHeight = true;
230 andreas 9131
        }
233 andreas 9132
        else if (low.find("p1=") != string::npos)
9133
        {
9134
            size_t pos = low.find("=");
9135
            string sP1 = low.substr(pos + 1);
9136
            p1 = atoi(sP1.c_str());
9137
            hasP1 = true;
9138
        }
9139
        else if (low.find("p2=") != string::npos)
9140
        {
9141
            size_t pos = low.find("=");
9142
            string sP2 = low.substr(pos + 1);
9143
            p2 = atoi(sP2.c_str());
9144
            hasP2 = true;
9145
        }
9146
        else if (low.find("f=") != string::npos || low.find("filter=") != string::npos)
9147
        {
9148
            size_t pos = low.find("=");
9149
            string sFilter = low.substr(pos + 1);
9150
            filter = isTrue(sFilter);
9151
            hasFilter = true;
9152
        }
9153
        else if (low.find("fh=") != string::npos || low.find("filterheight=") != string::npos)
9154
        {
9155
            size_t pos = low.find("=");
9156
            string sFilter = low.substr(pos + 1);
9157
            filterheight = atoi(sFilter.c_str());
9158
 
9159
            if (low.find("%") != string::npos)
9160
                filterHeightPercent = true;
9161
 
9162
            hasFilterHeight = true;
9163
        }
9164
        else if (low.find("as=") != string::npos || low.find("alphascroll=") != string::npos)
9165
        {
9166
            size_t pos = low.find("=");
9167
            string sAlpha = low.substr(pos + 1);
9168
            alphascroll = isTrue(sAlpha);
9169
            hasAlphaScroll = true;
9170
        }
230 andreas 9171
    }
9172
 
9173
    vector<TMap::MAP_T> map = findButtons(port, channels);
9174
 
9175
    if (TError::isError() || map.empty())
9176
        return;
9177
 
9178
    vector<Button::TButton *> buttons = collectButtons(map);
9179
 
9180
    if (buttons.size() > 0)
9181
    {
9182
        vector<Button::TButton *>::iterator mapIter;
9183
 
9184
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
9185
        {
9186
            Button::TButton *bt = *mapIter;
233 andreas 9187
 
9188
            if (hasColumns)         bt->setListViewColumns(columns);
9189
            if (hasComponent)       bt->setListViewComponent(component);
9190
            if (hasLayout)          bt->setListViewLayout(layout);
9191
            if (hasCellHeight)      bt->setListViewCellheight(cellheight, cellHeightPercent);
9192
            if (hasP1)              bt->setListViewP1(p1);
9193
            if (hasP2)              bt->setListViewP2(p2);
9194
            if (hasFilter)          bt->setListViewColumnFilter(filter);
9195
            if (hasFilterHeight)    bt->setListViewFilterHeight(filterheight, filterHeightPercent);
9196
            if (hasAlphaScroll)     bt->setListViewAlphaScroll(alphascroll);
230 andreas 9197
        }
9198
    }
9199
}
9200
 
233 andreas 9201
void TPageManager::doLVM(int port, vector<int> &channels, vector<string> &pars)
9202
{
9203
    DECL_TRACER("TPageManager::doLVM(int port, vector<int> &channels, vector<string> &pars)");
9204
 
9205
    if (pars.size() < 1)
9206
    {
9207
        MSG_ERROR("Expecting one parameter but got none! Ignoring command.");
9208
        return;
9209
    }
9210
 
9211
    TError::clear();
9212
    map<string,string> mapField;
9213
 
9214
    vector<string>::iterator iter;
9215
 
9216
    for (iter = pars.begin(); iter != pars.end(); ++iter)
9217
    {
9218
        string left, right;
9219
        size_t pos = 0;
9220
 
9221
        if ((pos = iter->find("=")) != string::npos)
9222
        {
9223
            string left = iter->substr(0, pos);
9224
            left = toLower(left);
9225
            string right = iter->substr(pos + 1);
9226
 
9227
            if (left == "t1" || left == "t2" || left == "i1")
9228
                mapField.insert(pair<string,string>(left, right));
9229
        }
9230
    }
9231
 
9232
    vector<TMap::MAP_T> map = findButtons(port, channels);
9233
 
9234
    if (TError::isError() || map.empty())
9235
        return;
9236
 
9237
    vector<Button::TButton *> buttons = collectButtons(map);
9238
 
9239
    if (buttons.size() > 0)
9240
    {
9241
        vector<Button::TButton *>::iterator mapIter;
9242
 
9243
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
9244
        {
9245
            Button::TButton *bt = *mapIter;
9246
            bt->setListViewFieldMap(mapField);
9247
        }
9248
    }
9249
}
9250
 
9251
void TPageManager::doLVN(int port, vector<int> &channels, vector<string> &pars)
9252
{
9253
    DECL_TRACER("TPageManager::doLVN(int port, vector<int> &channels, vector<string> &pars)");
9254
 
9255
    if (pars.size() < 1)
9256
    {
9257
        MSG_ERROR("Expecting one parameter but got none! Ignoring command.");
9258
        return;
9259
    }
9260
 
9261
    TError::clear();
9262
    string command = pars[0];
9263
    bool select = false;
9264
 
9265
    if (pars.size() > 1)
9266
    {
9267
        if (isTrue(pars[1]))
9268
            select = true;
9269
    }
9270
 
9271
    vector<TMap::MAP_T> map = findButtons(port, channels);
9272
 
9273
    if (TError::isError() || map.empty())
9274
        return;
9275
 
9276
    vector<Button::TButton *> buttons = collectButtons(map);
9277
 
9278
    if (buttons.size() > 0)
9279
    {
9280
        vector<Button::TButton *>::iterator mapIter;
9281
 
9282
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
9283
        {
9284
            Button::TButton *bt = *mapIter;
9285
            bt->listViewNavigate(command, select);
9286
        }
9287
    }
9288
}
9289
 
9290
void TPageManager::doLVR(int port, vector<int> &channels, vector<string> &pars)
9291
{
9292
    DECL_TRACER("TPageManager::doLVR(int port, vector<int> &channels, vector<string> &pars)");
9293
 
9294
    TError::clear();
9295
    int interval = -1;
9296
    bool force = false;
9297
 
9298
    if (pars.size() > 0)
9299
        interval = atoi(pars[0].c_str());
9300
 
9301
    if (pars.size() > 1)
9302
        force = isTrue(pars[1]);
9303
 
9304
    vector<TMap::MAP_T> map = findButtons(port, channels);
9305
 
9306
    if (TError::isError() || map.empty())
9307
        return;
9308
 
9309
    vector<Button::TButton *> buttons = collectButtons(map);
9310
 
9311
    if (buttons.size() > 0)
9312
    {
9313
        vector<Button::TButton *>::iterator mapIter;
9314
 
9315
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
9316
        {
9317
            Button::TButton *bt = *mapIter;
9318
            bt->listViewRefresh(interval, force);
9319
        }
9320
    }
9321
}
9322
 
9323
void TPageManager::doLVS(int port, vector<int> &channels, vector<string> &pars)
9324
{
9325
    DECL_TRACER("TPageManager::doLVS(int port, vector<int> &channels, vector<string> &pars)");
9326
 
9327
    TError::clear();
9328
    vector<string> sortColumns;
9329
    Button::LIST_SORT sort = Button::LIST_SORT_NONE;
9330
    string override;
9331
 
9332
    if (pars.size() > 0)
9333
    {
9334
        vector<string>::iterator iter;
9335
 
9336
        for (iter = pars.begin(); iter != pars.end(); ++iter)
9337
        {
9338
            if (iter->find(";") == string::npos)
9339
                sortColumns.push_back(*iter);
9340
            else
9341
            {
9342
                vector<string> parts = StrSplit(*iter, ";");
9343
                sortColumns.push_back(parts[0]);
9344
 
9345
                if (parts[1].find("a") != string::npos || parts[1].find("A") != string::npos)
9346
                    sort = Button::LIST_SORT_ASC;
9347
                else if (parts[1].find("d") != string::npos || parts[1].find("D") != string::npos)
9348
                    sort = Button::LIST_SORT_DESC;
9349
                else if (parts[1].find("*") != string::npos)
9350
                {
9351
                    if (parts.size() > 2 && !parts[2].empty())
9352
                    {
9353
                        override = parts[2];
9354
                        sort = Button::LIST_SORT_OVERRIDE;
9355
                    }
9356
                }
9357
                else if (parts[1].find("n") != string::npos || parts[1].find("N") != string::npos)
9358
                    sort = Button::LIST_SORT_NONE;
9359
            }
9360
        }
9361
    }
9362
 
9363
    vector<TMap::MAP_T> map = findButtons(port, channels);
9364
 
9365
    if (TError::isError() || map.empty())
9366
        return;
9367
 
9368
    vector<Button::TButton *> buttons = collectButtons(map);
9369
 
9370
    if (buttons.size() > 0)
9371
    {
9372
        vector<Button::TButton *>::iterator mapIter;
9373
 
9374
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
9375
        {
9376
            Button::TButton *bt = *mapIter;
9377
            bt->listViewSortData(sortColumns, sort, override);
9378
        }
9379
    }
9380
}
9381
 
134 andreas 9382
void TPageManager::doTPCCMD(int, vector<int>&, vector<string>& pars)
9383
{
9384
    DECL_TRACER("TPageManager::doTPCCMD(int, vector<int>&, vector<string>& pars)");
9385
 
9386
    if (pars.size() < 1)
9387
    {
9388
        MSG_ERROR("Too few arguments for TPCCMD!");
9389
        return;
9390
    }
9391
 
9392
    string cmd = pars[0];
9393
 
9394
    if (strCaseCompare(cmd, "LocalHost") == 0)
9395
    {
9396
        if (pars.size() < 2 || pars[1].empty())
9397
        {
9398
            MSG_ERROR("The command \"LocalHost\" requires an additional parameter!");
9399
            return;
9400
        }
9401
 
9402
        TConfig::saveController(pars[1]);
9403
    }
9404
    else if (strCaseCompare(cmd, "LocalPort") == 0)
9405
    {
9406
        if (pars.size() < 2 || pars[1].empty())
9407
        {
9408
            MSG_ERROR("The command \"LocalPort\" requires an additional parameter!");
9409
            return;
9410
        }
9411
 
9412
        int port = atoi(pars[1].c_str());
9413
 
9414
        if (port > 0 && port < 65536)
9415
            TConfig::savePort(port);
9416
        else
9417
        {
9418
            MSG_ERROR("Invalid network port " << port);
9419
        }
9420
    }
9421
    else if (strCaseCompare(cmd, "DeviceID") == 0)
9422
    {
9423
        if (pars.size() < 2 || pars[1].empty())
9424
        {
9425
            MSG_ERROR("The command \"DeviceID\" requires an additional parameter!");
9426
            return;
9427
        }
9428
 
9429
        int id = atoi(pars[1].c_str());
9430
 
9431
        if (id >= 10000 && id < 30000)
9432
            TConfig::setSystemChannel(id);
9433
    }
9434
    else if (strCaseCompare(cmd, "ApplyProfile") == 0)
9435
    {
9436
        // We restart the network connection only
9437
        if (gAmxNet)
9438
            gAmxNet->reconnect();
9439
    }
9440
    else if (strCaseCompare(cmd, "QueryDeviceInfo") == 0)
9441
    {
9442
        string info = "DEVICEINFO-TPANELID," + TConfig::getPanelType();
9443
        info += ";HOSTNAME,";
9444
        char hostname[HOST_NAME_MAX];
9445
 
9446
        if (gethostname(hostname, HOST_NAME_MAX) != 0)
9447
        {
9448
            MSG_ERROR("Can't get host name: " << strerror(errno));
9449
            return;
9450
        }
9451
 
9452
        info.append(hostname);
9453
        info += ";UUID," + TConfig::getUUID();
9454
        sendGlobalString(info);
9455
    }
9456
    else if (strCaseCompare(cmd, "LockRotation") == 0)
9457
    {
9458
        if (pars.size() < 2 || pars[1].empty())
9459
        {
9460
            MSG_ERROR("The command \"LockRotation\" requires an additional parameter!");
9461
            return;
9462
        }
9463
 
9464
        if (strCaseCompare(pars[1], "true") == 0)
9465
            TConfig::setRotationFixed(true);
9466
        else
9467
            TConfig::setRotationFixed(false);
9468
    }
9469
    else if (strCaseCompare(cmd, "ButtonHit") == 0)
9470
    {
9471
        if (pars.size() < 2 || pars[1].empty())
9472
        {
9473
            MSG_ERROR("The command \"ButtonHit\" requires an additional parameter!");
9474
            return;
9475
        }
9476
 
9477
        if (strCaseCompare(pars[1], "true") == 0)
9478
            TConfig::saveSystemSoundState(true);
9479
        else
9480
            TConfig::saveSystemSoundState(false);
9481
    }
9482
    else if (strCaseCompare(cmd, "ReprocessTP4") == 0)
9483
    {
9484
        if (_resetSurface)
9485
            _resetSurface();
9486
    }
9487
}
9488
 
9489
void TPageManager::doTPCACC(int, vector<int>&, vector<string>& pars)
9490
{
9491
    DECL_TRACER("TPageManager::doTPCACC(int, vector<int>&, vector<string>& pars)");
9492
 
9493
    if (pars.size() < 1)
9494
    {
9495
        MSG_ERROR("Too few arguments for TPCACC!");
9496
        return;
9497
    }
9498
 
9499
    string cmd = pars[0];
9500
 
9501
    if (strCaseCompare(cmd, "ENABLE") == 0)
9502
    {
9503
        mInformOrientation = true;
9504
        sendOrientation();
9505
    }
9506
    else if (strCaseCompare(cmd, "DISABLE") == 0)
9507
    {
9508
        mInformOrientation = false;
9509
    }
9510
    else if (strCaseCompare(cmd, "QUERY") == 0)
9511
    {
9512
        sendOrientation();
9513
    }
9514
}
153 andreas 9515
 
9516
void TPageManager::doTPCSIP(int, vector<int>&, vector<string>& pars)
9517
{
9518
    DECL_TRACER("TPageManager::doTPCSIP(int port, vector<int>& channels, vector<string>& pars)");
9519
 
9520
    if (pars.empty())
9521
        return;
9522
 
9523
    string cmd = toUpper(pars[0]);
9524
 
9525
    if (cmd == "SHOW" && _showPhoneDialog)
9526
        _showPhoneDialog(true);
9527
    else if (!_showPhoneDialog)
9528
    {
9529
        MSG_ERROR("There is no phone dialog registered!");
9530
    }
9531
}