Subversion Repositories tpanel

Rev

Rev 446 | Rev 457 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
446 andreas 1
/*
2
 * Copyright (C) 2020 to 2024 by Andreas Theofilu <andreas@theosys.at>
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 <QtGlobal>
20
 
21
#include <vector>
22
#include <thread>
23
#include <mutex>
24
 
25
#ifdef __ANDROID__
26
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
27
#       include <QtAndroidExtras/QAndroidJniObject>
28
#       include <QtAndroidExtras/QtAndroid>
29
#   else
30
#       include <QJniObject>
31
#       include <QCoreApplication>
32
#   endif
33
#   include <android/log.h>
34
#endif
35
#include <unistd.h>
36
#ifndef __ANDROID__
37
#   include <fstab.h>
38
#endif
39
 
40
#if __cplusplus < 201402L
41
#   error "This module requires at least C++14 standard!"
42
#else
43
#   if __cplusplus < 201703L
44
#       include <experimental/filesystem>
45
namespace fs = std::experimental::filesystem;
46
#       warning "Support for C++14 and experimental filesystem will be removed in a future version!"
47
#   else
48
#       include <filesystem>
49
#       ifdef __ANDROID__
50
namespace fs = std::__fs::filesystem;
51
#       else
52
namespace fs = std::filesystem;
53
#       endif
54
#   endif
55
#endif
56
 
57
#ifdef __APPLE__
58
#   include <unistd.h>
59
#   ifndef HOST_NAME_MAX
60
#       ifdef MAXHOSTNAMELEN
61
#           define HOST_NAME_MAX    MAXHOSTNAMELEN
62
#       else
63
#           define HOST_NAME_MAX    64
64
#       endif   // MAXHOSTNAMELEN
65
#   endif       // HOST_NAME_MAX
66
#endif          // __APPLE__
67
 
68
#include "tpagemanager.h"
69
#include "tcolor.h"
70
#include "terror.h"
71
#include "ticons.h"
72
#include "tbutton.h"
73
#include "tprjresources.h"
74
#include "tresources.h"
75
#include "tresources.h"
76
#include "tsystemsound.h"
77
#include "tvalidatefile.h"
78
#include "ttpinit.h"
79
#include "tconfig.h"
80
#include "tlock.h"
81
#include "tintborder.h"
82
#ifdef Q_OS_IOS
83
#include "ios/tiosbattery.h"
84
#endif
85
#if TESTMODE == 1
86
#include "testmode.h"
87
#endif
88
 
89
using std::vector;
90
using std::string;
91
using std::map;
92
using std::pair;
93
using std::to_string;
94
using std::thread;
95
using std::atomic;
96
using std::mutex;
97
using std::bind;
98
 
99
TIcons *gIcons = nullptr;
100
TPrjResources *gPrjResources = nullptr;
101
TPageManager *gPageManager = nullptr;
102
//std::vector<amx::ANET_COMMAND> TPageManager::mCommands;
103
 
104
extern amx::TAmxNet *gAmxNet;
105
extern std::atomic<bool> _netRunning;
106
extern bool _restart_;                          //!< If this is set to true then the whole program will start over.
107
 
108
bool prg_stopped = false;
109
 
110
#ifdef __ANDROID__
111
string javaJStringToString(JNIEnv *env, jstring str)
112
{
113
    if (!str)
114
        return string();
115
 
116
    const jclass stringClass = env->GetObjectClass(str);
117
    const jmethodID getBytes = env->GetMethodID(stringClass, "getBytes", "(Ljava/lang/String;)[B");
118
    const jbyteArray stringJbytes = (jbyteArray) env->CallObjectMethod(str, getBytes, env->NewStringUTF("UTF-8"));
119
 
120
    size_t length = (size_t) env->GetArrayLength(stringJbytes);
121
    jbyte* pBytes = env->GetByteArrayElements(stringJbytes, NULL);
122
 
123
    string ret = std::string((char *)pBytes, length);
124
    env->ReleaseByteArrayElements(stringJbytes, pBytes, JNI_ABORT);
125
 
126
    env->DeleteLocalRef(stringJbytes);
127
    env->DeleteLocalRef(stringClass);
128
    return ret;
129
}
130
 
131
JNIEXPORT void JNICALL Java_org_qtproject_theosys_BatteryState_informBatteryStatus(JNIEnv *, jclass, jint level, jboolean charging, jint chargeType)
132
{
133
    DECL_TRACER("JNICALL Java_org_qtproject_theosys_BatteryState_informBatteryStatus(JNIEnv *, jclass, jint level, jboolean charging, jint chargeType)");
134
 
135
    if (gPageManager)
136
        gPageManager->informBatteryStatus(level, charging, chargeType);
137
}
138
 
139
JNIEXPORT void JNICALL Java_org_qtproject_theosys_NetworkStatus_informTPanelNetwork(JNIEnv */*env*/, jclass /*clazz*/, jboolean conn, jint level, jint type)
140
{
141
    DECL_TRACER("JNICALL Java_org_qtproject_theosys_NetworkStatus_informTPanelNetwork(JNIEnv */*env*/, jclass /*clazz*/, jboolean conn, jint level, jint type)");
142
 
143
    //Call native side conterpart
144
    if (gPageManager)
145
        gPageManager->informTPanelNetwork(conn, level, type);
146
}
147
 
148
JNIEXPORT void JNICALL Java_org_qtproject_theosys_PhoneCallState_informPhoneState(JNIEnv *env, jclass, jboolean call, jstring pnumber)
149
{
150
    DECL_TRACER("JNICALL Java_org_qtproject_theosys_PhoneCallState_informPhoneState(JNIEnv *env, jclass, jboolean call, jstring pnumber)");
151
 
152
    string phoneNumber;
153
 
154
    if (pnumber)
155
        phoneNumber = javaJStringToString(env, pnumber);
156
 
157
    if (gPageManager)
158
        gPageManager->informPhoneState(call, phoneNumber);
159
}
160
 
161
JNIEXPORT void JNICALL Java_org_qtproject_theosys_Logger_logger(JNIEnv *env, jclass, jint mode, jstring msg)
162
{
163
    if (!msg)
164
        return;
165
 
166
    string ret = javaJStringToString(env, msg);
167
 
168
    try
169
    {
170
        if (TStreamError::checkFilter(mode))
171
        {
172
            *TError::Current()->getStream() << TError::append(mode) << ret << std::endl;
173
            TStreamError::resetFlags();
174
        }
175
    }
176
    catch (std::exception& e)
177
    {
178
        __android_log_print(ANDROID_LOG_ERROR, "tpanel", "%s", e.what());
179
    }
180
}
181
 
182
JNIEXPORT void JNICALL Java_org_qtproject_theosys_Orientation_informTPanelOrientation(JNIEnv */*env*/, jclass /*clazz*/, jint orientation)
183
{
184
    DECL_TRACER("Java_org_qtproject_theosys_Orientation_informTPanelOrientation(JNIEnv */*env*/, jclass /*clazz*/, jint orientation)");
185
 
186
    if (!gPageManager)
187
        return;
188
 
189
    if (gPageManager->onOrientationChange())
190
        gPageManager->onOrientationChange()(orientation);
191
 
192
    gPageManager->setOrientation(orientation);
193
 
194
    if (gPageManager->getInformOrientation())
195
        gPageManager->sendOrientation();
196
}
197
 
198
/* -------- Settings -------- */
199
 
200
JNIEXPORT void JNICALL Java_org_qtproject_theosys_SettingsActivity_saveSettings(JNIEnv *env, jclass clazz)
201
{
202
    DECL_TRACER("Java_org_qtproject_theosys_SettingsActivity_saveSettings(JNIEnv *env, jclass clazz)");
203
 
204
    Q_UNUSED(env);
205
    Q_UNUSED(clazz);
206
 
207
    TConfig::setTemporary(true);
208
    string oldNetlinx = TConfig::getController();
209
    int oldPort = TConfig::getPort();
210
    int oldChannelID = TConfig::getChannel();
211
    string oldSurface = TConfig::getFtpSurface();
212
    bool oldToolbarSuppress = TConfig::getToolbarSuppress();
213
    bool oldToolbarForce = TConfig::getToolbarForce();
214
    TConfig::setTemporary(false);
215
    MSG_DEBUG("Old values:\n" <<
216
              "   NetLinx: " << oldNetlinx << "\n" <<
217
              "   Port:    " << oldPort << "\n" <<
218
              "   Channel: " << oldChannelID << "\n" <<
219
              "   Surface: " << oldSurface << "\n" <<
220
              "   TB suppr:" << oldToolbarSuppress << "\n" <<
221
              "   TB force:" << oldToolbarForce);
222
    TConfig::saveSettings();
223
 
224
    MSG_DEBUG("New values:\n" <<
225
              "   NetLinx: " << TConfig::getController() << "\n" <<
226
              "   Port:    " << TConfig::getPort() << "\n" <<
227
              "   Channel: " << TConfig::getChannel() << "\n" <<
228
              "   Surface: " << TConfig::getFtpSurface() << "\n" <<
229
              "   TB suppr:" << TConfig::getToolbarSuppress() << "\n" <<
230
              "   TB force:" << TConfig::getToolbarForce());
231
 
232
    if (gPageManager && gPageManager->onSettingsChanged())
233
        gPageManager->onSettingsChanged()(oldNetlinx, oldPort, oldChannelID, oldSurface, oldToolbarSuppress, oldToolbarForce);
234
}
235
 
236
JNIEXPORT void JNICALL Java_org_qtproject_theosys_SettingsActivity_setNetlinxIp(JNIEnv *env, jclass clazz, jstring ip)
237
{
238
    DECL_TRACER("Java_org_qtproject_theosys_Settings_setNetlinxIp(JNIEnv *env, jclass clazz, jstring ip)");
239
 
240
    Q_UNUSED(clazz);
241
 
242
    string netlinxIp = javaJStringToString(env, ip);
243
 
244
    if (TConfig::getController() != netlinxIp)
245
        TConfig::saveController(netlinxIp);
246
}
247
 
248
JNIEXPORT void JNICALL Java_org_qtproject_theosys_SettingsActivity_setNetlinxPort(JNIEnv *env, jclass clazz, jint port)
249
{
250
    DECL_TRACER("Java_org_qtproject_theosys_Settings_setNetlinxPort(JNIEnv *env, jclass clazz, jint port)");
251
 
252
    Q_UNUSED(env);
253
    Q_UNUSED(clazz);
254
 
255
    if (port > 0 && port < 65535 && TConfig::getPort() != port)
256
        TConfig::savePort(port);
257
}
258
 
259
JNIEXPORT void JNICALL Java_org_qtproject_theosys_SettingsActivity_setNetlinxChannel(JNIEnv *env, jclass clazz, jint channel)
260
{
261
    DECL_TRACER("Java_org_qtproject_theosys_Settings_setNetlinxChannel(JNIEnv *env, jclass clazz, jint channel)");
262
 
263
    Q_UNUSED(env);
264
    Q_UNUSED(clazz);
265
 
266
    if (channel >= 10000 && channel < 20000 && TConfig::getChannel() != channel)
267
        TConfig::saveChannel(channel);
268
}
269
 
270
JNIEXPORT void JNICALL Java_org_qtproject_theosys_SettingsActivity_setNetlinxType(JNIEnv *env, jclass clazz, jstring type)
271
{
272
    DECL_TRACER("Java_org_qtproject_theosys_Settings_setNetlinxType(JNIEnv *env, jclass clazz, jstring type)");
273
 
274
    Q_UNUSED(clazz);
275
 
276
    string netlinxType = javaJStringToString(env, type);
277
 
278
    if (TConfig::getPanelType() != netlinxType)
279
        TConfig::savePanelType(netlinxType);
280
}
281
 
282
JNIEXPORT void JNICALL Java_org_qtproject_theosys_SettingsActivity_setNetlinxFtpUser(JNIEnv *env, jclass clazz, jstring user)
283
{
284
    DECL_TRACER("Java_org_qtproject_theosys_Settings_setNetlinxFtpUser(JNIEnv *env, jclass clazz, jstring user)");
285
 
286
    Q_UNUSED(clazz);
287
 
288
    string netlinxFtpUser = javaJStringToString(env, user);
289
 
290
    if (TConfig::getFtpUser() != netlinxFtpUser)
291
        TConfig::saveFtpUser(netlinxFtpUser);
292
}
293
 
294
JNIEXPORT void JNICALL Java_org_qtproject_theosys_SettingsActivity_setNetlinxFtpPassword(JNIEnv *env, jclass clazz, jstring pw)
295
{
296
    DECL_TRACER("Java_org_qtproject_theosys_Settings_setNetlinxFtpPassword(JNIEnv *env, jclass clazz, jstring pw)");
297
 
298
    Q_UNUSED(clazz);
299
 
300
    string netlinxPw = javaJStringToString(env, pw);
301
 
302
    if (TConfig::getFtpPassword() != netlinxPw)
303
        TConfig::saveFtpPassword(netlinxPw);
304
}
305
 
306
JNIEXPORT void JNICALL Java_org_qtproject_theosys_SettingsActivity_setNetlinxSurface(JNIEnv *env, jclass clazz, jstring surface)
307
{
308
    DECL_TRACER("Java_org_qtproject_theosys_Settings_setNetlinxIp(JNIEnv *env, jclass clazz, jstring surface)");
309
 
310
    Q_UNUSED(clazz);
311
 
312
    string netlinxSurface = javaJStringToString(env, surface);
313
 
314
    if (TConfig::getFtpSurface() != netlinxSurface)
315
        TConfig::saveFtpSurface(netlinxSurface);
316
}
317
 
318
JNIEXPORT void JNICALL Java_org_qtproject_theosys_SettingsActivity_setNetlinxFtpPassive(JNIEnv *env, jclass clazz, jboolean passive)
319
{
320
    DECL_TRACER("Java_org_qtproject_theosys_Settings_setNetlinxIp(JNIEnv *env, jclass clazz, jboolean passive)");
321
 
322
    Q_UNUSED(env);
323
    Q_UNUSED(clazz);
324
 
325
    if (TConfig::getFtpPassive() != passive)
326
        TConfig::saveFtpPassive(passive);
327
}
328
 
329
JNIEXPORT void JNICALL Java_org_qtproject_theosys_SettingsActivity_setViewScale(JNIEnv *env, jclass clazz, jboolean scale)
330
{
331
    DECL_TRACER("Java_org_qtproject_theosys_Settings_setViewScale(JNIEnv *env, jclass clazz, jboolean scale)");
332
 
333
    Q_UNUSED(env);
334
    Q_UNUSED(clazz);
335
 
336
    if (TConfig::getScale() != scale)
337
        TConfig::saveScale(scale);
338
}
339
 
340
JNIEXPORT void JNICALL Java_org_qtproject_theosys_SettingsActivity_setViewToolbar(JNIEnv *env, jclass clazz, jboolean bar)
341
{
342
    DECL_TRACER("Java_org_qtproject_theosys_Settings_setViewToolbar(JNIEnv *env, jclass clazz, jboolean bar)");
343
 
344
    Q_UNUSED(env);
345
    Q_UNUSED(clazz);
346
 
347
    if (TConfig::getToolbarSuppress() == bar)
348
        TConfig::saveToolbarSuppress(!bar);
349
}
350
 
351
JNIEXPORT void JNICALL Java_org_qtproject_theosys_SettingsActivity_setViewToolbarForce(JNIEnv *env, jclass clazz, jboolean bar)
352
{
353
    DECL_TRACER("Java_org_qtproject_theosys_Settings_setViewToolbarForce(JNIEnv *env, jclass clazz, jboolean bar)");
354
 
355
    Q_UNUSED(env);
356
    Q_UNUSED(clazz);
357
 
358
    if (TConfig::getToolbarForce() != bar)
359
        TConfig::saveToolbarForce(bar);
360
}
361
 
362
JNIEXPORT void JNICALL Java_org_qtproject_theosys_SettingsActivity_setViewRotation(JNIEnv *env, jclass clazz, jboolean rotate)
363
{
364
    DECL_TRACER("Java_org_qtproject_theosys_Settings_setViewRotation(JNIEnv *env, jclass clazz, jboolean rotate)");
365
 
366
    Q_UNUSED(env);
367
    Q_UNUSED(clazz);
368
 
369
    if (TConfig::getRotationFixed() != rotate)
370
        TConfig::setRotationFixed(rotate);
371
}
372
 
373
JNIEXPORT void JNICALL Java_org_qtproject_theosys_SettingsActivity_setSoundSystem(JNIEnv *env, jclass clazz, jstring sound)
374
{
375
    DECL_TRACER("Java_org_qtproject_theosys_Settings_setSoundSystem(JNIEnv *env, jclass clazz, jstring sound)");
376
 
377
    Q_UNUSED(clazz);
378
 
379
    string s = javaJStringToString(env, sound);
380
 
381
    if (TConfig::getSystemSound() != s)
382
        TConfig::saveSystemSoundFile(s);
383
}
384
 
385
JNIEXPORT void JNICALL Java_org_qtproject_theosys_SettingsActivity_setSoundSingle(JNIEnv *env, jclass clazz, jstring sound)
386
{
387
    DECL_TRACER("Java_org_qtproject_theosys_Settings_setSoundSingle(JNIEnv *env, jclass clazz, jstring sound)");
388
 
389
    Q_UNUSED(clazz);
390
 
391
    string s = javaJStringToString(env, sound);
392
 
393
    if (TConfig::getSingleBeepSound() != s)
394
        TConfig::saveSingleBeepFile(s);
395
}
396
 
397
JNIEXPORT void JNICALL Java_org_qtproject_theosys_SettingsActivity_setSoundDouble(JNIEnv *env, jclass clazz, jstring sound)
398
{
399
    DECL_TRACER("Java_org_qtproject_theosys_Settings_setSoundDouble(JNIEnv *env, jclass clazz, jstring sound)");
400
 
401
    Q_UNUSED(clazz);
402
 
403
    string s = javaJStringToString(env, sound);
404
 
405
    if (TConfig::getDoubleBeepSound() != s)
406
        TConfig::saveDoubleBeepFile(s);
407
}
408
 
409
JNIEXPORT void JNICALL Java_org_qtproject_theosys_SettingsActivity_setSoundEnable(JNIEnv *env, jclass clazz, jboolean sound)
410
{
411
    DECL_TRACER("Java_org_qtproject_theosys_Settings_setSoundEnable(JNIEnv *env, jclass clazz, jboolean sound)");
412
 
413
    Q_UNUSED(env);
414
    Q_UNUSED(clazz);
415
 
416
    if (TConfig::getSystemSoundState() != sound)
417
        TConfig::saveSystemSoundState(sound);
418
}
419
 
420
JNIEXPORT void JNICALL Java_org_qtproject_theosys_SettingsActivity_setSoundVolume(JNIEnv *env, jclass clazz, jint sound)
421
{
422
    DECL_TRACER("Java_org_qtproject_theosys_Settings_setSoundVolume(JNIEnv *env, jclass clazz, jint sound)");
423
 
424
    Q_UNUSED(env);
425
    Q_UNUSED(clazz);
426
 
427
    if (TConfig::getSystemVolume() != sound)
428
        TConfig::saveSystemVolume(sound);
429
}
430
 
431
JNIEXPORT void JNICALL Java_org_qtproject_theosys_SettingsActivity_setSoundGain(JNIEnv *env, jclass clazz, jint sound)
432
{
433
    DECL_TRACER("Java_org_qtproject_theosys_Settings_setSoundGain(JNIEnv *env, jclass clazz, jint sound)");
434
 
435
    Q_UNUSED(env);
436
    Q_UNUSED(clazz);
437
 
438
    if (TConfig::getSystemGain() != sound)
439
        TConfig::saveSystemGain(sound);
440
}
441
 
442
JNIEXPORT void JNICALL Java_org_qtproject_theosys_SettingsActivity_setSipProxy(JNIEnv *env, jclass clazz, jstring sip)
443
{
444
    DECL_TRACER("Java_org_qtproject_theosys_Settings_setSipProxy(JNIEnv *env, jclass clazz, jstring sip)");
445
 
446
    Q_UNUSED(clazz);
447
 
448
    string sipStr = javaJStringToString(env, sip);
449
 
450
    if (TConfig::getSIPproxy() != sipStr)
451
        TConfig::setSIPproxy(sipStr);
452
}
453
 
454
JNIEXPORT void JNICALL Java_org_qtproject_theosys_SettingsActivity_setSipPort(JNIEnv *env, jclass clazz, jint sip)
455
{
456
    DECL_TRACER("Java_org_qtproject_theosys_Settings_setSipPort(JNIEnv *env, jclass clazz, jint sip)");
457
 
458
    Q_UNUSED(env);
459
    Q_UNUSED(clazz);
460
 
461
    if (TConfig::getSIPport() != sip)
462
        TConfig::setSIPport(sip);
463
}
464
 
465
JNIEXPORT void JNICALL Java_org_qtproject_theosys_SettingsActivity_setSipTlsPort(JNIEnv *env, jclass clazz, jint sip)
466
{
467
    DECL_TRACER("Java_org_qtproject_theosys_Settings_setSipTlsPort(JNIEnv *env, jclass clazz, jint sip)");
468
 
469
    Q_UNUSED(env);
470
    Q_UNUSED(clazz);
471
 
472
    if (TConfig::getSIPportTLS() != sip)
473
        TConfig::setSIPportTLS(sip);
474
}
475
 
476
JNIEXPORT void JNICALL Java_org_qtproject_theosys_SettingsActivity_setSipStun(JNIEnv *env, jclass clazz, jstring sip)
477
{
478
    DECL_TRACER("Java_org_qtproject_theosys_Settings_setSipStun(JNIEnv *env, jclass clazz, jstring sip)");
479
 
480
    Q_UNUSED(clazz);
481
 
482
    string sipStr = javaJStringToString(env, sip);
483
 
484
    if (TConfig::getSIPstun() != sipStr)
485
        TConfig::setSIPstun(sipStr);
486
}
487
 
488
JNIEXPORT void JNICALL Java_org_qtproject_theosys_SettingsActivity_setSipDomain(JNIEnv *env, jclass clazz, jstring sip)
489
{
490
    DECL_TRACER("Java_org_qtproject_theosys_Settings_setSipDomain(JNIEnv *env, jclass clazz, jstring sip)");
491
 
492
    Q_UNUSED(clazz);
493
 
494
    string sipStr = javaJStringToString(env, sip);
495
 
496
    if (TConfig::getSIPdomain() != sipStr)
497
        TConfig::setSIPdomain(sipStr);
498
}
499
 
500
JNIEXPORT void JNICALL Java_org_qtproject_theosys_SettingsActivity_setSipUser(JNIEnv *env, jclass clazz, jstring sip)
501
{
502
    DECL_TRACER("Java_org_qtproject_theosys_Settings_setSipUser(JNIEnv *env, jclass clazz, jstring sip)");
503
 
504
    Q_UNUSED(clazz);
505
 
506
    string sipStr = javaJStringToString(env, sip);
507
 
508
    if (TConfig::getSIPuser() != sipStr)
509
        TConfig::setSIPuser(sipStr);
510
}
511
 
512
JNIEXPORT void JNICALL Java_org_qtproject_theosys_SettingsActivity_setSipPassword(JNIEnv *env, jclass clazz, jstring sip)
513
{
514
    DECL_TRACER("Java_org_qtproject_theosys_Settings_setSipPassword(JNIEnv *env, jclass clazz, jstring sip)");
515
 
516
    Q_UNUSED(clazz);
517
 
518
    string sipStr = javaJStringToString(env, sip);
519
 
520
    if (TConfig::getSIPpassword() != sipStr)
521
        TConfig::setSIPpassword(sipStr);
522
}
523
 
524
JNIEXPORT void JNICALL Java_org_qtproject_theosys_SettingsActivity_setSipIpv4(JNIEnv *env, jclass clazz, jboolean sip)
525
{
526
    DECL_TRACER("Java_org_qtproject_theosys_Settings_setSipIpv4(JNIEnv *env, jclass clazz, jboolean sip)");
527
 
528
    Q_UNUSED(env);
529
    Q_UNUSED(clazz);
530
 
531
    if (TConfig::getSIPnetworkIPv4() != sip)
532
        TConfig::setSIPnetworkIPv4(sip);
533
}
534
 
535
JNIEXPORT void JNICALL Java_org_qtproject_theosys_SettingsActivity_setSipIpv6(JNIEnv *env, jclass clazz, jboolean sip)
536
{
537
    DECL_TRACER("Java_org_qtproject_theosys_Settings_setSipIpv6(JNIEnv *env, jclass clazz, jboolean sip)");
538
 
539
    Q_UNUSED(env);
540
    Q_UNUSED(clazz);
541
 
542
    if (TConfig::getSIPnetworkIPv6() != sip)
543
        TConfig::setSIPnetworkIPv6(sip);
544
}
545
 
546
JNIEXPORT void JNICALL Java_org_qtproject_theosys_SettingsActivity_setSipEnabled(JNIEnv *env, jclass clazz, jboolean sip)
547
{
548
    DECL_TRACER("Java_org_qtproject_theosys_Settings_setSipEnabled(JNIEnv *env, jclass clazz, jboolean sip)");
549
 
550
    Q_UNUSED(env);
551
    Q_UNUSED(clazz);
552
 
553
    if (TConfig::getSIPstatus() != sip)
554
        TConfig::setSIPstatus(sip);
555
}
556
 
557
JNIEXPORT void JNICALL Java_org_qtproject_theosys_SettingsActivity_setSipIphone(JNIEnv *env, jclass clazz, jboolean sip)
558
{
559
    DECL_TRACER("Java_org_qtproject_theosys_Settings_setSipIphone(JNIEnv *env, jclass clazz, jboolean sip)");
560
 
561
    Q_UNUSED(env);
562
    Q_UNUSED(clazz);
563
 
564
    if (TConfig::getSIPiphone() != sip)
565
        TConfig::setSIPiphone(sip);
566
}
567
 
568
JNIEXPORT void JNICALL Java_org_qtproject_theosys_SettingsActivity_setLogInfo(JNIEnv *env, jclass clazz, jboolean log)
569
{
570
    DECL_TRACER("Java_org_qtproject_theosys_Settings_setLogInfo(JNIEnv *env, jclass clazz, jboolean log)");
571
 
572
    Q_UNUSED(env);
573
    Q_UNUSED(clazz);
574
 
575
    uint logSwitch = (log ? HLOG_INFO : 0);
576
 
577
    if ((TConfig::getLogLevelBits() & HLOG_INFO) != logSwitch)
578
    {
579
        if (!(TConfig::getLogLevelBits() & HLOG_INFO))
580
            TConfig::saveLogLevel(TConfig::getLogLevelBits() | HLOG_INFO);
581
        else
582
            TConfig::saveLogLevel(TConfig::getLogLevelBits() ^ HLOG_INFO);
583
    }
584
}
585
 
586
JNIEXPORT void JNICALL Java_org_qtproject_theosys_SettingsActivity_setLogWarning(JNIEnv *env, jclass clazz, jboolean log)
587
{
588
    DECL_TRACER("Java_org_qtproject_theosys_Settings_setLogWarning(JNIEnv *env, jclass clazz, jboolean log)");
589
 
590
    Q_UNUSED(env);
591
    Q_UNUSED(clazz);
592
 
593
    uint logSwitch = (log ? HLOG_WARNING : 0);
594
 
595
    if ((TConfig::getLogLevelBits() & HLOG_WARNING) != logSwitch)
596
    {
597
        if (!(TConfig::getLogLevelBits() & HLOG_INFO))
598
            TConfig::saveLogLevel(TConfig::getLogLevelBits() | HLOG_WARNING);
599
        else
600
            TConfig::saveLogLevel(TConfig::getLogLevelBits() ^ HLOG_WARNING);
601
    }
602
}
603
 
604
JNIEXPORT void JNICALL Java_org_qtproject_theosys_SettingsActivity_setLogError(JNIEnv *env, jclass clazz, jboolean log)
605
{
606
    DECL_TRACER("Java_org_qtproject_theosys_Settings_setLogError(JNIEnv *env, jclass clazz, jboolean log)");
607
 
608
    Q_UNUSED(env);
609
    Q_UNUSED(clazz);
610
 
611
    uint logSwitch = (log ? HLOG_ERROR : 0);
612
 
613
    if ((TConfig::getLogLevelBits() & HLOG_ERROR) != logSwitch)
614
    {
615
        if (!(TConfig::getLogLevelBits() & HLOG_ERROR))
616
            TConfig::saveLogLevel(TConfig::getLogLevelBits() | HLOG_ERROR);
617
        else
618
            TConfig::saveLogLevel(TConfig::getLogLevelBits() ^ HLOG_ERROR);
619
    }
620
}
621
 
622
JNIEXPORT void JNICALL Java_org_qtproject_theosys_SettingsActivity_setLogTrace(JNIEnv *env, jclass clazz, jboolean log)
623
{
624
    DECL_TRACER("Java_org_qtproject_theosys_Settings_setLogTrace(JNIEnv *env, jclass clazz, jboolean log)");
625
 
626
    Q_UNUSED(env);
627
    Q_UNUSED(clazz);
628
 
629
    uint logSwitch = (log ? HLOG_TRACE : 0);
630
 
631
    if ((TConfig::getLogLevelBits() & HLOG_TRACE) != logSwitch)
632
    {
633
        if (!(TConfig::getLogLevelBits() & HLOG_TRACE))
634
            TConfig::saveLogLevel(TConfig::getLogLevelBits() | HLOG_TRACE);
635
        else
636
            TConfig::saveLogLevel(TConfig::getLogLevelBits() ^ HLOG_TRACE);
637
    }
638
}
639
 
640
JNIEXPORT void JNICALL Java_org_qtproject_theosys_SettingsActivity_setLogDebug(JNIEnv *env, jclass clazz, jboolean log)
641
{
642
    DECL_TRACER("Java_org_qtproject_theosys_Settings_setLogDebug(JNIEnv *env, jclass clazz, jboolean log)");
643
 
644
    Q_UNUSED(env);
645
    Q_UNUSED(clazz);
646
 
647
    uint logSwitch = (log ? HLOG_DEBUG : 0);
648
 
649
    if ((TConfig::getLogLevelBits() & HLOG_DEBUG) != logSwitch)
650
    {
651
        if (!(TConfig::getLogLevelBits() & HLOG_DEBUG))
652
            TConfig::saveLogLevel(TConfig::getLogLevelBits() | HLOG_DEBUG);
653
        else
654
            TConfig::saveLogLevel(TConfig::getLogLevelBits() ^ HLOG_DEBUG);
655
    }
656
}
657
 
658
JNIEXPORT void JNICALL Java_org_qtproject_theosys_SettingsActivity_setLogProfile(JNIEnv *env, jclass clazz, jboolean log)
659
{
660
    DECL_TRACER("Java_org_qtproject_theosys_Settings_setLogProfile(JNIEnv *env, jclass clazz, jboolean log)");
661
 
662
    Q_UNUSED(env);
663
    Q_UNUSED(clazz);
664
 
665
    if (TConfig::getProfiling() != log)
666
        TConfig::saveProfiling(log);
667
}
668
 
669
JNIEXPORT void JNICALL Java_org_qtproject_theosys_SettingsActivity_setLogLongFormat(JNIEnv *env, jclass clazz, jboolean log)
670
{
671
    DECL_TRACER("Java_org_qtproject_theosys_Settings_setLogLongFormat(JNIEnv *env, jclass clazz, jboolean log)");
672
 
673
    Q_UNUSED(env);
674
    Q_UNUSED(clazz);
675
 
676
    if (TConfig::isLongFormat() != log)
677
        TConfig::saveFormat(log);
678
}
679
 
680
JNIEXPORT void JNICALL Java_org_qtproject_theosys_SettingsActivity_setLogEnableFile(JNIEnv *env, jclass clazz, jboolean log)
681
{
682
    DECL_TRACER("Java_org_qtproject_theosys_Settings_setLogEnableFile(JNIEnv *env, jclass clazz, jboolean log)");
683
 
684
    Q_UNUSED(env);
685
    Q_UNUSED(clazz);
686
 
687
    TConfig::setLogFileEnabled(log);
688
    TStreamError::setLogFileEnabled(log);
689
    string logFile = TConfig::getLogFile();
690
 
691
    if (log && !logFile.empty() && fs::is_regular_file(logFile))
692
        TStreamError::setLogFile(logFile);
693
    else if (!log)
694
        TStreamError::setLogFile("");
695
 
696
    __android_log_print(ANDROID_LOG_DEBUG, "tpanel", "JAVA::setLogEnableFile: Logfile was %s", (log ? "ENABLED" : "DISABLED"));
697
}
698
 
699
JNIEXPORT void JNICALL Java_org_qtproject_theosys_SettingsActivity_setLogFile(JNIEnv *env, jclass clazz, jstring log)
700
{
701
    DECL_TRACER("Java_org_qtproject_theosys_Settings_setLogFile(JNIEnv *env, jclass clazz, jstring sip)");
702
 
703
    Q_UNUSED(clazz);
704
 
705
    string logStr = javaJStringToString(env, log);
706
 
707
    if (TConfig::getLogFile() != logStr)
708
    {
709
        TConfig::saveLogFile(logStr);
710
        __android_log_print(ANDROID_LOG_DEBUG, "tpanel", "JAVA::setLogFile: Logfile set to: %s", logStr.c_str());
711
 
712
        if (fs::is_regular_file(logStr))
713
            TStreamError::setLogFile(logStr);
714
        else
715
        {
716
            TStreamError::setLogFile("");
717
            __android_log_print(ANDROID_LOG_WARN, "tpanel", "JAVA::setLogFile: Logfile \"%s\" is not accessible!", logStr.c_str());
718
        }
719
    }
720
}
721
 
722
JNIEXPORT void JNICALL Java_org_qtproject_theosys_SettingsActivity_setPassword1(JNIEnv *env, jclass clazz, jstring pw)
723
{
724
    DECL_TRACER("JNICALL Java_org_qtproject_theosys_SettingsActivity_setPassword1(JNIEnv *env, jclass clazz, jstring pw)");
725
 
726
    Q_UNUSED(clazz);
727
 
728
    string password = javaJStringToString(env, pw);
729
    TConfig::savePassword1(password);
730
}
731
 
732
JNIEXPORT void JNICALL Java_org_qtproject_theosys_SettingsActivity_setPassword2(JNIEnv *env, jclass clazz, jstring pw)
733
{
734
    DECL_TRACER("JNICALL Java_org_qtproject_theosys_SettingsActivity_setPassword2(JNIEnv *env, jclass clazz, jstring pw)");
735
 
736
    Q_UNUSED(clazz);
737
 
738
    string password = javaJStringToString(env, pw);
739
    TConfig::savePassword2(password);
740
}
741
 
742
JNIEXPORT void JNICALL Java_org_qtproject_theosys_SettingsActivity_setPassword3(JNIEnv *env, jclass clazz, jstring pw)
743
{
744
    DECL_TRACER("JNICALL Java_org_qtproject_theosys_SettingsActivity_setPassword3(JNIEnv *env, jclass clazz, jstring pw)");
745
 
746
    Q_UNUSED(clazz);
747
 
748
    string password = javaJStringToString(env, pw);
749
    TConfig::savePassword3(password);
750
}
751
 
752
JNIEXPORT void JNICALL Java_org_qtproject_theosys_SettingsActivity_setPassword4(JNIEnv *env, jclass clazz, jstring pw)
753
{
754
    DECL_TRACER("JNICALL Java_org_qtproject_theosys_SettingsActivity_setPassword4(JNIEnv *env, jclass clazz, jstring pw)");
755
 
756
    Q_UNUSED(clazz);
757
 
758
    string password = javaJStringToString(env, pw);
759
    TConfig::savePassword4(password);
760
}
761
#endif
762
 
763
TPageManager::TPageManager()
764
{
765
    TLOCKER(surface_mutex);
766
    DECL_TRACER("TPageManager::TPageManager()");
767
 
768
    gPageManager = this;
769
    TTPInit *tinit = new TTPInit;
770
    string projectPath = TConfig::getProjectPath();
771
    string pp = projectPath + "/prj.xma";
772
 
773
    tinit->setPath(projectPath);
774
    bool haveSurface = false;
775
 
776
    if (tinit->isVirgin())
777
        haveSurface = tinit->loadSurfaceFromController();
778
    else
779
        haveSurface = true;
780
 
781
    if (!haveSurface)
782
    {
783
        if (!isValidFile(pp))
784
            tinit->reinitialize();
785
    }
786
    else
787
        tinit->makeSystemFiles();
788
 
789
    delete tinit;
790
 
791
    // Read the AMX panel settings.
792
    mTSettings = new TSettings(projectPath);
793
 
794
    if (TError::isError())
795
    {
796
        MSG_ERROR("Settings were not read successfull!");
797
        return;
798
    }
799
 
800
    // Set the panel type from the project information
449 andreas 801
    TConfig::savePanelType(mTSettings->getPanelType());
446 andreas 802
 
803
    readMap();  // Start the initialisation of the AMX part.
804
 
805
    gPrjResources = new TPrjResources(mTSettings->getResourcesList());
806
    mPalette = new TPalette();
807
    vector<PALETTE_SETUP> pal = mTSettings->getSettings().palettes;
808
 
809
    if (pal.size() > 0)
810
    {
811
        vector<PALETTE_SETUP>::iterator iterPal;
812
 
813
        for (iterPal = pal.begin(); iterPal != pal.end(); ++iterPal)
814
            mPalette->initialize(iterPal->file);
815
    }
816
 
817
    if (!TError::isError())
818
        TColor::setPalette(mPalette);
819
 
820
    mFonts = new TFont();
821
 
822
    if (TError::isError())
823
    {
824
        MSG_ERROR("Initializing fonts was not successfull!");
825
    }
826
 
827
    gIcons = new TIcons();
828
 
829
    if (TError::isError())
830
    {
831
        MSG_ERROR("Initializing icons was not successfull!");
832
    }
833
 
834
    mPageList = new TPageList();
835
    mExternal = new TExternal();
836
    PAGELIST_T page;
837
 
449 andreas 838
    if (!mTSettings->getSettings().powerUpPage.empty())
446 andreas 839
    {
449 andreas 840
        if (readPage(mTSettings->getSettings().powerUpPage))
446 andreas 841
        {
449 andreas 842
            MSG_TRACE("Found power up page " << mTSettings->getSettings().powerUpPage);
843
            page = findPage(mTSettings->getSettings().powerUpPage);
844
            mActualPage = page.pageID;
446 andreas 845
        }
846
    }
847
    else
848
    {
449 andreas 849
        MSG_WARNING("No power up page defined! Setting default page to 1.");
850
        mActualPage = 1;
446 andreas 851
    }
852
 
853
    TPage *pg = getPage(mActualPage);
854
 
449 andreas 855
    vector<string> popups = mTSettings->getSettings().powerUpPopup;
446 andreas 856
 
857
    if (popups.size() > 0)
858
    {
859
        vector<string>::iterator iter;
860
 
861
        for (iter = popups.begin(); iter != popups.end(); ++iter)
862
        {
863
            if (readSubPage(*iter))
864
            {
865
                MSG_TRACE("Found power up popup " << *iter);
866
 
867
                if (pg)
868
                {
869
                    TSubPage *spage = getSubPage(*iter);
870
                    spage->setParent(pg->getHandle());
871
                    pg->addSubPage(spage);
872
                }
873
            }
874
        }
875
    }
876
 
877
    // Here we initialize the system resources like borders, cursors, sliders, ...
878
    mSystemDraw = new TSystemDraw(TConfig::getSystemPath(TConfig::BASE));
879
 
880
    // Here are the commands supported by this emulation.
881
    MSG_INFO("Registering commands ...");
882
    REG_CMD(doLEVON, "LEVON");  // Enable device to send level changes to the master.
883
    REG_CMD(doLEVOF, "LEVOF");  // Disable the device from sending level changes to the master.
884
    REG_CMD(doRXON, "RXON");    // Enable device to send STRING changes to the master.
885
    REG_CMD(doRXOF, "RXOF");    // Disable the device from sending STRING changes to the master.
886
    REG_CMD(doAFP, "@AFP");     // Flips to a page with the specified page name using an animated transition.
887
    REG_CMD(doAFP, "^AFP");     // Flips to a page with the specified page name using an animated transition.
888
    REG_CMD(doAPG, "@APG");     // Add a specific popup page to a specified popup group.
889
    REG_CMD(doCPG, "@CPG");     // Clear all popup pages from specified popup group.
890
    REG_CMD(doDPG, "@DPG");     // Delete a specific popup page from specified popup group if it exists
891
//    REG_CMD(doPDR, "@PDR");     // Set the popup location reset flag.
892
    REG_CMD(doPHE, "@PHE");     // Set the hide effect for the specified popup page to the named hide effect.
893
    REG_CMD(doPHP, "@PHP");     // Set the hide effect position.
894
    REG_CMD(doPHT, "@PHT");     // Set the hide effect time for the specified popup page.
895
    REG_CMD(doPPA, "@PPA");     // Close all popups on a specified page.
896
    REG_CMD(doPPA, "^PPA");     // G5: Close all popups on a specified page.
897
    REG_CMD(doPPF, "@PPF");     // Deactivate a specific popup page on either a specified page or the current page.
898
    REG_CMD(doPPF, "^PPF");     // G5: Deactivate a specific popup page on either a specified page or the current page.
899
    REG_CMD(doPPF, "PPOF");     // Deactivate a specific popup page on either a specified page or the current page
900
    REG_CMD(doPPG, "@PPG");     // Toggle a specific popup page on either a specified page or the current page.
901
    REG_CMD(doPPG, "^PPG");     // G5: Toggle a specific popup page on either a specified page or the current page.
902
    REG_CMD(doPPG, "PPOG");     // Toggle a specific popup page on either a specified page or the current page.
903
    REG_CMD(doPPK, "@PPK");     // Kill a specific popup page from all pages.
904
    REG_CMD(doPPK, "^PPK");     // G5: Kill a specific popup page from all pages.
905
    REG_CMD(doPPM, "@PPM");     // Set the modality of a specific popup page to Modal or NonModal.
906
    REG_CMD(doPPM, "^PPM");     // G5: Set the modality of a specific popup page to Modal or NonModal.
907
    REG_CMD(doPPN, "@PPN");     // Activate a specific popup page to launch on either a specified page or the current page.
908
    REG_CMD(doPPN, "^PPN");     // G5: Activate a specific popup page to launch on either a specified page or the current page.
909
    REG_CMD(doPPN, "PPON");     // Activate a specific popup page to launch on either a specified page or the current page.
910
    REG_CMD(doPPT, "@PPT");     // Set a specific popup page to timeout within a specified time.
911
    REG_CMD(doPPT, "^PPT");     // G5: Set a specific popup page to timeout within a specified time.
912
    REG_CMD(doPPX, "@PPX");     // Close all popups on all pages.
913
    REG_CMD(doPPX, "^PPX");     // G5: Close all popups on all pages.
914
    REG_CMD(doPSE, "@PSE");     // Set the show effect for the specified popup page to the named show effect.
915
    REG_CMD(doPSP, "@PSP");     // Set the show effect position.
916
    REG_CMD(doPST, "@PST");     // Set the show effect time for the specified popup page.
917
    REG_CMD(doPAGE, "PAGE");    // Flip to a specified page.
918
    REG_CMD(doPAGE, "^PGE");    // G5: Flip to a specified page.
919
 
920
    REG_CMD(doANI, "^ANI");     // Run a button animation (in 1/10 second).
921
    REG_CMD(doAPF, "^APF");     // Add page flip action to a button if it does not already exist.
922
    REG_CMD(doBAT, "^BAT");     // Append non-unicode text.
923
    REG_CMD(doBAU, "^BAU");     // Append unicode text. Same format as ^UNI.
924
    REG_CMD(doBCB, "^BCB");     // Set the border color.
925
    REG_CMD(getBCB, "?BCB");    // Get the current border color.
926
    REG_CMD(doBCF, "^BCF");     // Set the fill color to the specified color.
927
    REG_CMD(getBCF, "?BCF");    // Get the current fill color.
928
    REG_CMD(doBCT, "^BCT");     // Set the text color to the specified color.
929
    REG_CMD(getBCT, "?BCT");    // Get the current text color.
930
    REG_CMD(doBDO, "^BDO");     // Set the button draw order
931
    REG_CMD(doBFB, "^BFB");     // Set the feedback type of the button.
932
    REG_CMD(doBIM, "^BIM");     // Set the input mask for the specified address
933
    REG_CMD(doBMC, "^BMC");     // Button copy command.
934
    REG_CMD(doBMF, "^BMF");     // Button Modify Command - Set any/all button parameters by sending embedded codes and data.
935
//    REG_CMD(doBMI, "^BMI");    // Set the button mask image.
936
    REG_CMD(doBML, "^BML");     // Set the maximum length of the text area button.
937
    REG_CMD(doBMP, "^BMP");     // Assign a picture to those buttons with a defined addressrange.
938
    REG_CMD(getBMP, "?BMP");    // Get the current bitmap name.
939
    REG_CMD(doBOP, "^BOP");     // Set the button opacity.
940
    REG_CMD(getBOP, "?BOP");    // Get the button opacity.
941
    REG_CMD(doBOR, "^BOR");     // Set a border to a specific border style.
942
    REG_CMD(doBOS, "^BOS");     // Set the button to display either a Video or Non-Video window.
943
    REG_CMD(doBRD, "^BRD");     // Set the border of a button state/states.
944
    REG_CMD(getBRD, "?BRD");    // Get the border of a button state/states.
945
//    REG_CMD(doBSF, "^BSF");     // Set the focus to the text area.
946
    REG_CMD(doBSP, "^BSP");     // Set the button size and position.
947
    REG_CMD(doBSM, "^BSM");     // Submit text for text area buttons.
948
    REG_CMD(doBSO, "^BSO");     // Set the sound played when a button is pressed.
949
    REG_CMD(doBWW, "^BWW");     // Set the button word wrap feature to those buttons with a defined address range.
950
    REG_CMD(getBWW, "?BWW");    // Get the button word wrap feature to those buttons with a defined address range.
951
    REG_CMD(doCPF, "^CPF");     // Clear all page flips from a button.
952
    REG_CMD(doDPF, "^DPF");     // Delete page flips from button if it already exists.
953
    REG_CMD(doENA, "^ENA");     // Enable or disable buttons with a set variable text range.
954
    REG_CMD(doFON, "^FON");     // Set a font to a specific Font ID value for those buttons with a range.
955
    REG_CMD(getFON, "?FON");    // Get the current font index.
956
    REG_CMD(doGDI, "^GDI");     // Change the bargraph drag increment.
957
    REG_CMD(doGIV, "^GIV");     // Invert the joystick axis to move the origin to another corner.
958
    REG_CMD(doGLH, "^GLH");     // Change the bargraph upper limit.
959
    REG_CMD(doGLL, "^GLL");     // Change the bargraph lower limit.
960
    REG_CMD(doGRD, "^GRD");     // Change the bargraph ramp down time.
961
    REG_CMD(doGRU, "^GRU");     // Change the bargraph ramp up time.
962
    REG_CMD(doGSN, "^GSN");     // Set slider/cursor name.
963
    REG_CMD(doGSC, "^GSC");     // Change the bargraph slider color or joystick cursor color.
964
    REG_CMD(doICO, "^ICO");     // Set the icon to a button.
965
    REG_CMD(getICO, "?ICO");    // Get the current icon index.
966
    REG_CMD(doJSB, "^JSB");     // Set bitmap/picture alignment using a numeric keypad layout for those buttons with a defined address range.
967
    REG_CMD(getJSB, "?JSB");    // Get the current bitmap justification.
968
    REG_CMD(doJSI, "^JSI");     // Set icon alignment using a numeric keypad layout for those buttons with a defined address range.
969
    REG_CMD(getJSI, "?JSI");    // Get the current icon justification.
970
    REG_CMD(doJST, "^JST");     // Set text alignment using a numeric keypad layout for those buttons with a defined address range.
971
    REG_CMD(getJST, "?JST");    // Get the current text justification.
972
    REG_CMD(doMSP, "^MSP");     // Set marquee line speed.
973
    REG_CMD(doSHO, "^SHO");     // Show or hide a button with a set variable text range.
974
    REG_CMD(doTEC, "^TEC");     // Set the text effect color for the specified addresses/states to the specified color.
975
    REG_CMD(getTEC, "?TEC");    // Get the current text effect color.
976
    REG_CMD(doTEF, "^TEF");     // Set the text effect. The Text Effect is specified by name and can be found in TPD4.
977
    REG_CMD(getTEF, "?TEF");    // Get the current text effect name.
978
//    REG_CMD(doTOP, "^TOP");     // Send events to the Master as string events.
979
    REG_CMD(doTXT, "^TXT");     // Assign a text string to those buttons with a defined address range.
980
    REG_CMD(getTXT, "?TXT");    // Get the current text information.
981
    REG_CMD(doUNI, "^UNI");     // Set Unicode text.
982
    REG_CMD(doUTF, "^UTF");     // G5: Set button state text using UTF-8 text command.
983
    REG_CMD(doVTP, "^VTP");     // Simulates a touch/release/pulse at the given coordinate
984
 
985
    REG_CMD(doLPB, "^LPB");     // Assigns a user name to a button.
986
    REG_CMD(doLPC, "^LPC");     // Clear all users from the User Access Passwords list on the Password Setup page.
987
    REG_CMD(doLPR, "^LPR");     // Remove a given user from the User Access Passwords list on the Password Setup page.
988
    REG_CMD(doLPS, "^LPS");     // Set the user name and password.
989
 
990
    REG_CMD(doKPS, "^KPS");     // Set the keyboard passthru.
991
    REG_CMD(doVKS, "^VKS");     // Send one or more virtual key strokes to the G4 application.
992
 
993
    REG_CMD(doAPWD, "@PWD");    // Set the page flip password.
994
    REG_CMD(doPWD, "^PWD");     // Set the page flip password. Password level is required and must be 1 - 4.
995
 
996
    REG_CMD(doBBR, "^BBR");     // Set the bitmap of a button to use a particular resource.
997
    REG_CMD(doRAF, "^RAF");     // Add new resources
998
    REG_CMD(doRFR, "^RFR");     // Force a refresh for a given resource.
999
    REG_CMD(doRMF, "^RMF");     // Modify an existing resource.
1000
    REG_CMD(doRSR, "^RSR");     // Change the refresh rate for a given resource.
1001
 
1002
    REG_CMD(doABEEP, "ABEEP");  // Output a single beep even if beep is Off.
1003
    REG_CMD(doADBEEP, "ADBEEP");// Output a double beep even if beep is Off.
1004
    REG_CMD(doAKB, "@AKB");     // Pop up the keyboard icon and initialize the text string to that specified.
1005
    REG_CMD(doAKEYB, "AKEYB");  // Pop up the keyboard icon and initialize the text string to that specified.
1006
    REG_CMD(doAKP, "@AKP");     // Pop up the keypad icon and initialize the text string to that specified.
1007
    REG_CMD(doAKEYP, "AKEYP");  // Pop up the keypad icon and initialize the text string to that specified.
1008
    REG_CMD(doAKEYR, "AKEYR");  // Remove the Keyboard/Keypad.
1009
    REG_CMD(doAKR, "@AKR");     // Remove the Keyboard/Keypad.
1010
    REG_CMD(doBEEP, "BEEP");    // Play a single beep.
1011
    REG_CMD(doBEEP, "^ABP");    // G5: Play a single beep.
1012
    REG_CMD(doDBEEP, "DBEEP");  // Play a double beep.
1013
    REG_CMD(doDBEEP, "^ADB");   // G5: Play a double beep.
1014
    REG_CMD(doEKP, "@EKP");     // Pop up the keypad icon and initialize the text string to that specified.
1015
    REG_CMD(doPKP, "@PKB");     // Present a private keyboard.
1016
    REG_CMD(doPKP, "PKEYP");    // Present a private keypad.
1017
    REG_CMD(doPKP, "@PKP");     // Present a private keypad.
1018
    REG_CMD(doRPP, "^RPP");     // Reset protected password command
1019
    REG_CMD(doSetup, "SETUP");  // Send panel to SETUP page.
1020
    REG_CMD(doSetup, "^STP");   // G5: Open setup page.
1021
    REG_CMD(doShutdown, "SHUTDOWN");// Shut down the App
1022
    REG_CMD(doSOU, "@SOU");     // Play a sound file.
1023
    REG_CMD(doSOU, "^SOU");     // G5: Play a sound file.
1024
    REG_CMD(doMUT, "^MUT");     // G5: Panel Volume Mute
1025
    REG_CMD(doTKP, "@TKP");     // Present a telephone keypad.
1026
    REG_CMD(doTKP, "^TKP");     // G5: Bring up a telephone keypad.
1027
    REG_CMD(doTKP, "@VKB");     // Present a virtual keyboard
1028
    REG_CMD(doTKP, "^VKB");     // G5: Bring up a virtual keyboard.
1029
#ifndef _NOSIP_
1030
    // Here the SIP commands will take place
1031
    REG_CMD(doPHN, "^PHN");     // SIP commands
1032
    REG_CMD(getPHN, "?PHN");    // SIP state commands
1033
#endif
1034
    // SubView commands
1035
//    REG_CMD(doEPR, "^EPR");     // Execute Push on Release.
1036
//    REG_CMD(doSCE, "^SCE");     // Configures subpage custom events.
1037
//    REG_CMD(doSDR, "^SDR");     // Enabling subpage dynamic reordering.
1038
    REG_CMD(doSHA, "^SHA");     // Subpage Hide All Command
1039
    REG_CMD(doSHD, "^SHD");     // Hides subpage
1040
    REG_CMD(doSPD, "^SPD");     //  Set the padding between subpages on a subpage viewer button
1041
    REG_CMD(doSSH, "^SSH");     // Subpage show command.
1042
    REG_CMD(doSTG, "^STG");     // Subpage toggle command
1043
 
1044
    // ListView commands (G5)
1045
    REG_CMD(doLVD, "^LVD");     // G5: Set Listview Data Source
1046
    REG_CMD(doLVE, "^LVE");     // G5: Set ListView custom event number
1047
    REG_CMD(doLVF, "^LVF");     // G5: Listview Filter
1048
    REG_CMD(doLVL, "^LVL");     // G5: ListView layout
1049
    REG_CMD(doLVM, "^LVM");     // G5: ListView map fields
1050
    REG_CMD(doLVN, "^LVN");     // G5: ListView navigate
1051
    REG_CMD(doLVR, "^LVR");     // G5: ListView refresh data
1052
    REG_CMD(doLVS, "^LVS");     // G5: ListView sort data
1053
 
1054
    // State commands
1055
    REG_CMD(doON, "ON");
1056
    REG_CMD(doOFF, "OFF");
1057
    REG_CMD(doLEVEL, "LEVEL");
1058
    REG_CMD(doBLINK, "BLINK");
1059
    REG_CMD(doVER, "^VER?");    // Return version string to master
1060
#ifndef _NOSIP_
1061
    REG_CMD(doWCN, "^WCN?");    // Return SIP phone number
1062
#endif
1063
    // TPControl commands
1064
    REG_CMD(doTPCCMD, "TPCCMD");    // Profile related options
1065
    REG_CMD(doTPCACC, "TPCACC");    // Device orientation
1066
#ifndef _NOSIP_
1067
    REG_CMD(doTPCSIP, "TPCSIP");    // Show the built in SIP phone
1068
#endif
1069
    // Virtual internal commands
1070
    REG_CMD(doFTR, "#FTR");     // File transfer (virtual internal command)
1071
 
1072
    // At least we must add the SIP client
1073
#ifndef _NOSIP_
1074
    mSIPClient = new TSIPClient;
1075
 
1076
    if (TError::isError())
1077
    {
1078
        MSG_ERROR("Error initializing the SIP client!");
1079
        TConfig::setSIPstatus(false);
1080
    }
1081
#endif
1082
    TError::clear();
1083
    runClickQueue();
1084
    runUpdateSubViewItem();
1085
}
1086
 
1087
TPageManager::~TPageManager()
1088
{
1089
    DECL_TRACER("TPageManager::~TPageManager()");
1090
#ifndef _NOSIP_
1091
    if (mSIPClient)
1092
    {
1093
        delete mSIPClient;
1094
        mSIPClient = nullptr;
1095
    }
1096
#endif
1097
    PCHAIN_T *p = mPchain;
1098
    PCHAIN_T *next = nullptr;
1099
#ifdef __ANDROID__
1100
    stopNetworkState();
1101
#endif
1102
    try
1103
    {
1104
        while (p)
1105
        {
1106
            next = p->next;
1107
 
1108
            if (p->page)
1109
                delete p->page;
1110
 
1111
            delete p;
1112
            p = next;
1113
        }
1114
 
1115
        SPCHAIN_T *sp = mSPchain;
1116
        SPCHAIN_T *snext = nullptr;
1117
 
1118
        while (sp)
1119
        {
1120
            snext = sp->next;
1121
 
1122
            if (sp->page)
1123
                delete sp->page;
1124
 
1125
            delete sp;
1126
            sp = snext;
1127
        }
1128
 
1129
        mPchain = nullptr;
1130
        mSPchain = nullptr;
1131
        setPChain(mPchain);
1132
        setSPChain(mSPchain);
1133
 
1134
        if (mAmxNet)
1135
        {
1136
            delete mAmxNet;
1137
            mAmxNet = nullptr;
1138
        }
1139
 
1140
        if (mTSettings)
1141
        {
1142
            delete mTSettings;
1143
            mTSettings = nullptr;
1144
        }
1145
 
1146
        if (mPageList)
1147
        {
1148
            delete mPageList;
1149
            mPageList = nullptr;
1150
        }
1151
 
1152
        if (mPalette)
1153
        {
1154
            delete mPalette;
1155
            mPalette = nullptr;
1156
        }
1157
 
1158
        if (mFonts)
1159
        {
1160
            delete mFonts;
1161
            mFonts = nullptr;
1162
        }
1163
 
1164
        if (gIcons)
1165
        {
1166
            delete gIcons;
1167
            gIcons = nullptr;
1168
        }
1169
 
1170
        if (gPrjResources)
1171
        {
1172
            delete gPrjResources;
1173
            gPrjResources = nullptr;
1174
        }
1175
 
1176
        if (mExternal)
1177
        {
1178
            delete mExternal;
1179
            mExternal = nullptr;
1180
        }
1181
 
1182
        if (!mButtonStates.empty())
1183
        {
1184
            vector<TButtonStates *>::iterator iter;
1185
 
1186
            for (iter = mButtonStates.begin(); iter != mButtonStates.end(); ++iter)
1187
                delete *iter;
1188
 
1189
            mButtonStates.clear();
1190
        }
1191
    }
1192
    catch (std::exception& e)
1193
    {
1194
        MSG_ERROR("Memory error: " << e.what());
1195
    }
1196
 
1197
    gPageManager = nullptr;
1198
}
1199
 
1200
void TPageManager::initialize()
1201
{
1202
    DECL_TRACER("TPageManager::initialize()");
1203
 
1204
    surface_mutex.lock();
1205
    dropAllSubPages();
1206
    dropAllPages();
1207
 
1208
    string projectPath = TConfig::getProjectPath();
1209
 
1210
    if (!fs::exists(projectPath + "/prj.xma"))
1211
        projectPath += "/__system";
1212
 
1213
    if (mAmxNet && mAmxNet->isConnected())
1214
        mAmxNet->close();
1215
 
1216
    if (mTSettings)
1217
        mTSettings->loadSettings();
1218
    else
1219
        mTSettings = new TSettings(projectPath);
1220
 
1221
    if (TError::isError())
1222
    {
1223
        surface_mutex.unlock();
1224
        return;
1225
    }
1226
 
1227
    // Set the panel type from the project information
1228
    TConfig::savePanelType(mTSettings->getPanelType());
1229
 
1230
    if (gPrjResources)
1231
        delete gPrjResources;
1232
 
1233
    gPrjResources = new TPrjResources(mTSettings->getResourcesList());
1234
 
1235
    if (mPalette)
1236
        delete mPalette;
1237
 
1238
    mPalette = new TPalette();
1239
 
1240
    vector<PALETTE_SETUP> pal = mTSettings->getSettings().palettes;
1241
 
1242
    if (pal.size() > 0)
1243
    {
1244
        vector<PALETTE_SETUP>::iterator iterPal;
1245
 
1246
        for (iterPal = pal.begin(); iterPal != pal.end(); ++iterPal)
1247
            mPalette->initialize(iterPal->file);
1248
    }
1249
 
1250
    if (!TError::isError())
1251
        TColor::setPalette(mPalette);
1252
 
1253
    if (mFonts)
1254
        delete mFonts;
1255
 
1256
    mFonts = new TFont();
1257
 
1258
    if (TError::isError())
1259
    {
1260
        MSG_ERROR("Initializing fonts was not successfull!");
1261
        surface_mutex.unlock();
1262
        return;
1263
    }
1264
 
1265
    if (gIcons)
1266
        delete gIcons;
1267
 
1268
    gIcons = new TIcons();
1269
 
1270
    if (TError::isError())
1271
    {
1272
        MSG_ERROR("Initializing icons was not successfull!");
1273
        surface_mutex.unlock();
1274
        return;
1275
    }
1276
 
1277
    if (mPageList)
1278
        delete mPageList;
1279
 
1280
    mPageList = new TPageList();
1281
 
1282
    if (mExternal)
1283
        delete mExternal;
1284
 
1285
    mExternal = new TExternal();
1286
 
1287
    PAGELIST_T page;
1288
 
1289
    if (!mTSettings->getSettings().powerUpPage.empty())
1290
    {
1291
        if (readPage(mTSettings->getSettings().powerUpPage))
1292
        {
1293
            MSG_TRACE("Found power up page " << mTSettings->getSettings().powerUpPage);
1294
            page = findPage(mTSettings->getSettings().powerUpPage);
1295
            mActualPage = page.pageID;
1296
        }
1297
    }
1298
 
1299
    TPage *pg = getPage(mActualPage);
1300
 
1301
    vector<string> popups = mTSettings->getSettings().powerUpPopup;
1302
 
1303
    if (popups.size() > 0)
1304
    {
1305
        vector<string>::iterator iter;
1306
 
1307
        for (iter = popups.begin(); iter != popups.end(); ++iter)
1308
        {
1309
            if (readSubPage(*iter))
1310
            {
1311
                MSG_TRACE("Found power up popup " << *iter);
1312
 
1313
                if (pg)
1314
                {
1315
                    TSubPage *spage = getSubPage(*iter);
1316
                    spage->setParent(pg->getHandle());
1317
                    pg->addSubPage(spage);
1318
                }
1319
            }
1320
        }
1321
    }
1322
 
1323
    // Here we initialize the system resources like borders, cursors, sliders, ...
1324
    if (mSystemDraw)
1325
        delete mSystemDraw;
1326
 
1327
    mSystemDraw = new TSystemDraw(TConfig::getSystemPath(TConfig::BASE));
1328
 
1329
    TError::clear();        // Clear all errors who may be occured until here
1330
 
1331
    // Start the thread
1332
    startComm();
1333
 
1334
    surface_mutex.unlock();
1335
}
1336
 
1337
bool TPageManager::startComm()
1338
{
1339
    DECL_TRACER("TPageManager::startComm()");
1340
 
1341
    if (mAmxNet && mAmxNet->isNetRun())
1342
        return true;
1343
 
1344
    try
1345
    {
1346
        if (!mAmxNet)
1347
        {
1348
            if (_netRunning)
1349
            {
1350
                // Wait until previous connection thread ended
1351
                while (_netRunning)
1352
                    std::this_thread::sleep_for(std::chrono::milliseconds(100));
1353
            }
1354
 
1355
            mAmxNet = new amx::TAmxNet();
1356
            mAmxNet->setCallback(bind(&TPageManager::doCommand, this, std::placeholders::_1));
1357
            mAmxNet->setPanelID(TConfig::getChannel());
1358
            mAmxNet->setSerialNum(V_SERIAL);
1359
        }
1360
 
1361
        if (!mAmxNet->isNetRun())
1362
            mAmxNet->Run();
1363
    }
1364
    catch (std::exception& e)
1365
    {
1366
        MSG_ERROR("Error starting the AmxNet thread: " << e.what());
1367
        return false;
1368
    }
1369
 
1370
    return true;
1371
}
1372
 
1373
void TPageManager::startUp()
1374
{
1375
    DECL_TRACER("TPageManager::startUp()");
1376
 
1377
    if (mAmxNet)
1378
    {
1379
        MSG_WARNING("Communication with controller already initialized!");
1380
        return;
1381
    }
1382
 
1383
    if (!startComm())
1384
        return;
1385
 
1386
#ifdef __ANDROID__
1387
    initOrientation();
1388
    initNetworkState();
1389
#endif
1390
}
1391
 
1392
void TPageManager::reset()
1393
{
1394
    DECL_TRACER("TPageManager::reset()");
1395
 
1396
    // Freshly initialize everything.
1397
    initialize();
1398
}
1399
 
1400
void TPageManager::runCommands()
1401
{
1402
    DECL_TRACER("TPageManager::runCommands()");
1403
 
1404
    if (cmdLoop_busy)
1405
        return;
1406
 
1407
    try
1408
    {
1409
        mThreadCommand = std::thread([=] { this->commandLoop(); });
1410
        mThreadCommand.detach();
1411
    }
1412
    catch (std::exception& e)
1413
    {
1414
        MSG_ERROR("Error starting thread for command loop: " << e.what());
1415
        _netRunning = false;
1416
    }
1417
}
1418
 
1419
void TPageManager::showSetup()
1420
{
1421
    DECL_TRACER("TPageManager::showSetup()");
1422
#ifdef Q_OS_ANDROID
1423
    // Scan Netlinx for TP4 files and update the list of setup.
1424
    if (TConfig::getController().compare("0.0.0.0") != 0)
1425
    {
1426
        if (_startWait)
1427
            _startWait(string("Please wait while I try to load the list of surface files from Netlinx (") + TConfig::getController() + ")");
1428
 
1429
        TTPInit tpinit;
1430
        std::vector<TTPInit::FILELIST_t> fileList;
1431
        tpinit.setPath(TConfig::getProjectPath());
1432
        fileList = tpinit.getFileList(".tp4");
1433
 
1434
        if (fileList.size() > 0)
1435
        {
1436
            vector<TTPInit::FILELIST_t>::iterator iter;
1437
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
1438
            QAndroidJniObject::callStaticMethod<void>("org/qtproject/theosys/Settings", "clearSurfaces");
1439
#else
1440
            QJniObject::callStaticMethod<void>("org/qtproject/theosys/Settings", "clearSurfaces");
1441
#endif
1442
            for (iter = fileList.begin(); iter != fileList.end(); ++iter)
1443
            {
1444
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
1445
                QAndroidJniObject str = QAndroidJniObject::fromString(iter->fname.c_str());
1446
                QAndroidJniObject::callStaticMethod<void>("org/qtproject/theosys/Settings", "addSurface", "(Ljava/lang/String;)V", str.object<jstring>());
1447
#else
1448
                QJniObject str = QJniObject::fromString(iter->fname.c_str());
1449
                QJniObject::callStaticMethod<void>("org/qtproject/theosys/Settings", "addSurface", "(Ljava/lang/String;)V", str.object<jstring>());
1450
#endif
1451
            }
1452
        }
1453
 
1454
        if (_stopWait)
1455
            _stopWait();
1456
    }
1457
 
1458
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
1459
    QAndroidJniObject::callStaticMethod<void>("org/qtproject/theosys/Settings", "setLogLevel", "(Ljava/lang/Integer;)V", TConfig::getLogLevelBits());
1460
    QAndroidJniObject strPath = QAndroidJniObject::fromString(TConfig::getLogFile().c_str());
1461
    QAndroidJniObject::callStaticMethod<void>("org/qtproject/theosys/Settings", "setLogEnableFile", "(Z)V", TConfig::getLogFileEnabled());
1462
    QAndroidJniObject::callStaticMethod<void>("org/qtproject/theosys/Settings", "setLogPath", "(Ljava/lang/String;)V", strPath.object<jstring>());
1463
 
1464
    QAndroidJniObject pw1 = QAndroidJniObject::fromString(TConfig::getPassword1().c_str());
1465
    QAndroidJniObject pw2 = QAndroidJniObject::fromString(TConfig::getPassword2().c_str());
1466
    QAndroidJniObject pw3 = QAndroidJniObject::fromString(TConfig::getPassword3().c_str());
1467
    QAndroidJniObject pw4 = QAndroidJniObject::fromString(TConfig::getPassword4().c_str());
1468
    QAndroidJniObject::callStaticMethod<void>("org/qtproject/theosys/Settings", "setPassword", "(ILjava/lang/String;)V", 1, pw1.object<jstring>());
1469
    QAndroidJniObject::callStaticMethod<void>("org/qtproject/theosys/Settings", "setPassword", "(ILjava/lang/String;)V", 2, pw2.object<jstring>());
1470
    QAndroidJniObject::callStaticMethod<void>("org/qtproject/theosys/Settings", "setPassword", "(ILjava/lang/String;)V", 3, pw3.object<jstring>());
1471
    QAndroidJniObject::callStaticMethod<void>("org/qtproject/theosys/Settings", "setPassword", "(ILjava/lang/String;)V", 4, pw4.object<jstring>());
1472
#else
1473
    QJniObject::callStaticMethod<void>("org/qtproject/theosys/Settings", "setLogLevel", "(I)V", TConfig::getLogLevelBits());
1474
    QJniObject::callStaticMethod<void>("org/qtproject/theosys/Settings", "setLogEnableFile", "(I)V", (TConfig::getLogFileEnabled() ? 1 : 0));
1475
    QJniObject strPath = QJniObject::fromString(TConfig::getLogFile().c_str());
1476
    QJniObject::callStaticMethod<void>("org/qtproject/theosys/Settings", "setLogPath", "(Ljava/lang/String;)V", strPath.object<jstring>());
1477
 
1478
    QJniObject pw1 = QJniObject::fromString(TConfig::getPassword1().c_str());
1479
    QJniObject pw2 = QJniObject::fromString(TConfig::getPassword2().c_str());
1480
    QJniObject pw3 = QJniObject::fromString(TConfig::getPassword3().c_str());
1481
    QJniObject pw4 = QJniObject::fromString(TConfig::getPassword4().c_str());
1482
    QJniObject::callStaticMethod<void>("org/qtproject/theosys/Settings", "setPassword", "(ILjava/lang/String;)V", 1, pw1.object<jstring>());
1483
    QJniObject::callStaticMethod<void>("org/qtproject/theosys/Settings", "setPassword", "(ILjava/lang/String;)V", 2, pw2.object<jstring>());
1484
    QJniObject::callStaticMethod<void>("org/qtproject/theosys/Settings", "setPassword", "(ILjava/lang/String;)V", 3, pw3.object<jstring>());
1485
    QJniObject::callStaticMethod<void>("org/qtproject/theosys/Settings", "setPassword", "(ILjava/lang/String;)V", 4, pw4.object<jstring>());
1486
#endif
1487
 
1488
    enterSetup();
1489
#else
1490
        if (_callShowSetup)
1491
            _callShowSetup();
1492
#endif
1493
}
1494
 
1495
int TPageManager::getSelectedRow(ulong handle)
1496
{
1497
    DECL_TRACER("TPageManager::getSelectedRow(ulong handle)");
1498
 
1499
    int nPage = (handle >> 16) & 0x0000ffff;
1500
 
1501
    if ((nPage && TPage::isRegularPage(nPage)) || TPage::isSystemPage(nPage)) // Do we have a page?
1502
    {                                                   // Yes, then look on page
1503
        TPage *pg = getPage(nPage);
1504
 
1505
        if (!pg)
1506
            return -1;
1507
 
1508
        return pg->getSelectedRow(handle);
1509
    }
1510
    else if (TPage::isRegularSubPage(nPage) || TPage::isSystemSubPage(nPage))
1511
    {
1512
        TSubPage *subPg = getSubPage(nPage);
1513
 
1514
        if (!subPg)
1515
            return -1;
1516
 
1517
        return subPg->getSelectedRow(handle);
1518
    }
1519
 
1520
    MSG_WARNING("Invalid handle " << handleToString(handle) << " detected!");
1521
    return -1;
1522
}
1523
 
1524
string TPageManager::getSelectedItem(ulong handle)
1525
{
1526
    DECL_TRACER("TPageManager::getSelectedItem(ulong handle)");
1527
 
1528
    int nPage = (handle >> 16) & 0x0000ffff;
1529
 
1530
    if ((nPage && TPage::isRegularPage(nPage)) || TPage::isSystemPage(nPage)) // Do we have a page?
1531
    {                                                   // Yes, then look on page
1532
        TPage *pg = getPage(nPage);
1533
 
1534
        if (!pg)
1535
            return string();
1536
 
1537
        return pg->getSelectedItem(handle);
1538
    }
1539
    else if (TPage::isRegularSubPage(nPage) || TPage::isSystemSubPage(nPage))
1540
    {
1541
        TSubPage *subPg = getSubPage(nPage);
1542
 
1543
        if (!subPg)
1544
            return string();
1545
 
1546
        return subPg->getSelectedItem(handle);
1547
    }
1548
 
1549
    MSG_WARNING("Invalid handle " << handleToString(handle) << " detected!");
1550
    return string();
1551
}
1552
 
1553
void TPageManager::setSelectedRow(ulong handle, int row, const std::string& text)
1554
{
1555
    DECL_TRACER("TPageManager::setSelectedRow(ulong handle, int row)");
1556
 
1557
    int nPage = (handle >> 16) & 0x0000ffff;
1558
 
1559
    if (TPage::isRegularPage(nPage) || TPage::isSystemPage(nPage)) // Do we have a page?
1560
    {                                                   // Yes, then look on page
1561
        TPage *pg = getPage(nPage);
1562
 
1563
        if (!pg)
1564
            return;
1565
 
1566
        pg->setSelectedRow(handle, row);
1567
    }
1568
    else if (TPage::isRegularSubPage(nPage) || TPage::isSystemSubPage(nPage))   // Do we have a subpage?
1569
    {                                                   // Yes, then look on subpage
1570
        TSubPage *subPg = getSubPage(nPage);
1571
 
1572
        if (!subPg)
1573
            return;
1574
 
1575
        subPg->setSelectedRow(handle, row);
1576
        // Check if this is a system list. If so we must set the selected
1577
        // text to the input line or "label".
1578
        TPage *mainPage = nullptr;
1579
 
1580
        if (nPage >= SYSTEM_SUBPAGE_START)  // System subpage?
1581
        {
1582
            switch(nPage)
1583
            {
1584
                case SYSTEM_SUBPAGE_SYSTEMSOUND:
1585
                case SYSTEM_SUBPAGE_SINGLEBEEP:
1586
                case SYSTEM_SUBPAGE_DOUBLEBEEP:
1587
                    mainPage = getPage(SYSTEM_PAGE_SOUND);
1588
                break;
1589
 
1590
                case SYSTEM_SUBPAGE_SURFACE:
1591
                    mainPage = getPage(SYSTEM_PAGE_CONTROLLER);
1592
                break;
1593
            }
1594
        }
1595
 
1596
        if (mainPage)
1597
        {
1598
            if (nPage == SYSTEM_SUBPAGE_SYSTEMSOUND)  // System sound beep
1599
            {
1600
                Button::TButton *bt = mainPage->getButton(SYSTEM_PAGE_SOUND_TXSYSSOUND);
1601
 
1602
                if (bt)
1603
                {
1604
                    bt->setText(text, -1);
1605
                    TConfig::setTemporary(true);
1606
                    TConfig::saveSystemSoundFile(text);
1607
                }
1608
            }
1609
            else if (nPage == SYSTEM_SUBPAGE_SINGLEBEEP) // System sound single beep
1610
            {
1611
                Button::TButton *bt = mainPage->getButton(SYSTEM_PAGE_SOUND_TXSINGLEBEEP);
1612
 
1613
                if (bt)
1614
                {
1615
                    bt->setText(text, -1);
1616
                    TConfig::setTemporary(true);
1617
                    TConfig::saveSingleBeepFile(text);
1618
                }
1619
            }
1620
            else if (nPage == SYSTEM_SUBPAGE_DOUBLEBEEP) // System sound double beep
1621
            {
1622
                Button::TButton *bt = mainPage->getButton(SYSTEM_PAGE_SOUND_TXDOUBLEBEEP);
1623
 
1624
                if (bt)
1625
                {
1626
                    bt->setText(text, -1);
1627
                    TConfig::setTemporary(true);
1628
                    TConfig::saveDoubleBeepFile(text);
1629
                }
1630
            }
1631
            else if (nPage == SYSTEM_SUBPAGE_SURFACE)   // System TP4 files (surface files)
1632
            {
1633
                Button::TButton *bt = mainPage->getButton(SYSTEM_PAGE_CTRL_SURFACE);
1634
 
1635
                if (bt)
1636
                {
1637
                    MSG_DEBUG("Setting text: " << text);
1638
                    bt->setText(text, -1);
1639
                    TConfig::setTemporary(true);
1640
                    TConfig::saveFtpSurface(text);
1641
                }
1642
            }
1643
 
1644
            // Close the list subpage
1645
            subPg->drop();
1646
        }
1647
    }
1648
}
1649
 
1650
void TPageManager::redrawObject(ulong handle)
1651
{
1652
    DECL_TRACER("TPageManager::redrawObject(ulong handle)");
1653
 
1654
    int pnumber = (int)((handle >> 16) & 0x0000ffff);
1655
    int btnumber = (int)(handle & 0x0000ffff);
1656
 
1657
    if (pnumber < REGULAR_SUBPAGE_START)    // Is it a page?
1658
    {
1659
        TPage *page = getPage(pnumber);
1660
 
1661
        if (!page)
1662
        {
1663
            MSG_WARNING("Page " << pnumber << " not found!");
1664
            return;
1665
        }
1666
 
1667
        if (!page->isVisilble())
1668
            return;
1669
 
1670
        if (btnumber == 0)
1671
        {
1672
            page->show();
1673
            return;
1674
        }
1675
 
1676
        Button::TButton *button = page->getButton(btnumber);
1677
 
1678
        if (!button)
1679
        {
1680
            MSG_WARNING("Button " << btnumber << " on page " << pnumber << " not found!");
1681
            return;
1682
        }
1683
 
1684
        button->showLastButton();
1685
    }
1686
    else if (pnumber >= REGULAR_SUBPAGE_START && pnumber < SYSTEM_PAGE_START)
1687
    {
1688
        TSubPage *spage = getSubPage(pnumber);
1689
 
1690
        if (!spage)
1691
        {
1692
            MSG_WARNING("Subpage " << pnumber << " not found!");
1693
            return;
1694
        }
1695
 
1696
        if (!spage->isVisible())
1697
            return;
1698
 
1699
        if (btnumber == 0)
1700
        {
1701
            spage->show();
1702
            return;
1703
        }
1704
 
1705
        Button::TButton *button = spage->getButton(btnumber);
1706
 
1707
        if (!button)
1708
        {
1709
            MSG_WARNING("Button " << btnumber << " on subpage " << pnumber << " not found!");
1710
            return;
1711
        }
1712
 
1713
        button->showLastButton();
1714
    }
1715
    else
1716
    {
1717
        MSG_WARNING("System pages are not handled by redraw method! Ignoring page " << pnumber << ".");
1718
    }
1719
}
1720
 
1721
#ifdef _SCALE_SKIA_
1722
void TPageManager::setSetupScaleFactor(double scale, double sw, double sh)
1723
{
1724
    DECL_TRACER("TPageManager::setSetupScaleFactor(double scale, double sw, double sh)");
1725
 
1726
    mScaleSystem = scale;
1727
    mScaleSystemWidth = sw;
1728
    mScaleSystemHeight = sh;
1729
}
1730
#endif
1731
 
1732
/*
1733
 * The following method is called by the class TAmxNet whenever an event from
1734
 * the Netlinx occured.
1735
 */
1736
void TPageManager::doCommand(const amx::ANET_COMMAND& cmd)
1737
{
1738
    DECL_TRACER("TPageManager::doCommand(const amx::ANET_COMMAND& cmd)");
1739
 
1740
    if (!cmdLoop_busy)
1741
        runCommands();
1742
 
1743
    mCommands.push_back(cmd);
1744
}
1745
 
1746
void TPageManager::commandLoop()
1747
{
1748
    DECL_TRACER("TPageManager::commandLoop()");
1749
 
1750
    if (cmdLoop_busy)
1751
        return;
1752
 
1753
    cmdLoop_busy = true;
1754
    string com;
1755
 
1756
    while (cmdLoop_busy && !killed && !_restart_)
1757
    {
1758
        while (mCommands.size() > 0)
1759
        {
1760
            amx::ANET_COMMAND bef = mCommands.at(0);
1761
            mCommands.erase(mCommands.begin());
1762
 
1763
            switch (bef.MC)
1764
            {
1765
                case 0x0006:
1766
                case 0x0018:	// feedback channel on
1767
                    com.assign("ON-");
1768
                    com.append(to_string(bef.data.chan_state.channel));
1769
                    parseCommand(bef.device1, bef.data.chan_state.port, com);
1770
                break;
1771
 
1772
                case 0x0007:
1773
                case 0x0019:	// feedback channel off
1774
                    com.assign("OFF-");
1775
                    com.append(to_string(bef.data.chan_state.channel));
1776
                    parseCommand(bef.device1, bef.data.chan_state.port, com);
1777
                break;
1778
 
1779
                case 0x000a:	// level value change
1780
                    com = "LEVEL-";
1781
                    com += to_string(bef.data.message_value.value);
1782
                    com += ",";
1783
 
1784
                    switch (bef.data.message_value.type)
1785
                    {
1786
                        case 0x10: com += to_string(bef.data.message_value.content.byte); break;
1787
                        case 0x11: com += to_string(bef.data.message_value.content.ch); break;
1788
                        case 0x20: com += to_string(bef.data.message_value.content.integer); break;
1789
                        case 0x21: com += to_string(bef.data.message_value.content.sinteger); break;
1790
                        case 0x40: com += to_string(bef.data.message_value.content.dword); break;
1791
                        case 0x41: com += to_string(bef.data.message_value.content.sdword); break;
1792
                        case 0x4f: com += to_string(bef.data.message_value.content.fvalue); break;
1793
                        case 0x8f: com += to_string(bef.data.message_value.content.dvalue); break;
1794
                    }
1795
 
1796
                    parseCommand(bef.device1, bef.data.message_value.port, com);
1797
                break;
1798
 
1799
                case 0x000c:	// Command string
1800
                {
1801
                    amx::ANET_MSG_STRING msg = bef.data.message_string;
1802
 
1803
                    if (msg.length < strlen((char *)&msg.content))
1804
                    {
1805
                        mCmdBuffer.append((char *)&msg.content);
1806
                        break;
1807
                    }
1808
                    else if (mCmdBuffer.length() > 0)
1809
                    {
1810
                        mCmdBuffer.append((char *)&msg.content);
1811
                        size_t len = (mCmdBuffer.length() >= sizeof(msg.content)) ? (sizeof(msg.content)-1) : mCmdBuffer.length();
1812
                        strncpy((char *)&msg.content, mCmdBuffer.c_str(), len);
1813
                        msg.content[len] = 0;
1814
                    }
1815
 
1816
                    if (getCommand((char *)msg.content) == "^UTF" || bef.intern)  // This is already UTF8!
1817
                        com.assign((char *)msg.content);
1818
                    else
1819
                        com.assign(cp1250ToUTF8((char *)&msg.content));
1820
 
1821
                    parseCommand(bef.device1, msg.port, com);
1822
                    mCmdBuffer.clear();
1823
                }
1824
                break;
1825
 
1826
                case 0x0502:    // Blink message (contains date and time)
1827
                    com = "BLINK-" + to_string(bef.data.blinkMessage.hour) + ":";
1828
                    com += to_string(bef.data.blinkMessage.minute) + ":";
1829
                    com += to_string(bef.data.blinkMessage.second) + ",";
1830
                    com += to_string(bef.data.blinkMessage.year) + "-";
1831
                    com += to_string(bef.data.blinkMessage.month) + "-";
1832
                    com += to_string(bef.data.blinkMessage.day) + ",";
1833
                    com += to_string(bef.data.blinkMessage.weekday) + ",";
1834
                    com += ((bef.data.blinkMessage.LED & 0x0001) ? "ON" : "OFF");
1835
                    parseCommand(0, 0, com);
1836
                break;
1837
 
1838
                case 0x1000:	// Filetransfer
1839
                {
1840
                    amx::ANET_FILETRANSFER ftr = bef.data.filetransfer;
1841
 
1842
                    if (ftr.ftype == 0)
1843
                    {
1844
                        switch(ftr.function)
1845
                        {
1846
                            case 0x0100:	// Syncing directory
1847
                                com = "#FTR-SYNC:0:";
1848
                                com.append((char*)&ftr.data[0]);
1849
                                parseCommand(bef.device1, bef.port1, com);
1850
                            break;
1851
 
1852
                            case 0x0104:	// Delete file
1853
                                com = "#FTR-SYNC:"+to_string(bef.count)+":Deleting files ... ("+to_string(bef.count)+"%)";
1854
                                parseCommand(bef.device1, bef.port1, com);
1855
                            break;
1856
 
1857
                            case 0x0105:	// start filetransfer
1858
                                com = "#FTR-START";
1859
                                parseCommand(bef.device1, bef.port1, com);
1860
                            break;
1861
                        }
1862
                    }
1863
                    else
1864
                    {
1865
                        switch(ftr.function)
1866
                        {
1867
                            case 0x0003:	// Received part of file
1868
                            case 0x0004:	// End of file
1869
                                com = "#FTR-FTRPART:"+to_string(bef.count)+":"+to_string(ftr.info1);
1870
                                parseCommand(bef.device1, bef.port1, com);
1871
                            break;
1872
 
1873
                            case 0x0007:	// End of file transfer
1874
                            {
1875
                                com = "#FTR-END";
1876
                                parseCommand(bef.device1, bef.port1, com);
1877
                            }
1878
                            break;
1879
 
1880
                            case 0x0102:	// Receiving file
1881
                                com = "#FTR-FTRSTART:"+to_string(bef.count)+":"+to_string(ftr.info1)+":";
1882
                                com.append((char*)&ftr.data[0]);
1883
                                parseCommand(bef.device1, bef.port1, com);
1884
                            break;
1885
                        }
1886
                    }
1887
                }
1888
                break;
1889
            }
1890
        }
1891
 
1892
        std::this_thread::sleep_for(std::chrono::milliseconds(50));
1893
    }
1894
 
1895
    cmdLoop_busy = false;
1896
}
1897
 
1898
void TPageManager::deployCallbacks()
1899
{
1900
    DECL_TRACER("TPageManager::deployCallbacks()");
1901
 
1902
    PCHAIN_T *p = mPchain;
1903
 
1904
    while (p)
1905
    {
1906
        if (p->page)
1907
        {
1908
            if (_setBackground)
1909
                p->page->registerCallback(_setBackground);
1910
 
1911
            if (_callPlayVideo)
1912
                p->page->regCallPlayVideo(_callPlayVideo);
1913
        }
1914
 
1915
        p = p->next;
1916
    }
1917
 
1918
    SPCHAIN_T *sp = mSPchain;
1919
 
1920
    while (sp)
1921
    {
1922
        if (sp->page)
1923
        {
1924
            if (_setBackground)
1925
                sp->page->registerCallback(_setBackground);
1926
 
1927
            if (_callPlayVideo)
1928
                sp->page->regCallPlayVideo(_callPlayVideo);
1929
        }
1930
 
1931
        sp = sp->next;
1932
    }
1933
}
1934
 
1935
void TPageManager::regCallbackNetState(std::function<void (int)> callNetState, ulong handle)
1936
{
1937
    DECL_TRACER("TPageManager::regCallbackNetState(std::function<void (int)> callNetState, ulong handle)");
1938
 
1939
    if (handle == 0)
1940
        return;
1941
 
1942
    mNetCalls.insert(std::pair<int, std::function<void (int)> >(handle, callNetState));
1943
}
1944
 
1945
void TPageManager::unregCallbackNetState(ulong handle)
1946
{
1947
    DECL_TRACER("TPageManager::unregCallbackNetState(ulong handle)");
1948
 
1949
    if (mNetCalls.size() == 0)
1950
        return;
1951
 
1952
    std::map<int, std::function<void (int)> >::iterator iter = mNetCalls.find((int)handle);
1953
 
1954
    if (iter != mNetCalls.end())
1955
        mNetCalls.erase(iter);
1956
}
1957
#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS)
1958
#ifdef Q_OS_ANDROID
1959
void TPageManager::regCallbackBatteryState(std::function<void (int, bool, int)> callBatteryState, ulong handle)
1960
{
1961
    DECL_TRACER("TPageManager::regCallbackBatteryState(std::function<void (int, bool, int)> callBatteryState, ulong handle)");
1962
 
1963
    if (handle == 0)
1964
        return;
1965
 
1966
    mBatteryCalls.insert(std::pair<int, std::function<void (int, bool, int)> >(handle, callBatteryState));
1967
}
1968
#endif
1969
#ifdef Q_OS_IOS
1970
void TPageManager::regCallbackBatteryState(std::function<void (int, int)> callBatteryState, ulong handle)
1971
{
1972
    DECL_TRACER("TPageManager::regCallbackBatteryState(std::function<void (int, int)> callBatteryState, ulong handle)");
1973
 
1974
    if (handle == 0)
1975
        return;
1976
 
1977
    mBatteryCalls.insert(std::pair<int, std::function<void (int, int)> >(handle, callBatteryState));
1978
#ifdef Q_OS_IOS
1979
    mLastBatteryLevel = TIOSBattery::getBatteryLeft();
1980
    mLastBatteryState = TIOSBattery::getBatteryState();
1981
 
1982
#endif
1983
    if (mLastBatteryLevel > 0 || mLastBatteryState > 0)
1984
        informBatteryStatus(mLastBatteryLevel, mLastBatteryState);
1985
}
1986
#endif
1987
void TPageManager::unregCallbackBatteryState(ulong handle)
1988
{
1989
    DECL_TRACER("TPageManager::unregCallbackBatteryState(ulong handle)");
1990
 
1991
    if (mBatteryCalls.size() == 0)
1992
        return;
1993
#ifdef Q_OS_ANDROID
1994
    std::map<int, std::function<void (int, bool, int)> >::iterator iter = mBatteryCalls.find(handle);
1995
#endif
1996
#ifdef Q_OS_IOS
1997
    std::map<int, std::function<void (int, int)> >::iterator iter = mBatteryCalls.find((int)handle);
1998
#endif
1999
    if (iter != mBatteryCalls.end())
2000
        mBatteryCalls.erase(iter);
2001
}
2002
#endif  // defined(Q_OS_ANDROID) || defined(Q_OS_IOS)
2003
/*
2004
 * The following function must be called to start the "panel".
2005
 */
2006
bool TPageManager::run()
2007
{
2008
    DECL_TRACER("TPageManager::run()");
2009
 
2010
    if (mActualPage <= 0)
2011
        return false;
2012
 
2013
    TPage *pg = getPage(mActualPage);
2014
 
2015
    if (!pg || !_setPage || !mTSettings)
2016
        return false;
2017
 
2018
    surface_mutex.lock();
2019
    pg->setFonts(mFonts);
2020
    pg->registerCallback(_setBackground);
2021
    pg->regCallPlayVideo(_callPlayVideo);
2022
 
2023
    int width, height;
2024
    width = mTSettings->getWidth();
2025
    height = mTSettings->getHeight();
2026
#ifdef _SCALE_SKIA_
2027
    if (mScaleFactor != 1.0)
2028
    {
2029
        width = (int)((double)width * mScaleFactor);
2030
        height = (int)((double)height * mScaleFactor);
2031
    }
2032
#endif
2033
    _setPage((pg->getNumber() << 16) & 0xffff0000, width, height);
2034
    pg->show();
2035
 
2036
    TSubPage *subPg = pg->getFirstSubPage();
2037
 
2038
    while (subPg)
2039
    {
2040
        subPg->setFonts(mFonts);
2041
        subPg->registerCallback(_setBackground);
2042
        subPg->registerCallbackDB(_displayButton);
2043
        subPg->regCallDropSubPage(_callDropSubPage);
2044
        subPg->regCallPlayVideo(_callPlayVideo);
2045
 
2046
        if (_setSubPage)
2047
        {
2048
            MSG_DEBUG("Drawing page " << subPg->getNumber() << ": " << subPg->getName() << "...");
2049
            width = subPg->getWidth();
2050
            height = subPg->getHeight();
2051
            int left = subPg->getLeft();
2052
            int top = subPg->getTop();
2053
#ifdef _SCALE_SKIA_
2054
            if (mScaleFactor != 1.0)
2055
            {
2056
                width = (int)((double)width * mScaleFactor);
2057
                height = (int)((double)height * mScaleFactor);
2058
                left = (int)((double)left * mScaleFactor);
2059
                top = (int)((double)top * mScaleFactor);
2060
            }
2061
#endif
2062
            ANIMATION_t ani;
2063
            ani.showEffect = subPg->getShowEffect();
2064
            ani.showTime = subPg->getShowTime();
2065
            ani.hideEffect = subPg->getHideEffect();
2066
            ani.hideTime = subPg->getHideTime();
2067
 
2068
            subPg->setZOrder(pg->getNextZOrder());
2069
            _setSubPage(subPg->getHandle(), pg->getHandle(), left, top, width, height, ani, subPg->isModal());
2070
            subPg->show();
2071
        }
2072
 
2073
        subPg = pg->getNextSubPage();
2074
    }
2075
 
2076
    surface_mutex.unlock();
2077
    return true;
2078
}
2079
 
2080
TPage *TPageManager::getPage(int pageID)
2081
{
2082
    DECL_TRACER("TPageManager::getPage(int pageID)");
2083
 
2084
    if (pageID <= 0)
2085
        return nullptr;
2086
 
2087
    PCHAIN_T *p = mPchain;
2088
 
2089
    while (p)
2090
    {
2091
        if (p->page && p->page->getNumber() == pageID)
2092
            return p->page;
2093
 
2094
        p = p->next;
2095
    }
2096
 
2097
    return nullptr;
2098
}
2099
 
2100
TPage *TPageManager::getPage(const string& name)
2101
{
2102
    DECL_TRACER("TPageManager::getPage(const string& name)");
2103
 
2104
    if (name.empty())
2105
        return nullptr;
2106
 
2107
    PCHAIN_T *p = mPchain;
2108
 
2109
    while (p)
2110
    {
2111
        if (p->page && p->page->getName().compare(name) == 0)
2112
            return p->page;
2113
 
2114
        p = p->next;
2115
    }
2116
 
2117
    return nullptr;
2118
}
2119
 
2120
TPage *TPageManager::loadPage(PAGELIST_T& pl, bool *refresh)
2121
{
2122
    DECL_TRACER("TPageManager::loadPage(PAGELIST_T& pl, bool *refresh)");
2123
 
2124
    if (refresh)
2125
        *refresh = false;
2126
 
2127
    if (!pl.isValid)
2128
        return nullptr;
2129
 
2130
    TPage *pg = getPage(pl.pageID);
2131
 
2132
    if (!pg)
2133
    {
2134
        if (!readPage(pl.pageID))
2135
            return nullptr;
2136
 
2137
        pg = getPage(pl.pageID);
2138
 
2139
        if (!pg)
2140
        {
2141
            MSG_ERROR("Error loading page " << pl.pageID << ", " << pl.name << " from file " << pl.file << "!");
2142
            return nullptr;
2143
        }
2144
 
2145
        if (refresh)
2146
            *refresh = true;        // Indicate that the page was freshly loaded
2147
    }
2148
 
2149
    return pg;
2150
}
2151
 
2152
void TPageManager::reloadSystemPage(TPage *page)
2153
{
2154
    DECL_TRACER("TPageManager::reloadSystemPage(TPage *page)");
2155
 
2156
    if (!page)
2157
        return;
2158
 
2159
    vector<Button::TButton *> buttons = page->getAllButtons();
2160
    vector<Button::TButton *>::iterator iter;
2161
    TConfig::setTemporary(false);
2162
 
2163
    for (iter = buttons.begin(); iter != buttons.end(); ++iter)
2164
    {
2165
        Button::TButton *bt = *iter;
2166
 
2167
        if (bt->getAddressPort() == 0 && bt->getAddressChannel() > 0)
2168
        {
2169
            switch(bt->getAddressChannel())
2170
            {
2171
                case SYSTEM_ITEM_LOGLOGFILE:        bt->setTextOnly(TConfig::getLogFile(), -1); break;
2172
 
2173
                case SYSTEM_ITEM_NETLINX_IP:        bt->setTextOnly(TConfig::getController(), -1); break;
2174
                case SYSTEM_ITEM_NETLINX_PORT:      bt->setTextOnly(std::to_string(TConfig::getPort()), -1); break;
2175
                case SYSTEM_ITEM_NETLINX_CHANNEL:   bt->setTextOnly(std::to_string(TConfig::getChannel()), -1); break;
2176
                case SYSTEM_ITEM_NETLINX_PTYPE:     bt->setTextOnly(TConfig::getPanelType(), -1); break;
2177
                case SYSTEM_ITEM_FTPUSER:           bt->setTextOnly(TConfig::getFtpUser(), -1); break;
2178
                case SYSTEM_ITEM_FTPPASSWORD:       bt->setTextOnly(TConfig::getFtpPassword(), -1); break;
2179
                case SYSTEM_ITEM_FTPSURFACE:        bt->setTextOnly(TConfig::getFtpSurface(), -1); break;
2180
 
2181
                case SYSTEM_ITEM_SIPPROXY:          bt->setTextOnly(TConfig::getSIPproxy(), -1); break;
2182
                case SYSTEM_ITEM_SIPPORT:           bt->setTextOnly(std::to_string(TConfig::getSIPport()), -1); break;
2183
                case SYSTEM_ITEM_SIPSTUN:           bt->setTextOnly(TConfig::getSIPstun(), -1); break;
2184
                case SYSTEM_ITEM_SIPDOMAIN:         bt->setTextOnly(TConfig::getSIPdomain(), -1); break;
2185
                case SYSTEM_ITEM_SIPUSER:           bt->setTextOnly(TConfig::getSIPuser(), -1); break;
2186
                case SYSTEM_ITEM_SIPPASSWORD:       bt->setTextOnly(TConfig::getSIPpassword(), -1); break;
2187
 
2188
                case SYSTEM_ITEM_SYSTEMSOUND:       bt->setTextOnly(TConfig::getSystemSound(), -1); break;
2189
                case SYSTEM_ITEM_SINGLEBEEP:        bt->setTextOnly(TConfig::getSingleBeepSound(), -1); break;
2190
                case SYSTEM_ITEM_DOUBLEBEEP:        bt->setTextOnly(TConfig::getDoubleBeepSound(), -1); break;
2191
            }
2192
        }
2193
        else if (bt->getChannelPort() == 0 && bt->getChannelNumber() > 0)
2194
        {
2195
            switch(bt->getChannelNumber())
2196
            {
2197
                case SYSTEM_ITEM_DEBUGINFO:         bt->setActiveInstance(IS_LOG_INFO() ? 1 : 0); break;
2198
                case SYSTEM_ITEM_DEBUGWARNING:      bt->setActiveInstance(IS_LOG_WARNING() ? 1 : 0); break;
2199
                case SYSTEM_ITEM_DEBUGERROR:        bt->setActiveInstance(IS_LOG_ERROR() ? 1 : 0); break;
2200
                case SYSTEM_ITEM_DEBUGTRACE:        bt->setActiveInstance(IS_LOG_TRACE() ? 1 : 0); break;
2201
                case SYSTEM_ITEM_DEBUGDEBUG:        bt->setActiveInstance(IS_LOG_DEBUG() ? 1 : 0); break;
2202
                case SYSTEM_ITEM_DEBUGPROTOCOL:     bt->setActiveInstance(IS_LOG_PROTOCOL() ? 1 : 0); break;
2203
                case SYSTEM_ITEM_DEBUGALL:          bt->setActiveInstance(IS_LOG_ALL() ? 1 : 0); break;
2204
                case SYSTEM_ITEM_DEBUGLONG:         bt->setActiveInstance(TConfig::isLongFormat() ? 1 : 0); break;
2205
                case SYSTEM_ITEM_DEBUGPROFILE:      bt->setActiveInstance(TConfig::getProfiling() ? 1 : 0); break;
2206
 
2207
                case SYSTEM_ITEM_FTPPASSIVE:        bt->setActiveInstance(TConfig::getFtpPassive() ? 1 : 0); break;
2208
 
2209
                case SYSTEM_ITEM_SIPIPV4:           bt->setActiveInstance(TConfig::getSIPnetworkIPv4() ? 1 : 0); break;
2210
                case SYSTEM_ITEM_SIPIPV6:           bt->setActiveInstance(TConfig::getSIPnetworkIPv6() ? 1 : 0); break;
2211
                case SYSTEM_ITEM_SIPENABLE:         bt->setActiveInstance(TConfig::getSIPstatus() ? 1 : 0); break;
2212
                case SYSTEM_ITEM_SIPIPHONE:         bt->setActiveInstance(TConfig::getSIPiphone() ? 1 : 0); break;
2213
 
2214
                case SYSTEM_ITEM_SOUNDSWITCH:       bt->setActiveInstance(TConfig::getSystemSoundState() ? 1 : 0); break;
2215
 
2216
                case SYSTEM_ITEM_VIEWSCALEFIT:      bt->setActiveInstance(TConfig::getScale() ? 1 : 0); break;
2217
                case SYSTEM_ITEM_VIEWBANNER:        bt->setActiveInstance(TConfig::showBanner() ? 1 : 0); break;
2218
                case SYSTEM_ITEM_VIEWNOTOOLBAR:     bt->setActiveInstance(TConfig::getToolbarSuppress() ? 1 : 0); break;
2219
                case SYSTEM_ITEM_VIEWTOOLBAR:       bt->setActiveInstance(TConfig::getToolbarForce() ? 1 : 0); break;
2220
                case SYSTEM_ITEM_VIEWROTATE:        bt->setActiveInstance(TConfig::getRotationFixed() ? 1 : 0); break;
2221
            }
2222
        }
2223
        else if (bt->getLevelPort() == 0 && bt->getLevelChannel() > 0)
2224
        {
2225
            switch(bt->getLevelChannel())
2226
            {
2227
                case SYSTEM_ITEM_SYSVOLUME:         bt->drawBargraph(0, TConfig::getSystemVolume(), false); break;
2228
                case SYSTEM_ITEM_SYSGAIN:           bt->drawBargraph(0, TConfig::getSystemGain(), false); break;
2229
            }
2230
        }
2231
    }
2232
}
2233
 
2234
bool TPageManager::setPage(int PageID, bool forget)
2235
{
2236
    DECL_TRACER("TPageManager::setPage(int PageID, bool forget)");
2237
 
2238
    return _setPageDo(PageID, "", forget);
2239
}
2240
 
2241
bool TPageManager::setPage(const string& name, bool forget)
2242
{
2243
    DECL_TRACER("TPageManager::setPage(const string& name, bool forget)");
2244
 
2245
    return _setPageDo(0, name, forget);
2246
}
2247
 
2248
bool TPageManager::_setPageDo(int pageID, const string& name, bool forget)
2249
{
2250
    DECL_TRACER("TPageManager::_setPageDo(int pageID, const string& name, bool forget)");
2251
 
2252
    TPage *pg = nullptr;
2253
 
2254
    if (pageID > 0 && mActualPage == pageID)
2255
    {
2256
#if TESTMODE == 1
2257
        __success = true;
2258
        setScreenDone();
2259
#endif
2260
        return true;
2261
    }
2262
    else if (!name.empty())
2263
    {
2264
        pg = getPage(mActualPage);
2265
 
2266
        if (pg && pg->getName().compare(name) == 0)
2267
        {
2268
#if TESTMODE == 1
2269
            __success = true;
2270
            setScreenDone();
2271
#endif
2272
            return true;
2273
        }
2274
    }
2275
    else if (pageID > 0)
2276
        pg = getPage(mActualPage);
2277
    else
2278
    {
2279
#if TESTMODE == 1
2280
        setScreenDone();
2281
#endif
2282
        return false;
2283
    }
2284
 
2285
    // FIXME: Make this a vector array to hold a larger history!
2286
    if (!forget)
2287
        mPreviousPage = mActualPage;    // Necessary to be able to jump back to at least the last previous page
2288
 
2289
    if (pg)
2290
        pg->drop();
2291
 
2292
    mActualPage = 0;
2293
    PAGELIST_T listPg;
2294
 
2295
    if (pageID > 0)
2296
        listPg = findPage(pageID);
2297
    else
2298
        listPg = findPage(name);
2299
 
2300
    bool refresh = false;
2301
 
2302
    if ((pg = loadPage(listPg, &refresh)) == nullptr)
2303
    {
2304
#if TESTMODE == 1
2305
        setScreenDone();
2306
#endif
2307
        return false;
2308
    }
2309
 
2310
    mActualPage = pg->getNumber();
2311
 
2312
    if (mActualPage >= SYSTEM_PAGE_START && !refresh)
2313
        reloadSystemPage(pg);
2314
 
449 andreas 2315
    int width = mTSettings->getWidth();
2316
    int height = mTSettings->getHeight();
446 andreas 2317
 
2318
    if (_setPage)
2319
        _setPage((mActualPage << 16) & 0xffff0000, width, height);
2320
 
2321
    pg->show();
2322
    return true;
2323
}
2324
 
2325
 
2326
TSubPage *TPageManager::getSubPage(int pageID)
2327
{
2328
    DECL_TRACER("TPageManager::getSubPage(int pageID)");
2329
 
2330
    if (pageID < REGULAR_SUBPAGE_START)
2331
        return nullptr;
2332
 
2333
    SPCHAIN_T *p = mSPchain;
2334
 
2335
    while(p)
2336
    {
2337
        if (p->page->getNumber() == pageID)
2338
            return p->page;
2339
 
2340
        p = p->next;
2341
    }
2342
 
2343
    return nullptr;
2344
}
2345
 
2346
TSubPage *TPageManager::getSubPage(const std::string& name)
2347
{
2348
    DECL_TRACER("TPageManager::getSubPage(const std::string& name)");
2349
 
2350
    SPCHAIN_T *p = mSPchain;
2351
 
2352
    while (p)
2353
    {
2354
        if (p->page->getName().compare(name) == 0)
2355
            return p->page;
2356
 
2357
        p = p->next;
2358
    }
2359
 
2360
    MSG_DEBUG("Page " << name << " not found in cache.");
2361
    return nullptr;
2362
}
2363
 
2364
TSubPage *TPageManager::deliverSubPage(const string& name, TPage **pg)
2365
{
2366
    DECL_TRACER("TPageManager::deliverSubPage(const string& name, TPage **pg)");
2367
 
2368
    TPage *page = getActualPage();
2369
 
2370
    if (!page)
2371
    {
2372
        MSG_ERROR("No actual page loaded!");
2373
        return nullptr;
2374
    }
2375
 
2376
    if (pg)
2377
        *pg = page;
2378
 
2379
    TSubPage *subPage = getSubPage(name);
2380
 
2381
    if (!subPage)
2382
    {
2383
        if (!readSubPage(name))
2384
        {
2385
            MSG_ERROR("Error reading subpage " << name);
2386
            return nullptr;
2387
        }
2388
 
2389
        subPage = getSubPage(name);
2390
 
2391
        if (!subPage)
2392
        {
2393
            MSG_ERROR("Fatal: A page with name " << name << " does not exist!");
2394
            return nullptr;
2395
        }
2396
 
2397
        subPage->setParent(page->getHandle());
2398
    }
2399
 
2400
    return subPage;
2401
}
2402
 
2403
TSubPage *TPageManager::deliverSubPage(int number, TPage **pg)
2404
{
2405
    DECL_TRACER("TPageManager::deliverSubPage(int number, TPage **pg)");
2406
 
2407
    TPage *page = getActualPage();
2408
 
2409
    if (!page)
2410
    {
2411
        MSG_ERROR("No actual page loaded!");
2412
        return nullptr;
2413
    }
2414
 
2415
    if (pg)
2416
        *pg = page;
2417
 
2418
    TSubPage *subPage = getSubPage(number);
2419
 
2420
    if (!subPage)
2421
    {
2422
        if (!readSubPage(number))
2423
        {
2424
            MSG_ERROR("Error reading subpage " << number);
2425
            return nullptr;
2426
        }
2427
 
2428
        subPage = getSubPage(number);
2429
 
2430
        if (!subPage)
2431
        {
2432
            MSG_ERROR("Fatal: A page with name " << number << " does not exist!");
2433
            return nullptr;
2434
        }
2435
 
2436
        subPage->setParent(page->getHandle());
2437
    }
2438
 
2439
    return subPage;
2440
}
2441
 
2442
bool TPageManager::readPages()
2443
{
2444
    DECL_TRACER("TPageManager::readPages()");
2445
 
2446
    if (!mPageList)
2447
    {
2448
        MSG_ERROR("Page list is not initialized!");
2449
        TError::setError();
2450
        return false;
2451
    }
2452
 
2453
    // Read all pages
2454
    vector<PAGELIST_T> pageList = mPageList->getPagelist();
2455
 
2456
    if (pageList.size() > 0)
2457
    {
2458
        vector<PAGELIST_T>::iterator pgIter;
2459
 
2460
        for (pgIter = pageList.begin(); pgIter != pageList.end(); ++pgIter)
2461
        {
2462
            TPage *page = new TPage(pgIter->name+".xml");
2463
 
2464
            if (TError::isError())
2465
            {
2466
                delete page;
2467
                return false;
2468
            }
2469
 
2470
            page->setPalette(mPalette);
2471
            page->setFonts(mFonts);
2472
            page->registerCallback(_setBackground);
2473
            page->registerCallbackDB(_displayButton);
2474
            page->regCallPlayVideo(_callPlayVideo);
2475
 
2476
            if (!addPage(page))
2477
                return false;
2478
        }
2479
    }
2480
 
2481
    vector<SUBPAGELIST_T> subPageList = mPageList->getSubPageList();
2482
 
2483
    if (subPageList.size() > 0)
2484
    {
2485
        vector<SUBPAGELIST_T>::iterator spgIter;
2486
 
2487
        for (spgIter = subPageList.begin(); spgIter != subPageList.end(); ++spgIter)
2488
        {
2489
            TSubPage *page = new TSubPage(spgIter->name+".xml");
2490
 
2491
            if (TError::isError())
2492
            {
2493
                delete page;
2494
                return false;
2495
            }
2496
 
2497
            page->setPalette(mPalette);
2498
            page->setFonts(mFonts);
2499
            page->registerCallback(_setBackground);
2500
            page->registerCallbackDB(_displayButton);
2501
            page->regCallDropSubPage(_callDropSubPage);
2502
            page->regCallPlayVideo(_callPlayVideo);
2503
            page->setGroup(spgIter->group);
2504
 
2505
            if (!addSubPage(page))
2506
                return false;
2507
        }
2508
    }
2509
 
2510
    return true;
2511
}
2512
 
2513
bool TPageManager::readPage(const std::string& name)
2514
{
2515
    DECL_TRACER("TPageManager::readPage(const std::string& name)");
2516
 
2517
    PAGELIST_T page = findPage(name);
2518
 
2519
    if ((page.pageID <= 0 || page.pageID >= MAX_PAGE_ID) && page.pageID < SYSTEM_PAGE_START && page.pageID >= SYSTEM_SUBPAGE_START)
2520
    {
2521
        MSG_ERROR("Page " << name << " not found!");
2522
        return false;
2523
    }
2524
 
2525
    TPage *pg;
2526
 
2527
    if (name.compare("_progress") == 0)
2528
        pg = new TPage(name);
2529
    else
2530
        pg = new TPage(page.name+".xml");
2531
 
2532
    if (TError::isError())
2533
    {
2534
        delete pg;
2535
        return false;
2536
    }
2537
 
2538
    pg->setPalette(mPalette);
2539
    pg->setFonts(mFonts);
2540
    pg->registerCallback(_setBackground);
2541
    pg->registerCallbackDB(_displayButton);
2542
    pg->regCallPlayVideo(_callPlayVideo);
2543
 
2544
    if (!addPage(pg))
2545
        return false;
2546
 
2547
    return true;
2548
}
2549
 
2550
bool TPageManager::readPage(int ID)
2551
{
2552
    DECL_TRACER("TPageManager::readPage(int ID)");
2553
 
2554
    TError::clear();
2555
    PAGELIST_T page = findPage(ID);
2556
 
2557
    if (page.pageID <= 0)
2558
    {
2559
        MSG_ERROR("Page with ID " << ID << " not found!");
2560
        return false;
2561
    }
2562
 
2563
    TPage *pg;
2564
 
2565
    if (ID == 300)      // Progress page of system?
2566
        pg = new TPage("_progress");
2567
    else
2568
        pg = new TPage(page.name+".xml");
2569
 
2570
    if (TError::isError())
2571
    {
2572
        delete pg;
2573
        return false;
2574
    }
2575
 
2576
    pg->setPalette(mPalette);
2577
    pg->setFonts(mFonts);
2578
    pg->registerCallback(_setBackground);
2579
    pg->registerCallbackDB(_displayButton);
2580
    pg->regCallPlayVideo(_callPlayVideo);
2581
 
2582
    if (!addPage(pg))
2583
        return false;
2584
 
2585
    return true;
2586
}
2587
 
2588
bool TPageManager::readSubPage(const std::string& name)
2589
{
2590
    DECL_TRACER("TPageManager::readSubPage(const std::string& name)");
2591
 
2592
    TError::clear();
2593
    SUBPAGELIST_T page = findSubPage(name);
2594
 
2595
    if (page.pageID < MAX_PAGE_ID || (page.pageID >= SYSTEM_PAGE_START && page.pageID < SYSTEM_SUBPAGE_START))
2596
    {
2597
        MSG_ERROR("Subpage " << name << " not found!");
2598
        return false;
2599
    }
2600
 
2601
    if (haveSubPage(name))
2602
        return true;
2603
 
2604
    TSubPage *pg = new TSubPage(page.name+".xml");
2605
 
2606
    if (TError::isError())
2607
    {
2608
        delete pg;
2609
        return false;
2610
    }
2611
 
2612
    pg->setPalette(mPalette);
2613
    pg->setFonts(mFonts);
2614
    pg->registerCallback(_setBackground);
2615
    pg->registerCallbackDB(_displayButton);
2616
    pg->regCallDropSubPage(_callDropSubPage);
2617
    pg->regCallPlayVideo(_callPlayVideo);
2618
    pg->setGroup(page.group);
2619
 
2620
    if (!addSubPage(pg))
2621
    {
2622
        delete pg;
2623
        return false;
2624
    }
2625
 
2626
    return true;
2627
}
2628
 
2629
bool TPageManager::readSubPage(int ID)
2630
{
2631
    DECL_TRACER("TPageManager::readSubPage(int ID)");
2632
 
2633
    TError::clear();
2634
    SUBPAGELIST_T page = findSubPage(ID);
2635
 
2636
    if (page.pageID <= MAX_PAGE_ID)
2637
    {
2638
        MSG_ERROR("Subpage with ID " << ID << " not found!");
2639
        return false;
2640
    }
2641
 
2642
    TSubPage *pg = new TSubPage(page.name+".xml");
2643
 
2644
    if (TError::isError())
2645
    {
2646
        delete pg;
2647
        return false;
2648
    }
2649
 
2650
    pg->setPalette(mPalette);
2651
    pg->setFonts(mFonts);
2652
    pg->registerCallback(_setBackground);
2653
    pg->registerCallbackDB(_displayButton);
2654
    pg->regCallDropSubPage(_callDropSubPage);
2655
    pg->regCallPlayVideo(_callPlayVideo);
2656
    pg->setGroup(page.group);
2657
 
2658
    if (!addSubPage(pg))
2659
        return false;
2660
 
2661
    return true;
2662
}
2663
 
2664
vector<TSubPage *> TPageManager::createSubViewList(int id)
2665
{
2666
    DECL_TRACER("TPageManager::createSubViewList(int id)");
2667
 
2668
    vector<TSubPage *> subviews;
2669
 
2670
    if (id <= 0)
2671
        return subviews;
2672
 
2673
    if (!mPageList)
2674
    {
2675
        MSG_WARNING("Missing page list and because of this can't make a subview list!");
2676
        return subviews;
2677
    }
2678
 
2679
    SUBVIEWLIST_T slist = mPageList->findSubViewList(id);
2680
 
2681
    if (slist.id <= 0 || slist.items.empty())
2682
    {
2683
        if (slist.id <= 0)
2684
        {
2685
            MSG_WARNING("Found no subview list with ID " << id);
2686
        }
2687
        else
2688
        {
2689
            MSG_WARNING("Subview list " << id << " has no items!");
2690
        }
2691
 
2692
        return subviews;
2693
    }
2694
 
2695
    vector<SUBVIEWITEM_T>::iterator iter;
2696
 
2697
    for (iter = slist.items.begin(); iter != slist.items.end(); ++iter)
2698
    {
2699
        if (!haveSubPage(iter->pageID))
2700
        {
2701
            if (!readSubPage(iter->pageID))
2702
                return vector<TSubPage *>();
2703
        }
2704
 
2705
        TSubPage *pg = getSubPage(iter->pageID);
2706
 
2707
        if (pg)
2708
            subviews.push_back(pg);
2709
        else
2710
        {
2711
            MSG_DEBUG("No subpage with ID " << id);
2712
        }
2713
    }
2714
 
2715
    MSG_DEBUG("Found " << subviews.size() << " subview items.");
2716
    return subviews;
2717
}
2718
 
2719
void TPageManager::showSubViewList(int id, Button::TButton *bt)
2720
{
2721
    DECL_TRACER("TPageManager::showSubViewList(int id, Button::TButton *bt)");
2722
 
2723
    vector<TSubPage *> subviews = createSubViewList(id);
2724
 
2725
    if (subviews.empty() || !_addViewButtonItems || !bt)
2726
    {
2727
        MSG_DEBUG("Number views: " << subviews.size() << (_addViewButtonItems ? ", addView" : ", NO addView") << (_displayViewButton ? " display" : " NO display"));
2728
        return;
2729
    }
2730
 
2731
    ulong btHandle = bt->getHandle();
2732
    MSG_DEBUG("Working on button " << handleToString(btHandle) << " (" << bt->getName() << ") with " << subviews.size() << " pages.");
2733
    TBitmap bm = bt->getLastBitmap();
2734
    TColor::COLOR_T fillColor = TColor::getAMXColor(bt->getFillColor());
2735
    _displayViewButton(btHandle, bt->getParent(), bt->isSubViewVertical(), bm, bt->getWidth(), bt->getHeight(), bt->getLeftPosition(), bt->getTopPosition(), bt->getSubViewSpace(), fillColor);
2736
 
2737
    vector<PGSUBVIEWITEM_T> items;
2738
    PGSUBVIEWITEM_T svItem;
2739
    PGSUBVIEWATOM_T svAtom;
2740
    vector<TSubPage *>::iterator iter;
2741
 
2742
    for (iter = subviews.begin(); iter != subviews.end(); ++iter)
2743
    {
2744
        TSubPage *sub = *iter;
2745
        sub->setParent(btHandle);
2746
 
2747
        svItem.clear();
2748
        Button::TButton *button = sub->getFirstButton();
2749
        SkBitmap bitmap = sub->getBgImage();
2750
 
2751
        svItem.handle = sub->getHandle();
2752
        svItem.parent = btHandle;
2753
        svItem.width = sub->getWidth();
2754
        svItem.height = sub->getHeight();
2755
        svItem.bgcolor = TColor::getAMXColor(sub->getFillColor());
2756
        svItem.scrollbar = bt->getSubViewScrollbar();
2757
        svItem.scrollbarOffset = bt->getSubViewScrollbarOffset();
2758
        svItem.position = bt->getSubViewAnchor();
2759
        svItem.wrap = bt->getWrapSubViewPages();
2760
 
2761
        if (!bitmap.empty())
2762
            svItem.image.setBitmap((unsigned char *)bitmap.getPixels(), bitmap.info().width(), bitmap.info().height(), bitmap.info().bytesPerPixel());
2763
 
2764
        while (button)
2765
        {
2766
            button->drawButton(0, false, true);
2767
            svAtom.clear();
2768
            svAtom.handle = button->getHandle();
2769
            svAtom.parent = sub->getHandle();
2770
            svAtom.width = button->getWidth();
2771
            svAtom.height = button->getHeight();
2772
            svAtom.left = button->getLeftPosition();
2773
            svAtom.top = button->getTopPosition();
2774
            svAtom.bgcolor = TColor::getAMXColor(button->getFillColor(button->getActiveInstance()));
2775
            svAtom.bounding = button->getBounding();
2776
            Button::BITMAP_t bmap = button->getLastImage();
2777
 
2778
            if (bmap.buffer)
2779
                svAtom.image.setBitmap(bmap.buffer, bmap.width, bmap.height, (int)(bmap.rowBytes / bmap.width));
2780
 
2781
            svItem.atoms.push_back(svAtom);
2782
            button = sub->getNextButton();
2783
        }
2784
 
2785
        items.push_back(svItem);
2786
    }
2787
 
2788
    _addViewButtonItems(bt->getHandle(), items);
2789
 
2790
    if (_pageFinished)
2791
        _pageFinished(bt->getHandle());
2792
}
2793
 
2794
void TPageManager::updateSubViewItem(Button::TButton *bt)
2795
{
2796
    DECL_TRACER("TPageManager::updateSubViewItem(Button::TButton *bt)");
2797
 
2798
    if (!bt)
2799
        return;
2800
 
2801
    updview_mutex.lock();
2802
    mUpdateViews.push_back(bt);
2803
    updview_mutex.unlock();
2804
}
2805
 
2806
void TPageManager::_updateSubViewItem(Button::TButton *bt)
2807
{
2808
    DECL_TRACER("TPageManager::_updateSubViewItem(Button::TButton *bt)");
2809
 
2810
    if (!mPageList || !_updateViewButtonItem)
2811
        return;
2812
 
2813
    // The parent of this kind of button is always the button of type subview.
2814
    // If we take the parent handle and extract the page ID (upper 16 bits)
2815
    // we get the page ID of the subpage or page ID of the page the button is
2816
    // ordered to.
2817
    int pageID = (bt->getParent() >> 16) & 0x0000ffff;
2818
    ulong parent = 0;
2819
    Button::TButton *button = nullptr;
2820
    PGSUBVIEWITEM_T item;
2821
    PGSUBVIEWATOM_T atom;
2822
    SkBitmap bitmap;
2823
    TPage *pg = nullptr;
2824
    TSubPage *sub = nullptr;
2825
 
2826
    if (pageID < REGULAR_SUBPAGE_START)     // Is it a page?
2827
    {
2828
        pg = getPage(pageID);
2829
 
2830
        if (!pg)
2831
        {
2832
            MSG_WARNING("Invalid page " << pageID << "!");
2833
            return;
2834
        }
2835
 
2836
        button = pg->getFirstButton();
2837
        bitmap = pg->getBgImage();
2838
 
2839
        item.handle = pg->getHandle();
2840
        item.parent = bt->getParent();
2841
        item.width = pg->getWidth();
2842
        item.height = pg->getHeight();
2843
        item.bgcolor = TColor::getAMXColor(pg->getFillColor());
2844
    }
2845
    else
2846
    {
2847
        sub = getSubPage(pageID);
2848
 
2849
        if (!sub)
2850
        {
2851
            MSG_WARNING("Couldn't find the subpage " << pageID << "!");
2852
            return;
2853
        }
2854
 
2855
        parent = sub->getParent();
2856
        button = sub->getFirstButton();
2857
        bitmap = sub->getBgImage();
2858
 
2859
        item.handle = sub->getHandle();
2860
        item.parent = bt->getParent();
2861
        item.width = sub->getWidth();
2862
        item.height = sub->getHeight();
2863
        item.position = bt->getSubViewAnchor();
2864
        item.bgcolor = TColor::getAMXColor(sub->getFillColor());
2865
    }
2866
 
2867
 
2868
    if (!bitmap.empty())
2869
        item.image.setBitmap((unsigned char *)bitmap.getPixels(), bitmap.info().width(), bitmap.info().height(), bitmap.info().bytesPerPixel());
2870
 
2871
    while (button)
2872
    {
2873
        atom.clear();
2874
        atom.handle = button->getHandle();
2875
        atom.parent = item.handle;
2876
        atom.width = button->getWidth();
2877
        atom.height = button->getHeight();
2878
        atom.left = button->getLeftPosition();
2879
        atom.top = button->getTopPosition();
2880
        atom.bgcolor = TColor::getAMXColor(button->getFillColor(button->getActiveInstance()));
2881
        atom.bounding = button->getBounding();
2882
        Button::BITMAP_t bmap = button->getLastImage();
2883
 
2884
        if (bmap.buffer)
2885
            atom.image.setBitmap(bmap.buffer, bmap.width, bmap.height, (int)(bmap.rowBytes / bmap.width));
2886
 
2887
        item.atoms.push_back(atom);
2888
        button = (pg ? pg->getNextButton() : sub->getNextButton());
2889
    }
2890
 
2891
    _updateViewButtonItem(item, parent);
2892
}
2893
 
2894
void TPageManager::updateActualPage()
2895
{
2896
    DECL_TRACER("TPageManager::updateActualPage()");
2897
 
2898
    if (!mActualPage)
2899
        return;
2900
 
2901
    TPage *pg = getPage(mActualPage);
2902
    Button::TButton *bt = pg->getFirstButton();
2903
 
2904
    while (bt)
2905
    {
2906
        bt->refresh();
2907
        bt = pg->getNextButton();
2908
    }
2909
}
2910
 
2911
void TPageManager::updateSubpage(int ID)
2912
{
2913
    DECL_TRACER("TPageManager::updateSubpage(int ID)");
2914
 
2915
    TSubPage *pg = getSubPage(ID);
2916
 
2917
    if (!pg)
2918
        return;
2919
 
2920
    vector<Button::TButton *> blist = pg->getAllButtons();
2921
    vector<Button::TButton *>::iterator iter;
2922
 
2923
    if (blist.empty())
2924
        return;
2925
 
2926
    for (iter = blist.begin(); iter != blist.end(); ++iter)
2927
    {
2928
        Button::TButton *bt = *iter;
2929
        bt->refresh();
2930
    }
2931
}
2932
 
2933
void TPageManager::updateSubpage(const std::string &name)
2934
{
2935
    DECL_TRACER("TPageManager::updateSubpage(const std::string &name)");
2936
 
2937
    TSubPage *pg = getSubPage(name);
2938
 
2939
    if (!pg)
2940
        return;
2941
 
2942
    vector<Button::TButton *> blist = pg->getAllButtons();
2943
    vector<Button::TButton *>::iterator iter;
2944
 
2945
    if (blist.empty())
2946
        return;
2947
 
2948
    for (iter = blist.begin(); iter != blist.end(); ++iter)
2949
    {
2950
        Button::TButton *bt = *iter;
2951
        bt->refresh();
2952
    }
2953
}
2954
 
2955
/******************** Internal private methods *********************/
2956
 
2957
PAGELIST_T TPageManager::findPage(const std::string& name)
2958
{
2959
    DECL_TRACER("TPageManager::findPage(const std::string& name)");
2960
 
2961
    vector<PAGELIST_T> pageList;
2962
 
449 andreas 2963
    pageList = mPageList->getPagelist();
446 andreas 2964
 
2965
    if (pageList.size() > 0)
2966
    {
2967
        vector<PAGELIST_T>::iterator pgIter;
2968
 
2969
        for (pgIter = pageList.begin(); pgIter != pageList.end(); ++pgIter)
2970
        {
2971
            if (pgIter->name.compare(name) == 0)
2972
                return *pgIter;
2973
        }
2974
    }
2975
 
2976
    MSG_WARNING("Page " << name << " not found!");
2977
    return PAGELIST_T();
2978
}
2979
 
2980
PAGELIST_T TPageManager::findPage(int ID)
2981
{
2982
    DECL_TRACER("TPageManager::findPage(int ID)");
2983
 
2984
    vector<PAGELIST_T> pageList = (ID < SYSTEM_PAGE_START ? mPageList->getPagelist() : mPageList->getSystemPagelist());
2985
 
2986
    if (pageList.size() > 0)
2987
    {
2988
        vector<PAGELIST_T>::iterator pgIter;
2989
 
2990
        for (pgIter = pageList.begin(); pgIter != pageList.end(); ++pgIter)
2991
        {
2992
            if (pgIter->pageID == ID)
2993
                return *pgIter;
2994
        }
2995
    }
2996
 
2997
    return PAGELIST_T();
2998
}
2999
 
3000
SUBPAGELIST_T TPageManager::findSubPage(const std::string& name)
3001
{
3002
    DECL_TRACER("TPageManager::findSubPage(const std::string& name)");
3003
 
449 andreas 3004
    vector<SUBPAGELIST_T> pageList = mPageList->getSubPageList();
446 andreas 3005
 
3006
    if (pageList.size() > 0)
3007
    {
3008
        vector<SUBPAGELIST_T>::iterator pgIter;
3009
 
3010
        for (pgIter = pageList.begin(); pgIter != pageList.end(); ++pgIter)
3011
        {
3012
            if (pgIter->name.compare(name) == 0)
3013
                return *pgIter;
3014
        }
3015
    }
3016
 
3017
    return SUBPAGELIST_T();
3018
}
3019
 
3020
SUBPAGELIST_T TPageManager::findSubPage(int ID)
3021
{
3022
    DECL_TRACER("TPageManager::findSubPage(int ID)");
3023
 
3024
    vector<SUBPAGELIST_T> pageList = (ID < SYSTEM_PAGE_START ? mPageList->getSubPageList() : mPageList->getSystemSupPageList());
3025
 
3026
    if (pageList.size() > 0)
3027
    {
3028
        vector<SUBPAGELIST_T>::iterator pgIter;
3029
 
3030
        for (pgIter = pageList.begin(); pgIter != pageList.end(); ++pgIter)
3031
        {
3032
            if (pgIter->pageID == ID)
3033
                return *pgIter;
3034
        }
3035
    }
3036
 
3037
    return SUBPAGELIST_T();
3038
}
3039
 
3040
bool TPageManager::addPage(TPage* pg)
3041
{
3042
    DECL_TRACER("TPageManager::addPage(TPage* pg)");
3043
 
3044
    if (!pg)
3045
    {
3046
        MSG_ERROR("Parameter is NULL!");
3047
        TError::setError();
3048
        return false;
3049
    }
3050
 
3051
    PCHAIN_T *chain = new PCHAIN_T;
3052
    chain->page = pg;
3053
    chain->next = nullptr;
3054
 
3055
    if (mPchain)
3056
    {
3057
        PCHAIN_T *p = mPchain;
3058
 
3059
        while (p->next)
3060
            p = p->next;
3061
 
3062
        p->next = chain;
3063
    }
3064
    else
3065
    {
3066
        mPchain = chain;
3067
        setPChain(mPchain);
3068
    }
3069
 
3070
//    MSG_DEBUG("Added page " << chain->page->getName());
3071
    return true;
3072
}
3073
 
3074
bool TPageManager::addSubPage(TSubPage* pg)
3075
{
3076
    DECL_TRACER("TPageManager::addSubPage(TSubPage* pg)");
3077
 
3078
    if (!pg)
3079
    {
3080
        MSG_ERROR("Parameter is NULL!");
3081
        TError::setError();
3082
        return false;
3083
    }
3084
 
3085
    if (haveSubPage(pg->getNumber()))
3086
    {
3087
        MSG_ERROR("Subpage " << pg->getNumber() << ", " << pg->getName() << " is already in chain!");
3088
        return false;
3089
    }
3090
 
3091
    SPCHAIN_T *chain = new SPCHAIN_T;
3092
    chain->page = pg;
3093
    chain->next = nullptr;
3094
 
3095
    if (mSPchain)
3096
    {
3097
        SPCHAIN_T *p = mSPchain;
3098
 
3099
        while (p->next)
3100
            p = p->next;
3101
 
3102
        p->next = chain;
3103
    }
3104
    else
3105
    {
3106
        mSPchain = chain;
3107
        setSPChain(mSPchain);
3108
    }
3109
 
3110
    return true;
3111
}
3112
 
3113
void TPageManager::dropAllPages()
3114
{
3115
    DECL_TRACER("TPageManager::dropAllPages()");
3116
 
3117
    PCHAIN_T *pg = mPchain;
3118
    PCHAIN_T *next = nullptr;
3119
 
3120
    while (pg)
3121
    {
3122
        next = pg->next;
3123
 
3124
        if (pg->page)
3125
        {
3126
            if (_callDropPage)
3127
                _callDropPage((pg->page->getNumber() << 16) & 0xffff0000);
3128
 
3129
            delete pg->page;
3130
        }
3131
 
3132
        delete pg;
3133
        pg = next;
3134
    }
3135
 
3136
    mPchain = nullptr;
3137
    setPChain(mPchain);
3138
}
3139
 
3140
void TPageManager::dropAllSubPages()
3141
{
3142
    DECL_TRACER("TPageManager::dropAllSubPages()");
3143
 
3144
    SPCHAIN_T *spg = mSPchain;
3145
    SPCHAIN_T *next;
3146
 
3147
    while (spg)
3148
    {
3149
        next = spg->next;
3150
 
3151
        if (spg->page)
3152
        {
3153
            if (_callDropSubPage)
3154
                _callDropSubPage((spg->page->getNumber() << 16) & 0xffff0000, spg->page->getParent());
3155
 
3156
            delete spg->page;
3157
        }
3158
 
3159
        delete spg;
3160
        spg = next;
3161
    }
3162
 
3163
    mSPchain = nullptr;
3164
    setSPChain(mSPchain);
3165
}
3166
 
3167
bool TPageManager::destroyAll()
3168
{
3169
    DECL_TRACER("TPageManager::destroyAll()");
3170
 
3171
    dropAllSubPages();
3172
    dropAllPages();
3173
    mActualPage = 0;
3174
    mPreviousPage = 0;
3175
    mActualGroupName.clear();
3176
 
3177
    if (mPageList)
3178
    {
3179
        delete mPageList;
3180
        mPageList = nullptr;
3181
    }
3182
 
3183
    if (mTSettings)
3184
    {
3185
        delete mTSettings;
3186
        mTSettings = nullptr;
3187
    }
3188
 
3189
    if (mPalette)
3190
    {
3191
        delete mPalette;
3192
        mPalette = nullptr;
3193
    }
3194
 
3195
    if (mFonts)
3196
    {
3197
        delete mFonts;
3198
        mFonts = nullptr;
3199
    }
3200
 
3201
    if (mExternal)
3202
    {
3203
        delete mExternal;
3204
        mExternal = nullptr;
3205
    }
3206
 
3207
    if (gPrjResources)
3208
    {
3209
        delete gPrjResources;
3210
        gPrjResources = nullptr;
3211
    }
3212
 
3213
    if (gIcons)
3214
    {
3215
        delete gIcons;
3216
        gIcons = nullptr;
3217
    }
3218
 
3219
    if (TError::isError())
3220
        return false;
3221
 
3222
    return true;
3223
}
3224
 
3225
bool TPageManager::overlap(int x1, int y1, int w1, int h1, int x2, int y2, int w2, int h2)
3226
{
3227
    DECL_TRACER("TPageManager::overlap(int x1, int y1, int w1, int h1, int x2, int y2, int w2, int h2)");
3228
 
3229
    struct point
3230
    {
3231
        int x;
3232
        int y;
3233
    };
3234
 
3235
    struct point l1, r1, l2, r2;
3236
 
3237
    l1.x = x1;
3238
    l1.y = y1;
3239
    r1.x = x1 + w1;
3240
    r1.y = y1 + h1;
3241
 
3242
    l2.x = x2;
3243
    l2.y = y2;
3244
    r2.x = x2 + w2;
3245
    r2.y = y2 + h2;
3246
 
3247
    if (l1.x == r1.x || l1.y == r1.y || l2.x == r2.x || l2.y == r2.y)
3248
    {
3249
        // the line cannot have positive overlap
3250
        return false;
3251
    }
3252
 
3253
    return std::max(l1.x, l2.x) < std::min(r1.x, r2.x) &&
3254
           std::max(l1.y, l2.y) < std::min(r1.y, r2.y);
3255
}
3256
 
3257
Button::TButton *TPageManager::findButton(ulong handle)
3258
{
3259
    DECL_TRACER("TPageManager::findButton(ulong handle)");
3260
 
3261
    if (!handle)
3262
        return nullptr;
3263
 
3264
    TPage *pg = getPage(mActualPage);
3265
 
3266
    if (!pg)
3267
        return nullptr;
3268
 
3269
    vector<Button::TButton *> pgBtList = pg->getAllButtons();
3270
    vector<Button::TButton *>::iterator iter;
3271
 
3272
    if (pgBtList.size() > 0)
3273
    {
3274
        // First we look into the elements of the page
3275
        for (iter = pgBtList.begin(); iter != pgBtList.end(); ++iter)
3276
        {
3277
            Button::TButton *bt = *iter;
3278
 
3279
            if (bt->getHandle() == handle)
3280
                return bt;
3281
        }
3282
    }
3283
 
3284
    // We've not found the wanted element in the elements of the page. So
3285
    // we're looking at the elements of the subpages.
3286
    TSubPage *sp = pg->getFirstSubPage();
3287
 
3288
    if (!sp)
3289
        return nullptr;
3290
 
3291
    while (sp)
3292
    {
3293
        vector<Button::TButton *> spBtList = sp->getAllButtons();
3294
 
3295
        if (spBtList.size() > 0)
3296
        {
3297
            for (iter = spBtList.begin(); iter != spBtList.end(); ++iter)
3298
            {
3299
                Button::TButton *bt = *iter;
3300
 
3301
                if (bt->getHandle() == handle)
3302
                    return bt;
3303
            }
3304
        }
3305
 
3306
        sp = pg->getNextSubPage();
3307
    }
3308
 
3309
    return nullptr;
3310
}
3311
 
3312
/**
3313
 * @brief Find a bargraph
3314
 * The method can search for a bargraph on a particular page or subpage defined
3315
 * by \b parent. if no page or subpage defined, it searches on the actual page
3316
 * or subpage.
3317
 * If it finds a bargraph it returns the pointer to it. Otherwise a nullptr is
3318
 * returned.
3319
 *
3320
 * @param lp        The brgraph port number.
3321
 * @param lv        The bargraph code number.
3322
 * @param parent    The parent handle of the bargraph.
3323
 *
3324
 * @return If the wanted bargraph with the parent handle exists, the pointer to
3325
 * it is returned. Otherwise it return a \b nullptr.
3326
 */
3327
Button::TButton *TPageManager::findBargraph(int lp, int lv, ulong parent)
3328
{
3329
    DECL_TRACER("TPageManager::findBargraph(int lp, int lv, ulong parent)");
3330
 
3331
    int page = (parent >> 16) & 0x0000ffff;
3332
    vector<Button::TButton *>::iterator iter;
3333
 
3334
    if (!page)
3335
    {
3336
        page = mActualPage;
3337
 
3338
        if (!page)
3339
        {
3340
            MSG_WARNING("No valid active page!");
3341
            return nullptr;
3342
        }
3343
    }
3344
 
3345
    MSG_DEBUG("Searching for bargraph " << lp << ":" << lv << " on page " << page);
3346
 
3347
    if (page < REGULAR_SUBPAGE_START)
3348
    {
3349
        TPage *pg = getPage(mActualPage);
3350
 
3351
        if (!pg)
3352
            return nullptr;
3353
 
3354
        vector<Button::TButton *> pgBtList = pg->getAllButtons();
3355
        MSG_DEBUG("Found " << pgBtList.size() << " buttons.");
3356
 
3357
        if (pgBtList.size() > 0)
3358
        {
3359
            // First we look into the elements of the page
3360
            for (iter = pgBtList.begin(); iter != pgBtList.end(); ++iter)
3361
            {
3362
                Button::TButton *bt = *iter;
3363
 
3364
                if (bt->getButtonType() == BARGRAPH && bt->getLevelPort() == lp && bt->getLevelChannel() == lv && bt->getParent() == parent)
3365
                {
3366
                    MSG_DEBUG("Found bargraph LP:" << lp << ", LV:" << lv << " on page " << page);
3367
                    return bt;
3368
                }
3369
            }
3370
        }
3371
 
3372
        MSG_WARNING("No bargraph " << lp << ":" << lv << " on page " << page);
3373
        return nullptr;
3374
    }
3375
 
3376
    // We've not found the wanted element in the elements of the page. So
3377
    // we're looking at the elements of the subpage.
3378
    TSubPage *sp = getSubPage(page);
3379
 
3380
    if (!sp)
3381
    {
3382
        MSG_WARNING("Found no subpage " << page);
3383
        return nullptr;
3384
    }
3385
 
3386
    vector<Button::TButton *> spBtList = sp->getAllButtons();
3387
    MSG_DEBUG("Found " << spBtList.size() << " buttons.");
3388
 
3389
    if (spBtList.size() > 0)
3390
    {
3391
        for (iter = spBtList.begin(); iter != spBtList.end(); ++iter)
3392
        {
3393
            Button::TButton *bt = *iter;
3394
 
3395
            if (bt->getButtonType() == BARGRAPH && bt->getLevelPort() == lp && bt->getLevelChannel() == lv && bt->getParent() == parent)
3396
            {
3397
                MSG_DEBUG("Found bargraph LP:" << lp << ", LV:" << lv << " on subpage " << page);
3398
                return bt;
3399
            }
3400
        }
3401
    }
3402
 
3403
    MSG_WARNING("No bargraph " << lp << ":" << lv << " on subpage " << page);
3404
    return nullptr;
3405
}
3406
 
3407
TPage *TPageManager::getActualPage()
3408
{
3409
    DECL_TRACER("TPageManager::getActualPage()");
3410
 
3411
    return getPage(mActualPage);
3412
}
3413
 
3414
TSubPage *TPageManager::getFirstSubPage()
3415
{
3416
    DECL_TRACER("TPageManager::getFirstSubPage()");
3417
 
3418
    mLastSubPage = 0;
3419
    TPage *pg = getPage(mActualPage);
3420
 
3421
    if (!pg)
3422
        return nullptr;
3423
 
3424
    map<int, TSubPage *> sp = pg->getSortedSubpages(true);
3425
 
3426
    if (!sp.empty())
3427
    {
3428
        map<int, TSubPage *>::iterator iter = sp.begin();
3429
        mLastSubPage = iter->first;
3430
        return iter->second;
3431
    }
3432
 
3433
    return nullptr;
3434
}
3435
 
3436
TSubPage *TPageManager::getNextSubPage()
3437
{
3438
    DECL_TRACER("TPageManager::getNextSubPage()");
3439
 
3440
    TPage *pg = getPage(mActualPage);
3441
 
3442
    if (pg)
3443
    {
3444
        map<int, TSubPage *> sp = pg->getSortedSubpages();
3445
 
3446
        if (sp.empty())
3447
        {
3448
            mLastSubPage = 0;
3449
            return nullptr;
3450
        }
3451
        else
3452
        {
3453
            map<int, TSubPage *>::iterator iter = sp.find(mLastSubPage);
3454
 
3455
            if (iter != sp.end())
3456
            {
3457
                iter++;
3458
 
3459
                if (iter != sp.end())
3460
                {
3461
                    mLastSubPage = iter->first;
3462
                    return iter->second;
3463
                }
3464
            }
3465
        }
3466
    }
3467
 
3468
    mLastSubPage = 0;
3469
    return nullptr;
3470
}
3471
 
3472
TSubPage *TPageManager::getPrevSubPage()
3473
{
3474
    DECL_TRACER("TPageManager::getPrevSubPage()");
3475
 
3476
    TPage *pg = getPage(mActualPage);
3477
 
3478
    if (pg)
3479
    {
3480
        map<int, TSubPage *> sp = pg->getSortedSubpages();
3481
 
3482
        if (sp.empty())
3483
        {
3484
            mLastSubPage = 0;
3485
            return nullptr;
3486
        }
3487
        else
3488
        {
3489
            map<int, TSubPage *>::iterator iter = sp.find(mLastSubPage);
3490
 
3491
            if (iter != sp.end() && iter != sp.begin())
3492
            {
3493
                iter--;
3494
                mLastSubPage = iter->first;
3495
                return iter->second;
3496
            }
3497
 
3498
            MSG_DEBUG("Page " << mLastSubPage << " not found!");
3499
        }
3500
    }
3501
 
3502
    mLastSubPage = 0;
3503
    return nullptr;
3504
}
3505
 
3506
TSubPage *TPageManager::getLastSubPage()
3507
{
3508
    DECL_TRACER("TPageManager::getLastSubPage()");
3509
 
3510
    mLastSubPage = 0;
3511
    TPage *pg = getPage(mActualPage);
3512
 
3513
    if (pg)
3514
    {
3515
        map<int, TSubPage *> sp = pg->getSortedSubpages(true);
3516
 
3517
        if (sp.empty())
3518
            return nullptr;
3519
        else
3520
        {
3521
            map<int, TSubPage *>::iterator iter = sp.end();
3522
            iter--;
3523
            mLastSubPage = iter->first;
3524
            return iter->second;
3525
        }
3526
    }
3527
    else
3528
    {
3529
        MSG_WARNING("Actual page " << mActualPage << " not found!");
3530
    }
3531
 
3532
    return nullptr;
3533
}
3534
 
3535
TSubPage *TPageManager::getFirstSubPageGroup(const string& group)
3536
{
3537
    DECL_TRACER("TPageManager::getFirstSubPageGroup(const string& group)");
3538
 
3539
    if (group.empty())
3540
    {
3541
        MSG_WARNING("Empty group name is invalid. Ignoring it!");
3542
        mActualGroupName.clear();
3543
        mActualGroupPage = nullptr;
3544
        return nullptr;
3545
    }
3546
 
3547
    mActualGroupName = group;
3548
    TSubPage *pg = getFirstSubPage();
3549
 
3550
    while (pg)
3551
    {
3552
        MSG_DEBUG("Evaluating group " << pg->getGroupName() << " with " << group);
3553
 
3554
        if (pg->getGroupName().compare(group) == 0)
3555
        {
3556
            mActualGroupPage = pg;
3557
            return pg;
3558
        }
3559
 
3560
        pg = getNextSubPage();
3561
    }
3562
 
3563
    mActualGroupName.clear();
3564
    mActualGroupPage = nullptr;
3565
    return nullptr;
3566
}
3567
 
3568
TSubPage *TPageManager::getNextSubPageGroup()
3569
{
3570
    DECL_TRACER("TPageManager::getNextSubPageGroup()");
3571
 
3572
    if (mActualGroupName.empty())
3573
        return nullptr;
3574
 
3575
    TSubPage *pg = getFirstSubPage();
3576
    bool found = false;
3577
 
3578
    while (pg)
3579
    {
3580
        MSG_DEBUG("Evaluating group " << pg->getGroupName() << " with " << mActualGroupName);
3581
 
3582
        if (!found && pg == mActualGroupPage)
3583
        {
3584
            pg = getNextSubPage();
3585
            found = true;
3586
            continue;
3587
        }
3588
 
3589
        if (found && pg->getGroupName().compare(mActualGroupName) == 0)
3590
        {
3591
            mActualGroupPage = pg;
3592
            return pg;
3593
        }
3594
 
3595
        pg = getNextSubPage();
3596
    }
3597
 
3598
    mActualGroupName.clear();
3599
    mActualGroupPage = nullptr;
3600
    return nullptr;
3601
}
3602
 
3603
TSubPage *TPageManager::getNextSubPageGroup(const string& group, TSubPage* pg)
3604
{
3605
    DECL_TRACER("TPageManager::getNextSubPageGroup(const string& group, TSubPage* pg)");
3606
 
3607
    if (group.empty() || !pg)
3608
        return nullptr;
3609
 
3610
    TSubPage *page = getFirstSubPage();
3611
    bool found = false;
3612
 
3613
    while (page)
3614
    {
3615
        MSG_DEBUG("Evaluating group " << pg->getGroupName() << " with " << group);
3616
 
3617
        if (!found && pg == page)
3618
        {
3619
            page = getNextSubPage();
3620
            found = true;
3621
            continue;
3622
        }
3623
 
3624
        if (found && page->getGroupName().compare(group) == 0)
3625
            return page;
3626
 
3627
        page = getNextSubPage();
3628
    }
3629
 
3630
    return nullptr;
3631
}
3632
 
3633
TSubPage *TPageManager::getTopPage()
3634
{
3635
    DECL_TRACER("TPageManager::getTopPage()");
3636
 
3637
    // Scan for all occupied regions
3638
    vector<RECT_T> regions;
3639
 
3640
    TSubPage *pg = getFirstSubPage();
3641
 
3642
    while (pg)
3643
    {
3644
        RECT_T r = pg->getRegion();
3645
        regions.push_back(r);
3646
        pg = getNextSubPage();
3647
    }
3648
 
3649
    // Now scan all pages against all regions to find the top most
3650
    pg = getFirstSubPage();
3651
    TSubPage *top = nullptr;
3652
    int zPos = 0;
3653
 
3654
    while (pg)
3655
    {
3656
        RECT_T r = pg->getRegion();
3657
 
3658
        if (regions.size() > 0)
3659
        {
3660
            vector<RECT_T>::iterator iter;
3661
            int zo = 0;
3662
 
3663
            for (iter = regions.begin(); iter != regions.end(); ++iter)
3664
            {
3665
                if (doOverlap(*iter, r) && zPos > zo)
3666
                    top = pg;
3667
 
3668
                zo++;
3669
            }
3670
        }
3671
 
3672
        pg = getNextSubPage();
3673
        zPos++;
3674
    }
3675
 
3676
    return top;
3677
}
3678
 
3679
TSubPage *TPageManager::getCoordMatch(int x, int y)
3680
{
3681
    DECL_TRACER("TPageManager::getCoordMatch(int x, int y)");
3682
 
3683
    int realX = x;
3684
    int realY = y;
3685
 
3686
    // Reverse order of pages
3687
    TSubPage *pg = getLastSubPage();
3688
 
3689
    // Iterate in reverse order through array
3690
    while (pg)
3691
    {
3692
        if (!pg->isVisible() || pg->getZOrder() == ZORDER_INVALID)
3693
        {
3694
            pg = getPrevSubPage();
3695
            continue;
3696
        }
3697
 
3698
        MSG_DEBUG("Scanning subpage (Z: " << pg->getZOrder() << "): " << pg->getNumber() << ", " << pg->getName());
3699
        RECT_T r = pg->getRegion();
3700
 
3701
        if (r.left <= realX && (r.left + r.width) >= realX &&
3702
            r.top <= realY && (r.top + r.height) >= realY)
3703
        {
3704
            MSG_DEBUG("Click matches subpage " << pg->getNumber() << " (" << pg->getName() << ")");
3705
            return pg;
3706
        }
3707
 
3708
        pg = getPrevSubPage();
3709
    }
3710
 
3711
    return nullptr;
3712
}
3713
 
3714
Button::TButton *TPageManager::getCoordMatchPage(int x, int y)
3715
{
3716
    DECL_TRACER("TPageManager::getCoordMatchPage(int x, int y)");
3717
 
3718
    TPage *page = getActualPage();
3719
 
3720
    if (page)
3721
    {
3722
        Button::TButton *bt = page->getLastButton();
3723
 
3724
        while (bt)
3725
        {
3726
            bool clickable = bt->isClickable();
3727
            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"));
3728
 
3729
            if (!clickable)
3730
            {
3731
                bt = page->getPreviousButton();
3732
                continue;
3733
            }
3734
 
3735
            if (bt->getLeftPosition() <= x && (bt->getLeftPosition() + bt->getWidth()) >= x &&
3736
                bt->getTopPosition() <= y && (bt->getTopPosition() + bt->getHeight()) >= y)
3737
            {
3738
                if (!bt->isClickable(x - bt->getLeftPosition(), y - bt->getTopPosition()))
3739
                {
3740
                    bt = page->getPreviousButton();
3741
                    continue;
3742
                }
3743
 
3744
                MSG_DEBUG("Click matches button " << bt->getButtonIndex() << " (" << bt->getButtonName() << ")");
3745
                return bt;
3746
            }
3747
 
3748
            bt = page->getPreviousButton();
3749
        }
3750
    }
3751
 
3752
    return nullptr;
3753
}
3754
 
3755
bool TPageManager::doOverlap(RECT_T r1, RECT_T r2)
3756
{
3757
    DECL_TRACER("TPageManager::doOverlap(RECT_T r1, RECT_T r2)");
3758
 
3759
    // If one rectangle is on left side of other
3760
    if (r1.left >= r2.left || r2.left >= r1.left)
3761
        return false;
3762
 
3763
    // If one rectangle is above other
3764
    if (r1.top <= r2.top || r2.top <= r1.top)
3765
        return false;
3766
 
3767
    return true;
3768
}
3769
 
3770
bool TPageManager::havePage(const string& name)
3771
{
3772
    DECL_TRACER("TPageManager::havePage(const string& name)");
3773
 
3774
    if (name.empty())
3775
        return false;
3776
 
3777
    PCHAIN_T *pg = mPchain;
3778
 
3779
    while (pg)
3780
    {
3781
        if (pg->page && pg->page->getName().compare(name) == 0)
3782
            return true;
3783
 
3784
        pg = pg->next;
3785
    }
3786
 
3787
    return false;
3788
}
3789
 
3790
bool TPageManager::haveSubPage(const string& name)
3791
{
3792
    DECL_TRACER("TPageManager::haveSubPage(const string& name)");
3793
 
3794
    if (name.empty())
3795
        return false;
3796
 
3797
    SPCHAIN_T *pg = mSPchain;
3798
 
3799
    while (pg)
3800
    {
3801
        if (pg->page && pg->page->getName().compare(name) == 0)
3802
        {
3803
            MSG_DEBUG("Subpage " << pg->page->getNumber() << ", " << name << " found.");
3804
            return true;
3805
        }
3806
 
3807
        pg = pg->next;
3808
    }
3809
 
3810
    MSG_DEBUG("Subpage " << name << " not found.");
3811
    return false;
3812
}
3813
 
3814
bool TPageManager::haveSubPage(int id)
3815
{
3816
    DECL_TRACER("TPageManager::haveSubPage(int id)");
3817
 
3818
    SPCHAIN_T *pg = mSPchain;
3819
 
3820
    while (pg)
3821
    {
3822
        if (pg->page && pg->page->getNumber() == id)
3823
        {
3824
            MSG_DEBUG("Subpage " << pg->page->getNumber() << ", " << pg->page->getName() << " found.");
3825
            return true;
3826
        }
3827
 
3828
        pg = pg->next;
3829
    }
3830
 
3831
    MSG_DEBUG("Subpage " << id << " not found.");
3832
    return false;
3833
}
3834
 
3835
bool TPageManager::haveSubPage(const string& page, const string& name)
3836
{
3837
    DECL_TRACER("TPageManager::haveSubPage(const string& page, const string& name)");
3838
 
3839
    TPage *pg = getPage(page);
3840
 
3841
    if (!pg)
3842
        return false;
3843
 
3844
    TSubPage *spg = pg->getFirstSubPage();
3845
 
3846
    while (spg)
3847
    {
3848
        if (spg->getName().compare(name) == 0)
3849
        {
3850
            MSG_DEBUG("Subpage " << spg->getNumber() << ", " << name << " found.");
3851
            return true;
3852
        }
3853
 
3854
        spg = pg->getNextSubPage();
3855
    }
3856
 
3857
    MSG_DEBUG("Subpage " << name << " not found on page " << page << ".");
3858
    return false;
3859
}
3860
 
3861
bool TPageManager::haveSubPage(const string& page, int id)
3862
{
3863
    DECL_TRACER("TPageManager::haveSubPage(const string& page, int id)");
3864
 
3865
    TPage *pg = getPage(page);
3866
 
3867
    if (!pg)
3868
        return false;
3869
 
3870
    TSubPage *spg = pg->getFirstSubPage();
3871
 
3872
    while (spg)
3873
    {
3874
        if (spg->getNumber() == id)
3875
        {
3876
            MSG_DEBUG("Subpage " << spg->getNumber() << ", " << spg->getName() << " found.");
3877
            return true;
3878
        }
3879
 
3880
        spg = pg->getNextSubPage();
3881
    }
3882
 
3883
    MSG_DEBUG("Subpage " << id << " on page " << page << " not found.");
3884
    return false;
3885
}
3886
 
3887
void TPageManager::closeGroup(const string& group)
3888
{
3889
    DECL_TRACER("TPageManager::closeGroup(const string& group)");
3890
 
3891
    SPCHAIN_T *pg = mSPchain;
3892
 
3893
    while (pg)
3894
    {
3895
        if (pg->page->getGroupName().compare(group) == 0 && pg->page->isVisible())
3896
        {
3897
            pg->page->regCallDropSubPage(_callDropSubPage);
3898
            pg->page->drop();
3899
            break;
3900
        }
3901
 
3902
        pg = pg->next;
3903
    }
3904
}
3905
 
3906
void TPageManager::showSubPage(const string& name)
3907
{
3908
    DECL_TRACER("TPageManager::showSubPage(const string& name)");
3909
 
3910
    if (name.empty())
3911
    {
3912
#if TESTMODE == 1
3913
        setScreenDone();
3914
#endif
3915
        return;
3916
    }
3917
 
3918
    TPage *page = nullptr;
3919
    TSubPage *pg = deliverSubPage(name, &page);
3920
 
3921
    if (!pg)
3922
    {
3923
#if TESTMODE == 1
3924
        setScreenDone();
3925
#endif
3926
        return;
3927
    }
3928
 
3929
    if (page)
3930
    {
3931
        pg->setParent(page->getHandle());
3932
        page->addSubPage(pg);
3933
    }
3934
 
3935
    string group = pg->getGroupName();
3936
 
3937
    if (!group.empty())
3938
    {
3939
        TSubPage *sub = getFirstSubPageGroup(group);
3940
 
3941
        while(sub)
3942
        {
3943
            if (sub->isVisible() && sub->getNumber() != pg->getNumber())
3944
                sub->drop();
3945
 
3946
            sub = getNextSubPageGroup(group, sub);
3947
        }
3948
    }
3949
 
3950
    if (pg->isVisible())
3951
    {
3952
        MSG_DEBUG("Page " << pg->getName() << " is already visible but maybe not on top.");
3953
 
3954
        TSubPage *sub = getFirstSubPage();
3955
        bool redraw = false;
3956
 
3957
        while (sub)
3958
        {
3959
            if (sub->isVisible() && pg->getZOrder() < sub->getZOrder() &&
3960
                overlap(sub->getLeft(), sub->getTop(), sub->getWidth(), sub->getHeight(),
3961
                pg->getLeft(), pg->getTop(), pg->getWidth(), pg->getHeight()))
3962
            {
3963
                MSG_DEBUG("Page " << sub->getName() << " is overlapping page " << pg->getName());
3964
                redraw = true;
3965
                break;
3966
            }
3967
 
3968
            sub = getNextSubPage();
3969
        }
3970
 
3971
        if (redraw && _toFront)
3972
        {
3973
            _toFront((uint)pg->getHandle());
3974
            pg->setZOrder(page->getNextZOrder());
3975
//            page->sortSubpages();
3976
            MSG_DEBUG("Setting new Z-order " << page->getActZOrder() << " on subpage " << pg->getName());
3977
        }
3978
        else if (redraw && !_toFront)
3979
            pg->drop();
3980
    }
3981
 
3982
    if (!pg->isVisible())
3983
    {
3984
        if (!page)
3985
        {
3986
            page = getPage(mActualPage);
3987
 
3988
            if (!page)
3989
            {
3990
                MSG_ERROR("No active page found! Internal error.");
3991
                return;
3992
            }
3993
        }
3994
 
3995
        if (!haveSubPage(pg->getNumber()) && !page->addSubPage(pg))
3996
            return;
3997
 
3998
        pg->setZOrder(page->getNextZOrder());
3999
 
4000
        if (_setSubPage)
4001
        {
4002
            int left = pg->getLeft();
4003
            int top = pg->getTop();
4004
            int width = pg->getWidth();
4005
            int height = pg->getHeight();
4006
#ifdef _SCALE_SKIA_
4007
            if (mScaleFactor != 1.0)
4008
            {
4009
                left = (int)((double)left * mScaleFactor);
4010
                top = (int)((double)top * mScaleFactor);
4011
                width = (int)((double)width * mScaleFactor);
4012
                height = (int)((double)height * mScaleFactor);
4013
                MSG_DEBUG("Scaled subpage: left=" << left << ", top=" << top << ", width=" << width << ", height=" << height);
4014
            }
4015
#endif
4016
            ANIMATION_t ani;
4017
            ani.showEffect = pg->getShowEffect();
4018
            ani.showTime = pg->getShowTime();
4019
            ani.hideEffect = pg->getHideEffect();
4020
            ani.hideTime = pg->getHideTime();
4021
            // Test for a timer on the page
4022
            if (pg->getTimeout() > 0)
4023
                pg->startTimer();
4024
 
4025
            _setSubPage(pg->getHandle(), page->getHandle(), left, top, width, height, ani, pg->isModal());
4026
        }
4027
 
4028
        pg->show();
4029
    }
4030
}
4031
 
4032
void TPageManager::showSubPage(int number, bool force)
4033
{
4034
    DECL_TRACER("TPageManager::showSubPage(int number, bool force)");
4035
 
4036
    if (number <= 0)
4037
        return;
4038
 
4039
    TPage *page = nullptr;
4040
    TSubPage *pg = deliverSubPage(number, &page);
4041
 
4042
    if (!pg)
4043
        return;
4044
 
4045
    if (page)
4046
    {
4047
        pg->setParent(page->getHandle());
4048
        page->addSubPage(pg);
4049
    }
4050
 
4051
    string group = pg->getGroupName();
4052
 
4053
    if (!group.empty())
4054
    {
4055
        TSubPage *sub = getFirstSubPageGroup(group);
4056
 
4057
        while(sub)
4058
        {
4059
            if (sub->isVisible() && sub->getNumber() != pg->getNumber())
4060
                sub->drop();
4061
 
4062
            sub = getNextSubPageGroup(group, sub);
4063
        }
4064
    }
4065
 
4066
    if (pg->isVisible() && !force)
4067
    {
4068
        MSG_DEBUG("Page " << pg->getName() << " is already visible but maybe not on top.");
4069
 
4070
        TSubPage *sub = getFirstSubPage();
4071
        bool redraw = false;
4072
 
4073
        while (sub)
4074
        {
4075
            if (sub->isVisible() && pg->getZOrder() < sub->getZOrder() &&
4076
                overlap(sub->getLeft(), sub->getTop(), sub->getWidth(), sub->getHeight(),
4077
                        pg->getLeft(), pg->getTop(), pg->getWidth(), pg->getHeight()))
4078
            {
4079
                MSG_DEBUG("Page " << sub->getName() << " is overlapping page " << pg->getName());
4080
                redraw = true;
4081
                break;
4082
            }
4083
 
4084
            sub = getNextSubPage();
4085
        }
4086
 
4087
        if (redraw && _toFront)
4088
        {
4089
            _toFront((uint)pg->getHandle());
4090
            pg->setZOrder(page->getNextZOrder());
4091
            page->sortSubpages();
4092
            MSG_DEBUG("Setting new Z-order " << page->getActZOrder() << " on subpage " << pg->getName());
4093
        }
4094
        else if (redraw && !_toFront)
4095
            pg->drop();
4096
    }
4097
 
4098
    if (!pg->isVisible() || force)
4099
    {
4100
        if (!page)
4101
        {
4102
            MSG_ERROR("No active page found! Internal error.");
4103
            return;
4104
        }
4105
 
4106
        if (!haveSubPage(pg->getNumber()) && !page->addSubPage(pg))
4107
            return;
4108
 
4109
        if (!pg->isVisible())
4110
            pg->setZOrder(page->getNextZOrder());
4111
 
4112
        if (_setSubPage)
4113
        {
4114
            int left = pg->getLeft();
4115
            int top = pg->getTop();
4116
            int width = pg->getWidth();
4117
            int height = pg->getHeight();
4118
#ifdef _SCALE_SKIA_
4119
            if (mScaleFactor != 1.0)
4120
            {
4121
                left = (int)((double)left * mScaleFactor);
4122
                top = (int)((double)top * mScaleFactor);
4123
                width = (int)((double)width * mScaleFactor);
4124
                height = (int)((double)height * mScaleFactor);
4125
                MSG_DEBUG("Scaled subpage: left=" << left << ", top=" << top << ", width=" << width << ", height=" << height);
4126
            }
4127
#endif
4128
            ANIMATION_t ani;
4129
            ani.showEffect = pg->getShowEffect();
4130
            ani.showTime = pg->getShowTime();
4131
            ani.hideEffect = pg->getHideEffect();
4132
            ani.hideTime = pg->getHideTime();
4133
            // Test for a timer on the page
4134
            if (pg->getTimeout() > 0)
4135
                pg->startTimer();
4136
 
4137
            _setSubPage(pg->getHandle(), page->getHandle(), left, top, width, height, ani, pg->isModal());
4138
        }
4139
    }
4140
 
4141
    pg->show();
4142
}
4143
 
4144
void TPageManager::hideSubPage(const string& name)
4145
{
4146
    DECL_TRACER("TPageManager::hideSubPage(const string& name)");
4147
 
4148
    if (name.empty())
4149
    {
4150
#if TESTMODE == 1
4151
        setScreenDone();
4152
#endif
4153
        return;
4154
    }
4155
 
4156
    TPage *page = getPage(mActualPage);
4157
 
4158
    if (!page)
4159
    {
4160
        MSG_ERROR("No active page found! Internal error.");
4161
#if TESTMODE == 1
4162
        setScreenDone();
4163
#endif
4164
        return;
4165
    }
4166
 
4167
    TSubPage *pg = getSubPage(name);
4168
 
4169
    if (pg)
4170
    {
4171
        pg->drop();
4172
        page->decZOrder();
4173
    }
4174
}
4175
 
4176
/**
4177
 * @brief TPageManager::runClickQueue - Processing mouse clicks
4178
 * The following method is starting a thread which tests a queue containing
4179
 * the mouse clicks. To not drain the CPU, it sleeps for a short time if there
4180
 * are no more events in the queue.
4181
 * If there is an entry in the queue, it copies it to a local struct and
4182
 * deletes it from the queue. It take always the oldest antry (first entry)
4183
 * and removes this entry from the queue until the queue is empty. This makes
4184
 * it to a FIFO (first in, first out).
4185
 * Depending on the state of the variable "coords" the method for mouse
4186
 * coordinate click is executed or the method for a handle.
4187
 * The thread runs as long as the variable "mClickQueueRun" is TRUE and the
4188
 * variable "prg_stopped" is FALSE.
4189
 */
4190
void TPageManager::runClickQueue()
4191
{
4192
    DECL_TRACER("TPageManager::runClickQueue()");
4193
 
4194
    if (mClickQueueRun)
4195
        return;
4196
 
4197
    mClickQueueRun = true;
4198
 
4199
    try
4200
    {
4201
        std::thread thr = std::thread([=] {
4202
            MSG_PROTOCOL("Thread \"TPageManager::runClickQueue()\" was started.");
4203
 
4204
            while (mClickQueueRun && !prg_stopped)
4205
            {
4206
                while (!mClickQueue.empty())
4207
                {
4208
#ifdef QT_DEBUG
4209
                    if (mClickQueue[0].coords)
4210
                        MSG_TRACE("TPageManager::runClickQueue() -- executing: _mouseEvent(" << mClickQueue[0].x << ", " << mClickQueue[0].y << ", " << (mClickQueue[0].pressed ? "TRUE" : "FALSE") << ")")
4211
                    else
4212
                        MSG_TRACE("TPageManager::runClickQueue() -- executing: _mouseEvent(" << handleToString(mClickQueue[0].handle) << ", " << (mClickQueue[0].pressed ? "TRUE" : "FALSE") << ")")
4213
#endif
4214
                    if (mClickQueue[0].eventType == _EVENT_MOUSE_CLICK)
4215
                    {
4216
                        if (mClickQueue[0].coords)
4217
                            _mouseEvent(mClickQueue[0].x, mClickQueue[0].y, mClickQueue[0].pressed);
4218
                        else
4219
                            _mouseEvent(mClickQueue[0].handle, mClickQueue[0].handle);
4220
                    }
4221
                    else  if (mClickQueue[0].eventType == _EVENT_MOUSE_MOVE)
4222
                        _mouseMoveEvent(mClickQueue[0].x, mClickQueue[0].y);
4223
 
4224
                    mClickQueue.erase(mClickQueue.begin()); // Remove first entry
4225
                }
4226
 
4227
                std::this_thread::sleep_for(std::chrono::microseconds(10));
4228
            }
4229
 
4230
            mClickQueueRun = false;
4231
            return;
4232
        });
4233
 
4234
        thr.detach();
4235
    }
4236
    catch (std::exception& e)
4237
    {
4238
        MSG_ERROR("Error starting a thread to handle the click queue: " << e.what());
4239
        mClickQueueRun = false;
4240
    }
4241
}
4242
 
4243
void TPageManager::runUpdateSubViewItem()
4244
{
4245
    DECL_TRACER("TPageManager::runUpdateSubViewItem()");
4246
 
4247
    if (mUpdateViewsRun)
4248
        return;
4249
 
4250
    mUpdateViewsRun = true;
4251
 
4252
    try
4253
    {
4254
        std::thread thr = std::thread([=] {
4255
            MSG_PROTOCOL("Thread \"TPageManager::runUpdateSubViewItem()\" was started.");
4256
 
4257
            while (mUpdateViewsRun && !prg_stopped)
4258
            {
4259
                while (!mUpdateViews.empty())
4260
                {
4261
                    _updateSubViewItem(mUpdateViews[0]);
4262
                    mUpdateViews.erase(mUpdateViews.begin()); // Remove first entry
4263
                }
4264
 
4265
                std::this_thread::sleep_for(std::chrono::microseconds(10));
4266
            }
4267
 
4268
            mUpdateViewsRun = false;
4269
            return;
4270
        });
4271
 
4272
        thr.detach();
4273
    }
4274
    catch (std::exception& e)
4275
    {
4276
        MSG_ERROR("Error starting a thread to handle the click queue: " << e.what());
4277
        mUpdateViewsRun = false;
4278
    }
4279
}
4280
 
4281
/*
4282
 * Catch the mouse presses and scan all pages and subpages for an element to
4283
 * receive the klick.
4284
 */
4285
void TPageManager::mouseEvent(int x, int y, bool pressed)
4286
{
4287
    DECL_TRACER("TPageManager::mouseEvent(int x, int y, bool pressed)");
4288
 
4289
    TTRYLOCK(click_mutex);
4290
 
4291
    _CLICK_QUEUE_t cq;
4292
    cq.eventType = _EVENT_MOUSE_CLICK;
4293
    cq.x = x;
4294
    cq.y = y;
4295
    cq.pressed = pressed;
4296
    cq.coords = true;
4297
    mClickQueue.push_back(cq);
4298
#if TESTMODE == 1
4299
    setScreenDone();
4300
#endif
4301
}
4302
 
4303
void TPageManager::mouseMoveEvent(int x, int y)
4304
{
4305
    DECL_TRACER("TPageManager::mouseMoveEvent(int x, int y)");
4306
 
4307
    TTRYLOCK(click_mutex);
4308
 
4309
    _CLICK_QUEUE_t cq;
4310
    cq.eventType = _EVENT_MOUSE_MOVE;
4311
    cq.x = x;
4312
    cq.y = y;
4313
    cq.coords = true;
4314
    mClickQueue.push_back(cq);
4315
#if TESTMODE == 1
4316
    setScreenDone();
4317
#endif
4318
}
4319
 
4320
void TPageManager::_mouseEvent(int x, int y, bool pressed)
4321
{
4322
    DECL_TRACER("TPageManager::_mouseEvent(int x, int y, bool pressed)");
4323
 
4324
    TError::clear();
4325
#if TESTMODE == 1
4326
    if (_gTestMode)
4327
        _gTestMode->setMouseClick(x, y, pressed);
4328
#endif
4329
    int realX = x - mFirstLeftPixel;
4330
    int realY = y - mFirstTopPixel;
4331
 
4332
    MSG_DEBUG("Mouse at " << realX << ", " << realY << ", state " << ((pressed) ? "PRESSED" : "RELEASED") << ", [ " << x << " | " << y << " ]");
4333
#ifdef _SCALE_SKIA_
4334
    if (mScaleFactor != 1.0 && mScaleFactor > 0.0)
4335
    {
4336
        realX = (int)((double)realX / mScaleFactor);
4337
        realY = (int)((double)realY / mScaleFactor);
4338
        MSG_DEBUG("Scaled coordinates: x=" << realX << ", y=" << realY);
4339
    }
4340
#endif
4341
 
4342
    TSubPage *subPage = nullptr;
4343
 
4344
    if (pressed)
4345
        subPage = getCoordMatch(realX, realY);
4346
    else if (mLastPagePush)
4347
        subPage = getSubPage(mLastPagePush);
4348
    else
4349
        subPage = getCoordMatch(realX, realY);
4350
 
4351
    if (!subPage)
4352
    {
4353
        Button::TButton *bt = getCoordMatchPage(realX, realY);
4354
 
4355
        if (bt)
4356
        {
4357
            MSG_DEBUG("Button on page " << bt->getButtonIndex() << ": size: left=" << bt->getLeftPosition() << ", top=" << bt->getTopPosition() << ", width=" << bt->getWidth() << ", height=" << bt->getHeight());
4358
            bt->doClick(x - bt->getLeftPosition(), y - bt->getTopPosition(), pressed);
4359
        }
4360
 
4361
        if (pressed)
4362
            mLastPagePush = getActualPageNumber();
4363
 
4364
        return;
4365
    }
4366
 
4367
    MSG_DEBUG("Subpage " << subPage->getNumber() << " [" << subPage->getName() << "]: size: left=" << subPage->getLeft() << ", top=" << subPage->getTop() << ", width=" << subPage->getWidth() << ", height=" << subPage->getHeight());
4368
 
4369
    if (pressed)
4370
        mLastPagePush = subPage->getNumber();
4371
    else
4372
        mLastPagePush = 0;
4373
 
4374
    subPage->doClick(realX - subPage->getLeft(), realY - subPage->getTop(), pressed);
4375
}
4376
 
4377
void TPageManager::_mouseMoveEvent(int x, int y)
4378
{
4379
    DECL_TRACER("TPageManager::_mouseMoveEvent(int x, int y)");
4380
 
4381
    int realX = x - mFirstLeftPixel;
4382
    int realY = y - mFirstTopPixel;
4383
 
4384
#ifdef _SCALE_SKIA_
4385
    if (mScaleFactor != 1.0 && mScaleFactor > 0.0)
4386
    {
4387
        realX = (int)((double)realX / mScaleFactor);
4388
        realY = (int)((double)realY / mScaleFactor);
4389
        MSG_DEBUG("Scaled coordinates: x=" << realX << ", y=" << realY);
4390
    }
4391
#endif
4392
 
4393
    TSubPage *subPage = nullptr;
4394
    subPage = getCoordMatch(realX, realY);
4395
 
4396
    if (!subPage)
4397
    {
4398
        Button::TButton *bt = getCoordMatchPage(realX, realY);
4399
 
4400
        if (bt)
4401
        {
4402
            if (bt->getButtonType() == BARGRAPH)
4403
                bt->moveBargraphLevel(realX - bt->getLeftPosition(), realY - bt->getTopPosition());
4404
            else if (bt->getButtonType() == JOYSTICK && !bt->getLevelFuction().empty())
4405
            {
4406
                bt->drawJoystick(realX - bt->getLeftPosition(), realY - bt->getTopPosition());
4407
                // Send the levels
4408
                bt->sendJoystickLevels();
4409
            }
4410
        }
4411
 
4412
        return;
4413
    }
4414
 
4415
    subPage->moveMouse(realX - subPage->getLeft(), realY - subPage->getTop());
4416
}
4417
 
4418
void TPageManager::mouseEvent(ulong handle, bool pressed)
4419
{
4420
    DECL_TRACER("TPageManager::mouseEvent(ulong handle, bool pressed)");
4421
 
4422
    if (!mClickQueue.empty() && mClickQueue.back().handle == handle && mClickQueue.back().pressed == pressed)
4423
        return;
4424
 
4425
    TLOCKER(click_mutex);
4426
 
4427
    _CLICK_QUEUE_t cq;
4428
    cq.handle = handle;
4429
    cq.pressed = pressed;
4430
    mClickQueue.push_back(cq);
4431
    MSG_DEBUG("Queued click for handle " << handleToString(cq.handle) << " state " << (cq.pressed ? "PRESSED" : "RELEASED"));
4432
}
4433
 
4434
void TPageManager::_mouseEvent(ulong handle, bool pressed)
4435
{
4436
    DECL_TRACER("TPageManager::_mouseEvent(ulong handle, bool pressed)");
4437
 
4438
    MSG_DEBUG("Doing click for handle " << handleToString(handle) << " state " << (pressed ? "PRESSED" : "RELEASED"));
4439
 
4440
    if (!handle)
4441
        return;
4442
 
4443
    int pageID = (handle >> 16) & 0x0000ffff;
4444
    int buttonID = (handle & 0x0000ffff);
4445
 
4446
    if (pageID < REGULAR_SUBPAGE_START || buttonID == 0)
4447
        return;
4448
 
4449
    TSubPage *subPage = getSubPage(pageID);
4450
 
4451
    if (subPage)
4452
    {
4453
        Button::TButton *bt = subPage->getButton(buttonID);
4454
 
4455
        if (bt)
4456
        {
4457
            MSG_DEBUG("Button on subpage " << pageID << ": " << buttonID);
4458
            bt->doClick(bt->getLeftPosition() + bt->getWidth() / 2, bt->getTopPosition() + bt->getHeight() / 2, pressed);
4459
        }
4460
    }
4461
}
4462
 
4463
void TPageManager::inputButtonFinished(ulong handle, const std::string &content)
4464
{
4465
    DECL_TRACER("TPageManager::inputButtonFinished(ulong handle, const std::string &content)");
4466
 
4467
    Button::TButton *bt = findButton(handle);
4468
 
4469
    if (!bt)
4470
    {
4471
        MSG_WARNING("Invalid button handle " << handleToString(handle));
4472
        return;
4473
    }
4474
 
4475
    bt->setTextOnly(content, -1);
4476
}
4477
 
4478
void TPageManager::inputCursorPositionChanged(ulong handle, int oldPos, int newPos)
4479
{
4480
    DECL_TRACER("TPageManager::inputCursorPositionChanged(ulong handle, int oldPos, int newPos)");
4481
 
4482
    Button::TButton *bt = findButton(handle);
4483
 
4484
    if (!bt)
4485
    {
4486
        MSG_WARNING("Invalid button handle " << handleToString(handle));
4487
        return;
4488
    }
4489
 
4490
    ulong pageID = (bt->getHandle() >> 16) & 0x0000ffff;
4491
 
4492
    if (pageID < REGULAR_SUBPAGE_START)
4493
    {
4494
        TPage *pg = getPage((int)pageID);
4495
 
4496
        if (!pg)
4497
            return;
4498
 
4499
        pg->setCursorPosition(handle, oldPos, newPos);
4500
    }
4501
    else
4502
    {
4503
        TSubPage *pg = getSubPage((int)pageID);
4504
 
4505
        if (!pg)
4506
            return;
4507
 
4508
        pg->setCursorPosition(handle, oldPos, newPos);
4509
    }
4510
}
4511
 
4512
void TPageManager::inputFocusChanged(ulong handle, bool in)
4513
{
4514
    DECL_TRACER("TPageManager::inputFocusChanged(ulong handle, bool in)");
4515
 
4516
    Button::TButton *bt = findButton(handle);
4517
 
4518
    if (!bt)
4519
    {
4520
        MSG_WARNING("Invalid button handle " << handleToString(handle));
4521
        return;
4522
    }
4523
 
4524
    ulong pageID = (bt->getHandle() >> 16) & 0x0000ffff;
4525
    MSG_DEBUG("Searching for page " << pageID);
4526
 
4527
    if (pageID < REGULAR_SUBPAGE_START)
4528
    {
4529
        TPage *pg = getPage((int)pageID);
4530
 
4531
        if (!pg)
4532
            return;
4533
 
4534
        pg->setInputFocus(handle, in);
4535
    }
4536
    else
4537
    {
4538
        TSubPage *pg = getSubPage((int)pageID);
4539
 
4540
        if (!pg)
4541
            return;
4542
 
4543
        pg->setInputFocus(handle, in);
4544
    }
4545
}
4546
 
4547
void TPageManager::setTextToButton(ulong handle, const string& txt, bool redraw)
4548
{
4549
    DECL_TRACER("TPageManager::setTextToButton(ulong handle, const string& txt, bool redraw)");
4550
 
4551
    // First we search for the button the handle points to
4552
    Button::TButton *button = findButton(handle);
4553
 
4554
    if (!button)
4555
    {
4556
        MSG_ERROR("No button with handle " << handleToString(handle) << " found!");
4557
        return;
4558
    }
4559
 
4560
    // Now we search for all buttons with the same channel and port number
4561
    vector<int> channels;
4562
    channels.push_back(button->getAddressChannel());
4563
    vector<TMap::MAP_T> map = findButtons(button->getAddressPort(), channels);
4564
 
4565
    if (TError::isError() || map.empty())
4566
        return;
4567
 
4568
    // Here we load all buttons found.
4569
    vector<Button::TButton *> buttons = collectButtons(map);
4570
 
4571
    if (buttons.size() > 0)
4572
    {
4573
        vector<Button::TButton *>::iterator mapIter;
4574
        // Finaly we iterate through all found buttons and set the text
4575
        for (mapIter = buttons.begin(); mapIter != buttons.end(); ++mapIter)
4576
        {
4577
            Button::TButton *bt = *mapIter;
4578
 
4579
            if (redraw)
4580
                bt->setText(txt, -1);
4581
            else
4582
                bt->setTextOnly(txt, -1);
4583
        }
4584
    }
4585
}
4586
 
4587
vector<Button::TButton *> TPageManager::collectButtons(vector<TMap::MAP_T>& map)
4588
{
4589
    DECL_TRACER("TPageManager::collectButtons(vector<TMap::MAP_T>& map)");
4590
 
4591
    vector<Button::TButton *> buttons;
4592
 
4593
    if (map.size() == 0)
4594
        return buttons;
4595
 
4596
    vector<TMap::MAP_T>::iterator iter;
4597
 
4598
    for (iter = map.begin(); iter != map.end(); ++iter)
4599
    {
4600
        if (iter->pg < REGULAR_SUBPAGE_START || (iter->pg >= SYSTEM_PAGE_START && iter->pg < SYSTEM_SUBPAGE_START))     // Main page?
4601
        {
4602
            TPage *page;
4603
 
4604
            if ((page = getPage(iter->pg)) == nullptr)
4605
            {
4606
                MSG_TRACE("Page " << iter->pg << ", " << iter->pn << " not found in memory. Reading it ...");
4607
 
4608
                if (!readPage(iter->pg))
4609
                    return buttons;
4610
 
4611
                page = getPage(iter->pg);
4612
            }
4613
 
4614
            Button::TButton *bt = page->getButton(iter->bt);
4615
 
4616
            if (bt)
4617
                buttons.push_back(bt);
4618
        }
4619
        else
4620
        {
4621
            TSubPage *subpage;
4622
 
4623
            if ((subpage = getSubPage(iter->pg)) == nullptr)
4624
            {
4625
                MSG_TRACE("Subpage " << iter->pg << ", " << iter->pn << " not found in memory. Reading it ...");
4626
 
4627
                if (!readSubPage(iter->pg))
4628
                    return buttons;
4629
 
4630
                subpage = getSubPage(iter->pg);
4631
                TPage *page = getActualPage();
4632
 
4633
                if (!page)
4634
                {
4635
                    MSG_ERROR("No actual page loaded!");
4636
                    return buttons;
4637
                }
4638
            }
4639
 
4640
            Button::TButton *bt = subpage->getButton(iter->bt);
4641
 
4642
            if (bt)
4643
                buttons.push_back(bt);
4644
        }
4645
    }
4646
 
4647
    return buttons;
4648
}
4649
 
4650
/****************************************************************************
4651
 * Calls from a Java activity. This is only available for Android OS.
4652
 ****************************************************************************/
4653
#ifdef Q_OS_ANDROID
4654
void TPageManager::initNetworkState()
4655
{
4656
    DECL_TRACER("TPageManager::initNetworkState()");
4657
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
4658
    QAndroidJniObject activity = QtAndroid::androidActivity();
4659
    QAndroidJniObject::callStaticMethod<void>("org/qtproject/theosys/NetworkStatus", "Init", "(Landroid/app/Activity;)V", activity.object());
4660
    activity.callStaticMethod<void>("org/qtproject/theosys/NetworkStatus", "InstallNetworkListener", "()V");
4661
#else
4662
    QJniObject activity = QNativeInterface::QAndroidApplication::context();
4663
    QJniObject::callStaticMethod<void>("org/qtproject/theosys/NetworkStatus", "Init", "(Landroid/app/Activity;)V", activity.object());
4664
    activity.callStaticMethod<void>("org/qtproject/theosys/NetworkStatus", "InstallNetworkListener", "()V");
4665
#endif
4666
}
4667
 
4668
void TPageManager::stopNetworkState()
4669
{
4670
    DECL_TRACER("TPageManager::stopNetworkState()");
4671
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
4672
    QAndroidJniObject::callStaticMethod<void>("org/qtproject/theosys/NetworkStatus", "destroyNetworkListener", "()V");
4673
#else
4674
    QJniObject::callStaticMethod<void>("org/qtproject/theosys/NetworkStatus", "destroyNetworkListener", "()V");
4675
#endif
4676
}
4677
 
4678
void TPageManager::initBatteryState()
4679
{
4680
    DECL_TRACER("TPageManager::initBatteryState()");
4681
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
4682
    QAndroidJniObject activity = QtAndroid::androidActivity();
4683
    QAndroidJniObject::callStaticMethod<void>("org/qtproject/theosys/BatteryState", "Init", "(Landroid/app/Activity;)V", activity.object());
4684
#else
4685
    QJniObject activity = QNativeInterface::QAndroidApplication::context();
4686
    QJniObject::callStaticMethod<void>("org/qtproject/theosys/BatteryState", "Init", "(Landroid/app/Activity;)V", activity.object());
4687
#endif
4688
    activity.callStaticMethod<void>("org/qtproject/theosys/BatteryState", "InstallBatteryListener", "()V");
4689
}
4690
 
4691
void TPageManager::initPhoneState()
4692
{
4693
    DECL_TRACER("TPageManager::initPhoneState()");
4694
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
4695
    QAndroidJniObject activity = QtAndroid::androidActivity();
4696
    QAndroidJniObject::callStaticMethod<void>("org/qtproject/theosys/PhoneCallState", "Init", "(Landroid/app/Activity;)V", activity.object());
4697
#else
4698
    QJniObject activity = QNativeInterface::QAndroidApplication::context();
4699
    QJniObject::callStaticMethod<void>("org/qtproject/theosys/PhoneCallState", "Init", "(Landroid/app/Activity;)V", activity.object());
4700
#endif
4701
    activity.callStaticMethod<void>("org/qtproject/theosys/PhoneCallState", "InstallPhoneListener", "()V");
4702
}
4703
 
4704
void TPageManager::stopBatteryState()
4705
{
4706
    DECL_TRACER("TPageManager::stopBatteryState()");
4707
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
4708
    QAndroidJniObject::callStaticMethod<void>("org/qtproject/theosys/BatteryState", "destroyBatteryListener", "()V");
4709
#else
4710
    QJniObject::callStaticMethod<void>("org/qtproject/theosys/BatteryState", "destroyBatteryListener", "()V");
4711
#endif
4712
}
4713
 
4714
void TPageManager::informTPanelNetwork(jboolean conn, jint level, jint type)
4715
{
4716
    DECL_TRACER("TPageManager::informTPanelNetwork(jboolean conn, jint level, jint type)");
4717
 
4718
    int l = 0;
4719
    string sType;
4720
 
4721
    switch (type)
4722
    {
4723
        case 1: sType = "Wifi"; break;
4724
        case 2: sType = "Mobile"; break;
4725
 
4726
        default:
4727
            sType = "Unknown"; break;
4728
    }
4729
 
4730
    if (conn)
4731
        l = level;
4732
 
4733
    if (mNetState && mNetState != type)     // Has the connection type changed?
4734
    {
4735
        if (gAmxNet)
4736
            gAmxNet->reconnect();
4737
    }
4738
 
4739
    mNetState = type;
4740
 
4741
    MSG_INFO("Connection status: " << (conn ? "Connected" : "Disconnected") << ", level: " << level << ", type: " << sType);
4742
 
4743
    if (mNetCalls.size() > 0)
4744
    {
4745
        std::map<int, std::function<void (int level)> >::iterator iter;
4746
 
4747
        for (iter = mNetCalls.begin(); iter != mNetCalls.end(); ++iter)
4748
            iter->second(l);
4749
    }
4750
}
4751
 
4752
void TPageManager::informBatteryStatus(jint level, jboolean charging, jint chargeType)
4753
{
4754
    DECL_TRACER("TPageManager::informBatteryStatus(jint level, jboolean charging, jint chargeType)");
4755
 
4756
    MSG_INFO("Battery status: level: " << level << ", " << (charging ? "Charging" : "not charging") << ", type: " << chargeType << ", Elements: " << mBatteryCalls.size());
4757
 
4758
    if (mBatteryCalls.size() > 0)
4759
    {
4760
        std::map<int, std::function<void (int, bool, int)> >::iterator iter;
4761
 
4762
        for (iter = mBatteryCalls.begin(); iter != mBatteryCalls.end(); ++iter)
4763
            iter->second(level, charging, chargeType);
4764
    }
4765
}
4766
 
4767
void TPageManager::informPhoneState(bool call, const string &pnumber)
4768
{
4769
    DECL_TRACER("TPageManager::informPhoneState(bool call, const string &pnumber)");
4770
 
4771
    MSG_INFO("Call state: " << (call ? "Call in progress" : "No call") << ", phone number: " << pnumber);
4772
 
4773
    if (!gAmxNet)
4774
    {
4775
        MSG_WARNING("The network manager for the AMX controller is not initialized!");
4776
        return;
4777
    }
4778
}
4779
 
4780
void TPageManager::initOrientation()
4781
{
4782
    DECL_TRACER("TPageManager::initOrientation()");
4783
 
4784
    int rotate = getSettings()->getRotate();
4785
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
4786
    QAndroidJniObject activity = QtAndroid::androidActivity();
4787
    QAndroidJniObject::callStaticMethod<void>("org/qtproject/theosys/Orientation", "Init", "(Landroid/app/Activity;I)V", activity.object(), rotate);
4788
#else
4789
    QJniObject activity = QNativeInterface::QAndroidApplication::context();
4790
    QJniObject::callStaticMethod<void>("org/qtproject/theosys/Orientation", "Init", "(Landroid/app/Activity;I)V", activity.object(), rotate);
4791
#endif
4792
    activity.callStaticMethod<void>("org/qtproject/theosys/Orientation", "InstallOrientationListener", "()V");
4793
}
4794
 
4795
void TPageManager::enterSetup()
4796
{
4797
    DECL_TRACER("TPageManager::enterSetup()");
4798
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
4799
    QAndroidJniObject activity = QtAndroid::androidActivity();
4800
    QAndroidJniObject::callStaticMethod<void>("org/qtproject/theosys/Settings", "callSettings", "(Landroid/app/Activity;)V", activity.object());
4801
#else
4802
    QJniObject activity = QNativeInterface::QAndroidApplication::context();
4803
    QJniObject::callStaticMethod<void>("org/qtproject/theosys/Settings", "callSettings", "(Landroid/app/Activity;)V", activity.object());
4804
#endif
4805
}
4806
#endif  // __ANDROID__
4807
#ifdef Q_OS_IOS
4808
void TPageManager::informBatteryStatus(int level, int state)
4809
{
4810
    DECL_TRACER("TPageManager::informBatteryStatus(int level, int state)");
4811
 
4812
    MSG_INFO("Battery status: level: " << level << ", " << state);
4813
 
4814
    if (mBatteryCalls.size() > 0)
4815
    {
4816
        std::map<int, std::function<void (int, int)> >::iterator iter;
4817
 
4818
        for (iter = mBatteryCalls.begin(); iter != mBatteryCalls.end(); ++iter)
4819
            iter->second(level, state);
4820
    }
4821
}
4822
 
4823
void TPageManager::informTPanelNetwork(bool conn, int level, int type)
4824
{
4825
    DECL_TRACER("TPageManager::informTPanelNetwork(bool conn, int level, int type)");
4826
 
4827
    int l = 0;
4828
    string sType;
4829
 
4830
    switch (type)
4831
    {
4832
        case 1: sType = "Ethernet"; break;
4833
        case 2: sType = "Mobile"; break;
4834
        case 3: sType = "WiFi"; break;
4835
        case 4: sType = "Bluetooth"; break;
4836
 
4837
        default:
4838
            sType = "Unknown"; break;
4839
    }
4840
 
4841
    if (conn)
4842
        l = level;
4843
 
4844
    if (mNetState && mNetState != type)     // Has the connection type changed?
4845
    {
4846
        if (gAmxNet)
4847
            gAmxNet->reconnect();
4848
    }
4849
 
4850
    mNetState = type;
4851
 
4852
    MSG_INFO("Connection status: " << (conn ? "Connected" : "Disconnected") << ", level: " << level << ", type: " << sType);
4853
 
4854
    if (mNetCalls.size() > 0)
4855
    {
4856
        std::map<int, std::function<void (int level)> >::iterator iter;
4857
 
4858
        for (iter = mNetCalls.begin(); iter != mNetCalls.end(); ++iter)
4859
            iter->second(l);
4860
    }
4861
}
4862
 
4863
#endif
4864
 
4865
void TPageManager::setButtonCallbacks(Button::TButton *bt)
4866
{
4867
    DECL_TRACER("TPageManager::setButtonCallbacks(Button::TButton *bt)");
4868
 
4869
    if (!bt)
4870
        return;
4871
 
4872
    bt->registerCallback(_displayButton);
4873
    bt->regCallPlayVideo(_callPlayVideo);
4874
    bt->setFonts(mFonts);
4875
    bt->setPalette(mPalette);
4876
}
4877
 
4878
void TPageManager::externalButton(extButtons_t bt, bool checked)
4879
{
4880
    DECL_TRACER("TPageManager::externalButton(extButtons_t bt)");
4881
 
4882
    if (!mExternal)
4883
        return;
4884
 
4885
    EXTBUTTON_t button = mExternal->getButton(bt);
4886
 
4887
    if (button.type == EXT_NOBUTTON)
4888
        return;
4889
 
4890
    if (button.cp && button.ch)
4891
    {
4892
        amx::ANET_SEND scmd;
4893
 
4894
        scmd.device = TConfig::getChannel();
4895
        scmd.port = button.cp;
4896
        scmd.channel = button.ch;
4897
 
4898
        if (checked)
4899
            scmd.MC = 0x0084;   // push button
4900
        else
4901
            scmd.MC = 0x0085;   // release button
4902
 
4903
        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") << ")");
4904
 
4905
        if (gAmxNet)
4906
            gAmxNet->sendCommand(scmd);
4907
        else
4908
        {
4909
            MSG_WARNING("Missing global class TAmxNet. Can't send a message!");
4910
        }
4911
    }
4912
}
4913
 
4914
void TPageManager::sendKeyboard(const std::string& text)
4915
{
4916
    DECL_TRACER("TPageManager::sendKeyboard(const std::string& text)");
4917
 
4918
    amx::ANET_SEND scmd;
4919
    scmd.port = 1;
4920
    scmd.channel = 0;
4921
    scmd.msg = UTF8ToCp1250(text);
4922
    scmd.MC = 0x008b;
4923
    MSG_DEBUG("Sending keyboard: " << text);
4924
 
4925
    if (gAmxNet)
4926
        gAmxNet->sendCommand(scmd);
4927
    else
4928
        MSG_WARNING("Missing global class TAmxNet. Can't send message!");
4929
}
4930
 
4931
void TPageManager::sendKeypad(const std::string& text)
4932
{
4933
    DECL_TRACER("TPageManager::sendKeypad(const std::string& text)");
4934
 
4935
    sendKeyboard(text);
4936
}
4937
 
4938
void TPageManager::sendString(uint handle, const std::string& text)
4939
{
4940
    DECL_TRACER("TPageManager::sendString(uint handle, const std::string& text)");
4941
 
4942
    Button::TButton *bt = findButton(handle);
4943
 
4944
    if (!bt)
4945
    {
4946
        MSG_WARNING("Button " << handleToString(handle) << " not found!");
4947
        return;
4948
    }
4949
 
4950
    amx::ANET_SEND scmd;
4951
    scmd.port = bt->getAddressPort();
4952
    scmd.channel = bt->getAddressChannel();
4953
    scmd.msg = UTF8ToCp1250(text);
4954
    scmd.MC = 0x008b;
4955
 
4956
    if (gAmxNet)
4957
        gAmxNet->sendCommand(scmd);
4958
    else
4959
        MSG_WARNING("Missing global class TAmxNet. Can't send message!");
4960
}
4961
 
4962
void TPageManager::sendGlobalString(const string& text)
4963
{
4964
    DECL_TRACER("TPageManager::sendGlobalString(const string& text)");
4965
 
4966
    if (text.empty() || text.find("-") == string::npos)
4967
        return;
4968
 
4969
    amx::ANET_SEND scmd;
4970
    scmd.port = 1;
4971
    scmd.channel = 0;
4972
    scmd.msg = text;
4973
    scmd.MC = 0x008b;
4974
 
4975
    if (gAmxNet)
4976
        gAmxNet->sendCommand(scmd);
4977
    else
4978
        MSG_WARNING("Missing global class TAmxNet. Can't send message!");
4979
}
4980
 
4981
void TPageManager::sendCommandString(int port, const string& cmd)
4982
{
4983
    DECL_TRACER("TPageManager::sendGlobalString(const string& text)");
4984
 
4985
    if (cmd.empty())
4986
        return;
4987
 
4988
    amx::ANET_SEND scmd;
4989
    scmd.port = port;
4990
    scmd.channel = 0;
4991
    scmd.msg = cmd;
4992
    scmd.MC = 0x008c;
4993
 
4994
    if (gAmxNet)
4995
        gAmxNet->sendCommand(scmd);
4996
    else
4997
        MSG_WARNING("Missing global class TAmxNet. Can't send message!");
4998
}
4999
 
5000
void TPageManager::sendLevel(int lp, int lv, int level)
5001
{
5002
    DECL_TRACER("TPageManager::sendLevel(int lp, int lv, int level)");
5003
 
5004
    if (!lv)
5005
        return;
5006
 
5007
    amx::ANET_SEND scmd;
5008
    scmd.device = TConfig::getChannel();
5009
    scmd.port = lp;
5010
    scmd.channel = lv;
5011
    scmd.level = lv;
5012
    scmd.MC = 0x008a;
5013
    scmd.value = level;
5014
 
5015
    if (gAmxNet)
5016
        gAmxNet->sendCommand(scmd);
5017
    else
5018
        MSG_WARNING("Missing global class TAmxNet. Can't send message!");
5019
}
5020
 
5021
void TPageManager::sendInternalLevel(int lp, int lv, int level)
5022
{
5023
    DECL_TRACER("TPageManager::sendInternalLevel(int lp, int lv, int level)");
5024
 
5025
    amx::ANET_COMMAND cmd;
5026
    int channel = TConfig::getChannel();
5027
    int system = TConfig::getSystem();
5028
 
5029
    cmd.MC = 0x000a;
5030
    cmd.device1 = channel;
5031
    cmd.port1 = lp;
5032
    cmd.system = system;
5033
    cmd.data.message_value.system = system;
5034
    cmd.data.message_value.device = channel;
5035
    cmd.data.message_value.port = lp;           // Must be the address port of bargraph
5036
    cmd.data.message_value.value = lv;          // Must be the level channel of bargraph
5037
    cmd.data.message_value.type = DTSZ_UINT;    // unsigned integer
5038
    cmd.data.message_value.content.sinteger = level;
5039
    doCommand(cmd);
5040
}
5041
 
5042
void TPageManager::sendPHNcommand(const std::string& cmd)
5043
{
5044
    DECL_TRACER("TPageManager::sendPHNcommand(const std::string& cmd)");
5045
 
5046
    amx::ANET_SEND scmd;
5047
    scmd.port = mTSettings->getSettings().voipCommandPort;
5048
    scmd.channel = TConfig::getChannel();
5049
    scmd.msg = "^PHN-" + cmd;
5050
    scmd.MC = 0x008c;
5051
    MSG_DEBUG("Sending PHN command: ^PHN-" << cmd);
5052
 
5053
    if (gAmxNet)
5054
        gAmxNet->sendCommand(scmd);
5055
    else
5056
        MSG_WARNING("Missing global class TAmxNet. Can't send ^PHN command!");
5057
}
5058
 
5059
void TPageManager::sendKeyStroke(char key)
5060
{
5061
    DECL_TRACER("TPageManager::sendKeyStroke(char key)");
5062
 
5063
    if (!key)
5064
        return;
5065
 
5066
    char msg[2];
5067
    msg[0] = key;
5068
    msg[1] = 0;
5069
 
5070
    amx::ANET_SEND scmd;
5071
    scmd.port = 1;
5072
    scmd.channel = 0;
5073
    scmd.msg.assign(msg);
5074
    scmd.MC = 0x008c;
5075
 
5076
    if (gAmxNet)
5077
        gAmxNet->sendCommand(scmd);
5078
    else
5079
        MSG_WARNING("Missing global class TAmxNet. Can't send message!");
5080
}
5081
 
5082
/**
5083
 * Sending a custom event is identical in all cases. Because of this I
5084
 * implemented this method to send a custom event. This is called in all cases
5085
 * where a ?XXX command is received.
5086
 *
5087
 * @param value1    The instance of the button.
5088
 * @param value2    The value of a numeric request or the length of the string.
5089
 * @param value3    Always 0
5090
 * @param msg       In case of a string this contains the string.
5091
 * @param evType    This is the event type, a number between 1001 and 1099.
5092
 * @param cp        Channel port of button.
5093
 * @param cn        Channel number. of button.
5094
 *
5095
 * @return If all parameters are valid it returns TRUE.
5096
 */
5097
bool TPageManager::sendCustomEvent(int value1, int value2, int value3, const string& msg, int evType, int cp, int cn)
5098
{
5099
    DECL_TRACER("TPageManager::sendCustomEvent(int value1, int value2, int value3, const string& msg, int evType)");
5100
 
5101
    if (value1 < 1)
5102
        return false;
5103
 
5104
    amx::ANET_SEND scmd;
5105
    scmd.port = cp;
5106
    scmd.channel = cn;
5107
    scmd.ID = scmd.channel;
5108
    scmd.flag = 0;
5109
    scmd.type = evType;
5110
    scmd.value1 = value1;   // instance
5111
    scmd.value2 = value2;
5112
    scmd.value3 = value3;
5113
    scmd.msg = msg;
5114
 
5115
    if (!msg.empty())
5116
        scmd.dtype = 0x0001;// Char array
5117
 
5118
    scmd.MC = 0x008d;       // custom event
5119
 
5120
    if (gAmxNet)
5121
        gAmxNet->sendCommand(scmd);
5122
    else
5123
        MSG_WARNING("Missing global class TAmxNet. Can't send message!");
5124
 
5125
    return true;
5126
}
5127
#ifndef _NOSIP_
5128
string TPageManager::sipStateToString(TSIPClient::SIP_STATE_t s)
5129
{
5130
    DECL_TRACER("TPageManager::sipStateToString(TSIPClient::SIP_STATE_t s)");
5131
 
5132
    switch(s)
5133
    {
5134
        case TSIPClient::SIP_CONNECTED:     return "CONNECTED";
5135
        case TSIPClient::SIP_DISCONNECTED:  return "DISCONNECTED";
5136
        case TSIPClient::SIP_HOLD:          return "HOLD";
5137
        case TSIPClient::SIP_RINGING:       return "RINGING";
5138
        case TSIPClient::SIP_TRYING:        return "TRYING";
5139
 
5140
        default:
5141
            return "IDLE";
5142
    }
5143
 
5144
    return "IDLE";
5145
}
5146
#endif
5147
void TPageManager::sendOrientation()
5148
{
5149
    string ori;
5150
 
5151
    switch(mOrientation)
5152
    {
5153
        case O_PORTRAIT:            ori = "DeviceOrientationPortrait"; break;
5154
        case O_REVERSE_PORTRAIT:    ori = "DeviceOrientationPortraitUpsideDown"; break;
5155
        case O_LANDSCAPE:           ori = "DeviceOrientationLandscapeLeft"; break;
5156
        case O_REVERSE_LANDSCAPE:   ori = "DeviceOrientationLandscapeRight"; break;
5157
        case O_FACE_UP:             ori = "DeviceOrientationFaceUp"; break;
5158
        case O_FACE_DOWN:           ori = "DeviceOrientationFaceDown"; break;
5159
        default:
5160
            return;
5161
    }
5162
 
5163
    sendGlobalString("TPCACC-" + ori);
5164
}
5165
 
5166
void TPageManager::callSetPassword(ulong handle, const string& pw, int x, int y)
5167
{
5168
    DECL_TRACER("TPageManager::callSetPassword(ulong handle, const string& pw, int x, int y)");
5169
 
5170
    Button::TButton *bt = findButton(handle);
5171
 
5172
    if (!bt)
5173
    {
5174
        MSG_WARNING("callSetPassword: Button " << handleToString(handle) << " not found!");
5175
        return;
5176
    }
5177
 
5178
    string pass = pw;
5179
 
5180
    if (pass.empty())
5181
        pass = "\x01";
5182
 
5183
    bt->setPassword(pass);
5184
    bt->doClick(x, y, true);
5185
    bt->doClick(x, y, false);
5186
}
5187
 
5188
TButtonStates *TPageManager::addButtonState(BUTTONTYPE t, int rap, int rad, int rch, int rcp, int rlp, int rlv)
5189
{
5190
    DECL_TRACER("TPageManager::addButtonState(BUTTONTYPE t, int rap, int rad, int rch, int rcp, int rlp, int rlv)");
5191
 
5192
    TButtonStates *pbs = new TButtonStates(t, rap, rad, rch, rcp, rlp, rlv);
5193
    uint32_t id = pbs->getID();
5194
 
5195
    if (!mButtonStates.empty())
5196
    {
5197
        vector<TButtonStates *>::iterator iter;
5198
 
5199
        for (iter = mButtonStates.begin(); iter != mButtonStates.end(); ++iter)
5200
        {
5201
            TButtonStates *bs = *iter;
5202
 
5203
            if (bs->isButton(t, id))
5204
            {
5205
                delete pbs;
5206
                return bs;
5207
            }
5208
        }
5209
    }
5210
 
5211
    mButtonStates.push_back(pbs);
5212
    return pbs;
5213
}
5214
 
5215
TButtonStates *TPageManager::addButtonState(const TButtonStates& rbs)
5216
{
5217
    DECL_TRACER("TPageManager::addButtonState(const TButtonStates& rbs)");
5218
 
5219
    if (!mButtonStates.empty())
5220
    {
5221
        vector<TButtonStates *>::iterator iter;
5222
        TButtonStates bs = rbs;
5223
        BUTTONTYPE type = bs.getType();
5224
        uint32_t id = bs.getID();
5225
 
5226
        for (iter = mButtonStates.begin(); iter != mButtonStates.end(); ++iter)
5227
        {
5228
            TButtonStates *pbs = *iter;
5229
 
5230
            if (pbs->isButton(type, id))
5231
                return pbs;
5232
        }
5233
    }
5234
 
5235
    TButtonStates *pbs = new TButtonStates(rbs);
5236
    mButtonStates.push_back(pbs);
5237
    return pbs;
5238
}
5239
 
5240
TButtonStates *TPageManager::getButtonState(BUTTONTYPE t, int rap, int rad, int rch, int rcp, int rlp, int rlv)
5241
{
5242
    DECL_TRACER("TPageManager::getButtonState(BUTTONTYPE t, int rap, int rad, int rch, int rcp, int rlp, int rlv)");
5243
 
5244
    if (mButtonStates.empty())
5245
        return nullptr;
5246
 
5247
    vector<TButtonStates *>::iterator iter;
5248
    MSG_DEBUG("Found " << mButtonStates.size() << " button states.");
5249
 
5250
    for (iter = mButtonStates.begin(); iter != mButtonStates.end(); ++iter)
5251
    {
5252
        TButtonStates *bs = *iter;
5253
 
5254
        if (bs->isButton(t, rap, rad, rch, rcp, rlp, rlv))
5255
            return bs;
5256
    }
5257
 
5258
    return nullptr;
5259
}
5260
 
5261
TButtonStates *TPageManager::getButtonState(uint32_t id)
5262
{
5263
    DECL_TRACER("TPageManager::getButtonState(uint32_t id)");
5264
 
5265
    if (mButtonStates.empty())
5266
        return nullptr;
5267
 
5268
    vector<TButtonStates *>::iterator iter;
5269
    MSG_DEBUG("Found " << mButtonStates.size() << " button states.");
5270
 
5271
    for (iter = mButtonStates.begin(); iter != mButtonStates.end(); ++iter)
5272
    {
5273
        TButtonStates *bs = *iter;
5274
 
5275
        if (bs->isButton(id))
5276
            return bs;
5277
    }
5278
 
5279
    return nullptr;
5280
}
5281
 
5282
TButtonStates *TPageManager::getButtonState(BUTTONTYPE t, uint32_t id)
5283
{
5284
    DECL_TRACER("TPageManager::getButtonState(BUTTONTYPE t, uint32_t id)");
5285
 
5286
    if (mButtonStates.empty())
5287
        return nullptr;
5288
 
5289
    vector<TButtonStates *>::iterator iter;
5290
    MSG_DEBUG("Found " << mButtonStates.size() << " button states.");
5291
 
5292
    for (iter = mButtonStates.begin(); iter != mButtonStates.end(); ++iter)
5293
    {
5294
        TButtonStates *bs = *iter;
5295
 
5296
        if (bs->isButton(t, id))
5297
            return bs;
5298
    }
5299
 
5300
    return nullptr;
5301
}
5302
 
5303
void TPageManager::onSwipeEvent(TPageManager::SWIPES sw)
5304
{
5305
    DECL_TRACER("TPageManager::onSwipeEvent(TPageManager::SWIPES sw)");
5306
 
5307
    // Swipes are defined in "external".
5308
    if (!mExternal)
5309
        return;
5310
 
5311
    extButtons_t eBt;
5312
    string dbg;
5313
 
5314
    switch(sw)
5315
    {
5316
        case SW_LEFT:   eBt = EXT_GESTURE_LEFT; dbg.assign("LEFT"); break;
5317
        case SW_RIGHT:  eBt = EXT_GESTURE_RIGHT; dbg.assign("RIGHT"); break;
5318
        case SW_UP:     eBt = EXT_GESTURE_UP; dbg.assign("UP"); break;
5319
        case SW_DOWN:   eBt = EXT_GESTURE_DOWN; dbg.assign("DOWN"); break;
5320
 
5321
        default:
5322
            return;
5323
    }
5324
 
5325
    int pgNum = getActualPageNumber();
5326
    EXTBUTTON_t bt = mExternal->getButton(pgNum, eBt);
5327
 
5328
    if (bt.bi == 0)
5329
        return;
5330
 
5331
    MSG_DEBUG("Received swipe " << dbg << " event for page " << pgNum << " on button " << bt.bi << " \"" << bt.na << "\"");
5332
 
5333
    if (!bt.cm.empty() && bt.co == 0)           // Feed command to ourself?
5334
    {                                           // Yes, then feed it into command queue.
5335
        MSG_DEBUG("Button has a self feed command");
5336
 
5337
        int channel = TConfig::getChannel();
5338
        int system = TConfig::getSystem();
5339
 
5340
        amx::ANET_COMMAND cmd;
5341
        cmd.MC = 0x000c;
5342
        cmd.device1 = channel;
5343
        cmd.port1 = bt.ap;
5344
        cmd.system = system;
5345
        cmd.data.message_string.device = channel;
5346
        cmd.data.message_string.port = bt.ap;  // Must be the address port of button
5347
        cmd.data.message_string.system = system;
5348
        cmd.data.message_string.type = 1;   // 8 bit char string
5349
 
5350
        vector<string>::iterator iter;
5351
 
5352
        for (iter = bt.cm.begin(); iter != bt.cm.end(); ++iter)
5353
        {
5354
            cmd.data.message_string.length = iter->length();
5355
            memset(&cmd.data.message_string.content, 0, sizeof(cmd.data.message_string.content));
5356
            strncpy((char *)&cmd.data.message_string.content, iter->c_str(), sizeof(cmd.data.message_string.content));
5357
            doCommand(cmd);
5358
        }
5359
    }
5360
    else if (!bt.cm.empty())
5361
    {
5362
        MSG_DEBUG("Button sends a command on port " << bt.co);
5363
 
5364
        vector<string>::iterator iter;
5365
 
5366
        for (iter = bt.cm.begin(); iter != bt.cm.end(); ++iter)
5367
            sendCommandString(bt.co, *iter);
5368
    }
5369
}
5370
 
5371
/****************************************************************************
5372
 * The following functions implements one of the commands the panel accepts.
5373
 ****************************************************************************/
5374
 
5375
/**
5376
 * This is a special function handling the progress bars when the files of the
5377
 * panel are updated. Instead of simply displaying a ready page, it fakes one
5378
 * with the actual dimensions of the main page. This is possible, because we've
5379
 * always a main page even if the panel is started for the first time.
5380
 */
5381
void TPageManager::doFTR(int port, vector<int>& channels, vector<string>& pars)
5382
{
5383
    DECL_TRACER("TPageManager::doFTR(int, vector<int>&, vector<string>& pars)");
5384
 
5385
    if (pars.empty())
5386
    {
5387
        MSG_WARNING("Command #FTR needs at least 1 parameter! Ignoring command.");
5388
        return;
5389
    }
5390
 
5391
    if (TStreamError::checkFilter(HLOG_DEBUG))
5392
    {
5393
        for (size_t i = 0; i < pars.size(); i++)
5394
        {
5395
            MSG_DEBUG("[" << i << "]: " << pars.at(i));
5396
        }
5397
    }
5398
 
5399
    if (pars.at(0).compare("START") == 0)
5400
    {
5401
        // Here we have to drop all pages and subpages first and then display
5402
        // the faked page with the progress bars.
5403
        MSG_DEBUG("Starting file transfer ...");
5404
        doPPX(port, channels, pars);
5405
        TPage *pg = getPage("_progress");
5406
 
5407
        if (!pg)
5408
        {
5409
            if (!readPage("_progress"))
5410
            {
5411
                MSG_ERROR("Error creating the system page _progress!");
5412
                return;
5413
            }
5414
 
5415
            pg = getPage("_progress");
5416
 
5417
            if (!pg)
5418
            {
5419
                MSG_ERROR("Error getting system page _progress!");
5420
                return;
5421
            }
5422
        }
5423
 
5424
        pg->setFonts(mFonts);
5425
        pg->registerCallback(_setBackground);
5426
        pg->regCallPlayVideo(_callPlayVideo);
5427
 
5428
        if (!pg || !_setPage || !mTSettings)
5429
            return;
5430
 
5431
        int width, height;
5432
        width = mTSettings->getWidth();
5433
        height = mTSettings->getHeight();
5434
#ifdef _SCALE_SKIA_
5435
        if (mScaleFactor != 1.0)
5436
        {
5437
            width = (int)((double)width * mScaleFactor);
5438
            height = (int)((double)height * mScaleFactor);
5439
        }
5440
#endif
5441
        _setPage((pg->getNumber() << 16) & 0xffff0000, width, height);
5442
        pg->show();
5443
        MSG_DEBUG("Page _progress on screen");
5444
    }
5445
    else if (pars.at(0).compare("SYNC") == 0)
5446
    {
5447
        TPage *pg = getPage("_progress");
5448
 
5449
        if (!pg)
5450
        {
5451
            MSG_ERROR("Page _progress not found!");
5452
            return;
5453
        }
5454
 
5455
        Button::TButton *bt = pg->getButton(1);   // Line 1
5456
 
5457
        if (!bt)
5458
        {
5459
            MSG_ERROR("Button 160 of page _progress not found!");
5460
            return;
5461
        }
5462
 
5463
        bt->setText(pars.at(2), 0);
5464
        bt->show();
5465
    }
5466
    else if (pars.at(0).compare("FTRSTART") == 0)
5467
    {
5468
        TPage *pg = getPage("_progress");
5469
 
5470
        if (!pg)
5471
        {
5472
            MSG_ERROR("Page _progress not found!");
5473
            return;
5474
        }
5475
 
5476
        Button::TButton *bt1 = pg->getButton(1);   // Line 1
5477
        Button::TButton *bt2 = pg->getButton(2);   // Line 2
5478
        Button::TButton *bt3 = pg->getButton(3);   // Bargraph 1
5479
        Button::TButton *bt4 = pg->getButton(4);   // Bargraph 2
5480
 
5481
        if (!bt1 || !bt2 || !bt3 || !bt4)
5482
        {
5483
            MSG_ERROR("Buttons of page _progress not found!");
5484
            return;
5485
        }
5486
 
5487
        bt1->setText("Transfering files ...", 0);
5488
        bt1->show();
5489
        bt2->setText(pars.at(3), 0);
5490
        bt2->show();
5491
        bt3->drawBargraph(0, atoi(pars.at(1).c_str()), true);
5492
        bt4->drawBargraph(0, atoi(pars.at(2).c_str()), true);
5493
    }
5494
    else if (pars.at(0).compare("FTRPART") == 0)
5495
    {
5496
        TPage *pg = getPage("_progress");
5497
 
5498
        if (!pg)
5499
        {
5500
            MSG_ERROR("Page _progress not found!");
5501
            return;
5502
        }
5503
 
5504
        Button::TButton *bt = pg->getButton(4);   // Bargraph 2
5505
 
5506
        if (!bt)
5507
        {
5508
            MSG_ERROR("Buttons of page _progress not found!");
5509
            return;
5510
        }
5511
 
5512
        bt->drawBargraph(0, atoi(pars.at(2).c_str()), true);
5513
    }
5514
    else if (pars.at(0).compare("END") == 0)
5515
    {
5516
        MSG_TRACE("End of file transfer reached.");
5517
 
5518
        // To make sure the new surface will not be deleted and replaced by the
5519
        // default build in surface, we must delete the "virgin" marker first.
5520
        // This is a file called <project path>/.system.
5521
        string virgin = TConfig::getProjectPath() + "/.system";
5522
        remove(virgin.c_str());     // Because this file may not exist we don't care about the result code.
5523
 
5524
        if (_resetSurface)
5525
            _resetSurface();
5526
        else
5527
        {
5528
            MSG_WARNING("Missing callback function \"resetSurface\"!");
5529
        }
5530
    }
5531
}
5532
 
5533
void TPageManager::doLEVON(int, vector<int>&, vector<string>&)
5534
{
5535
    DECL_TRACER("TPageManager::doLEVON(int, vector<int>&, vector<string>&)");
5536
 
5537
    mLevelSend = true;
5538
#if TESTMODE == 1
5539
    __success = true;
5540
    setAllDone();
5541
#endif
5542
}
5543
 
5544
void TPageManager::doLEVOF(int, vector<int>&, vector<string>&)
5545
{
5546
    DECL_TRACER("TPageManager::doLEVOF(int, vector<int>&, vector<string>&)");
5547
 
5548
    mLevelSend = false;
5549
#if TESTMODE == 1
5550
    __success = true;
5551
    setAllDone();
5552
#endif
5553
}
5554
 
5555
void TPageManager::doRXON(int, vector<int>&, vector<string>&)
5556
{
5557
    DECL_TRACER("TPageManager::doRXON(int, vector<int>&, vector<string>&)");
5558
 
5559
    mRxOn = true;
5560
#if TESTMODE == 1
5561
    __success = true;
5562
    setAllDone();
5563
#endif
5564
}
5565
 
5566
void TPageManager::doRXOF(int, vector<int>&, vector<string>&)
5567
{
5568
    DECL_TRACER("TPageManager::doRXOF(int, vector<int>&, vector<string>&)");
5569
 
5570
    mRxOn = false;
5571
#if TESTMODE == 1
5572
    __success = true;
5573
    setAllDone();
5574
#endif
5575
}
5576
 
5577
void TPageManager::doON(int port, vector<int>&, vector<string>& pars)
5578
{
5579
    DECL_TRACER("TPageManager::doON(int port, vector<int>& channels, vector<string>& pars)");
5580
 
5581
    if (pars.empty())
5582
    {
5583
        MSG_WARNING("Command ON needs 1 parameter! Ignoring command.");
5584
#if TESTMODE == 1
5585
        setAllDone();
5586
#endif
5587
        return;
5588
    }
5589
 
5590
    TError::clear();
5591
    int c = atoi(pars[0].c_str());
5592
 
5593
    if (c <= 0)
5594
    {
5595
        MSG_WARNING("Invalid channel " << c << "! Ignoring command.");
5596
#if TESTMODE == 1
5597
        setAllDone();
5598
#endif
5599
        return;
5600
    }
5601
 
5602
    vector<int> chans = { c };
5603
    vector<TMap::MAP_T> map = findButtons(port, chans, TMap::TYPE_CM);
5604
 
5605
    if (TError::isError() || map.empty())
5606
    {
5607
#if TESTMODE == 1
5608
        setAllDone();
5609
#endif
5610
        return;
5611
    }
5612
 
5613
    vector<Button::TButton *> buttons = collectButtons(map);
5614
 
5615
    if (buttons.size() > 0)
5616
    {
5617
        vector<Button::TButton *>::iterator mapIter;
5618
 
5619
        for (mapIter = buttons.begin(); mapIter != buttons.end(); ++mapIter)
5620
        {
5621
            Button::TButton *bt = *mapIter;
5622
 
5623
            if (bt->getButtonType() == GENERAL)
5624
            {
5625
                bt->setActive(1);
5626
#if TESTMODE == 1
5627
                if (_gTestMode)
5628
                    _gTestMode->setResult(intToString(bt->getActiveInstance() + 1));
5629
#endif
5630
            }
5631
        }
5632
    }
5633
#if TESTMODE == 1
5634
    setDone();
5635
#endif
5636
}
5637
 
5638
void TPageManager::doOFF(int port, vector<int>&, vector<string>& pars)
5639
{
5640
    DECL_TRACER("TPageManager::doOFF(int port, vector<int>& channels, vector<string>& pars)");
5641
 
5642
    if (pars.empty())
5643
    {
5644
        MSG_WARNING("Command OFF needs 1 parameter! Ignoring command.");
5645
#if TESTMODE == 1
5646
        setAllDone();
5647
#endif
5648
        return;
5649
    }
5650
 
5651
    TError::clear();
5652
    int c = atoi(pars[0].c_str());
5653
 
5654
    if (c <= 0)
5655
    {
5656
        MSG_WARNING("Invalid channel " << c << "! Ignoring command.");
5657
#if TESTMODE == 1
5658
        setAllDone();
5659
#endif
5660
        return;
5661
    }
5662
 
5663
    vector<int> chans = { c };
5664
    vector<TMap::MAP_T> map = findButtons(port, chans, TMap::TYPE_CM);
5665
 
5666
    if (TError::isError() || map.empty())
5667
        return;
5668
 
5669
    vector<Button::TButton *> buttons = collectButtons(map);
5670
 
5671
    if (buttons.size() > 0)
5672
    {
5673
        vector<Button::TButton *>::iterator mapIter;
5674
 
5675
        for (mapIter = buttons.begin(); mapIter != buttons.end(); ++mapIter)
5676
        {
5677
            Button::TButton *bt = *mapIter;
5678
 
5679
            if (bt->getButtonType() == GENERAL)
5680
                bt->setActive(0);
5681
#if TESTMODE == 1
5682
                if (_gTestMode)
5683
                    _gTestMode->setResult(intToString(bt->getActiveInstance() + 1));
5684
#endif
5685
        }
5686
    }
5687
#if TESTMODE == 1
5688
    setDone();
5689
#endif
5690
}
5691
 
5692
void TPageManager::doLEVEL(int port, vector<int>&, vector<string>& pars)
5693
{
5694
    DECL_TRACER("TPageManager::doLEVEL(int port, vector<int>& channels, vector<string>& pars)");
5695
 
5696
    if (pars.size() < 2)
5697
    {
5698
        MSG_WARNING("Command LEVEL needs 2 parameters! Ignoring command.");
5699
#if TESTMODE == 1
5700
        setAllDone();
5701
#endif
5702
        return;
5703
    }
5704
 
5705
    TError::clear();
5706
    int c = atoi(pars[0].c_str());
5707
    int level = atoi(pars[1].c_str());
5708
 
5709
    if (c <= 0)
5710
    {
5711
        MSG_WARNING("Invalid channel " << c << "! Ignoring command.");
5712
#if TESTMODE == 1
5713
        setAllDone();
5714
#endif
5715
        return;
5716
    }
5717
 
5718
    vector<int> chans = { c };
5719
    vector<TMap::MAP_T> map = findBargraphs(port, chans);
5720
 
5721
    if (TError::isError() || map.empty())
5722
    {
5723
        MSG_WARNING("No bargraphs found!");
5724
#if TESTMODE == 1
5725
        setAllDone();
5726
#endif
5727
        return;
5728
    }
5729
 
5730
    vector<Button::TButton *> buttons = collectButtons(map);
5731
 
5732
    if (buttons.size() > 0)
5733
    {
5734
        MSG_DEBUG("Found " << buttons.size() << " buttons.");
5735
        vector<Button::TButton *>::iterator mapIter;
5736
 
5737
        for (mapIter = buttons.begin(); mapIter != buttons.end(); ++mapIter)
5738
        {
5739
            Button::TButton *bt = *mapIter;
5740
            MSG_DEBUG("Evaluating button " << handleToString(bt->getHandle()))
5741
 
5742
            if (bt->getButtonType() == BARGRAPH && bt->getLevelChannel() == c)
5743
            {
5744
                if (bt->isBargraphInverted())
5745
                    level = (bt->getRangeHigh() - bt->getRangeLow()) - level;
5746
 
5747
                bt->drawBargraph(bt->getActiveInstance(), level);
5748
                bt->sendBargraphLevel();
5749
#if TESTMODE == 1
5750
                if (_gTestMode)
5751
                    _gTestMode->setResult(intToString(bt->getLevelValue()));
5752
#endif
5753
            }
5754
            else if (bt->getButtonType() == JOYSTICK)
5755
            {
5756
                int x = (bt->getLevelChannel() == c ? level : bt->getLevelAxisX());
5757
                int y = (bt->getLevelChannel() == c ? bt->getLevelAxisY() : level);
5758
 
5759
                if (bt->isBargraphInverted())
5760
                    x = (bt->getRangeHigh() - bt->getRangeLow()) - x;
5761
 
5762
                if (bt->isJoystickAuxInverted())
5763
                    y = (bt->getRangeHigh() - bt->getRangeLow()) - y;
5764
 
5765
                bt->drawJoystick(x, y);
5766
                bt->sendJoystickLevels();
5767
#if TESTMODE == 1
5768
                if (_gTestMode)
5769
                {
5770
                    std::stringstream s;
5771
                    s << x << "|" << y;
5772
                    _gTestMode->setResult(s.str());
5773
                }
5774
#endif
5775
            }
5776
            else if (bt->getButtonType() == MULTISTATE_BARGRAPH && bt->getLevelChannel() == c)
5777
            {
5778
                int state = (int)((double)bt->getStateCount() / (double)(bt->getRangeHigh() - bt->getRangeLow()) * (double)level);
5779
                bt->setActive(state);
5780
                bt->sendBargraphLevel();
5781
#if TESTMODE == 1
5782
                if (_gTestMode)
5783
                    _gTestMode->setResult(intToString(bt->getActiveInstance()));
5784
#endif
5785
            }
5786
        }
5787
    }
5788
    else
5789
        MSG_DEBUG("No buttons found!");
5790
 
5791
#if TESTMODE == 1
5792
    setDone();
5793
#endif
5794
}
5795
 
5796
void TPageManager::doBLINK(int, vector<int>&, vector<string>& pars)
5797
{
5798
    DECL_TRACER("TPageManager::doBLINK(int port, vector<int>& channels, vector<string>& pars)");
5799
 
5800
    if (pars.size() < 4)
5801
    {
5802
        MSG_WARNING("Command BLINK expects 4 parameters! Command ignored.");
5803
#if TESTMODE == 1
5804
        setAllDone();
5805
#endif
5806
        return;
5807
    }
5808
 
5809
    TError::clear();
5810
    vector<int> sysButtons = { 141, 142, 143, 151, 152, 153, 154, 155, 156, 157, 158 };
5811
    vector<TMap::MAP_T> map = findButtons(0, sysButtons);
5812
 
5813
    if (TError::isError() || map.empty())
5814
    {
5815
        MSG_WARNING("No system buttons found.");
5816
#if TESTMODE == 1
5817
        setAllDone();
5818
#endif
5819
        return;
5820
    }
5821
 
5822
    vector<Button::TButton *> buttons = collectButtons(map);
5823
    vector<Button::TButton *>::iterator mapIter;
5824
 
5825
    for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
5826
    {
5827
        Button::TButton *bt = *mapIter;
5828
        bt->setActive(0);
5829
#if TESTMODE == 1
5830
                if (_gTestMode)
5831
                    _gTestMode->setResult(intToString(bt->getActiveInstance() + 1));
5832
#endif
5833
    }
5834
#if TESTMODE == 1
5835
    setDone();
5836
#endif
5837
}
5838
 
5839
/**
5840
 * Send the version of the panel to the NetLinx. This is the real application
5841
 * version.
5842
 */
5843
void TPageManager::doVER(int, vector<int>&, vector<string>&)
5844
{
5845
    DECL_TRACER("TPageManager::doVER(int, vector<int>&, vector<string>&)");
5846
 
5847
    amx::ANET_SEND scmd;
5848
    scmd.port = 1;
5849
    scmd.channel = 0;
5850
    scmd.msg.assign(string("^VER-")+VERSION_STRING());
5851
    scmd.MC = 0x008c;
5852
 
5853
    if (gAmxNet)
5854
    {
5855
        gAmxNet->sendCommand(scmd);
5856
#if TESTMODE == 1
5857
        __success = true;
5858
 
5859
        if (_gTestMode)
5860
            _gTestMode->setResult(VERSION_STRING());
5861
#endif
5862
    }
5863
    else
5864
        MSG_WARNING("Missing global class TAmxNet. Can't send message!");
5865
#if TESTMODE == 1
5866
    setAllDone();
5867
#endif
5868
}
5869
 
5870
/**
5871
 * Returns the user name used to connect to a SIP server. An empty string is
5872
 * returned if there is no user defined.
5873
 */
5874
#ifndef _NOSIP_
5875
void TPageManager::doWCN(int, vector<int>&, vector<string>&)
5876
{
5877
    DECL_TRACER("TPageManager::doWCN(int, vector<int>&, vector<string>&)");
5878
 
5879
    if (!TConfig::getSIPstatus())
5880
    {
5881
#if TESTMODE == 1
5882
        setAllDone();
5883
#endif
5884
        return;
5885
    }
5886
 
5887
    amx::ANET_SEND scmd;
5888
    scmd.port = 1;
5889
    scmd.channel = 0;
5890
    scmd.msg.assign("^WCN-" + TConfig::getSIPuser());
5891
    scmd.MC = 0x008c;
5892
 
5893
    if (gAmxNet)
5894
    {
5895
        gAmxNet->sendCommand(scmd);
5896
#if TESTMODE == 1
5897
        __success = true;
5898
 
5899
        if (_gTestMode)
5900
            _gTestMode->setResult(TConfig::getSIPuser());
5901
#endif
5902
    }
5903
    else
5904
        MSG_WARNING("Missing global class TAmxNet. Can't send message!");
5905
#if TESTMODE == 1
5906
        setAllDone();
5907
#endif
5908
}
5909
#endif
5910
/**
5911
 * Flip to specified page using the named animation.
5912
 * FIXME: Implement animation for pages.
5913
 */
5914
void TPageManager::doAFP(int, vector<int>&, vector<string>& pars)
5915
{
5916
    DECL_TRACER("TPageManager::doAFP(int, vector<int>&, vector<string>& pars)");
5917
 
5918
    if (pars.size() < 4)
5919
    {
5920
        MSG_ERROR("Less than 4 parameters!");
5921
#if TESTMODE == 1
5922
        setAllDone();
5923
#endif
5924
        return;
5925
    }
5926
 
5927
    TError::clear();
5928
    string pname = pars[0];
5929
//    string ani = pars[1];
5930
//    int origin = atoi(pars[2].c_str());
5931
//    int duration = atoi(pars[3].c_str());
5932
 
5933
    // FIXME: Animation of pages is currently not implemented.
5934
 
5935
    if (!pname.empty())
5936
        setPage(pname);
5937
    else if (mPreviousPage)
5938
        setPage(mPreviousPage);
5939
#if TESTMODE == 1
5940
    if (_gTestMode)
5941
        _gTestMode->setResult(getActualPage()->getName());
5942
 
5943
    setDone();
5944
#endif
5945
}
5946
 
5947
/**
5948
 * Add a specific popup page to a specified popup group if it does not already
5949
 * exist. If the new popup is added to a group which has a popup displayed on
5950
 * the current page along with the new pop-up, the displayed popup will be
5951
 * hidden and the new popup will be displayed.
5952
 */
5953
void TPageManager::doAPG(int, std::vector<int>&, std::vector<std::string>& pars)
5954
{
5955
    DECL_TRACER("TPageManager::doAPG(int port, std::vector<int>& channels, std::vector<std::string>& pars)");
5956
 
5957
    if (pars.size() < 2)
5958
    {
5959
        MSG_ERROR("Less than 2 parameters!");
5960
#if TESTMODE == 1
5961
        setAllDone();
5962
#endif
5963
        return;
5964
    }
5965
 
5966
    TError::clear();
5967
    closeGroup(pars[1]);
5968
 
5969
    TPage *page = nullptr;
5970
    TSubPage *subPage = deliverSubPage(pars[0], &page);
5971
 
5972
    if (!subPage)
5973
    {
5974
        MSG_ERROR("Subpage " << pars[0] << " couldn't either found or created!");
5975
#if TESTMODE == 1
5976
        setAllDone();
5977
#endif
5978
        return;
5979
    }
5980
 
5981
    if (!page)
5982
    {
5983
        MSG_ERROR("There seems to be no page for subpage " << pars[0]);
5984
#if TESTMODE == 1
5985
        setAllDone();
5986
#endif
5987
        return;
5988
    }
5989
 
5990
    page->addSubPage(subPage);
5991
    subPage->setGroup(pars[1]);
5992
    subPage->setZOrder(page->getNextZOrder());
5993
    MSG_DEBUG("Setting new Z-order " << page->getActZOrder() << " on page " << page->getName());
5994
    subPage->show();
5995
#if TESTMODE == 1
5996
    if (_gTestMode)
5997
        _gTestMode->setResult(subPage->getGroupName() + ":" + subPage->getName());
5998
 
5999
    setDone();
6000
#endif
6001
}
6002
 
6003
/**
6004
 * Clear all popup pages from specified popup group.
6005
 */
6006
void TPageManager::doCPG(int, std::vector<int>&, std::vector<std::string>& pars)
6007
{
6008
    DECL_TRACER("TPageManager::doCPG(int port, std::vector<int>& channels, std::vector<std::string>& pars)");
6009
 
6010
    if (pars.size() < 1)
6011
    {
6012
        MSG_ERROR("Expecting 1 parameter but got only 1!");
6013
#if TESTMODE == 1
6014
        setAllDone();
6015
#endif
6016
        return;
6017
    }
6018
 
6019
    TError::clear();
6020
    vector<SUBPAGELIST_T> pageList = mPageList->getSubPageList();
6021
 
6022
    if (pageList.size() > 0)
6023
    {
6024
        vector<SUBPAGELIST_T>::iterator pgIter;
6025
 
6026
        for (pgIter = pageList.begin(); pgIter != pageList.end(); pgIter++)
6027
        {
6028
            if (pgIter->group.compare(pars[0]) == 0)
6029
            {
6030
                pgIter->group.clear();
6031
                TSubPage *pg = getSubPage(pgIter->pageID);
6032
 
6033
                if (pg)
6034
                    pg->setGroup(pgIter->group);
6035
#if TESTMODE == 1
6036
                __success = true;
6037
#endif
6038
            }
6039
        }
6040
    }
6041
#if TESTMODE == 1
6042
    setDone();
6043
#endif
6044
}
6045
 
6046
/**
6047
 * Delete a specific popup page from specified popup group if it exists.
6048
 */
6049
void TPageManager::doDPG(int, std::vector<int>&, std::vector<std::string>& pars)
6050
{
6051
    DECL_TRACER("TPageManager::doDPG(int port, std::vector<int>& channels, std::vector<std::string>& pars)");
6052
 
6053
    if (pars.size() < 2)
6054
    {
6055
        MSG_ERROR("Less than 2 parameters!");
6056
#if TESTMODE == 1
6057
        setAllDone();
6058
#endif
6059
        return;
6060
    }
6061
 
6062
    TError::clear();
6063
    SUBPAGELIST_T listPg = findSubPage(pars[0]);
6064
 
6065
    if (!listPg.isValid)
6066
    {
6067
#if TESTMODE == 1
6068
        setAllDone();
6069
#endif
6070
        return;
6071
    }
6072
 
6073
    if (listPg.group.compare(pars[1]) == 0)
6074
    {
6075
        listPg.group.clear();
6076
        TSubPage *pg = getSubPage(listPg.pageID);
6077
 
6078
        if (pg)
6079
            pg->setGroup(listPg.group);
6080
#if TESTMODE == 1
6081
        __success = true;
6082
#endif
6083
    }
6084
#if TESTMODE == 1
6085
    setDone();
6086
#endif
6087
}
6088
 
6089
/**
6090
 * Set the hide effect for the specified popup page to the named hide effect.
6091
 */
6092
void TPageManager::doPHE(int, vector<int>&, vector<string>& pars)
6093
{
6094
    DECL_TRACER("TPageManager::doPHE(int port, vector<int>& channels, vector<string>& pars)");
6095
 
6096
    if (pars.size() < 2)
6097
    {
6098
        MSG_ERROR("Less than 2 parameters!");
6099
#if TESTMODE == 1
6100
        setAllDone();
6101
#endif
6102
        return;
6103
    }
6104
 
6105
    TError::clear();
6106
    TSubPage *pg = deliverSubPage(pars[0]);
6107
 
6108
    if (!pg)
6109
    {
6110
#if TESTMODE == 1
6111
        setAllDone();
6112
#endif
6113
        return;
6114
    }
6115
 
6116
    if (strCaseCompare(pars[1], "fade") == 0)
6117
        pg->setHideEffect(SE_FADE);
6118
    else if (strCaseCompare(pars[1], "slide to left") == 0)
6119
        pg->setHideEffect(SE_SLIDE_LEFT);
6120
    else if (strCaseCompare(pars[1], "slide to right") == 0)
6121
        pg->setHideEffect(SE_SLIDE_RIGHT);
6122
    else if (strCaseCompare(pars[1], "slide to top") == 0)
6123
        pg->setHideEffect(SE_SLIDE_TOP);
6124
    else if (strCaseCompare(pars[1], "slide to bottom") == 0)
6125
        pg->setHideEffect(SE_SLIDE_BOTTOM);
6126
    else if (strCaseCompare(pars[1], "slide to left fade") == 0)
6127
        pg->setHideEffect(SE_SLIDE_LEFT_FADE);
6128
    else if (strCaseCompare(pars[1], "slide to right fade") == 0)
6129
        pg->setHideEffect(SE_SLIDE_RIGHT_FADE);
6130
    else if (strCaseCompare(pars[1], "slide to top fade") == 0)
6131
        pg->setHideEffect(SE_SLIDE_TOP_FADE);
6132
    else if (strCaseCompare(pars[1], "slide to bottom fade") == 0)
6133
        pg->setHideEffect(SE_SLIDE_BOTTOM_FADE);
6134
    else
6135
        pg->setHideEffect(SE_NONE);
6136
#if TESTMODE == 1
6137
    if (_gTestMode)
6138
        _gTestMode->setResult(intToString(pg->getHideEffect()));
6139
 
6140
    __success = true;
6141
    setAllDone();
6142
#endif
6143
}
6144
 
6145
/**
6146
 * Set the hide effect position. Only 1 coordinate is ever needed for an effect;
6147
 * however, the command will specify both. This command sets the location at
6148
 * which the effect will end at.
6149
 */
6150
void TPageManager::doPHP(int, vector<int>&, vector<string>& pars)
6151
{
6152
    DECL_TRACER("TPageManager::doPHP(int port, vector<int>& channels, vector<string>& pars)");
6153
 
6154
    if (pars.size() < 2)
6155
    {
6156
        MSG_ERROR("Less than 2 parameters!");
6157
#if TESTMODE == 1
6158
        setAllDone();
6159
#endif
6160
        return;
6161
    }
6162
 
6163
    TError::clear();
6164
    size_t pos = pars[1].find(",");
6165
    int x, y;
6166
 
6167
    if (pos == string::npos)
6168
    {
6169
        x = atoi(pars[1].c_str());
6170
        y = 0;
6171
    }
6172
    else
6173
    {
6174
        x = atoi(pars[1].substr(0, pos).c_str());
6175
        y = atoi(pars[1].substr(pos+1).c_str());
6176
    }
6177
 
6178
    TSubPage *pg = deliverSubPage(pars[0]);
6179
 
6180
    if (!pg)
6181
    {
6182
#if TESTMODE == 1
6183
        setAllDone();
6184
#endif
6185
        return;
6186
    }
6187
 
6188
    pg->setHideEndPosition(x, y);
6189
#if TESTMODE == 1
6190
    if (_gTestMode)
6191
    {
6192
        int x, y;
6193
        pg->getHideEndPosition(&x, &y);
6194
        _gTestMode->setResult(intToString(x) + "," + intToString(y));
6195
    }
6196
 
6197
    __success = true;
6198
    setAllDone();
6199
#endif
6200
}
6201
 
6202
/**
6203
 * Set the hide effect time for the specified popup page.
6204
 */
6205
void TPageManager::doPHT(int, vector<int>&, vector<string>& pars)
6206
{
6207
    DECL_TRACER("TPageManager::doPHT(int port, vector<int>& channels, vector<string>& pars)");
6208
 
6209
    if (pars.size() < 2)
6210
    {
6211
        MSG_ERROR("Less than 2 parameters!");
6212
#if TESTMODE == 1
6213
        setAllDone();
6214
#endif
6215
        return;
6216
    }
6217
 
6218
    TError::clear();
6219
    TSubPage *pg = deliverSubPage(pars[0]);
6220
 
6221
    if (!pg)
6222
    {
6223
#if TESTMODE == 1
6224
        setAllDone();
6225
#endif
6226
        return;
6227
    }
6228
 
6229
    pg->setHideTime(atoi(pars[1].c_str()));
6230
#if TESTMODE == 1
6231
    if (_gTestMode)
6232
        _gTestMode->setResult(intToString(pg->getHideTime()));
6233
 
6234
    __success = true;
6235
    setAllDone();
6236
#endif
6237
}
6238
 
6239
/**
6240
 * Close all popups on a specified page. If the page name is empty, the current
6241
 * page is used. Same as the ’Clear Page’ command in TPDesign4.
6242
 */
6243
void TPageManager::doPPA(int, std::vector<int>&, std::vector<std::string>& pars)
6244
{
6245
    DECL_TRACER("TPageManager::doPPA(int port, std::vector<int>& channels, std::vector<std::string>& pars)");
6246
 
6247
    TError::clear();
6248
    TPage *pg;
6249
 
6250
    if (pars.size() == 0)
6251
        pg = getPage(mActualPage);
6252
    else
6253
        pg = getPage(pars[0]);
6254
 
6255
    if (!pg)
6256
    {
6257
#if TESTMODE == 1
6258
        setAllDone();
6259
#endif
6260
        return;
6261
    }
6262
 
6263
    pg->drop();
6264
    pg->resetZOrder();
6265
#if TESTMODE == 1
6266
    setDone();
6267
#endif
6268
}
6269
 
6270
/**
6271
 * Deactivate a specific popup page on either a specified page or the current
6272
 * page. If the page name is empty, the current page is used. If the popup page
6273
 * is part of a group, the whole group is deactivated. This command works in
6274
 * the same way as the ’Hide Popup’ command in TPDesign4.
6275
 */
6276
void TPageManager::doPPF(int, std::vector<int>&, std::vector<std::string>& pars)
6277
{
6278
    DECL_TRACER("TPageManager::doPPF(int port, std::vector<int>& channels, std::vector<std::string>& pars)");
6279
 
6280
    if (pars.size() < 1)
6281
    {
6282
        MSG_ERROR("At least 1 parameter is expected!");
6283
#if TESTMODE == 1
6284
        setAllDone();
6285
#endif
6286
        return;
6287
    }
6288
 
6289
    TError::clear();
6290
    hideSubPage(pars[0]);
6291
#if TESTMODE == 1
6292
    setDone();
6293
#endif
6294
}
6295
 
6296
/**
6297
 * Toggle a specific popup page on either a specified page or the current page.
6298
 * If the page name is empty, the current page is used. Toggling refers to the
6299
 * activating/deactivating (On/Off) of a popup page. This command works in the
6300
 * same way as the ’Toggle Popup’ command in TPDesign4.
6301
 */
6302
void TPageManager::doPPG(int, std::vector<int>&, std::vector<std::string>& pars)
6303
{
6304
    DECL_TRACER("TPageManager::doPPG(int port, std::vector<int>& channels, std::vector<std::string>& pars)");
6305
 
6306
    if (pars.size() < 1)
6307
    {
6308
        MSG_ERROR("At least 1 parameter is expected!");
6309
#if TESTMODE == 1
6310
        setAllDone();
6311
#endif
6312
        return;
6313
    }
6314
 
6315
    TError::clear();
6316
    TPage *page = getPage(mActualPage);
6317
 
6318
    if (!page)
6319
    {
6320
        MSG_ERROR("No active page found! Internal error.");
6321
#if TESTMODE == 1
6322
        setAllDone();
6323
#endif
6324
        return;
6325
    }
6326
 
6327
    TSubPage *pg = getSubPage(pars[0]);
6328
 
6329
    if (!pg)
6330
    {
6331
#if TESTMODE == 1
6332
        setAllDone();
6333
#endif
6334
        return;
6335
    }
6336
 
6337
    if (pg->isVisible())
6338
    {
6339
        pg->drop();
6340
        page->decZOrder();
6341
#if TESTMODE == 1
6342
        setDone();
6343
#endif
6344
        return;
6345
    }
6346
 
6347
    TSubPage *sub = getFirstSubPageGroup(pg->getGroupName());
6348
 
6349
    while(sub)
6350
    {
6351
        if (sub->getGroupName().compare(pg->getGroupName()) == 0 && sub->isVisible())
6352
            sub->drop();
6353
 
6354
        sub = getNextSubPageGroup(pg->getGroupName(), sub);
6355
    }
6356
 
6357
    pg->setZOrder(page->getNextZOrder());
6358
    MSG_DEBUG("Setting new Z-order " << page->getActZOrder() << " on page " << page->getName());
6359
    pg->show();
6360
#if TESTMODE == 1
6361
    setDone();
6362
#endif
6363
}
6364
 
6365
/**
6366
 * Kill refers to the deactivating (Off) of a popup window from all pages. If
6367
 * the pop-up page is part of a group, the whole group is deactivated. This
6368
 * command works in the same way as the 'Clear Group' command in TPDesign 4.
6369
 */
6370
void TPageManager::doPPK(int, std::vector<int>&, std::vector<std::string>& pars)
6371
{
6372
    DECL_TRACER("TPageManager::doPPK(int port, std::vector<int>& channels, std::vector<std::string>& pars)");
6373
 
6374
    if (pars.size() < 1)
6375
    {
6376
        MSG_ERROR("At least 1 parameter is expected!");
6377
#if TESTMODE == 1
6378
        setAllDone();
6379
#endif
6380
        return;
6381
    }
6382
 
6383
    TError::clear();
6384
    TPage *page = getPage(mActualPage);
6385
 
6386
    if (!page)
6387
    {
6388
        MSG_ERROR("No active page found! Internal error.");
6389
#if TESTMODE == 1
6390
        setAllDone();
6391
#endif
6392
        return;
6393
    }
6394
 
6395
    TSubPage *pg = getSubPage(pars[0]);
6396
 
6397
    if (pg)
6398
    {
6399
        pg->drop();
6400
        page->decZOrder();
6401
    }
6402
#if TESTMODE == 1
6403
        setDone();
6404
#endif
6405
}
6406
 
6407
/**
6408
 * Set the modality of a specific popup page to Modal or NonModal.
6409
 * A Modal popup page, when active, only allows you to use the buttons and
6410
 * features on that popup page. All other buttons on the panel page are
6411
 * inactivated.
6412
 */
6413
void TPageManager::doPPM(int, std::vector<int>&, std::vector<std::string>& pars)
6414
{
6415
    DECL_TRACER("TPageManager::doPPM(int port, std::vector<int>& channels, std::vector<std::string>& pars)");
6416
 
6417
    if (pars.size() < 2)
6418
    {
6419
        MSG_ERROR("Expecting 2 parameters!");
6420
#if TESTMODE == 1
6421
        setAllDone();
6422
#endif
6423
        return;
6424
    }
6425
 
6426
    TError::clear();
6427
    TSubPage *pg = getSubPage(pars[0]);
6428
 
6429
    if (pg)
6430
    {
6431
        if (pars[1] == "1" || strCaseCompare(pars[1], "modal") == 0)
6432
            pg->setModal(1);
6433
        else
6434
            pg->setModal(0);
6435
#if TESTMODE == 1
6436
        if (_gTestMode)
6437
            _gTestMode->setResult(pg->isModal() ? "TRUE" : "FALSE");
6438
#endif
6439
    }
6440
#if TESTMODE == 1
6441
        setAllDone();
6442
#endif
6443
}
6444
 
6445
/**
6446
 * Activate a specific popup page to launch on either a specified page or the
6447
 * current page. If the page name is empty, the current page is used. If the
6448
 * popup page is already on, do not re-draw it. This command works in the same
6449
 * way as the ’Show Popup’ command in TPDesign4.
6450
 */
6451
void TPageManager::doPPN(int, std::vector<int>&, std::vector<std::string>& pars)
6452
{
6453
    DECL_TRACER("TPageManager::doPPN(int port, std::vector<int>& channels, std::vector<std::string>& pars)");
6454
 
6455
    if (pars.size() < 1)
6456
    {
6457
        MSG_ERROR("At least 1 parameter is expected!");
6458
#if TESTMODE == 1
6459
        setAllDone();
6460
#endif
6461
        return;
6462
    }
6463
 
6464
    TError::clear();
6465
    showSubPage(pars[0]);
6466
#if TESTMODE == 1
6467
    setDone();
6468
#endif
6469
}
6470
 
6471
/**
6472
 * Set a specific popup page to timeout within a specified time. If timeout is
6473
 * empty, popup page will clear the timeout.
6474
 */
6475
void TPageManager::doPPT(int, vector<int>&, vector<string>& pars)
6476
{
6477
    DECL_TRACER("TPageManager::doPPT(int port, vector<int>& channels, vector<string>& pars)");
6478
 
6479
    if (pars.size() < 2)
6480
    {
6481
        MSG_ERROR("Expecting 2 parameters!");
6482
#if TESTMODE == 1
6483
        setAllDone();
6484
#endif
6485
        return;
6486
    }
6487
 
6488
    TError::clear();
6489
    TSubPage *pg = deliverSubPage(pars[0]);
6490
 
6491
    if (!pg)
6492
    {
6493
#if TESTMODE == 1
6494
        setAllDone();
6495
#endif
6496
        return;
6497
    }
6498
 
6499
    pg->setTimeout(atoi(pars[1].c_str()));
6500
#if TESTMODE == 1
6501
    if (_gTestMode)
6502
        _gTestMode->setResult(intToString(pg->getTimeout()));
6503
 
6504
    __success = true;
6505
    setAllDone();
6506
#endif
6507
}
6508
 
6509
/**
6510
 * Close all popups on all pages. This command works in the same way as the
6511
 * 'Clear All' command in TPDesign 4.
6512
 */
6513
void TPageManager::doPPX(int, std::vector<int>&, std::vector<std::string>&)
6514
{
6515
    DECL_TRACER("TPageManager::doPPX(int port, std::vector<int>& channels, std::vector<std::string>& pars)");
6516
 
6517
    TError::clear();
6518
    PCHAIN_T *chain = mPchain;
6519
 
6520
    while(chain)
6521
    {
6522
        TSubPage *sub = chain->page->getFirstSubPage();
6523
 
6524
        while (sub)
6525
        {
6526
            MSG_DEBUG("Dropping subpage " << sub->getNumber() << ", \"" << sub->getName() << "\".");
6527
            sub->drop();
6528
            sub = chain->page->getNextSubPage();
6529
        }
6530
 
6531
        chain = chain->next;
6532
    }
6533
 
6534
    TPage *page = getPage(mActualPage);
6535
 
6536
    if (!page)
6537
    {
6538
        MSG_ERROR("No active page found! Internal error.");
6539
#if TESTMODE == 1
6540
        setAllDone();
6541
#endif
6542
        return;
6543
    }
6544
 
6545
    page->resetZOrder();
6546
#if TESTMODE == 1
6547
    setDone();
6548
#endif
6549
}
6550
 
6551
/**
6552
 * Set the show effect for the specified popup page to the named show effect.
6553
 */
6554
void TPageManager::doPSE(int, vector<int>&, vector<string>& pars)
6555
{
6556
    DECL_TRACER("TPageManager::doPSE(int port, vector<int>& channels, vector<string>& pars)");
6557
 
6558
    if (pars.size() < 2)
6559
    {
6560
        MSG_ERROR("Less than 2 parameters!");
6561
#if TESTMODE == 1
6562
        setAllDone();
6563
#endif
6564
        return;
6565
    }
6566
 
6567
    TError::clear();
6568
    TSubPage *pg = deliverSubPage(pars[0]);
6569
 
6570
    if (!pg)
6571
    {
6572
#if TESTMODE == 1
6573
        setAllDone();
6574
#endif
6575
        return;
6576
    }
6577
 
6578
    if (strCaseCompare(pars[1], "fade") == 0)
6579
        pg->setShowEffect(SE_FADE);
6580
    else if (strCaseCompare(pars[1], "slide to left") == 0)
6581
        pg->setShowEffect(SE_SLIDE_LEFT);
6582
    else if (strCaseCompare(pars[1], "slide to right") == 0)
6583
        pg->setShowEffect(SE_SLIDE_RIGHT);
6584
    else if (strCaseCompare(pars[1], "slide to top") == 0)
6585
        pg->setShowEffect(SE_SLIDE_TOP);
6586
    else if (strCaseCompare(pars[1], "slide to bottom") == 0)
6587
        pg->setShowEffect(SE_SLIDE_BOTTOM);
6588
    else if (strCaseCompare(pars[1], "slide to left fade") == 0)
6589
        pg->setShowEffect(SE_SLIDE_LEFT_FADE);
6590
    else if (strCaseCompare(pars[1], "slide to right fade") == 0)
6591
        pg->setShowEffect(SE_SLIDE_RIGHT_FADE);
6592
    else if (strCaseCompare(pars[1], "slide to top fade") == 0)
6593
        pg->setShowEffect(SE_SLIDE_TOP_FADE);
6594
    else if (strCaseCompare(pars[1], "slide to bottom fade") == 0)
6595
        pg->setShowEffect(SE_SLIDE_BOTTOM_FADE);
6596
    else
6597
        pg->setShowEffect(SE_NONE);
6598
#if TESTMODE == 1
6599
    if (_gTestMode)
6600
        _gTestMode->setResult(intToString(pg->getShowEffect()));
6601
 
6602
    __success = true;
6603
    setAllDone();
6604
#endif
6605
}
6606
 
6607
/**
6608
 * Set the show effect position. Only 1 coordinate is ever needed for an effect;
6609
 * however, the command will specify both. This command sets the location at
6610
 * which the effect will begin.
6611
 */
6612
void TPageManager::doPSP(int, vector<int>&, vector<string>& pars)
6613
{
6614
    DECL_TRACER("TPageManager::doPSP(int port, vector<int>& channels, vector<string>& pars)");
6615
 
6616
    if (pars.size() < 2)
6617
    {
6618
        MSG_ERROR("Less than 2 parameters!");
6619
#if TESTMODE == 1
6620
        setAllDone();
6621
#endif
6622
        return;
6623
    }
6624
 
6625
    TError::clear();
6626
    size_t pos = pars[1].find(",");
6627
    int x, y;
6628
 
6629
    if (pos == string::npos)
6630
    {
6631
        x = atoi(pars[1].c_str());
6632
        y = 0;
6633
    }
6634
    else
6635
    {
6636
        x = atoi(pars[1].substr(0, pos).c_str());
6637
        y = atoi(pars[1].substr(pos+1).c_str());
6638
    }
6639
 
6640
    TSubPage *pg = deliverSubPage(pars[0]);
6641
 
6642
    if (!pg)
6643
    {
6644
#if TESTMODE == 1
6645
        setAllDone();
6646
#endif
6647
        return;
6648
    }
6649
 
6650
    pg->setShowEndPosition(x, y);
6651
#if TESTMODE == 1
6652
    pg->getShowEndPosition(&x, &y);
6653
 
6654
    if (_gTestMode)
6655
        _gTestMode->setResult(intToString(x) + "," + intToString(y));
6656
 
6657
    __success = true;
6658
    setAllDone();
6659
#endif
6660
}
6661
 
6662
/**
6663
 * Set the show effect time for the specified popup page.
6664
 */
6665
void TPageManager::doPST(int, vector<int>&, vector<string>& pars)
6666
{
6667
    DECL_TRACER("TPageManager::doPST(int port, vector<int>& channels, vector<string>& pars)");
6668
 
6669
    if (pars.size() < 2)
6670
    {
6671
        MSG_ERROR("Less than 2 parameters!");
6672
#if TESTMODE == 1
6673
        setAllDone();
6674
#endif
6675
        return;
6676
    }
6677
 
6678
    TError::clear();
6679
    TSubPage *pg = deliverSubPage(pars[0]);
6680
 
6681
    if (!pg)
6682
    {
6683
#if TESTMODE == 1
6684
        setAllDone();
6685
#endif
6686
        return;
6687
    }
6688
 
6689
    pg->setShowTime(atoi(pars[1].c_str()));
6690
#if TESTMODE == 1
6691
    if (_gTestMode)
6692
        _gTestMode->setResult(intToString(pg->getShowTime()));
6693
 
6694
    __success = 1;
6695
    setAllDone();
6696
#endif
6697
}
6698
 
6699
/**
6700
 * Flips to a page with a specified page name. If the page is currently active,
6701
 * it will not redraw the page.
6702
 */
6703
void TPageManager::doPAGE(int, std::vector<int>&, std::vector<std::string>& pars)
6704
{
6705
    DECL_TRACER("TPageManager::doPAGE(int port, std::vector<int>& channels, std::vector<std::string>& pars)");
6706
 
6707
    if (pars.empty())
6708
    {
6709
        MSG_WARNING("Got no page parameter!");
6710
#if TESTMODE == 1
6711
        setAllDone();
6712
#endif
6713
        return;
6714
    }
6715
 
6716
    TError::clear();
6717
    setPage(pars[0]);
6718
#if TESTMODE == 1
6719
    if (_gTestMode)
6720
        _gTestMode->setResult(intToString(getActualPageNumber()));
6721
 
6722
    setDone();
6723
#endif
6724
}
6725
 
6726
/**
6727
 * @brief TPageManager::doANI Run a button animation (in 1/10 second).
6728
 * Syntax:
6729
 *      ^ANI-<vt addr range>,<start state>,<end state>,<time>
6730
 * Variable:
6731
 *      variable text address range = 1 - 4000.
6732
 *      start state = Beginning of button state (0= current state).
6733
 *      end state = End of button state.
6734
 *      time = In 1/10 second intervals.
6735
 * Example:
6736
 *      SEND_COMMAND Panel,"'^ANI-500,1,25,100'"
6737
 * Runs a button animation at text range 500 from state 1 to state 25 for 10 seconds.
6738
 *
6739
 * @param port      The port number
6740
 * @param channels  The channels of the buttons
6741
 * @param pars      The parameters
6742
 */
6743
void TPageManager::doANI(int port, std::vector<int> &channels, std::vector<std::string> &pars)
6744
{
6745
    DECL_TRACER("TPageManager::doANI(int port, std::vector<int> &channels, std::vector<std::string> &pars)");
6746
 
6747
    if (pars.size() < 3)
6748
    {
6749
        MSG_ERROR("Expecting 3 parameters but got " << pars.size() << "! Ignoring command.");
6750
        return;
6751
    }
6752
 
6753
    TError::clear();
6754
    int stateStart = atoi(pars[0].c_str());
6755
    int endState = atoi(pars[1].c_str());
6756
    int runTime = atoi(pars[2].c_str());
6757
 
6758
    vector<TMap::MAP_T> map = findButtons(port, channels);
6759
 
6760
    if (TError::isError() || map.empty())
6761
        return;
6762
 
6763
    vector<Button::TButton *> buttons = collectButtons(map);
6764
 
6765
    if (buttons.size() > 0)
6766
    {
6767
        vector<Button::TButton *>::iterator mapIter;
6768
 
6769
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
6770
        {
6771
            Button::TButton *bt = *mapIter;
6772
            bt->startAnimation(stateStart, endState, runTime);
6773
        }
6774
    }
6775
#if TESTMODE == 1
6776
    if (_gTestMode)
6777
        _gTestMode->setResult(intToString(stateStart) + "," + intToString(endState) + "," + intToString(runTime));
6778
 
6779
    setDone();
6780
#endif
6781
}
6782
 
6783
/**
6784
 * Add page flip action to a button if it does not already exist.
6785
 */
6786
void TPageManager::doAPF(int port, vector<int>& channels, vector<string>& pars)
6787
{
6788
    DECL_TRACER("TPageManager::doAPF(int port, vector<int>& channels, vector<string>& pars)");
6789
 
6790
    if (pars.size() < 2)
6791
    {
6792
        MSG_ERROR("Expecting 2 parameters but got " << pars.size() << "! Ignoring command.");
6793
#if TESTMODE == 1
6794
        setAllDone();
6795
#endif
6796
        return;
6797
    }
6798
 
6799
    TError::clear();
6800
    string action = pars[0];
6801
    string pname = pars[1];
6802
 
6803
    vector<TMap::MAP_T> map = findButtons(port, channels);
6804
 
6805
    if (TError::isError() || map.empty())
6806
    {
6807
#if TESTMODE == 1
6808
        setAllDone();
6809
#endif
6810
        return;
6811
    }
6812
 
6813
    vector<Button::TButton *> buttons = collectButtons(map);
6814
 
6815
    if (buttons.size() > 0)
6816
    {
6817
        vector<Button::TButton *>::iterator mapIter;
6818
 
6819
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
6820
        {
6821
            Button::TButton *bt = *mapIter;
6822
            bt->addPushFunction(action, pname);
6823
        }
6824
    }
6825
#if TESTMODE == 1
6826
    if (_gTestMode)
6827
        _gTestMode->setResult(toUpper(action) + "," + toUpper(pname));
6828
 
6829
    __success = true;
6830
    setAllDone();
6831
#endif
6832
}
6833
 
6834
/**
6835
 * Append non-unicode text.
6836
 */
6837
void TPageManager::doBAT(int port, vector<int> &channels, vector<string> &pars)
6838
{
6839
    DECL_TRACER("TPageManager::doBAT(int port, vector<int> &channels, vector<string> &pars)");
6840
 
6841
    if (pars.size() < 1)
6842
    {
6843
        MSG_ERROR("Expecting 1 parameters but got none! Ignoring command.");
6844
#if TESTMODE == 1
6845
        setAllDone();
6846
#endif
6847
        return;
6848
    }
6849
 
6850
    TError::clear();
6851
    int btState = atoi(pars[0].c_str());
6852
    string text;
6853
 
6854
    if (pars.size() > 1)
6855
        text = pars[1];
6856
 
6857
    vector<TMap::MAP_T> map = findButtons(port, channels);
6858
 
6859
    if (TError::isError() || map.empty())
6860
    {
6861
#if TESTMODE == 1
6862
        setAllDone();
6863
#endif
6864
        return;
6865
    }
6866
 
6867
    vector<Button::TButton *> buttons = collectButtons(map);
6868
 
6869
    if (buttons.empty())
6870
    {
6871
#if TESTMODE == 1
6872
        setAllDone();
6873
#endif
6874
        return;
6875
    }
6876
 
6877
    vector<Button::TButton *>::iterator mapIter;
6878
 
6879
    for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
6880
    {
6881
        Button::TButton *bt = *mapIter;
6882
 
6883
        bt->appendText(text, btState - 1);
6884
#if TESTMODE == 1
6885
        if (_gTestMode)
6886
        {
6887
            int st = (btState > 0 ? (btState - 1) : 0);
6888
            _gTestMode->setResult(bt->getText(st));
6889
        }
6890
 
6891
        __success = true;
6892
#endif
6893
    }
6894
#if TESTMODE == 1
6895
    setDone();
6896
#endif
6897
}
6898
 
6899
/**
6900
 * @brief Append unicode text. Same format as ^UNI.
6901
 * This command allows to set up to 50 characters of ASCII code. The unicode
6902
 * characters must be set as hex numbers.
6903
 */
6904
void TPageManager::doBAU(int port, vector<int>& channels, vector<string>& pars)
6905
{
6906
    DECL_TRACER("TPageManager::doBAU(int port, vector<int>& channels, vector<string>& pars)");
6907
 
6908
    if (pars.size() < 1)
6909
    {
6910
        MSG_ERROR("Expecting 1 parameters but got none! Ignoring command.");
6911
#if TESTMODE == 1
6912
        setAllDone();
6913
#endif
6914
        return;
6915
    }
6916
 
6917
    TError::clear();
6918
    int btState = atoi(pars[0].c_str());
6919
    string text;
6920
    char ch[3];
6921
 
6922
    if (pars.size() > 1)
6923
        text = pars[1];
6924
 
6925
    if ((text.size() % 4) == 0)
6926
    {
6927
        try
6928
        {
6929
            text = pars[1];
6930
            MSG_DEBUG("Processing UTF16 string: " << text);
6931
            // Because the unicode characters are hex numbers, we scan the text
6932
            // and convert the hex numbers into real numbers.
6933
            size_t len = text.length();
6934
            bool inHex = false;
6935
            int lastChar = 0;
6936
            uint16_t *numstr = new uint16_t[len / 4];
6937
            int uniPos = 0;
6938
            int cntCount = 0;
6939
 
6940
            for (size_t i = 0; i < len; i++)
6941
            {
6942
                int c = text.at(i);
6943
 
6944
                if (!inHex && isHex(c))
6945
                {
6946
                    inHex = true;
6947
                    lastChar = c;
6948
                    continue;
6949
                }
6950
 
6951
                if (inHex && !isHex(c))
6952
                    break;
6953
 
6954
                if (inHex && isHex(c))
6955
                {
6956
                    ch[0] = lastChar;
6957
                    ch[1] = c;
6958
                    ch[2] = 0;
6959
                    uint16_t num = (uint16_t)strtol(ch, NULL, 16);
6960
 
6961
                    if ((cntCount % 2) != 0)
6962
                    {
6963
                        numstr[uniPos] |= num;
6964
                        uniPos++;
6965
                    }
6966
                    else
6967
                        numstr[uniPos] = (num << 8) & 0xff00;
6968
 
6969
                    cntCount++;
6970
                    inHex = false;
6971
 
6972
                    if (uniPos >= 50)
6973
                        break;
6974
                }
6975
            }
6976
 
6977
            text.clear();
6978
            // Here we make from the real numbers a UTF8 string
6979
            for (size_t i = 0; i < len / 4; ++i)
6980
            {
6981
                if (numstr[i] <= 0x00ff)
6982
                {
6983
                    ch[0] = numstr[i];
6984
                    ch[1] = 0;
6985
                    text.append(ch);
6986
                }
6987
                else
6988
                {
6989
                    ch[0] = (numstr[i] >> 8) & 0x00ff;
6990
                    ch[1] = numstr[i] & 0x00ff;
6991
                    ch[2] = 0;
6992
                    text.append(ch);
6993
                }
6994
            }
6995
 
6996
            delete[] numstr;
6997
        }
6998
        catch (std::exception const & e)
6999
        {
7000
            MSG_ERROR("Character conversion error: " << e.what());
7001
#if TESTMODE == 1
7002
            setAllDone();
7003
#endif
7004
            return;
7005
        }
7006
    }
7007
    else
7008
    {
7009
        MSG_WARNING("No or invalid UTF16 string: " << text);
7010
#if TESTMODE == 1
7011
        setAllDone();
7012
#endif
7013
        return;
7014
    }
7015
 
7016
    vector<TMap::MAP_T> map = findButtons(port, channels);
7017
 
7018
    if (TError::isError() || map.empty())
7019
    {
7020
#if TESTMODE == 1
7021
        setAllDone();
7022
#endif
7023
        return;
7024
    }
7025
 
7026
    vector<Button::TButton *> buttons = collectButtons(map);
7027
 
7028
    if (buttons.size() > 0)
7029
    {
7030
        vector<Button::TButton *>::iterator mapIter;
7031
 
7032
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
7033
        {
7034
            Button::TButton *bt = *mapIter;
7035
 
7036
            bt->appendText(text, btState - 1);
7037
#if TESTMODE == 1
7038
            if (_gTestMode)
7039
                _gTestMode->setResult(bt->getText(btState - 1));
7040
 
7041
            __success = true;
7042
#endif
7043
        }
7044
    }
7045
#if TESTMODE == 1
7046
    setDone();
7047
#endif
7048
}
7049
 
7050
/**
7051
 * @brief TPageManager::doBCB Set the border color.
7052
 * Set the border color to the specified color. Only if the specified border
7053
 * color is not the same as the current color.
7054
 * Note: Color can be assigned by color name (without spaces), number or
7055
 * R,G,B value (RRGGBB or RRGGBBAA).
7056
 */
7057
void TPageManager::doBCB(int port, vector<int> &channels, vector<string> &pars)
7058
{
7059
    DECL_TRACER("TPageManager::doBCB(int port, vector<int> &channels, vector<string> &pars)");
7060
 
7061
    if (pars.size() < 1)
7062
    {
7063
        MSG_ERROR("Expecting 1 parameters but got none! Ignoring command.");
7064
#if TESTMODE == 1
7065
        setAllDone();
7066
#endif
7067
        return;
7068
    }
7069
 
7070
    TError::clear();
7071
    int btState = atoi(pars[0].c_str());
7072
    string color;
7073
 
7074
    if (pars.size() > 1)
7075
        color = pars[1];
7076
 
7077
    vector<TMap::MAP_T> map = findButtons(port, channels);
7078
 
7079
    if (TError::isError() || map.empty())
7080
    {
7081
#if TESTMODE == 1
7082
        setAllDone();
7083
#endif
7084
        return;
7085
    }
7086
 
7087
    vector<Button::TButton *> buttons = collectButtons(map);
7088
 
7089
    if (buttons.size() > 0)
7090
    {
7091
        vector<Button::TButton *>::iterator mapIter;
7092
 
7093
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
7094
        {
7095
            Button::TButton *bt = *mapIter;
7096
            bt->setBorderColor(color, btState - 1);
7097
#if TESTMODE == 1
7098
            if (_gTestMode)
7099
                _gTestMode->setResult(bt->getBorderColor(btState == 0 ? 0 : btState - 1));
7100
#endif
7101
        }
7102
    }
7103
#if TESTMODE == 1
7104
    setDone();
7105
#endif
7106
}
7107
 
7108
/*
7109
 * Get the border color and send it as a custom event.
7110
 */
7111
void TPageManager::getBCB(int port, vector<int> &channels, vector<string> &pars)
7112
{
7113
    DECL_TRACER("TPageManager::getBCB(int port, vector<int> &channels, vector<string> &pars)");
7114
 
7115
    if (pars.size() < 1)
7116
    {
7117
        MSG_ERROR("Expecting 1 parameters but got none! Ignoring command.");
7118
#if TESTMODE == 1
7119
        setAllDone();
7120
#endif
7121
        return;
7122
    }
7123
 
7124
    TError::clear();
7125
    int btState = atoi(pars[0].c_str());
7126
    string color;
7127
 
7128
    vector<TMap::MAP_T> map = findButtons(port, channels);
7129
 
7130
    if (TError::isError() || map.empty())
7131
    {
7132
#if TESTMODE == 1
7133
        setAllDone();
7134
#endif
7135
        return;
7136
    }
7137
 
7138
    vector<Button::TButton *> buttons = collectButtons(map);
7139
 
7140
    if (buttons.empty())
7141
    {
7142
#if TESTMODE == 1
7143
        setAllDone();
7144
#endif
7145
        return;
7146
    }
7147
 
7148
    vector<Button::TButton *>::iterator iter;
7149
 
7150
    for (iter = buttons.begin(); iter != buttons.end(); ++iter)
7151
    {
7152
        Button::TButton *bt = *iter;
7153
 
7154
        if (btState == 0)       // All instances?
7155
        {
7156
            int bst = bt->getNumberInstances();
7157
 
7158
            for (int i = 0; i < bst; i++)
7159
            {
7160
                color = bt->getBorderColor(i);
7161
 
7162
                if (color.empty())
7163
                    continue;
7164
 
7165
                sendCustomEvent(i + 1, (int)color.length(), 0, color, 1011, bt->getChannelPort(), bt->getChannelNumber());
7166
#if TESTMODE == 1
7167
                __success = true;
7168
 
7169
                if (_gTestMode)
7170
                    _gTestMode->setResult(color);
7171
#endif
7172
            }
7173
        }
7174
        else
7175
        {
7176
            color = bt->getBorderColor(btState - 1);
7177
 
7178
            if (color.empty())
7179
                continue;
7180
 
7181
            sendCustomEvent(btState, (int)color.length(), 0, color, 1011, bt->getChannelPort(), bt->getChannelNumber());
7182
#if TESTMODE == 1
7183
            __success = true;
7184
 
7185
            if (_gTestMode)
7186
                _gTestMode->setResult(color);
7187
#endif
7188
        }
7189
    }
7190
#if TESTMODE == 1
7191
    setAllDone();
7192
#endif
7193
}
7194
 
7195
/**
7196
 * @brief Set the fill color to the specified color.
7197
 * Only if the specified fill color is not the same as the current color.
7198
 * Note: Color can be assigned by color name (without spaces), number or R,G,B value (RRGGBB or RRGGBBAA).
7199
 */
7200
void TPageManager::doBCF(int port, vector<int>& channels, vector<std::string>& pars)
7201
{
7202
    DECL_TRACER("TPageManager::doBCF(int port, vector<int>& channels, vector<std::string>& pars)");
7203
 
7204
    if (pars.size() < 1)
7205
    {
7206
        MSG_ERROR("Expecting 1 parameters but got none! Ignoring command.");
7207
#if TESTMODE == 1
7208
        setAllDone();
7209
#endif
7210
        return;
7211
    }
7212
 
7213
    TError::clear();
7214
    int btState = atoi(pars[0].c_str());
7215
    string color;
7216
 
7217
    if (pars.size() > 1)
7218
        color = pars[1];
7219
 
7220
    vector<TMap::MAP_T> map = findButtons(port, channels);
7221
 
7222
    if (TError::isError() || map.empty())
7223
    {
7224
#if TESTMODE == 1
7225
        setAllDone();
7226
#endif
7227
        return;
7228
    }
7229
 
7230
    vector<Button::TButton *> buttons = collectButtons(map);
7231
 
7232
    if (buttons.size() > 0)
7233
    {
7234
        vector<Button::TButton *>::iterator mapIter;
7235
 
7236
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
7237
        {
7238
            Button::TButton *bt = *mapIter;
7239
            bt->setFillColor(color, btState - 1);
7240
#if TESTMODE == 1
7241
            if (_gTestMode)
7242
                _gTestMode->setResult(bt->getFillColor(btState == 0 ? 0 : btState - 1));
7243
#endif
7244
        }
7245
    }
7246
#if TESTMODE == 1
7247
    setDone();
7248
#endif
7249
}
7250
 
7251
/*
7252
 * Get the fill color and send it via a custom event to the NetLinx.
7253
 */
7254
void TPageManager::getBCF(int port, vector<int> &channels, vector<string> &pars)
7255
{
7256
    DECL_TRACER("TPageManager::getBCF(int port, vector<int> &channels, vector<string> &pars)");
7257
 
7258
    if (pars.size() < 1)
7259
    {
7260
        MSG_ERROR("Expecting 1 parameters but got none! Ignoring command.");
7261
#if TESTMODE == 1
7262
        setAllDone();
7263
#endif
7264
        return;
7265
    }
7266
 
7267
    TError::clear();
7268
    int btState = atoi(pars[0].c_str());
7269
    string color;
7270
 
7271
    vector<TMap::MAP_T> map = findButtons(port, channels);
7272
 
7273
    if (TError::isError() || map.empty())
7274
    {
7275
#if TESTMODE == 1
7276
        setAllDone();
7277
#endif
7278
        return;
7279
    }
7280
 
7281
    vector<Button::TButton *> buttons = collectButtons(map);
7282
 
7283
    if (buttons.empty())
7284
    {
7285
#if TESTMODE == 1
7286
        setAllDone();
7287
#endif
7288
        return;
7289
    }
7290
 
7291
    vector<Button::TButton *>::iterator iter;
7292
 
7293
    for (iter = buttons.begin(); iter != buttons.end(); ++iter)
7294
    {
7295
        Button::TButton *bt = *iter;
7296
 
7297
        if (btState == 0)       // All instances?
7298
        {
7299
            int bst = bt->getNumberInstances();
7300
 
7301
            for (int i = 0; i < bst; i++)
7302
            {
7303
                color = bt->getFillColor(i);
7304
 
7305
                if (color.empty())
7306
                    continue;
7307
 
7308
                sendCustomEvent(i + 1, (int)color.length(), 0, color, 1012, bt->getChannelPort(), bt->getChannelNumber());
7309
#if TESTMODE == 1
7310
                __success = true;
7311
 
7312
                if (_gTestMode)
7313
                    _gTestMode->setResult(color);
7314
#endif
7315
            }
7316
        }
7317
        else
7318
        {
7319
            color = bt->getFillColor(btState-1);
7320
 
7321
            if (color.empty())
7322
                continue;
7323
 
7324
            sendCustomEvent(btState, (int)color.length(), 0, color, 1012, bt->getChannelPort(), bt->getChannelNumber());
7325
#if TESTMODE == 1
7326
            __success = true;
7327
 
7328
            if (_gTestMode)
7329
                _gTestMode->setResult(color);
7330
#endif
7331
        }
7332
    }
7333
#if TESTMODE == 1
7334
    setAllDone();
7335
#endif
7336
}
7337
 
7338
/**
7339
 * @brief Set the text color to the specified color.
7340
 * Only if the specified text color is not the same as the current color.
7341
 * Note: Color can be assigned by color name (without spaces), number or R,G,B value (RRGGBB or RRGGBBAA).
7342
 */
7343
void TPageManager::doBCT(int port, vector<int>& channels, vector<string>& pars)
7344
{
7345
    DECL_TRACER("TPageManager::doBCT(int port, vector<int>& channels, vector<string>& pars)");
7346
 
7347
    if (pars.size() < 1)
7348
    {
7349
        MSG_ERROR("Expecting 1 parameters but got none! Ignoring command.");
7350
#if TESTMODE == 1
7351
        setAllDone();
7352
#endif
7353
        return;
7354
    }
7355
 
7356
    TError::clear();
7357
    int btState = atoi(pars[0].c_str());
7358
    string color;
7359
 
7360
    if (pars.size() > 1)
7361
        color = pars[1];
7362
 
7363
    vector<TMap::MAP_T> map = findButtons(port, channels);
7364
 
7365
    if (TError::isError() || map.empty())
7366
    {
7367
#if TESTMODE == 1
7368
        setAllDone();
7369
#endif
7370
        return;
7371
    }
7372
 
7373
    vector<Button::TButton *> buttons = collectButtons(map);
7374
 
7375
    if (buttons.size() > 0)
7376
    {
7377
        vector<Button::TButton *>::iterator mapIter;
7378
 
7379
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
7380
        {
7381
            Button::TButton *bt = *mapIter;
7382
            bt->setTextColor(color, btState - 1);
7383
#if TESTMODE == 1
7384
            if (_gTestMode)
7385
                _gTestMode->setResult(bt->getTextColor(btState == 0 ? 0 : btState - 1));
7386
#endif
7387
        }
7388
    }
7389
#if TESTMODE == 1
7390
    setDone();
7391
#endif
7392
}
7393
 
7394
/*
7395
 * Get the text color of a button and send it via a custom event to the NetLinx.
7396
 */
7397
void TPageManager::getBCT(int port, vector<int> &channels, vector<string> &pars)
7398
{
7399
    DECL_TRACER("TPageManager::getBCT(int port, vector<int> &channels, vector<string> &pars)");
7400
 
7401
    if (pars.size() < 1)
7402
    {
7403
        MSG_ERROR("Expecting 1 parameters but got none! Ignoring command.");
7404
#if TESTMODE == 1
7405
        setAllDone();
7406
#endif
7407
        return;
7408
    }
7409
 
7410
    TError::clear();
7411
    int btState = atoi(pars[0].c_str());
7412
    string color;
7413
 
7414
    vector<TMap::MAP_T> map = findButtons(port, channels);
7415
 
7416
    if (TError::isError() || map.empty())
7417
    {
7418
#if TESTMODE == 1
7419
        setAllDone();
7420
#endif
7421
        return;
7422
    }
7423
 
7424
    vector<Button::TButton *> buttons = collectButtons(map);
7425
 
7426
    if (buttons.empty())
7427
    {
7428
#if TESTMODE == 1
7429
        setAllDone();
7430
#endif
7431
        return;
7432
    }
7433
 
7434
    vector<Button::TButton *>::iterator iter;
7435
 
7436
    for (iter = buttons.begin(); iter != buttons.end(); ++iter)
7437
    {
7438
        Button::TButton *bt = *iter;
7439
 
7440
        if (btState == 0)       // All instances?
7441
        {
7442
            int bst = bt->getNumberInstances();
7443
 
7444
            for (int i = 0; i < bst; i++)
7445
            {
7446
                color = bt->getTextColor(i);
7447
 
7448
                if (color.empty())
7449
                    continue;
7450
 
7451
                sendCustomEvent(i + 1, (int)color.length(), 0, color, 1013, bt->getChannelPort(), bt->getChannelNumber());
7452
#if TESTMODE == 1
7453
                __success = true;
7454
 
7455
                if (_gTestMode)
7456
                    _gTestMode->setResult(color);
7457
#endif
7458
            }
7459
        }
7460
        else
7461
        {
7462
            color = bt->getTextColor(btState - 1);
7463
 
7464
            if (color.empty())
7465
                continue;
7466
 
7467
            sendCustomEvent(btState, (int)color.length(), 0, color, 1013, bt->getChannelPort(), bt->getChannelNumber());
7468
#if TESTMODE == 1
7469
            __success = true;
7470
 
7471
            if (_gTestMode)
7472
                _gTestMode->setResult(color);
7473
#endif
7474
        }
7475
    }
7476
#if TESTMODE == 1
7477
    setAllDone();
7478
#endif
7479
}
7480
 
7481
/**
7482
 * Set the button draw order
7483
 * Determines what order each layer of the button is drawn.
7484
 */
7485
void TPageManager::doBDO(int port, vector<int>& channels, vector<std::string>& pars)
7486
{
7487
    DECL_TRACER("TPageManager::doBDO(int port, vector<int>& channels, vector<std::string>& pars)");
7488
 
7489
    if (pars.size() < 1)
7490
    {
7491
        MSG_ERROR("Expecting 1 parameters but got none! Ignoring command.");
7492
#if TESTMODE == 1
7493
        setAllDone();
7494
#endif
7495
        return;
7496
    }
7497
 
7498
    TError::clear();
7499
    int btState = atoi(pars[0].c_str());
7500
    string order;
7501
 
7502
    if (pars.size() > 1)
7503
    {
7504
        string ord = pars[1];
7505
        // Convert the numbers into the expected draw order
7506
        for (size_t i = 0; i < ord.length(); i++)
7507
        {
7508
            if (ord.at(i) >= '1' && ord.at(i) <= '5')
7509
            {
7510
                char hv0[32];
7511
                snprintf(hv0, sizeof(hv0), "%02d", (int)(ord.at(i) - '0'));
7512
                order.append(hv0);
7513
            }
7514
            else
7515
            {
7516
                MSG_ERROR("Illegal order number " << ord.substr(i, 1) << "!");
7517
                return;
7518
            }
7519
        }
7520
 
7521
        if (order.length() != 10)
7522
        {
7523
            MSG_ERROR("Expected 5 order numbers but got " << (order.length() / 2)<< "!");
7524
            return;
7525
        }
7526
    }
7527
 
7528
    vector<TMap::MAP_T> map = findButtons(port, channels);
7529
 
7530
    if (TError::isError() || map.empty())
7531
    {
7532
#if TESTMODE == 1
7533
        setAllDone();
7534
#endif
7535
        return;
7536
    }
7537
 
7538
    vector<Button::TButton *> buttons = collectButtons(map);
7539
 
7540
    if (buttons.size() > 0)
7541
    {
7542
        vector<Button::TButton *>::iterator mapIter;
7543
 
7544
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
7545
        {
7546
            Button::TButton *bt = *mapIter;
7547
            bt->setDrawOrder(order, btState - 1);
7548
#if TESTMODE == 1
7549
            if (_gTestMode)
7550
                _gTestMode->setResult(bt->getDrawOrder(btState == 0 ? 0 : btState - 1));
7551
#endif
7552
        }
7553
    }
7554
#if TESTMODE == 1
7555
    setDone();
7556
#endif
7557
}
7558
 
7559
/**
7560
 * Set the feedback type of the button.
7561
 * ONLY works on General-type buttons.
7562
 */
7563
void TPageManager::doBFB(int port, vector<int>& channels, vector<std::string>& pars)
7564
{
7565
    DECL_TRACER("TPageManager::doBFB(int port, vector<int>& channels, vector<std::string>& pars)");
7566
 
7567
    if (pars.size() < 1)
7568
    {
7569
        MSG_ERROR("Expecting 1 parameters but got none! Ignoring command.");
7570
#if TESTMODE == 1
7571
        setAllDone();
7572
#endif
7573
        return;
7574
    }
7575
 
7576
    TError::clear();
7577
    Button::FEEDBACK type = Button::FB_NONE;
7578
    string stype = pars[0];
7579
    vector<string> stypes = { "None", "Channel", "Invert", "On", "Momentary", "Blink" };
7580
    vector<string>::iterator iter;
7581
    int i = 0;
7582
 
7583
    for (iter = stypes.begin(); iter != stypes.end(); ++iter)
7584
    {
7585
        if (strCaseCompare(stype, *iter) == 0)
7586
        {
7587
            type = (Button::FEEDBACK)i;
7588
            break;
7589
        }
7590
 
7591
        i++;
7592
    }
7593
 
7594
    vector<TMap::MAP_T> map = findButtons(port, channels);
7595
 
7596
    if (TError::isError() || map.empty())
7597
    {
7598
#if TESTMODE == 1
7599
        setAllDone();
7600
#endif
7601
        return;
7602
    }
7603
 
7604
    vector<Button::TButton *> buttons = collectButtons(map);
7605
 
7606
    if (buttons.size() > 0)
7607
    {
7608
        vector<Button::TButton *>::iterator mapIter;
7609
 
7610
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
7611
        {
7612
            Button::TButton *bt = *mapIter;
7613
            bt->setFeedback(type);
7614
#if TESTMODE == 1
7615
            if (_gTestMode)
7616
                _gTestMode->setResult(intToString(bt->getFeedback()));
7617
#endif
7618
        }
7619
    }
7620
#if TESTMODE == 1
7621
    setDone();
7622
#endif
7623
}
7624
 
7625
/*
7626
 * Set the input mask for the specified address.
7627
 */
7628
void TPageManager::doBIM(int port, vector<int>& channels, vector<std::string>& pars)
7629
{
7630
    DECL_TRACER("TPageManager::doBIM(int port, vector<int>& channels, vector<std::string>& pars)");
7631
 
7632
    if (pars.size() < 1)
7633
    {
7634
        MSG_ERROR("Expecting 1 parameters but got none! Ignoring command.");
7635
#if TESTMODE == 1
7636
        setAllDone();
7637
#endif
7638
        return;
7639
    }
7640
 
7641
    TError::clear();
7642
    string mask = pars[0];
7643
    vector<TMap::MAP_T> map = findButtons(port, channels);
7644
 
7645
    if (TError::isError() || map.empty())
7646
    {
7647
#if TESTMODE == 1
7648
        setAllDone();
7649
#endif
7650
        return;
7651
    }
7652
 
7653
    vector<Button::TButton *> buttons = collectButtons(map);
7654
 
7655
    if (buttons.size() > 0)
7656
    {
7657
        vector<Button::TButton *>::iterator mapIter;
7658
 
7659
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
7660
        {
7661
            Button::TButton *bt = *mapIter;
7662
            bt->setInputMask(mask);
7663
#if TESTMODE == 1
7664
            if (_gTestMode)
7665
                _gTestMode->setResult(bt->getInputMask());
7666
#endif
7667
        }
7668
    }
7669
#if TESTMODE == 1
7670
    setDone();
7671
#endif
7672
}
7673
 
7674
/**
7675
 * @brief Button copy command.
7676
 * Copy attributes of the source button to all the
7677
 * destination buttons. Note that the source is a single button state. Each
7678
 * state must be copied as a separate command. The <codes> section represents
7679
 * what attributes will be copied. All codes are 2 char pairs that can be
7680
 * separated by comma, space, percent or just ran together.
7681
 */
7682
void TPageManager::doBMC(int port, vector<int>& channels, vector<std::string>& pars)
7683
{
7684
    DECL_TRACER("TPageManager::doBMC(int port, vector<int>& channels, vector<std::string>& pars)");
7685
 
7686
    if (pars.size() < 5)
7687
    {
7688
        MSG_ERROR("Expecting 5 parameters but got " << pars.size() << ". Ignoring command.");
7689
#if TESTMODE == 1
7690
        setAllDone();
7691
#endif
7692
        return;
7693
    }
7694
 
7695
    TError::clear();
7696
    int btState = atoi(pars[0].c_str());
7697
    int src_port = atoi(pars[1].c_str());
7698
    int src_addr = atoi(pars[2].c_str());
7699
    int src_state = atoi(pars[3].c_str());
7700
    string src_codes = pars[4];
7701
    vector<int> src_channel;
7702
    src_channel.push_back(src_addr);
7703
 
7704
    vector<TMap::MAP_T> src_map = findButtons(src_port, src_channel);
7705
 
7706
    if (src_map.size() == 0)
7707
    {
7708
        MSG_WARNING("Button <" << TConfig::getChannel() << ":" << src_port << ":" << TConfig::getSystem() << ">:" << src_addr << " does not exist!");
7709
#if TESTMODE == 1
7710
        setAllDone();
7711
#endif
7712
        return;
7713
    }
7714
 
7715
    vector<Button::TButton *>src_buttons = collectButtons(src_map);
7716
 
7717
    if (src_buttons.size() == 0)
7718
    {
7719
        MSG_WARNING("Button <" << TConfig::getChannel() << ":" << src_port << ":" << TConfig::getSystem() << ">:" << src_addr << " does not exist!");
7720
#if TESTMODE == 1
7721
        setAllDone();
7722
#endif
7723
        return;
7724
    }
7725
 
7726
    if (src_buttons[0]->getNumberInstances() < src_state)
7727
    {
7728
        MSG_WARNING("Button <" << TConfig::getChannel() << ":" << src_port << ":" << TConfig::getSystem() << ">:" << src_addr << " has less then " << src_state << " elements.");
7729
#if TESTMODE == 1
7730
        setAllDone();
7731
#endif
7732
        return;
7733
    }
7734
 
7735
    if (src_state < 1)
7736
    {
7737
        MSG_WARNING("Button <" << TConfig::getChannel() << ":" << src_port << ":" << TConfig::getSystem() << ">:" << src_addr << " has invalid source state " << src_state << ".");
7738
#if TESTMODE == 1
7739
        setAllDone();
7740
#endif
7741
        return;
7742
    }
7743
 
7744
    src_state--;
7745
 
7746
    if (btState > 0)
7747
        btState--;
7748
 
7749
    vector<TMap::MAP_T> map = findButtons(port, channels);
7750
    vector<Button::TButton *> buttons = collectButtons(map);
7751
    //                        0     1     2     3     4     5     6     7
7752
    vector<string>codes = { "BM", "BR", "CB", "CF", "CT", "EC", "EF", "FT",
7753
                            "IC", "JB", "JI", "JT", "LN", "OP", "SO", "TX", // 8 - 15
7754
                            "VI", "WW" };   // 16, 17
7755
 
7756
    for (size_t ibuttons = 0; ibuttons < buttons.size(); ibuttons++)
7757
    {
7758
        vector<string>::iterator iter;
7759
        int idx = 0;
7760
 
7761
        for (iter = codes.begin(); iter != codes.end(); ++iter)
7762
        {
7763
            if (src_codes.find(*iter) != string::npos)
7764
            {
7765
                int j, x, y;
7766
 
7767
                switch(idx)
7768
                {
7769
                    case 0: buttons[ibuttons]->setBitmap(src_buttons[0]->getBitmapName(src_state), btState); break;
7770
                    case 1: buttons[ibuttons]->setBorderStyle(src_buttons[0]->getBorderStyle(src_state), btState); break;
7771
                    case 2: buttons[ibuttons]->setBorderColor(src_buttons[0]->getBorderColor(src_state), btState); break;
7772
                    case 3: buttons[ibuttons]->setFillColor(src_buttons[0]->getFillColor(src_state), btState); break;
7773
                    case 4: buttons[ibuttons]->setTextColor(src_buttons[0]->getTextColor(src_state), btState); break;
7774
                    case 5: buttons[ibuttons]->setTextEffectColor(src_buttons[0]->getTextEffectColor(src_state), btState); break;
7775
                    case 6: buttons[ibuttons]->setTextEffect(src_buttons[0]->getTextEffect(src_state), btState); break;
7776
                    case 7: buttons[ibuttons]->setFontIndex(src_buttons[0]->getFontIndex(src_state), btState); break;
7777
                    case 8: buttons[ibuttons]->setIcon(src_buttons[0]->getIconIndex(src_state), btState); break;
7778
 
7779
                    case 9:
7780
                        j = src_buttons[0]->getBitmapJustification(&x, &y, src_state);
7781
                        buttons[ibuttons]->setBitmapJustification(j, x, y, btState);
7782
                    break;
7783
 
7784
                    case 10:
7785
                        j = src_buttons[0]->getIconJustification(&x, &y, src_state);
7786
                        buttons[ibuttons]->setIconJustification(j, x, y, btState);
7787
                    break;
7788
 
7789
                    case 11:
7790
                        j = src_buttons[0]->getTextJustification(&x, &y, src_state);
7791
                        buttons[ibuttons]->setTextJustification(j, x, y, btState);
7792
                    break;
7793
 
7794
                    case 12: MSG_INFO("\"Lines of video removed\" not supported!"); break;
7795
                    case 13: buttons[ibuttons]->setOpacity(src_buttons[0]->getOpacity(src_state), btState); break;
7796
                    case 14: buttons[ibuttons]->setSound(src_buttons[0]->getSound(src_state), btState); break;
7797
                    case 15: buttons[ibuttons]->setText(src_buttons [0]->getText(src_state), btState); break;
7798
                    case 16: MSG_INFO("\"Video slot ID\" not supported!"); break;
7799
                    case 17: buttons[ibuttons]->setTextWordWrap(src_buttons[0]->getTextWordWrap(src_state), btState); break;
7800
                }
7801
            }
7802
 
7803
            idx++;
7804
        }
7805
    }
7806
}
7807
 
7808
void TPageManager::doBMF (int port, vector<int>& channels, vector<string>& pars)
7809
{
7810
    DECL_TRACER("TPageManager::doBMF (int port, vector<int>& channels, vector<string>& pars)");
7811
 
7812
    if (pars.size() < 2)
7813
    {
7814
        MSG_ERROR("Less then 2 parameters!");
7815
#if TESTMODE == 1
7816
        setAllDone();
7817
#endif
7818
        return;
7819
    }
7820
 
7821
    TError::clear();
7822
    int btState = atoi(pars[0].c_str()) - 1;
7823
    string commands;
7824
 
7825
    for (size_t i = 1; i < pars.size(); ++i)
7826
    {
7827
        if (i > 1)
7828
            commands += ",";
7829
 
7830
        commands += pars[i];
7831
    }
7832
 
7833
    vector<TMap::MAP_T> map = findButtons(port, channels);
7834
 
7835
    if (TError::isError() || map.empty())
7836
    {
7837
#if TESTMODE == 1
7838
        setAllDone();
7839
#endif
7840
        return;
7841
    }
7842
 
7843
    // Start of parsing the command line
7844
    // We splitt the command line into parts by searching for a percent (%) sign.
7845
    vector<string> parts = StrSplit(commands, "%");
7846
 
7847
    if (parts.empty())
7848
        parts.push_back(commands);
7849
 
7850
    // Search for all buttons who need to be updated
7851
    vector<Button::TButton *> buttons = collectButtons(map);
7852
 
7853
    if (buttons.size() > 0)
7854
    {
7855
        vector<Button::TButton *>::iterator mapIter;
7856
 
7857
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
7858
        {
7859
            Button::TButton *bt = *mapIter;
7860
 
7861
            if (!bt)
7862
            {
7863
                MSG_WARNING("Command ^BMF found an invalid pointer to a button!")
7864
                continue;
7865
            }
7866
 
7867
            // Iterate through commands and apply them to button
7868
            vector<string>::iterator iter;
7869
 
7870
            for (iter = parts.begin(); iter != parts.end(); ++iter)
7871
            {
7872
                char cmd = iter->at(0);
7873
                char cmd2;
7874
                string content;
7875
 
7876
                switch(cmd)
7877
                {
7878
                    case 'B':   // Border style
7879
                        if (iter->at(1) == ',')
7880
                            content = iter->substr(2);
7881
                        else
7882
                            content = iter->substr(1);
7883
 
7884
                        if (!content.empty() && isdigit(content[0]))
7885
                            bt->setBorderStyle(atoi(content.c_str()), btState);
7886
                        else
7887
                            bt->setBorderStyle(content, btState);
7888
#if TESTMODE == 1
7889
                        if (_gTestMode)
7890
                            _gTestMode->setResult(bt->getBorderStyle(btState < 0 ? 0 : btState));
7891
#endif
7892
                    break;
7893
 
7894
                    case 'C':   // Colors
7895
                        cmd2 = iter->at(1);
7896
                        content = iter->substr(2);
7897
 
7898
                        switch(cmd2)
7899
                        {
7900
                            case 'B':   // Border color
7901
                                bt->setBorderColor(content, btState);
7902
#if TESTMODE == 1
7903
                                if (_gTestMode)
7904
                                    _gTestMode->setResult(bt->getBorderColor(btState < 0 ? 0 : btState));
7905
#endif
7906
                            break;
7907
 
7908
                            case 'F':   // Fill color
7909
                                bt->setFillColor(content, btState);
7910
#if TESTMODE == 1
7911
                                if (_gTestMode)
7912
                                    _gTestMode->setResult(bt->getFillColor(btState < 0 ? 0 : btState));
7913
#endif
7914
                            break;
7915
 
7916
                            case 'T':   // Text color
7917
                                bt->setTextColor(content, btState);
7918
#if TESTMODE == 1
7919
                                if (_gTestMode)
7920
                                    _gTestMode->setResult(bt->getTextColor(btState < 0 ? 0 : btState));
7921
#endif
7922
                            break;
7923
                        }
7924
                    break;
7925
 
7926
                    case 'D':   // Draw order
7927
                        cmd2 = iter->at(1);
7928
                        content = iter->substr(2);
7929
 
7930
                        if (cmd2 == 'O')
7931
                        {
7932
                            bt->setDrawOrder(content, btState);
7933
#if TESTMODE == 1
7934
                            if (_gTestMode)
7935
                                _gTestMode->setResult(bt->getDrawOrder(btState < 0 ? 0 : btState));
7936
#endif
7937
                        }
7938
                    break;
7939
 
7940
                    case 'E':   // Text effect
7941
                        cmd2 = iter->at(1);
7942
                        content = iter->substr(2);
7943
 
7944
                        switch(cmd2)
7945
                        {
7946
                            case 'C':   // Text effect color
7947
                                bt->setTextEffectColor(content, btState);
7948
#if TESTMODE == 1
7949
                                if (_gTestMode)
7950
                                    _gTestMode->setResult(bt->getTextEffectColor(btState < 0 ? 0 : btState));
7951
#endif
7952
                            break;
7953
 
7954
                            case 'F':   // Text effect name
7955
                                bt->setTextEffectName(content, btState);
7956
#if TESTMODE == 1
7957
                                if (_gTestMode)
7958
                                    _gTestMode->setResult(bt->getTextEffectName(btState < 0 ? 0 : btState));
7959
#endif
7960
                            break;
7961
 
7962
                            case 'N':   // Enable/disable button
7963
                                bt->setEnable((content[0] == '1' ? true : false));
7964
#if TESTMODE == 1
7965
                                if (_gTestMode)
7966
                                {
7967
                                    _gTestMode->setResult(bt->isEnabled() ? "TRUE" : "FALSE");
7968
                                    __success = true;
7969
                                    setScreenDone();
7970
                                }
7971
#endif
7972
                            break;
7973
                        }
7974
                    break;
7975
 
7976
                    case 'F':   // Set font file name
7977
                        if (iter->at(1) == ',')
7978
                            content = iter->substr(2);
7979
                        else
7980
                            content = iter->substr(1);
7981
 
7982
                        if (!isdigit(content[0]))
7983
                            bt->setFontName(content, btState);
7984
                        else
7985
                            bt->setFontIndex(atoi(content.c_str()), btState);
7986
#if TESTMODE == 1
7987
                        if (_gTestMode)
7988
                            _gTestMode->setResult(intToString(bt->getFontIndex(btState < 0 ? 0 : btState)));
7989
#endif
7990
                    break;
7991
 
7992
                    case 'G':   // Bargraphs
7993
                        cmd2 = iter->at(1);
7994
                        content = iter->substr(2);
7995
 
7996
                        switch(cmd2)
7997
                        {
7998
                            case 'C':   // Bargraph slider color
7999
                                bt->setBargraphSliderColor(content);
8000
                            break;
8001
 
8002
                            case 'D':   // Ramp down time
8003
                                bt->setBargraphRampDownTime(atoi(content.c_str()));
8004
                            break;
8005
 
8006
                            case 'G':   // Drag increment
8007
                                bt->setBargraphDragIncrement(atoi(content.c_str()));
8008
                            break;
8009
 
8010
                            case 'H':   // Upper limit
8011
                                bt->setBargraphUpperLimit(atoi(content.c_str()));
8012
                            break;
8013
 
8014
                            case 'I':   // Invert/noninvert
8015
                                if (bt->getButtonType() == BARGRAPH || bt->getButtonType() == MULTISTATE_BARGRAPH)
8016
                                    bt->setBargraphInvert(atoi(content.c_str()) > 0 ? true : false);
8017
                            break;
8018
 
8019
                            case 'L':   // Lower limit
8020
                                bt->setBargraphLowerLimit(atoi(content.c_str()));
8021
                            break;
8022
 
8023
                            case 'N':   // Slider name
8024
                                bt->setBargraphSliderName(content);
8025
                            break;
8026
 
8027
                            case 'R':   // Repeat interval
8028
                                // FIXME: Add function to set repeat interval
8029
                            break;
8030
 
8031
                            case 'U':   // Ramp up time
8032
                                bt->setBargraphRampUpTime(atoi(content.c_str()));
8033
                            break;
8034
 
8035
                            case 'V':   // Bargraph value
8036
                                bt->setBargraphLevel(atoi(content.c_str()));
8037
                            break;
8038
                        }
8039
                    break;
8040
 
8041
                    case 'I':   // Set the icon
8042
                        content = iter->substr(1);
8043
                        bt->setIcon(atoi(content.c_str()), btState);
8044
#if TESTMODE == 1
8045
                        if (_gTestMode)
8046
                            _gTestMode->setResult(intToString(bt->getIconIndex()));
8047
#endif
8048
                    break;
8049
 
8050
                    case 'J':   // Set text justification
8051
                        cmd2 = iter->at(1);
8052
 
8053
                        if (cmd2 == ',')
8054
                        {
8055
                            content = iter->substr(1);
8056
                            int just = atoi(content.c_str());
8057
                            int x = 0, y = 0;
8058
 
8059
                            if (just == 0)
8060
                            {
8061
                                vector<string> coords = StrSplit(content, ",");
8062
 
8063
                                if (coords.size() >= 3)
8064
                                {
8065
                                    x = atoi(coords[1].c_str());
8066
                                    y = atoi(coords[2].c_str());
8067
                                }
8068
                            }
8069
 
8070
                            bt->setTextJustification(atoi(content.c_str()), x, y, btState);
8071
#if TESTMODE == 1
8072
                            if (_gTestMode)
8073
                            {
8074
                                just = bt->getTextJustification(&x, &y, btState < 0 ? 0 : btState);
8075
                                string s = intToString(just) + "," + intToString(x) + "," + intToString(y);
8076
                                _gTestMode->setResult(s);
8077
                            }
8078
#endif
8079
                        }
8080
                        else if (cmd2 == 'T' || cmd2 == 'B' || cmd2 == 'I')
8081
                        {
8082
                            content = iter->substr(2);
8083
                            int x = 0, y = 0;
8084
                            int just = atoi(content.c_str());
8085
 
8086
                            if (just == 0)
8087
                            {
8088
                                vector<string> coords = StrSplit(content, ",");
8089
 
8090
                                if (coords.size() >= 3)
8091
                                {
8092
                                    x = atoi(coords[1].c_str());
8093
                                    y = atoi(coords[2].c_str());
8094
                                }
8095
                            }
8096
 
8097
                            switch(cmd2)
8098
                            {
8099
                                case 'B':   // Alignment of bitmap
8100
                                    bt->setBitmapJustification(atoi(content.c_str()), x, y, btState);
8101
#if TESTMODE == 1
8102
                                    just = bt->getBitmapJustification(&x, &y, btState < 0 ? 0 : btState);
8103
#endif
8104
                                break;
8105
 
8106
                                case 'I':   // Alignment of icon
8107
                                    bt->setIconJustification(atoi(content.c_str()), x, y, btState);
8108
#if TESTMODE == 1
8109
                                    just = bt->getIconJustification(&x, &y, btState < 0 ? 0 : btState);
8110
#endif
8111
                                break;
8112
 
8113
                                case 'T':   // Alignment of text
8114
                                    bt->setTextJustification(atoi(content.c_str()), x, y, btState);
8115
#if TESTMODE == 1
8116
                                    just = bt->getTextJustification(&x, &y, btState < 0 ? 0 : btState);
8117
#endif
8118
                                break;
8119
                            }
8120
#if TESTMODE == 1
8121
                            if (_gTestMode)
8122
                            {
8123
                                string s = intToString(just) + "," + intToString(x) + "," + intToString(y);
8124
                                _gTestMode->setResult(s);
8125
                            }
8126
#endif
8127
                        }
8128
                    break;
8129
 
8130
                    case 'M':   // Text area
8131
                        cmd2 = iter->at(1);
8132
                        content = iter->substr(2);
8133
 
8134
                        switch(cmd2)
8135
                        {
8136
                            case 'I':   // Set mask image
8137
                                // FIXME: Add code for image mask
8138
                            break;
8139
 
8140
                            case 'K':   // Input mask of text area
8141
                                // FIXME: Add input mask
8142
                            break;
8143
 
8144
                            case 'L':   // Maximum length of text area
8145
                                // FIXME: Add code to set maximum length
8146
                            break;
8147
                        }
8148
                    break;
8149
 
8150
                    case 'O':   // Set feedback typ, opacity
8151
                        cmd2 = iter->at(1);
8152
 
8153
                        switch(cmd2)
8154
                        {
8155
                            case 'P':   // Set opacity
8156
                                bt->setOpacity(atoi(iter->substr(2).c_str()), btState);
8157
                            break;
8158
 
8159
                            case 'T':   // Set feedback type
8160
                                content = iter->substr(2);
8161
                                content = toUpper(content);
8162
 
8163
                                if (content == "NONE")
8164
                                    bt->setFeedback(Button::FB_NONE);
8165
                                else if (content == "CHANNEL")
8166
                                    bt->setFeedback(Button::FB_CHANNEL);
8167
                                else if (content == "INVERT")
8168
                                    bt->setFeedback(Button::FB_INV_CHANNEL);
8169
                                else if (content == "ON")
8170
                                    bt->setFeedback(Button::FB_ALWAYS_ON);
8171
                                else if (content == "MOMENTARY")
8172
                                    bt->setFeedback(Button::FB_MOMENTARY);
8173
                                else if (content == "BLINK")
8174
                                    bt->setFeedback(Button::FB_BLINK);
8175
                                else
8176
                                {
8177
                                    MSG_WARNING("Unknown feedback type " << content);
8178
                                }
8179
#if TESTMODE == 1
8180
                                if (_gTestMode)
8181
                                    _gTestMode->setResult(intToString(bt->getFeedback()));
8182
#endif
8183
                            break;
8184
 
8185
                            default:
8186
                                content = iter->substr(1);
8187
                                // FIXME: Add code to set the feedback type
8188
                        }
8189
                    break;
8190
 
8191
                    case 'P':   // Set picture/bitmap file name
8192
                        content = iter->substr(1);
8193
 
8194
                        if (content.find(".") == string::npos)  // If the image has no extension ...
8195
                        {                                       // we must find the image in the map
8196
                            string iname = findImage(content);
8197
 
8198
                            if (!iname.empty())
8199
                                content = iname;
8200
                        }
8201
 
8202
                        bt->setBitmap(content, btState);
8203
                    break;
8204
 
8205
                    case 'R':   // Set rectangle
8206
                    {
8207
                        content = iter->substr(1);
8208
                        vector<string> corners = StrSplit(content, ",");
8209
 
8210
                        if (corners.size() > 0)
8211
                        {
8212
                            vector<string>::iterator itcorn;
8213
                            int pos = 0;
8214
                            int left, top, right, bottom;
8215
                            left = top = right = bottom = 0;
8216
 
8217
                            for (itcorn = corners.begin(); itcorn != corners.end(); ++itcorn)
8218
                            {
8219
                                switch(pos)
8220
                                {
8221
                                    case 0: left   = atoi(itcorn->c_str()); break;
8222
                                    case 1: top    = atoi(itcorn->c_str()); break;
8223
                                    case 2: right  = atoi(itcorn->c_str()); break;
8224
                                    case 3: bottom = atoi(itcorn->c_str()); break;
8225
                                }
8226
 
8227
                                pos++;
8228
                            }
8229
 
8230
                            if (pos >= 4)
8231
                            {
8232
                                bt->setRectangle(left, top, right, bottom);
8233
                                bt->refresh();
8234
                            }
8235
                        }
8236
#if TESTMODE == 1
8237
                        if (_gTestMode)
8238
                        {
8239
                            int left, top, width, height;
8240
                            bt->getRectangle(&left, &top, &height, &width);
8241
                            string res(intToString(left) + "," + intToString(top) + "," + intToString(width) + "," + intToString(height));
8242
                            _gTestMode->setResult(res);
8243
                        }
8244
#endif
8245
                    }
8246
                    break;
8247
 
8248
                    case 'S':   // show/hide, style, sound
8249
                        cmd2 = iter->at(1);
8250
                        content = iter->substr(2);
8251
 
8252
                        switch(cmd2)
8253
                        {
8254
                            case 'F':   // Set focus of text area button
8255
                                // FIXME: Add code to set the focus of text area button
8256
                            break;
8257
 
8258
                            case 'M':   // Submit text
8259
                                if (content.find("|"))  // To be replaced by LF (0x0a)?
8260
                                {
8261
                                    size_t pos = 0;
8262
 
8263
                                    while ((pos = content.find("|")) != string::npos)
8264
                                        content = content.replace(pos, 1, "\n");
8265
                                }
8266
 
8267
                                bt->setText(content, btState);
8268
                            break;
8269
 
8270
                            case 'O':   // Sound
8271
                                bt->setSound(content, btState);
8272
#if TESTMODE == 1
8273
                                if (_gTestMode)
8274
                                    _gTestMode->setResult(bt->getSound(btState < 0 ? 0 : btState));
8275
#endif
8276
                            break;
8277
 
8278
                            case 'T':   // Button style
8279
                                // FIXME: Add code to set the button style
8280
                            break;
8281
 
8282
                            case 'W':   // Show / hide button
8283
                                if (content[0] == '0')
8284
                                    bt->hide(true);
8285
                                else
8286
                                    bt->show();
8287
#if TESTMODE == 1
8288
                                if (_gTestMode)
8289
                                    _gTestMode->setResult(bt->isVisible() ? "TRUE" : "FALSE");
8290
#endif
8291
                            break;
8292
                        }
8293
                    break;
8294
 
8295
                    case 'T':   // Set text
8296
                        content = iter->substr(1);
8297
 
8298
                        if (content.find("|"))  // To be replaced by LF (0x0a)?
8299
                        {
8300
                            size_t pos = 0;
8301
 
8302
                            while ((pos = content.find("|")) != string::npos)
8303
                                content = content.replace(pos, 1, "\n");
8304
                        }
8305
 
8306
                        bt->setText(content, btState);
8307
#if TESTMODE == 1
8308
                        if (_gTestMode)
8309
                            _gTestMode->setResult(bt->getText(btState < 0 ? 0 : btState));
8310
#endif
8311
                    break;
8312
 
8313
                    case 'U':   // Set the unicode text
8314
                        if (iter->at(1) == 'N')
8315
                        {
8316
                            content = iter->substr(2);
8317
                            string byte, text;
8318
                            size_t pos = 0;
8319
 
8320
                            while (pos < content.length())
8321
                            {
8322
                                byte = content.substr(pos, 2);
8323
                                char ch = (char)strtol(byte.c_str(), NULL, 16);
8324
                                text += ch;
8325
                                pos += 2;
8326
                            }
8327
 
8328
                            if (text.find("|"))  // To be replaced by LF (0x0a)?
8329
                            {
8330
                                size_t pos = 0;
8331
 
8332
                                while ((pos = text.find("|")) != string::npos)
8333
                                    text = text.replace(pos, 1, "\n");
8334
                            }
8335
 
8336
                            bt->setText(text, btState);
8337
                        }
8338
                    break;
8339
 
8340
                    case 'V':   // Video on / off
8341
                        cmd2 = iter->at(1);
8342
                        // Controlling a computer remotely is not supported.
8343
                        if (cmd2 != 'L' && cmd2 != 'N' && cmd2 != 'P')
8344
                        {
8345
                            content = iter->substr(2);
8346
                            // FIXME: Add code to switch video on or off
8347
                        }
8348
                    break;
8349
 
8350
                    case 'W':   // Word wrap
8351
                        if (iter->at(1) == 'W')
8352
                        {
8353
                            content = iter->substr(2);
8354
                            bt->setTextWordWrap(content[0] == '1' ? true : false, btState);
8355
                        }
8356
                    break;
8357
                }
8358
            }
8359
        }
8360
    }
8361
#if TESTMODE == 1
8362
    setDone();
8363
#endif
8364
}
8365
 
8366
/**
8367
 * Set the maximum length of the text area button. If this value is set to
8368
 * zero (0), the text area has no max length. The maximum length available is
8369
 * 2000. This is only for a Text area input button and not for a Text area input
8370
 * masking button.
8371
 */
8372
void TPageManager::doBML(int port, vector<int>& channels, vector<string>& pars)
8373
{
8374
    DECL_TRACER("TPageManager::doBML(int port, vector<int>& channels, vector<string>& pars)");
8375
 
8376
    if (pars.size() < 1)
8377
    {
8378
        MSG_ERROR("Expecting 1 parameter but got " << pars.size() << "! Ignoring command.");
8379
        return;
8380
    }
8381
 
8382
    TError::clear();
8383
    int maxLen = atoi(pars[0].c_str());
8384
 
8385
    if (maxLen < 0 || maxLen > 2000)
8386
    {
8387
        MSG_WARNING("Got illegal length of text area! [" << maxLen << "]");
8388
        return;
8389
    }
8390
 
8391
    vector<TMap::MAP_T> map = findButtons(port, channels);
8392
 
8393
    if (TError::isError() || map.empty())
8394
        return;
8395
 
8396
    vector<Button::TButton *> buttons = collectButtons(map);
8397
 
8398
    if (buttons.size() > 0)
8399
    {
8400
        vector<Button::TButton *>::iterator mapIter;
8401
 
8402
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
8403
        {
8404
            Button::TButton *bt = *mapIter;
8405
            bt->setTextMaxChars(maxLen);
8406
        }
8407
    }
8408
}
8409
 
8410
/**
8411
 * Assign a picture to those buttons with a defined address range.
8412
 */
8413
void TPageManager::doBMP(int port, vector<int>& channels, vector<string>& pars)
8414
{
8415
    DECL_TRACER("TPageManager::doBMP(int port, vector<int>& channels, vector<string>& pars)");
8416
 
8417
    if (pars.size() < 2)
8418
    {
8419
        MSG_ERROR("Expecting 2 parameters but got " << pars.size() << "! Ignoring command.");
8420
        return;
8421
    }
8422
 
8423
    TError::clear();
8424
    int btState = atoi(pars[0].c_str());
8425
    string bitmap = pars[1];
8426
    // If this is a G5 command, we may have up to 2 additional parameters.
8427
    int slot = -1, justify = -1, jx = 0, jy = 0;
8428
 
8429
    if (pars.size() > 2)
8430
    {
8431
        slot = atoi(pars[2].c_str());
8432
 
8433
        if (pars.size() >= 4)
8434
        {
8435
            justify = atoi(pars[4].c_str());
8436
 
8437
            if (justify == 0)
8438
            {
8439
                if (pars.size() >= 5)
8440
                    jx = atoi(pars[5].c_str());
8441
 
8442
                if (pars.size() >= 6)
8443
                    jy = atoi(pars[6].c_str());
8444
            }
8445
        }
8446
    }
8447
 
8448
    vector<TMap::MAP_T> map = findButtons(port, channels);
8449
 
8450
    if (TError::isError() || map.empty())
8451
        return;
8452
 
8453
    vector<Button::TButton *> buttons = collectButtons(map);
8454
 
8455
    if (buttons.size() > 0)
8456
    {
8457
        vector<Button::TButton *>::iterator mapIter;
8458
 
8459
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
8460
        {
8461
            Button::TButton *bt = *mapIter;
8462
//            setButtonCallbacks(bt);
8463
 
8464
            if (btState == 0)       // All instances?
8465
            {
8466
                int bst = bt->getNumberInstances();
8467
                MSG_DEBUG("Setting bitmap " << bitmap << " on all " << bst << " instances...");
8468
 
8469
                for (int i = 0; i < bst; i++)
8470
                {
8471
                    if (justify >= 0)
8472
                    {
8473
                        if (slot == 2)
8474
                            bt->setIconJustification(justify, jx, jy, i);
8475
                        else
8476
                            bt->setBitmapJustification(justify, jx, jy, i);
8477
                    }
8478
 
8479
                    if (slot >= 0)
8480
                    {
8481
                        switch(slot)
8482
                        {
8483
                            case 0: bt->setCameleon(bitmap, i); break;
8484
                            case 2: bt->setIcon(bitmap, i); break;  // On G4 we have no bitmap layer. Therefor we use layer 2 as icon layer.
8485
                            default:
8486
                                bt->setBitmap(bitmap, i);
8487
                        }
8488
                    }
8489
                    else
8490
                        bt->setBitmap(bitmap, i);
8491
                }
8492
            }
8493
            else
8494
            {
8495
                if (justify >= 0)
8496
                {
8497
                    if (slot == 2)
8498
                        bt->setIconJustification(justify, jx, jy, btState);
8499
                    else
8500
                        bt->setBitmapJustification(justify, jx, jy, btState);
8501
                }
8502
 
8503
                if (slot >= 0)
8504
                {
8505
                    switch(slot)
8506
                    {
8507
                        case 0: bt->setCameleon(bitmap, btState); break;
8508
                        case 2: bt->setIcon(bitmap, btState); break;      // On G4 we have no bitmap layer. Therefor we use layer 2 as icon layer.
8509
                        default:
8510
                            bt->setBitmap(bitmap, btState);
8511
                    }
8512
                }
8513
                else
8514
                    bt->setBitmap(bitmap, btState);
8515
            }
8516
        }
8517
    }
8518
}
8519
 
8520
void TPageManager::getBMP(int port, vector<int> &channels, vector<string> &pars)
8521
{
8522
    DECL_TRACER("TPageManager::getBMP(int port, vector<int> &channels, vector<string> &pars)");
8523
 
8524
    if (pars.size() < 1)
8525
    {
8526
        MSG_ERROR("Expecting 1 parameters but got none! Ignoring command.");
8527
        return;
8528
    }
8529
 
8530
    TError::clear();
8531
    int btState = atoi(pars[0].c_str());
8532
    string bmp;
8533
 
8534
    vector<TMap::MAP_T> map = findButtons(port, channels);
8535
 
8536
    if (TError::isError() || map.empty())
8537
        return;
8538
 
8539
    vector<Button::TButton *> buttons = collectButtons(map);
8540
 
8541
    if (buttons.size() > 0)
8542
    {
8543
        Button::TButton *bt = buttons[0];
8544
 
8545
        if (btState == 0)       // All instances?
8546
        {
8547
            int bst = bt->getNumberInstances();
8548
 
8549
            for (int i = 0; i < bst; i++)
8550
            {
8551
                bmp = bt->getBitmapName(i);
8552
 
8553
                if (bmp.empty())
8554
                    continue;
8555
 
8556
                sendCustomEvent(i + 1, (int)bmp.length(), 0, bmp, 1002, bt->getChannelPort(), bt->getChannelNumber());
8557
            }
8558
        }
8559
        else
8560
        {
8561
            bmp = bt->getTextColor(btState-1);
8562
            sendCustomEvent(btState, (int)bmp.length(), 0, bmp, 1002, bt->getChannelPort(), bt->getChannelNumber());
8563
        }
8564
    }
8565
}
8566
 
8567
/**
8568
 * Set the button opacity. The button opacity can be specified as a decimal
8569
 * between 0 - 255, where zero (0) is invisible and 255 is opaque, or as a
8570
 * HEX code, as used in the color commands by preceding the HEX code with
8571
 * the # sign. In this case, #00 becomes invisible and #FF becomes opaque.
8572
 * If the opacity is set to zero (0), this does not make the button inactive,
8573
 * only invisible.
8574
 */
8575
void TPageManager::doBOP(int port, vector<int>& channels, vector<string>& pars)
8576
{
8577
    DECL_TRACER("TPageManager::doBOP(int port, vector<int>& channels, vector<string>& pars)");
8578
 
8579
    if (pars.size() < 2)
8580
    {
8581
        MSG_ERROR("Expecting 2 parameters but got " << pars.size() << "! Ignoring command.");
8582
#if TESTMODE == 1
8583
        setAllDone();
8584
#endif
8585
        return;
8586
    }
8587
 
8588
    TError::clear();
8589
    int btState = atoi(pars[0].c_str()) - 1;
8590
    int btOpacity = 0;
8591
 
8592
    if (pars[1].at(0) == '#')
8593
        btOpacity = (int)strtol(pars[1].substr(1).c_str(), NULL, 16);
8594
    else
8595
        btOpacity = atoi(pars[1].c_str());
8596
 
8597
    vector<TMap::MAP_T> map = findButtons(port, channels);
8598
 
8599
    if (TError::isError() || map.empty())
8600
    {
8601
#if TESTMODE == 1
8602
        setAllDone();
8603
#endif
8604
        return;
8605
    }
8606
 
8607
    vector<Button::TButton *> buttons = collectButtons(map);
8608
 
8609
    if (buttons.size() > 0)
8610
    {
8611
        vector<Button::TButton *>::iterator mapIter;
8612
 
8613
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
8614
        {
8615
            Button::TButton *bt = *mapIter;
8616
            bt->setOpacity(btOpacity, btState);
8617
#if TESTMODE == 1
8618
            if (_gTestMode)
8619
                _gTestMode->setResult(intToString(bt->getOpacity(btState < 0 ? 0 : btState)));
8620
#endif
8621
        }
8622
    }
8623
#if TESTMODE == 1
8624
    setDone();
8625
#endif
8626
}
8627
 
8628
void TPageManager::getBOP(int port, vector<int>& channels, vector<string>& pars)
8629
{
8630
    DECL_TRACER("TPageManager::getBOP(int port, vector<int>& channels, vector<string>& pars)");
8631
 
8632
    if (pars.size() < 1)
8633
    {
8634
        MSG_ERROR("Expecting 1 parameters but got none! Ignoring command.");
8635
        return;
8636
    }
8637
 
8638
    TError::clear();
8639
    int btState = atoi(pars[0].c_str());
8640
 
8641
    vector<TMap::MAP_T> map = findButtons(port, channels);
8642
 
8643
    if (TError::isError() || map.empty())
8644
        return;
8645
 
8646
    vector<Button::TButton *> buttons = collectButtons(map);
8647
 
8648
    if (buttons.size() > 0)
8649
    {
8650
        Button::TButton *bt = buttons[0];
8651
 
8652
        if (btState == 0)       // All instances?
8653
        {
8654
            int bst = bt->getNumberInstances();
8655
 
8656
            for (int i = 0; i < bst; i++)
8657
            {
8658
                int oo = bt->getOpacity(i);
8659
                sendCustomEvent(i + 1, oo, 0, "", 1015, bt->getChannelPort(), bt->getChannelNumber());
8660
            }
8661
        }
8662
        else
8663
        {
8664
            int oo = bt->getOpacity(btState-1);
8665
            sendCustomEvent(btState, oo, 0, "", 1015, bt->getChannelPort(), bt->getChannelNumber());
8666
        }
8667
    }
8668
}
8669
 
8670
void TPageManager::doBOR(int port, vector<int>& channels, vector<string>& pars)
8671
{
8672
    DECL_TRACER("TPageManager::doBOR(int port, vector<int>& channels, vector<string>& pars)");
8673
 
8674
    if (pars.size() < 1)
8675
    {
8676
        MSG_ERROR("Expecting at least 1 parameter but got " << pars.size() << "! Ignoring command.");
8677
#if TESTMODE == 1
8678
        setAllDone();
8679
#endif
8680
        return;
8681
    }
8682
 
8683
    TError::clear();
8684
    // Numbers of styles from 0 to 41
8685
    string bor = pars[0];
8686
    string border = "None";
8687
    int ibor = -1;
8688
    Border::TIntBorder borders;
8689
 
8690
    if (bor.at(0) >= '0' && bor.at(0) <= '9')
8691
    {
8692
        ibor = atoi(bor.c_str());
8693
 
8694
        if (ibor >= 0 && ibor <= 41)
8695
            border = borders.getTP4BorderName(ibor);
8696
        else
8697
        {
8698
            MSG_WARNING("Invalid border style ID " << ibor);
8699
#if TESTMODE == 1
8700
            setAllDone();
8701
#endif
8702
            return;
8703
        }
8704
 
8705
        MSG_DEBUG("Id " << ibor << " is border " << border);
8706
    }
8707
    else
8708
    {
8709
        if (!borders.isTP4BorderValid(bor))
8710
        {
8711
            MSG_WARNING("Unknown border style " << bor);
8712
#if TESTMODE == 1
8713
            setAllDone();
8714
#endif
8715
            return;
8716
        }
8717
 
8718
        border = bor;
8719
    }
8720
 
8721
    vector<TMap::MAP_T> map = findButtons(port, channels);
8722
 
8723
    if (TError::isError() || map.empty())
8724
    {
8725
#if TESTMODE == 1
8726
        setAllDone();
8727
#endif
8728
        return;
8729
    }
8730
 
8731
    vector<Button::TButton *> buttons = collectButtons(map);
8732
 
8733
    if (buttons.size() > 0)
8734
    {
8735
        vector<Button::TButton *>::iterator mapIter;
8736
 
8737
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
8738
        {
8739
            Button::TButton *bt = *mapIter;
8740
            bt->setBorderStyle(border);
8741
#if TESTMODE == 1
8742
            if (_gTestMode)
8743
                _gTestMode->setResult(bt->getBorderStyle(0));
8744
#endif
8745
        }
8746
    }
8747
#if TESTMODE == 1
8748
    setDone();
8749
#endif
8750
}
8751
 
8752
void TPageManager::doBOS(int port, vector<int>& channels, vector<string>& pars)
8753
{
8754
    DECL_TRACER("TPageManager::doBOS(int port, vector<int>& channels, vector<string>& pars)");
8755
 
8756
    if (pars.size() < 2)
8757
    {
8758
        MSG_ERROR("Expecting at least 2 parameters but got " << pars.size() << "! Ignoring command.");
8759
        return;
8760
    }
8761
 
8762
    TError::clear();
8763
    int btState = atoi(pars[0].c_str());
8764
    int videoState = atoi(pars[1].c_str());
8765
 
8766
    vector<TMap::MAP_T> map = findButtons(port, channels);
8767
 
8768
    if (TError::isError() || map.empty())
8769
        return;
8770
 
8771
    vector<Button::TButton *> buttons = collectButtons(map);
8772
 
8773
    if (buttons.size() > 0)
8774
    {
8775
        vector<Button::TButton *>::iterator mapIter;
8776
 
8777
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
8778
        {
8779
            Button::TButton *bt = *mapIter;
8780
 
8781
            if (btState == 0)       // All instances?
8782
                bt->setDynamic(videoState);
8783
            else
8784
                bt->setDynamic(videoState, btState-1);
8785
        }
8786
    }
8787
}
8788
 
8789
/**
8790
 * Set the border of a button state/states.
8791
 * The border names are available through the TPDesign4 border-name drop-down
8792
 * list.
8793
 */
8794
void TPageManager::doBRD(int port, vector<int>& channels, vector<string>& pars)
8795
{
8796
    DECL_TRACER("TPageManager::doBRD(int port, vector<int>& channels, vector<string>& pars)");
8797
 
8798
    if (pars.size() < 1)
8799
    {
8800
        MSG_ERROR("Expecting at least 1 parameter but got " << pars.size() << "! Ignoring command.");
8801
        return;
8802
    }
8803
 
8804
    TError::clear();
8805
    int btState = atoi(pars[0].c_str());
8806
    string border = "None";
8807
 
8808
    if (pars.size() > 1)
8809
        border = pars[1];
8810
 
8811
    vector<TMap::MAP_T> map = findButtons(port, channels);
8812
 
8813
    if (TError::isError() || map.empty())
8814
        return;
8815
 
8816
    vector<Button::TButton *> buttons = collectButtons(map);
8817
 
8818
    if (buttons.size() > 0)
8819
    {
8820
        vector<Button::TButton *>::iterator mapIter;
8821
 
8822
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
8823
        {
8824
            Button::TButton *bt = *mapIter;
8825
//            setButtonCallbacks(bt);
8826
 
8827
            if (btState == 0)       // All instances?
8828
            {
8829
                int bst = bt->getNumberInstances();
8830
 
8831
                for (int i = 0; i < bst; i++)
8832
                    bt->setBorderStyle(border, i+1);
8833
            }
8834
            else
8835
                bt->setBorderStyle(border, btState);
8836
        }
8837
    }
8838
}
8839
 
8840
void TPageManager::getBRD(int port, vector<int>& channels, vector<string>& pars)
8841
{
8842
    DECL_TRACER("TPageManager::getBRD(int port, vector<int>& channels, vector<string>& pars)");
8843
 
8844
    if (pars.size() < 1)
8845
    {
8846
        MSG_ERROR("Expecting at least 1 parameter but got " << pars.size() << "! Ignoring command.");
8847
        return;
8848
    }
8849
 
8850
    TError::clear();
8851
    int btState = atoi(pars[0].c_str());
8852
 
8853
    vector<TMap::MAP_T> map = findButtons(port, channels);
8854
 
8855
    if (TError::isError() || map.empty())
8856
        return;
8857
 
8858
    vector<Button::TButton *> buttons = collectButtons(map);
8859
 
8860
    if (buttons.size() > 0)
8861
    {
8862
        Button::TButton *bt = buttons[0];
8863
 
8864
        if (btState == 0)       // All instances?
8865
        {
8866
            int bst = bt->getNumberInstances();
8867
 
8868
            for (int i = 0; i < bst; i++)
8869
            {
8870
                string bname = bt->getBorderStyle(i);
8871
                sendCustomEvent(i + 1, (int)bname.length(), 0, bname, 1014, bt->getChannelPort(), bt->getChannelNumber());
8872
            }
8873
        }
8874
        else
8875
        {
8876
            string bname = bt->getBorderStyle(btState-1);
8877
            sendCustomEvent(btState, (int)bname.length(), 0, bname, 1014, bt->getChannelPort(), bt->getChannelNumber());
8878
        }
8879
    }
8880
}
8881
 
8882
/**
8883
 * Set the button size and its position on the page.
8884
 */
8885
void TPageManager::doBSP(int port, vector<int>& channels, vector<string>& pars)
8886
{
8887
    DECL_TRACER("TPageManager::doBSP(int port, vector<int>& channels, vector<string>& pars)");
8888
 
8889
    if (pars.size() < 1)
8890
    {
8891
        MSG_ERROR("Expecting at least 1 parameter but got " << pars.size() << "! Ignoring command.");
8892
#if TESTMODE == 1
8893
        setAllDone();
8894
#endif
8895
        return;
8896
    }
8897
 
8898
    TError::clear();
8899
    bool bLeft = false, bTop = false, bRight = false, bBottom = false;
8900
    int x, y;
8901
 
8902
    if (pars.size() > 0)
8903
    {
8904
        vector<string>::iterator iter;
8905
 
8906
        for (iter = pars.begin(); iter != pars.end(); iter++)
8907
        {
8908
            if (iter->compare("left") == 0)
8909
                bLeft = true;
8910
            else if (iter->compare("top") == 0)
8911
                bTop = true;
8912
            else if (iter->compare("right") == 0)
8913
                bRight = true;
8914
            else if (iter->compare("bottom") == 0)
8915
                bBottom = true;
8916
        }
8917
    }
8918
 
8919
    vector<TMap::MAP_T> map = findButtons(port, channels);
8920
 
8921
    if (TError::isError() || map.empty())
8922
        return;
8923
 
8924
    vector<Button::TButton *> buttons = collectButtons(map);
8925
    x = y = 0;
8926
 
8927
    if (buttons.size() > 0)
8928
    {
8929
        vector<Button::TButton *>::iterator mapIter;
8930
 
8931
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
8932
        {
8933
            Button::TButton *bt = *mapIter;
8934
 
8935
            if (bLeft)
8936
                x = 0;
8937
 
8938
            if (bTop)
8939
                y = 0;
8940
 
8941
            if (bRight || bBottom)
8942
            {
8943
                ulong handle = bt->getHandle();
8944
                int parentID = (handle >> 16) & 0x0000ffff;
8945
                int pwidth = 0;
8946
                int pheight = 0;
8947
 
8948
                if (parentID < 500)
8949
                {
8950
                    TPage *pg = getPage(parentID);
8951
 
8952
                    if (!pg)
8953
                    {
8954
                        MSG_ERROR("Internal error: Page " << parentID << " not found!");
8955
                        return;
8956
                    }
8957
 
8958
                    pwidth = pg->getWidth();
8959
                    pheight = pg->getHeight();
8960
                }
8961
                else
8962
                {
8963
                    TSubPage *spg = getSubPage(parentID);
8964
 
8965
                    if (!spg)
8966
                    {
8967
                        MSG_ERROR("Internal error: Subpage " << parentID << " not found!");
8968
                        return;
8969
                    }
8970
 
8971
                    pwidth = spg->getWidth();
8972
                    pheight = spg->getHeight();
8973
                }
8974
 
8975
                if (bRight)
8976
                    x = pwidth - bt->getWidth();
8977
 
8978
                if (bBottom)
8979
                    y = pheight - bt->getHeight();
8980
            }
8981
 
8982
            bt->setLeftTop(x, y);
8983
#if TESTMODE == 1
8984
            if (_gTestMode)
8985
            {
8986
                int left = bt->getLeftPosition();
8987
                int top = bt->getTopPosition();
8988
                string res = intToString(left) + "," + intToString(top);
8989
                _gTestMode->setResult(res);
8990
            }
8991
#endif
8992
        }
8993
    }
8994
#if TESTMODE == 1
8995
    setDone();
8996
#endif
8997
}
8998
 
8999
/**
9000
 * Submit text for text area buttons. This command causes the text areas to
9001
 * send their text as strings to the NetLinx Master.
9002
 */
9003
void TPageManager::doBSM(int port, vector<int>& channels, vector<string>&)
9004
{
9005
    DECL_TRACER("TPageManager::doBSM(int port, vector<int>& channels, vector<string>& pars)");
9006
 
9007
    TError::clear();
9008
    vector<TMap::MAP_T> map = findButtons(port, channels);
9009
 
9010
    if (TError::isError() || map.empty())
9011
    {
9012
#if TESTMODE == 1
9013
        setAllDone();
9014
#endif
9015
        return;
9016
    }
9017
 
9018
    vector<Button::TButton *> buttons = collectButtons(map);
9019
 
9020
    if (buttons.size() > 0)
9021
    {
9022
        vector<Button::TButton *>::iterator mapIter;
9023
 
9024
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
9025
        {
9026
            Button::TButton *bt = *mapIter;
9027
 
9028
            if (bt->getButtonType() != TEXT_INPUT && bt->getButtonType() != GENERAL)
9029
            {
9030
#if TESTMODE == 1
9031
                setAllDone();
9032
#endif
9033
                return;
9034
            }
9035
 
9036
            amx::ANET_SEND scmd;
9037
            scmd.port = bt->getChannelPort();
9038
            scmd.channel = bt->getChannelNumber();
9039
            scmd.ID = scmd.channel;
9040
            scmd.msg = bt->getText(0);
9041
            scmd.MC = 0x008b;       // string value
9042
 
9043
            if (gAmxNet)
9044
                gAmxNet->sendCommand(scmd);
9045
            else
9046
                MSG_WARNING("Missing global class TAmxNet. Can't send message!");
9047
 
9048
        }
9049
    }
9050
}
9051
 
9052
/**
9053
 * Set the sound played when a button is pressed. If the sound name is blank
9054
 * the sound is then cleared. If the sound name is not matched, the button
9055
 * sound is not changed.
9056
 */
9057
void TPageManager::doBSO(int port, vector<int>& channels, vector<string>& pars)
9058
{
9059
    DECL_TRACER("TPageManager::doBSO(int port, vector<int>& channels, vector<string>& pars)");
9060
 
9061
    if (pars.size() < 2)
9062
    {
9063
        MSG_ERROR("Expecting 2 parameters but got " << pars.size() << "! Ignoring command.");
9064
        return;
9065
    }
9066
 
9067
    if (!gPrjResources)
9068
        return;
9069
 
9070
    TError::clear();
9071
    int btState = atoi(pars[0].c_str());
9072
    string sound = pars[1];
9073
 
9074
    if (!soundExist(sound))
9075
        return;
9076
 
9077
    vector<TMap::MAP_T> map = findButtons(port, channels);
9078
 
9079
    if (TError::isError() || map.empty())
9080
        return;
9081
 
9082
    vector<Button::TButton *> buttons = collectButtons(map);
9083
 
9084
    if (buttons.size() > 0)
9085
    {
9086
        vector<Button::TButton *>::iterator mapIter;
9087
 
9088
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
9089
        {
9090
            Button::TButton *bt = *mapIter;
9091
 
9092
            if (btState == 0)
9093
            {
9094
                int bst = bt->getNumberInstances();
9095
 
9096
                for (int i = 0; i < bst; i++)
9097
                    bt->setSound(sound, i);
9098
            }
9099
            else
9100
                bt->setSound(sound, btState-1);
9101
        }
9102
    }
9103
}
9104
 
9105
/**
9106
 * Set the button word wrap feature to those buttons with a defined address
9107
 * range. By default, word-wrap is Off.
9108
 */
9109
void TPageManager::doBWW(int port, vector<int>& channels, vector<string>& pars)
9110
{
9111
    DECL_TRACER("TPageManager::doBWW(int port, vector<int>& channels, vector<string>& pars)");
9112
 
9113
    if (pars.size() < 1)
9114
    {
9115
        MSG_ERROR("Expecting 1 parameter but got " << pars.size() << "! Ignoring command.");
9116
        return;
9117
    }
9118
 
9119
    TError::clear();
9120
    int btState = atoi(pars[0].c_str());
9121
 
9122
    vector<TMap::MAP_T> map = findButtons(port, channels);
9123
 
9124
    if (TError::isError() || map.empty())
9125
        return;
9126
 
9127
    vector<Button::TButton *> buttons = collectButtons(map);
9128
 
9129
    if (buttons.size() > 0)
9130
    {
9131
        vector<Button::TButton *>::iterator mapIter;
9132
 
9133
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
9134
        {
9135
            Button::TButton *bt = *mapIter;
9136
//            setButtonCallbacks(bt);
9137
 
9138
            if (btState == 0)       // All instances?
9139
            {
9140
                int bst = bt->getNumberInstances();
9141
                MSG_DEBUG("Setting word wrap on all " << bst << " instances...");
9142
 
9143
                for (int i = 0; i < bst; i++)
9144
                    bt->setTextWordWrap(true, i);
9145
            }
9146
            else
9147
                bt->setTextWordWrap(true, btState - 1);
9148
        }
9149
    }
9150
}
9151
 
9152
void TPageManager::getBWW(int port, vector<int>& channels, vector<string>& pars)
9153
{
9154
    DECL_TRACER("TPageManager::getBWW(int port, vector<int>& channels, vector<string>& pars)");
9155
 
9156
    if (pars.size() < 1)
9157
    {
9158
        MSG_ERROR("Expecting at least 1 parameter but got " << pars.size() << "! Ignoring command.");
9159
        return;
9160
    }
9161
 
9162
    TError::clear();
9163
    int btState = atoi(pars[0].c_str());
9164
 
9165
    vector<TMap::MAP_T> map = findButtons(port, channels);
9166
 
9167
    if (TError::isError() || map.empty())
9168
        return;
9169
 
9170
    vector<Button::TButton *> buttons = collectButtons(map);
9171
 
9172
    if (buttons.size() > 0)
9173
    {
9174
        Button::TButton *bt = buttons[0];
9175
 
9176
        if (btState == 0)       // All instances?
9177
        {
9178
            int bst = bt->getNumberInstances();
9179
 
9180
            for (int i = 0; i < bst; i++)
9181
                sendCustomEvent(i + 1, bt->getTextWordWrap(i), 0, "", 1010, bt->getChannelPort(), bt->getChannelNumber());
9182
        }
9183
        else
9184
            sendCustomEvent(btState, bt->getTextWordWrap(btState-1), 0, "", 1010, bt->getChannelPort(), bt->getChannelNumber());
9185
    }
9186
}
9187
 
9188
/**
9189
 * Clear all page flips from a button.
9190
 */
9191
void TPageManager::doCPF(int port, vector<int>& channels, vector<string>&)
9192
{
9193
    DECL_TRACER("TPageManager::doCPF(int port, vector<int>& channels, vector<string>& pars)");
9194
 
9195
    TError::clear();
9196
    vector<TMap::MAP_T> map = findButtons(port, channels);
9197
 
9198
    if (TError::isError() || map.empty())
9199
        return;
9200
 
9201
    vector<Button::TButton *> buttons = collectButtons(map);
9202
 
9203
    if (buttons.size() > 0)
9204
    {
9205
        vector<Button::TButton *>::iterator mapIter;
9206
 
9207
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
9208
        {
9209
            Button::TButton *bt = *mapIter;
9210
//            setButtonCallbacks(bt);
9211
            bt->clearPushFunctions();
9212
        }
9213
    }
9214
}
9215
 
9216
/**
9217
 * Delete page flips from button if it already exists.
9218
 */
9219
void TPageManager::doDPF(int port, vector<int>& channels, vector<string>& pars)
9220
{
9221
    DECL_TRACER("TPageManager::doDPF(int port, vector<int>& channels, vector<string>& pars)");
9222
 
9223
    if (pars.size() < 1)
9224
    {
9225
        MSG_ERROR("Expecting at least 1 parameter but got " << pars.size() << "! Ignoring command.");
9226
        return;
9227
    }
9228
 
9229
    TError::clear();
9230
    string action = pars[0];
9231
    string pname;
9232
 
9233
    if (pars.size() >= 2)
9234
    {
9235
        pname = pars[1];
9236
        vector<Button::TButton *> list;
9237
        // First we search for a subpage because this is more likely
9238
        TSubPage *spg = getSubPage(pname);
9239
 
9240
        if (spg)
9241
            list = spg->getButtons(port, channels[0]);
9242
        else    // Then for a page
9243
        {
9244
            TPage *pg = getPage(pname);
9245
 
9246
            if (pg)
9247
                list = pg->getButtons(port, channels[0]);
9248
            else
9249
            {
9250
                MSG_WARNING("The name " << pname << " doesn't name either a page or a subpage!");
9251
                return;
9252
            }
9253
        }
9254
 
9255
        if (list.empty())
9256
            return;
9257
 
9258
        vector<Button::TButton *>::iterator it;
9259
 
9260
        for (it = list.begin(); it != list.end(); it++)
9261
        {
9262
            Button::TButton *bt = *it;
9263
//            setButtonCallbacks(bt);
9264
            bt->clearPushFunction(action);
9265
        }
9266
 
9267
        return;
9268
    }
9269
 
9270
    // Here we don't have a page name
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
//            setButtonCallbacks(bt);
9286
            bt->clearPushFunction(action);
9287
        }
9288
    }
9289
}
9290
 
9291
/**
9292
 * Enable or disable buttons with a set variable text range.
9293
 */
9294
void TPageManager::doENA(int port, vector<int>& channels, vector<string>& pars)
9295
{
9296
    DECL_TRACER("TPageManager::doENA(int port, vector<int>& channels, vector<string>& pars)");
9297
 
9298
    if (pars.empty())
9299
    {
9300
        MSG_ERROR("Expecting 1 parameter but got none! Ignoring command.");
9301
#if TESTMODE == 1
9302
        setAllDone();
9303
#endif
9304
        return;
9305
    }
9306
 
9307
    TError::clear();
9308
    int cvalue = atoi(pars[0].c_str());
9309
 
9310
    vector<TMap::MAP_T> map = findButtons(port, channels);
9311
 
9312
    if (TError::isError() || map.empty())
9313
    {
9314
#if TESTMODE == 1
9315
        setAllDone();
9316
#endif
9317
        return;
9318
    }
9319
 
9320
    vector<Button::TButton *> buttons = collectButtons(map);
9321
 
9322
    if (buttons.size() > 0)
9323
    {
9324
        vector<Button::TButton *>::iterator mapIter;
9325
 
9326
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
9327
        {
9328
            Button::TButton *bt = *mapIter;
9329
            bt->setEnable(((cvalue)?true:false));
9330
#if TESTMODE == 1
9331
            __success = true;
9332
 
9333
            if (_gTestMode)
9334
                _gTestMode->setResult(intToString(cvalue));
9335
#endif
9336
        }
9337
    }
9338
#if TESTMODE == 1
9339
    setAllDone();
9340
#endif
9341
}
9342
 
9343
/**
9344
 * Set a font to a specific Font ID value for those buttons with a defined
9345
 * address range. Font ID numbers are generated by the TPDesign4 programmers
9346
 * report.
9347
 */
9348
void TPageManager::doFON(int port, vector<int>& channels, vector<string>& pars)
9349
{
9350
    DECL_TRACER("TPageManager::doFON(int port, vector<int>& channels, vector<string>& pars)");
9351
 
9352
    if (pars.size() < 2)
9353
    {
9354
        MSG_ERROR("Expecting 2 parameters but got " << pars.size() << "! Ignoring command.");
9355
#if TESTMODE == 1
9356
        setAllDone();
9357
#endif
9358
        return;
9359
    }
9360
 
9361
    TError::clear();
9362
    int btState = atoi(pars[0].c_str()) - 1;
9363
    int fvalue = atoi(pars[1].c_str());
9364
 
9365
    vector<TMap::MAP_T> map = findButtons(port, channels);
9366
 
9367
    if (TError::isError() || map.empty())
9368
        return;
9369
 
9370
    vector<Button::TButton *> buttons = collectButtons(map);
9371
 
9372
    if (buttons.size() > 0)
9373
    {
9374
        vector<Button::TButton *>::iterator mapIter;
9375
 
9376
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
9377
        {
9378
            Button::TButton *bt = *mapIter;
9379
            bt->setFont(fvalue, btState);
9380
#if TESTMODE == 1
9381
            if (_gTestMode)
9382
                _gTestMode->setResult(intToString(bt->getFontIndex(btState < 0 ? 0 : btState)));
9383
#endif
9384
        }
9385
    }
9386
#if TESTMODE == 1
9387
    setDone();
9388
#endif
9389
}
9390
 
9391
void TPageManager::getFON(int port, vector<int>& channels, vector<string>& pars)
9392
{
9393
    DECL_TRACER("TPageManager::getFON(int port, vector<int>& channels, vector<string>& pars)");
9394
 
9395
    if (pars.size() < 1)
9396
    {
9397
        MSG_ERROR("Expecting at least 1 parameter but got " << pars.size() << "! Ignoring command.");
9398
#if TESTMODE == 1
9399
        setAllDone();
9400
#endif
9401
        return;
9402
    }
9403
 
9404
    TError::clear();
9405
    int btState = atoi(pars[0].c_str());
9406
 
9407
    vector<TMap::MAP_T> map = findButtons(port, channels);
9408
 
9409
    if (TError::isError() || map.empty())
9410
    {
9411
#if TESTMODE == 1
9412
        setAllDone();
9413
#endif
9414
        return;
9415
    }
9416
 
9417
    vector<Button::TButton *> buttons = collectButtons(map);
9418
 
9419
    if (buttons.size() > 0)
9420
    {
9421
        Button::TButton *bt = buttons[0];
9422
 
9423
        if (btState == 0)       // All instances?
9424
        {
9425
            int bst = bt->getNumberInstances();
9426
 
9427
            for (int i = 0; i < bst; i++)
9428
                sendCustomEvent(i + 1, bt->getFontIndex(i), 0, "", 1007, bt->getChannelPort(), bt->getChannelNumber());
9429
        }
9430
        else
9431
            sendCustomEvent(btState, bt->getFontIndex(btState - 1), 0, "", 1007, bt->getChannelPort(), bt->getChannelNumber());
9432
#if TESTMODE == 1
9433
        if (_gTestMode)
9434
            _gTestMode->setResult(intToString(bt->getFontIndex(btState < 0 ? 0 : btState)));
9435
#endif
9436
    }
9437
#if TESTMODE == 1
9438
    __success = true;
9439
    setAllDone();
9440
#endif
9441
}
9442
 
9443
void TPageManager::doGDI(int port, vector<int>& channels, vector<std::string>& pars)
9444
{
9445
    DECL_TRACER("TPageManager::doGDI(int port, vector<int>& channels, vector<std::string>& pars)");
9446
 
9447
    if (pars.size() < 1)
9448
    {
9449
        MSG_ERROR("Expecting 1 parameter but got " << pars.size() << "! Ignoring command.");
9450
        return;
9451
    }
9452
 
9453
    TError::clear();
9454
    int inc = atoi(pars[0].c_str());
9455
 
9456
    if (inc < 0)
9457
    {
9458
        MSG_ERROR("Invalid drag increment of " << inc << "!");
9459
        return;
9460
    }
9461
 
9462
    vector<TMap::MAP_T> map = findButtons(port, channels);
9463
 
9464
    if (TError::isError() || map.empty())
9465
        return;
9466
 
9467
    vector<Button::TButton *> buttons = collectButtons(map);
9468
 
9469
    if (buttons.size() > 0)
9470
    {
9471
        vector<Button::TButton *>::iterator mapIter;
9472
 
9473
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
9474
        {
9475
            Button::TButton *bt = *mapIter;
9476
            bt->setBargraphDragIncrement(inc);
9477
        }
9478
    }
9479
}
9480
/*
9481
 * Invert the joystick axis to move the origin to another corner.
9482
 */
9483
void TPageManager::doGIV(int port, vector<int>& channels, vector<std::string>& pars)
9484
{
9485
    DECL_TRACER("TPageManager::doGIV(int port, vector<int>& channels, vector<std::string>& pars)");
9486
 
9487
    if (pars.empty())
9488
        return;
9489
 
9490
    TError::clear();
9491
    int inv = atoi(pars[0].c_str());
9492
 
9493
    if (inv < 0 || inv > 3)
9494
    {
9495
        MSG_ERROR("Invalid invert type " << inv);
9496
        return;
9497
    }
9498
 
9499
    vector<TMap::MAP_T> map = findButtons(port, channels);
9500
 
9501
    if (TError::isError() || map.empty())
9502
        return;
9503
 
9504
    vector<Button::TButton *> buttons = collectButtons(map);
9505
 
9506
    if (buttons.size() > 0)
9507
    {
9508
        vector<Button::TButton *>::iterator mapIter;
9509
 
9510
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
9511
        {
9512
            Button::TButton *bt = *mapIter;
9513
            bt->setBargraphInvert(inv);
9514
        }
9515
    }
9516
}
9517
 
9518
/**
9519
 * Change the bargraph upper limit.
9520
 */
9521
void TPageManager::doGLH(int port, vector<int>& channels, vector<std::string>& pars)
9522
{
9523
    DECL_TRACER("TPageManager::doGLH(int port, vector<int>& channels, vector<std::string>& pars)");
9524
 
9525
    if (pars.size() < 1)
9526
    {
9527
        MSG_ERROR("Expecting 1 parameter but got " << pars.size() << "! Ignoring command.");
9528
        return;
9529
    }
9530
 
9531
    TError::clear();
9532
    int limit = atoi(pars[0].c_str());
9533
 
9534
    if (limit < 1)
9535
    {
9536
        MSG_ERROR("Invalid upper limit " << limit << "!");
9537
        return;
9538
    }
9539
 
9540
    vector<TMap::MAP_T> map = findButtons(port, channels);
9541
 
9542
    if (TError::isError() || map.empty())
9543
        return;
9544
 
9545
    vector<Button::TButton *> buttons = collectButtons(map);
9546
 
9547
    if (buttons.size() > 0)
9548
    {
9549
        vector<Button::TButton *>::iterator mapIter;
9550
 
9551
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
9552
        {
9553
            Button::TButton *bt = *mapIter;
9554
            bt->setBargraphUpperLimit(limit);
9555
        }
9556
    }
9557
}
9558
 
9559
/**
9560
 * Change the bargraph lower limit.
9561
 */
9562
void TPageManager::doGLL(int port, vector<int>& channels, vector<std::string>& pars)
9563
{
9564
    DECL_TRACER("TPageManager::doGLL(int port, vector<int>& channels, vector<std::string>& pars)");
9565
 
9566
    if (pars.size() < 1)
9567
    {
9568
        MSG_ERROR("Expecting 1 parameter but got " << pars.size() << "! Ignoring command.");
9569
        return;
9570
    }
9571
 
9572
    TError::clear();
9573
    int limit = atoi(pars[0].c_str());
9574
 
9575
    if (limit < 1)
9576
    {
9577
        MSG_ERROR("Invalid lower limit " << limit << "!");
9578
        return;
9579
    }
9580
 
9581
    vector<TMap::MAP_T> map = findButtons(port, channels);
9582
 
9583
    if (TError::isError() || map.empty())
9584
        return;
9585
 
9586
    vector<Button::TButton *> buttons = collectButtons(map);
9587
 
9588
    if (buttons.size() > 0)
9589
    {
9590
        vector<Button::TButton *>::iterator mapIter;
9591
 
9592
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
9593
        {
9594
            Button::TButton *bt = *mapIter;
9595
            bt->setBargraphLowerLimit(limit);
9596
        }
9597
    }
9598
}
9599
 
9600
/*
9601
 * Change the bargraph slider color or joystick cursor color.
9602
 */
9603
void TPageManager::doGSC(int port, vector<int>& channels, vector<string>& pars)
9604
{
9605
    DECL_TRACER("TPageManager::doGSC(int port, vector<int>& channels, vector<string>& pars)");
9606
 
9607
    if (pars.size() < 1)
9608
    {
9609
        MSG_ERROR("Expecting 1 parameter but got " << pars.size() << "! Ignoring command.");
9610
        return;
9611
    }
9612
 
9613
    TError::clear();
9614
    string color = pars[0];
9615
    vector<TMap::MAP_T> map = findButtons(port, channels);
9616
 
9617
    if (TError::isError() || map.empty())
9618
        return;
9619
 
9620
    vector<Button::TButton *> buttons = collectButtons(map);
9621
 
9622
    if (buttons.size() > 0)
9623
    {
9624
        vector<Button::TButton *>::iterator mapIter;
9625
 
9626
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
9627
        {
9628
            Button::TButton *bt = *mapIter;
9629
            bt->setBargraphSliderColor(color);
9630
        }
9631
    }
9632
}
9633
 
9634
/*
9635
 * Set bargraph ramp down time in 1/10 seconds.
9636
 */
9637
void TPageManager::doGRD(int port, vector<int>& channels, vector<string>& pars)
9638
{
9639
    DECL_TRACER("TPageManager::doGRD(int port, vector<int>& channels, vector<string>& pars)");
9640
 
9641
    if (pars.size() < 1)
9642
    {
9643
        MSG_ERROR("Expecting 1 parameter but got " << pars.size() << "! Ignoring command.");
9644
        return;
9645
    }
9646
 
9647
    TError::clear();
9648
    int t = atoi(pars[0].c_str());
9649
 
9650
    if (t < 0)
9651
    {
9652
        MSG_ERROR("Invalid ramp down time limit " << t << "!");
9653
        return;
9654
    }
9655
 
9656
    vector<TMap::MAP_T> map = findButtons(port, channels);
9657
 
9658
    if (TError::isError() || map.empty())
9659
        return;
9660
 
9661
    vector<Button::TButton *> buttons = collectButtons(map);
9662
 
9663
    if (buttons.size() > 0)
9664
    {
9665
        vector<Button::TButton *>::iterator mapIter;
9666
 
9667
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
9668
        {
9669
            Button::TButton *bt = *mapIter;
9670
            bt->setBargraphRampDownTime(t);
9671
        }
9672
    }
9673
}
9674
 
9675
/*
9676
 * Set bargraph ramp up time in 1/10 seconds.
9677
 */
9678
void TPageManager::doGRU(int port, vector<int>& channels, vector<string>& pars)
9679
{
9680
    DECL_TRACER("TPageManager::doGRU(int port, vector<int>& channels, vector<string>& pars)");
9681
 
9682
    if (pars.size() < 1)
9683
    {
9684
        MSG_ERROR("Expecting 1 parameter but got " << pars.size() << "! Ignoring command.");
9685
        return;
9686
    }
9687
 
9688
    TError::clear();
9689
    int t = atoi(pars[0].c_str());
9690
 
9691
    if (t < 0)
9692
    {
9693
        MSG_ERROR("Invalid ramp up time limit " << t << "!");
9694
        return;
9695
    }
9696
 
9697
    vector<TMap::MAP_T> map = findButtons(port, channels);
9698
 
9699
    if (TError::isError() || map.empty())
9700
        return;
9701
 
9702
    vector<Button::TButton *> buttons = collectButtons(map);
9703
 
9704
    if (buttons.size() > 0)
9705
    {
9706
        vector<Button::TButton *>::iterator mapIter;
9707
 
9708
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
9709
        {
9710
            Button::TButton *bt = *mapIter;
9711
            bt->setBargraphRampUpTime(t);
9712
        }
9713
    }
9714
}
9715
 
9716
/*
9717
 * Change the bargraph slider name or joystick cursor name.
9718
 */
9719
void TPageManager::doGSN(int port, vector<int>& channels, vector<string>& pars)
9720
{
9721
    DECL_TRACER("TPageManager::doGSN(int port, vector<int>& channels, vector<string>& pars)");
9722
 
9723
    if (pars.size() < 1)
9724
    {
9725
        MSG_ERROR("Expecting 1 parameter but got " << pars.size() << "! Ignoring command.");
9726
        return;
9727
    }
9728
 
9729
    TError::clear();
9730
    string name = pars[0];
9731
    vector<TMap::MAP_T> map = findButtons(port, channels);
9732
 
9733
    if (TError::isError() || map.empty())
9734
        return;
9735
 
9736
    vector<Button::TButton *> buttons = collectButtons(map);
9737
 
9738
    if (buttons.size() > 0)
9739
    {
9740
        vector<Button::TButton *>::iterator mapIter;
9741
 
9742
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
9743
        {
9744
            Button::TButton *bt = *mapIter;
9745
            bt->setBargraphSliderName(name);
9746
        }
9747
    }
9748
}
9749
 
9750
/**
9751
 * Set the icon to a button.
9752
 */
9753
void TPageManager::doICO(int port, vector<int>& channels, vector<string>& pars)
9754
{
9755
    DECL_TRACER("TPageManager::doICO(int port, vector<int>& channels, vector<string>& pars)");
9756
 
9757
    if (pars.size() < 2)
9758
    {
9759
        MSG_ERROR("Expecting 2 parameters but got " << pars.size() << "! Ignoring command.");
9760
        return;
9761
    }
9762
 
9763
    TError::clear();
9764
    int btState = atoi(pars[0].c_str());
9765
    int iconIdx = atoi(pars[1].c_str());
9766
 
9767
    vector<TMap::MAP_T> map = findButtons(port, channels);
9768
 
9769
    if (TError::isError() || map.empty())
9770
        return;
9771
 
9772
    vector<Button::TButton *> buttons = collectButtons(map);
9773
 
9774
    if (buttons.size() > 0)
9775
    {
9776
        vector<Button::TButton *>::iterator mapIter;
9777
 
9778
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
9779
        {
9780
            Button::TButton *bt = *mapIter;
9781
 
9782
            if (btState == 0)       // All instances?
9783
            {
9784
                if (iconIdx > 0)
9785
                    bt->setIcon(iconIdx, -1);
9786
                else
9787
                    bt->revokeIcon(-1);
9788
            }
9789
            else if (iconIdx > 0)
9790
                bt->setIcon(iconIdx, btState - 1);
9791
            else
9792
                bt->revokeIcon(btState - 1);
9793
        }
9794
    }
9795
}
9796
 
9797
void TPageManager::getICO(int port, vector<int>& channels, vector<string>& pars)
9798
{
9799
    DECL_TRACER("TPageManager::getICO(int port, vector<int>& channels, vector<string>& pars)");
9800
 
9801
    if (pars.size() < 1)
9802
    {
9803
        MSG_ERROR("Expecting at least 1 parameter but got " << pars.size() << "! Ignoring command.");
9804
        return;
9805
    }
9806
 
9807
    TError::clear();
9808
    int btState = atoi(pars[0].c_str());
9809
 
9810
    vector<TMap::MAP_T> map = findButtons(port, channels);
9811
 
9812
    if (TError::isError() || map.empty())
9813
        return;
9814
 
9815
    vector<Button::TButton *> buttons = collectButtons(map);
9816
 
9817
    if (buttons.size() > 0)
9818
    {
9819
        Button::TButton *bt = buttons[0];
9820
 
9821
        if (btState == 0)       // All instances?
9822
        {
9823
            int bst = bt->getNumberInstances();
9824
 
9825
            for (int i = 0; i < bst; i++)
9826
                sendCustomEvent(i + 1, bt->getIconIndex(i), 0, "", 1003, bt->getChannelPort(), bt->getChannelNumber());
9827
        }
9828
        else
9829
            sendCustomEvent(btState, bt->getIconIndex(btState - 1), 0, "", 1003, bt->getChannelPort(), bt->getChannelNumber());
9830
    }
9831
}
9832
 
9833
/**
9834
 * Set bitmap/picture alignment using a numeric keypad layout for those buttons
9835
 * with a defined address range. The alignment of 0 is followed by
9836
 * ',<left>,<top>'. The left and top coordinates are relative to the upper left
9837
 * corner of the button.
9838
 */
9839
void TPageManager::doJSB(int port, vector<int>& channels, vector<string>& pars)
9840
{
9841
    DECL_TRACER("TPageManager::doJSB(int port, vector<int>& channels, vector<string>& pars)");
9842
 
9843
    if (pars.size() < 2)
9844
    {
9845
        MSG_ERROR("Expecting at least 2 parameters but got less! Ignoring command.");
9846
        return;
9847
    }
9848
 
9849
    TError::clear();
9850
    int btState = atoi(pars[0].c_str());
9851
    int align = atoi(pars[1].c_str());
9852
    int x = 0, y = 0;
9853
 
9854
    if (!align && pars.size() >= 3)
9855
    {
9856
        x = atoi(pars[2].c_str());
9857
 
9858
        if (pars.size() >= 4)
9859
            y = atoi(pars[3].c_str());
9860
    }
9861
 
9862
    vector<TMap::MAP_T> map = findButtons(port, channels);
9863
 
9864
    if (TError::isError() || map.empty())
9865
        return;
9866
 
9867
    vector<Button::TButton *> buttons = collectButtons(map);
9868
 
9869
    if (buttons.size() > 0)
9870
    {
9871
        vector<Button::TButton *>::iterator mapIter;
9872
 
9873
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
9874
        {
9875
            Button::TButton *bt = *mapIter;
9876
 
9877
            if (btState == 0)
9878
                bt->setBitmapJustification(align, x, y, -1);
9879
            else
9880
                bt->setBitmapJustification(align, x, y, btState-1);
9881
        }
9882
    }
9883
}
9884
 
9885
void TPageManager::getJSB(int port, vector<int>& channels, vector<string>& pars)
9886
{
9887
    DECL_TRACER("TPageManager::getJSB(int port, vector<int>& channels, vector<string>& pars)");
9888
 
9889
    if (pars.size() < 1)
9890
    {
9891
        MSG_ERROR("Expecting at least 1 parameter but got " << pars.size() << "! Ignoring command.");
9892
        return;
9893
    }
9894
 
9895
    TError::clear();
9896
    int btState = atoi(pars[0].c_str());
9897
    int j, x, y;
9898
 
9899
    vector<TMap::MAP_T> map = findButtons(port, channels);
9900
 
9901
    if (TError::isError() || map.empty())
9902
        return;
9903
 
9904
    vector<Button::TButton *> buttons = collectButtons(map);
9905
 
9906
    if (buttons.size() > 0)
9907
    {
9908
        Button::TButton *bt = buttons[0];
9909
 
9910
        if (btState == 0)       // All instances?
9911
        {
9912
            int bst = bt->getNumberInstances();
9913
 
9914
            for (int i = 0; i < bst; i++)
9915
            {
9916
                j = bt->getBitmapJustification(&x, &y, i);
9917
                sendCustomEvent(i + 1, j, 0, "", 1005, bt->getChannelPort(), bt->getChannelNumber());
9918
            }
9919
        }
9920
        else
9921
        {
9922
            j = bt->getBitmapJustification(&x, &y, btState-1);
9923
            sendCustomEvent(btState, j, 0, "", 1005, bt->getChannelPort(), bt->getChannelNumber());
9924
        }
9925
    }
9926
}
9927
 
9928
/**
9929
 * Set icon alignment using a numeric keypad layout for those buttons with a
9930
 * defined address range. The alignment of 0 is followed by ',<left>,<top>'.
9931
 * The left and top coordinates are relative to the upper left corner of the
9932
 * button.
9933
 */
9934
void TPageManager::doJSI(int port, vector<int>& channels, vector<string>& pars)
9935
{
9936
    DECL_TRACER("TPageManager::doJSB(int port, vector<int>& channels, vector<string>& pars)");
9937
 
9938
    if (pars.size() < 2)
9939
    {
9940
        MSG_ERROR("Expecting at least 2 parameters but got less! Ignoring command.");
9941
        return;
9942
    }
9943
 
9944
    TError::clear();
9945
    int btState = atoi(pars[0].c_str());
9946
    int align = atoi(pars[1].c_str());
9947
    int x = 0, y = 0;
9948
 
9949
    if (!align && pars.size() >= 3)
9950
    {
9951
        x = atoi(pars[2].c_str());
9952
 
9953
        if (pars.size() >= 4)
9954
            y = atoi(pars[3].c_str());
9955
    }
9956
 
9957
    vector<TMap::MAP_T> map = findButtons(port, channels);
9958
 
9959
    if (TError::isError() || map.empty())
9960
        return;
9961
 
9962
    vector<Button::TButton *> buttons = collectButtons(map);
9963
 
9964
    if (buttons.size() > 0)
9965
    {
9966
        vector<Button::TButton *>::iterator mapIter;
9967
 
9968
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
9969
        {
9970
            Button::TButton *bt = *mapIter;
9971
 
9972
            if (btState == 0)
9973
                bt->setIconJustification(align, x, y, -1);
9974
            else
9975
                bt->setIconJustification(align, x, y, btState-1);
9976
        }
9977
    }
9978
}
9979
 
9980
void TPageManager::getJSI(int port, vector<int>& channels, vector<string>& pars)
9981
{
9982
    DECL_TRACER("TPageManager::getJSB(int port, vector<int>& channels, vector<string>& pars)");
9983
 
9984
    if (pars.size() < 1)
9985
    {
9986
        MSG_ERROR("Expecting at least 1 parameter but got " << pars.size() << "! Ignoring command.");
9987
        return;
9988
    }
9989
 
9990
    TError::clear();
9991
    int btState = atoi(pars[0].c_str());
9992
    int j, x, y;
9993
 
9994
    vector<TMap::MAP_T> map = findButtons(port, channels);
9995
 
9996
    if (TError::isError() || map.empty())
9997
        return;
9998
 
9999
    vector<Button::TButton *> buttons = collectButtons(map);
10000
 
10001
    if (buttons.size() > 0)
10002
    {
10003
        Button::TButton *bt = buttons[0];
10004
 
10005
        if (btState == 0)       // All instances?
10006
        {
10007
            int bst = bt->getNumberInstances();
10008
 
10009
            for (int i = 0; i < bst; i++)
10010
            {
10011
                j = bt->getIconJustification(&x, &y, i);
10012
                sendCustomEvent(i + 1, j, 0, "", 1006, bt->getChannelPort(), bt->getChannelNumber());
10013
            }
10014
        }
10015
        else
10016
        {
10017
            j = bt->getIconJustification(&x, &y, btState-1);
10018
            sendCustomEvent(btState, j, 0, "", 1006, bt->getChannelPort(), bt->getChannelNumber());
10019
        }
10020
    }
10021
}
10022
 
10023
void TPageManager::doJST(int port, vector<int>& channels, vector<string>& pars)
10024
{
10025
    DECL_TRACER("TPageManager::doJSB(int port, vector<int>& channels, vector<string>& pars)");
10026
 
10027
    if (pars.size() < 2)
10028
    {
10029
        MSG_ERROR("Expecting at least 2 parameters but got less! Ignoring command.");
10030
        return;
10031
    }
10032
 
10033
    TError::clear();
10034
    int btState = atoi(pars[0].c_str());
10035
    int align = atoi(pars[1].c_str());
10036
    int x = 0, y = 0;
10037
 
10038
    if (!align && pars.size() >= 3)
10039
    {
10040
        x = atoi(pars[2].c_str());
10041
 
10042
        if (pars.size() >= 4)
10043
            y = atoi(pars[3].c_str());
10044
    }
10045
 
10046
    vector<TMap::MAP_T> map = findButtons(port, channels);
10047
 
10048
    if (TError::isError() || map.empty())
10049
        return;
10050
 
10051
    vector<Button::TButton *> buttons = collectButtons(map);
10052
 
10053
    if (buttons.size() > 0)
10054
    {
10055
        vector<Button::TButton *>::iterator mapIter;
10056
 
10057
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
10058
        {
10059
            Button::TButton *bt = *mapIter;
10060
 
10061
            if (btState == 0)
10062
                bt->setTextJustification(align, x, y, -1);
10063
            else
10064
                bt->setTextJustification(align, x, y, btState-1);
10065
        }
10066
    }
10067
}
10068
 
10069
void TPageManager::getJST(int port, vector<int>& channels, vector<string>& pars)
10070
{
10071
    DECL_TRACER("TPageManager::getJSB(int port, vector<int>& channels, vector<string>& pars)");
10072
 
10073
    if (pars.size() < 1)
10074
    {
10075
        MSG_ERROR("Expecting at least 1 parameter but got " << pars.size() << "! Ignoring command.");
10076
        return;
10077
    }
10078
 
10079
    TError::clear();
10080
    int btState = atoi(pars[0].c_str());
10081
    int j, x, y;
10082
 
10083
    vector<TMap::MAP_T> map = findButtons(port, channels);
10084
 
10085
    if (TError::isError() || map.empty())
10086
        return;
10087
 
10088
    vector<Button::TButton *> buttons = collectButtons(map);
10089
 
10090
    if (buttons.size() > 0)
10091
    {
10092
        Button::TButton *bt = buttons[0];
10093
 
10094
        if (btState == 0)       // All instances?
10095
        {
10096
            int bst = bt->getNumberInstances();
10097
 
10098
            for (int i = 0; i < bst; i++)
10099
            {
10100
                j = bt->getTextJustification(&x, &y, i);
10101
                sendCustomEvent(i + 1, j, 0, "", 1004, bt->getChannelPort(), bt->getChannelNumber());
10102
            }
10103
        }
10104
        else
10105
        {
10106
            j = bt->getTextJustification(&x, &y, btState-1);
10107
            sendCustomEvent(btState, j, 0, "", 1004, bt->getChannelPort(), bt->getChannelNumber());
10108
        }
10109
    }
10110
}
10111
 
10112
/**
10113
 * @brief TPageManager::getMSP
10114
 * Sets the speed of a marquee line. Allowed range is from 1 to 10, where 10 is
10115
 * the fastest speed.
10116
 *
10117
 * @param port      The port number
10118
 * @param channels  The channels
10119
 * @param pars      Parameters
10120
 */
10121
void TPageManager::doMSP(int port, vector<int>& channels, vector<string>& pars)
10122
{
10123
    DECL_TRACER("TPageManager::getMSP(int port, vector<int>& channels, vector<string>& pars)");
10124
 
10125
    if (pars.size() < 2)
10126
    {
10127
        MSG_ERROR("Expecting at least 2 parameter but got less! Command ignored.");
10128
        return;
10129
    }
10130
 
10131
    TError::clear();
10132
    int btState = atoi(pars[0].c_str()) - 1;
10133
    int speed = atoi(pars[1].c_str());
10134
 
10135
    if (speed < 1 || speed > 10)
10136
    {
10137
        MSG_ERROR("Speed for marquee line is out of range!");
10138
        return;
10139
    }
10140
 
10141
    vector<TMap::MAP_T> map = findButtons(port, channels);
10142
 
10143
    if (TError::isError() || map.empty())
10144
        return;
10145
 
10146
    vector<Button::TButton *> buttons = collectButtons(map);
10147
 
10148
    if (buttons.size() > 0)
10149
    {
10150
        vector<Button::TButton *>::iterator iter;
10151
 
10152
        for (iter = buttons.begin(); iter != buttons.end(); ++iter)
10153
        {
10154
            Button::TButton *bt = buttons[0];
10155
            bt->setMarqueeSpeed(speed, btState);
10156
        }
10157
    }
10158
}
10159
 
10160
/**
10161
 * Show or hide a button with a set variable text range.
10162
 */
10163
void TPageManager::doSHO(int port, vector<int>& channels, vector<string>& pars)
10164
{
10165
    DECL_TRACER("TPageManager::doSHO(int port, vector<int>& channels, vector<string>& pars)");
10166
 
10167
    if (pars.empty())
10168
    {
10169
        MSG_ERROR("Expecting 1 parameter but got none! Ignoring command.");
10170
        return;
10171
    }
10172
 
10173
    TError::clear();
10174
    int cvalue = atoi(pars[0].c_str());
10175
 
10176
    vector<TMap::MAP_T> map = findButtons(port, channels);
10177
 
10178
    if (TError::isError() || map.empty())
10179
        return;
10180
 
10181
    vector<Button::TButton *> buttons = collectButtons(map);
10182
 
10183
    if (buttons.size() > 0)
10184
    {
10185
        vector<Button::TButton *>::iterator mapIter;
10186
 
10187
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
10188
        {
10189
            Button::TButton *bt = *mapIter;
10190
 
10191
            int pgID = (bt->getParent() >> 16) & 0x0000ffff;
10192
            bool pVisible = false;
10193
 
10194
            if (pgID < 500)
10195
            {
10196
                TPage *pg = getPage(pgID);
10197
 
10198
                if (pg && pg->isVisilble())
10199
                    pVisible = true;
10200
            }
10201
            else
10202
            {
10203
                TSubPage *pg = getSubPage(pgID);
10204
 
10205
                if (pg && pg->isVisible())
10206
                    pVisible = true;
10207
            }
10208
 
10209
            bool oldV = bt->isVisible();
10210
            bool visible = cvalue ? true : false;
10211
            MSG_DEBUG("Button " << bt->getButtonIndex() << ", \"" << bt->getButtonName() << "\" set " << (visible ? "VISIBLE" : "HIDDEN") << " (Previous: " << (oldV ? "VISIBLE" : "HIDDEN") << ")");
10212
 
10213
            if (visible != oldV)
10214
            {
10215
                bt->setVisible(visible);
10216
 
10217
                if (pVisible)
10218
                {
10219
                    setButtonCallbacks(bt);
10220
 
10221
                    if (_setVisible)
10222
                        _setVisible(bt->getHandle(), visible);
10223
                    else
10224
                        bt->refresh();
10225
                }
10226
            }
10227
        }
10228
    }
10229
}
10230
 
10231
void TPageManager::doTEC(int port, vector<int>& channels, vector<string>& pars)
10232
{
10233
    DECL_TRACER("TPageManager::doTEC(int port, vector<int>& channels, vector<string>& pars)");
10234
 
10235
    if (pars.size() < 2)
10236
    {
10237
        MSG_ERROR("Expecting at least 2 parameters but got less! Ignoring command.");
10238
        return;
10239
    }
10240
 
10241
    TError::clear();
10242
    int btState = atoi(pars[0].c_str());
10243
    string color = pars[1];
10244
 
10245
    vector<TMap::MAP_T> map = findButtons(port, channels);
10246
 
10247
    if (TError::isError() || map.empty())
10248
        return;
10249
 
10250
    vector<Button::TButton *> buttons = collectButtons(map);
10251
 
10252
    if (buttons.size() > 0)
10253
    {
10254
        vector<Button::TButton *>::iterator mapIter;
10255
 
10256
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
10257
        {
10258
            Button::TButton *bt = *mapIter;
10259
 
10260
            if (btState == 0)
10261
                bt->setTextEffectColor(color);
10262
            else
10263
                bt->setTextEffectColor(color, btState-1);
10264
        }
10265
    }
10266
}
10267
 
10268
void TPageManager::getTEC(int port, vector<int>& channels, vector<string>& pars)
10269
{
10270
    DECL_TRACER("TPageManager::getTEC(int port, vector<int>& channels, vector<string>& pars)");
10271
 
10272
    if (pars.size() < 1)
10273
    {
10274
        MSG_ERROR("Expecting at least 1 parameter but got " << pars.size() << "! Ignoring command.");
10275
        return;
10276
    }
10277
 
10278
    TError::clear();
10279
    int btState = atoi(pars[0].c_str());
10280
 
10281
    vector<TMap::MAP_T> map = findButtons(port, channels);
10282
 
10283
    if (TError::isError() || map.empty())
10284
        return;
10285
 
10286
    vector<Button::TButton *> buttons = collectButtons(map);
10287
 
10288
    if (buttons.size() > 0)
10289
    {
10290
        Button::TButton *bt = buttons[0];
10291
 
10292
        if (btState == 0)       // All instances?
10293
        {
10294
            int bst = bt->getNumberInstances();
10295
 
10296
            for (int i = 0; i < bst; i++)
10297
            {
10298
                string c = bt->getTextEffectColor(i);
10299
                sendCustomEvent(i + 1, (int)c.length(), 0, c, 1009, bt->getChannelPort(), bt->getChannelNumber());
10300
            }
10301
        }
10302
        else
10303
        {
10304
            string c = bt->getTextEffectColor(btState-1);
10305
            sendCustomEvent(btState, (int)c.length(), 0, c, 1009, bt->getChannelPort(), bt->getChannelNumber());
10306
        }
10307
    }
10308
}
10309
 
10310
void TPageManager::doTEF(int port, vector<int>& channels, vector<string>& pars)
10311
{
10312
    DECL_TRACER("TPageManager::doTEF(int port, vector<int>& channels, vector<string>& pars)");
10313
 
10314
    if (pars.size() < 2)
10315
    {
10316
        MSG_ERROR("Expecting at least 2 parameters but got less! Ignoring command.");
10317
        return;
10318
    }
10319
 
10320
    TError::clear();
10321
    int btState = atoi(pars[0].c_str());
10322
    string tef = pars[1];
10323
 
10324
    vector<TMap::MAP_T> map = findButtons(port, channels);
10325
 
10326
    if (TError::isError() || map.empty())
10327
        return;
10328
 
10329
    vector<Button::TButton *> buttons = collectButtons(map);
10330
 
10331
    if (buttons.size() > 0)
10332
    {
10333
        vector<Button::TButton *>::iterator mapIter;
10334
 
10335
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
10336
        {
10337
            Button::TButton *bt = *mapIter;
10338
 
10339
            if (btState == 0)
10340
                bt->setTextEffectName(tef);
10341
            else
10342
                bt->setTextEffectName(tef, btState-1);
10343
        }
10344
    }
10345
}
10346
 
10347
void TPageManager::getTEF(int port, vector<int>& channels, vector<string>& pars)
10348
{
10349
    DECL_TRACER("TPageManager::getTEF(int port, vector<int>& channels, vector<string>& pars)");
10350
 
10351
    if (pars.size() < 1)
10352
    {
10353
        MSG_ERROR("Expecting at least 1 parameter but got " << pars.size() << "! Ignoring command.");
10354
        return;
10355
    }
10356
 
10357
    TError::clear();
10358
    int btState = atoi(pars[0].c_str());
10359
 
10360
    vector<TMap::MAP_T> map = findButtons(port, channels);
10361
 
10362
    if (TError::isError() || map.empty())
10363
        return;
10364
 
10365
    vector<Button::TButton *> buttons = collectButtons(map);
10366
 
10367
    if (buttons.size() > 0)
10368
    {
10369
        Button::TButton *bt = buttons[0];
10370
 
10371
        if (btState == 0)       // All instances?
10372
        {
10373
            int bst = bt->getNumberInstances();
10374
 
10375
            for (int i = 0; i < bst; i++)
10376
            {
10377
                string c = bt->getTextEffectName(i);
10378
                sendCustomEvent(i + 1, (int)c.length(), 0, c, 1008, bt->getChannelPort(), bt->getChannelNumber());
10379
            }
10380
        }
10381
        else
10382
        {
10383
            string c = bt->getTextEffectName(btState-1);
10384
            sendCustomEvent(btState, (int)c.length(), 0, c, 1008, bt->getChannelPort(), bt->getChannelNumber());
10385
        }
10386
    }
10387
}
10388
 
10389
/**
10390
 * Assign a text string to those buttons with a defined address range.
10391
 * Sets Non-Unicode text.
10392
 */
10393
void TPageManager::doTXT(int port, vector<int>& channels, vector<string>& pars)
10394
{
10395
    DECL_TRACER("TPageManager::doTXT(int port, vector<int>& channels, vector<string>& pars)");
10396
 
10397
    if (pars.size() < 1)
10398
    {
10399
        MSG_ERROR("Expecting 1 parameters but got none! Ignoring command.");
10400
#if TESTMODE == 1
10401
        setAllDone();
10402
#endif
10403
        return;
10404
    }
10405
 
10406
    TError::clear();
10407
    int btState = atoi(pars[0].c_str()) - 1;
10408
    string text;
10409
 
10410
    // Every comma (,) in the text produces a new parameter. Therefor we must
10411
    // concatenate this parameters together and insert the comma.
10412
    if (pars.size() > 1)
10413
    {
10414
        for (size_t i = 1; i < pars.size(); ++i)
10415
        {
10416
            if (i > 1)
10417
                text += ",";
10418
 
10419
            text += pars[i];
10420
        }
10421
    }
10422
 
10423
    vector<TMap::MAP_T> map = findButtons(port, channels);
10424
 
10425
    if (TError::isError() || map.empty())
10426
    {
10427
#if TESTMODE == 1
10428
        setAllDone();
10429
#endif
10430
        return;
10431
    }
10432
 
10433
    vector<Button::TButton *> buttons = collectButtons(map);
10434
 
10435
    if (buttons.size() > 0)
10436
    {
10437
        vector<Button::TButton *>::iterator mapIter;
10438
 
10439
        for (mapIter = buttons.begin(); mapIter != buttons.end(); ++mapIter)
10440
        {
10441
            Button::TButton *bt = *mapIter;
10442
 
10443
            if (!bt)
10444
                continue;
10445
 
10446
            bt->setText(text, btState);
10447
#if TESTMODE == 1
10448
            if (_gTestMode)
10449
                _gTestMode->setResult(bt->getText(btState < 0 ? 0 : btState));
10450
 
10451
            __success = true;
10452
#endif
10453
        }
10454
    }
10455
#if TESTMODE == 1
10456
    setDone();
10457
#endif
10458
}
10459
 
10460
void TPageManager::getTXT(int port, vector<int>& channels, vector<string>& pars)
10461
{
10462
    DECL_TRACER("TPageManager::getTXT(int port, vector<int>& channels, vector<string>& pars)");
10463
 
10464
    if (pars.size() < 1)
10465
    {
10466
        MSG_ERROR("Expecting at least 1 parameter but got " << pars.size() << "! Ignoring command.");
10467
        return;
10468
    }
10469
 
10470
    TError::clear();
10471
    int btState = atoi(pars[0].c_str());
10472
 
10473
    vector<TMap::MAP_T> map = findButtons(port, channels);
10474
 
10475
    if (TError::isError() || map.empty())
10476
        return;
10477
 
10478
    vector<Button::TButton *> buttons = collectButtons(map);
10479
 
10480
    if (buttons.size() > 0)
10481
    {
10482
        Button::TButton *bt = buttons[0];
10483
 
10484
        if (btState == 0)       // All instances?
10485
        {
10486
            int bst = bt->getNumberInstances();
10487
 
10488
            for (int i = 0; i < bst; i++)
10489
            {
10490
                string c = bt->getText(i);
10491
                sendCustomEvent(i + 1, (int)c.length(), 0, c, 1001, bt->getChannelPort(), bt->getChannelNumber());
10492
#if TESTMODE == 1
10493
                if (_gTestMode)
10494
                    _gTestMode->setResult(c);
10495
#endif
10496
            }
10497
        }
10498
        else
10499
        {
10500
            string c = bt->getText(btState-1);
10501
            sendCustomEvent(btState, (int)c.length(), 0, c, 1001, bt->getChannelPort(), bt->getChannelNumber());
10502
#if TESTMODE == 1
10503
            if (_gTestMode)
10504
                _gTestMode->setResult(c);
10505
#endif
10506
        }
10507
    }
10508
#if TESTMODE == 1
10509
    setAllDone();
10510
#endif
10511
}
10512
 
10513
/*
10514
 * Set button state legacy unicode text command.
10515
 *
10516
 * Set Unicode text in the legacy G4 format. For the ^UNI command, the Unicode
10517
 * text is sent as ASCII-HEX nibbles.
10518
 */
10519
void TPageManager::doUNI(int port, vector<int>& channels, vector<string>& pars)
10520
{
10521
    DECL_TRACER("TPageManager::doUNI(int port, vector<int>& channels, vector<string>& pars)");
10522
 
10523
    if (pars.size() < 1)
10524
    {
10525
        MSG_ERROR("Expecting 1 parameters but got none! Ignoring command.");
10526
#if TESTMODE == 1
10527
        setAllDone();
10528
#endif
10529
        return;
10530
    }
10531
 
10532
    TError::clear();
10533
    int btState = atoi(pars[0].c_str()) - 1;
10534
    string text;
10535
 
10536
    // Unicode is the stadard character set used by Windows internally. It
10537
    // consists of 16 bit unsiged numbers. This can't be transported into a
10538
    // standard character string because a NULL byte means end of string.
10539
    // Therefor we must convert it to UFT-8.
10540
    if (pars.size() > 1)
10541
    {
10542
        string byte;
10543
        std::wstring uni;
10544
        size_t pos = 0;
10545
 
10546
        while (pos < pars[1].length())
10547
        {
10548
            byte = pars[1].substr(pos, 4);
10549
            wchar_t ch = (char)strtol(byte.c_str(), NULL, 16);
10550
            uni += ch;
10551
            pos += 4;
10552
        }
10553
 
10554
        text = UnicodeToUTF8(uni);
10555
    }
10556
 
10557
    vector<TMap::MAP_T> map = findButtons(port, channels);
10558
 
10559
    if (TError::isError() || map.empty())
10560
    {
10561
#if TESTMODE == 1
10562
        setAllDone();
10563
#endif
10564
        return;
10565
    }
10566
 
10567
    vector<Button::TButton *> buttons = collectButtons(map);
10568
 
10569
    if (buttons.size() > 0)
10570
    {
10571
        vector<Button::TButton *>::iterator mapIter;
10572
 
10573
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
10574
        {
10575
            Button::TButton *bt = *mapIter;
10576
 
10577
#if TESTMODE == 1
10578
            bool res = bt->setText(text, btState);
10579
 
10580
            if (_gTestMode)
10581
                _gTestMode->setResult(bt->getText(btState < 0 ? 0 : btState));
10582
 
10583
            __success = res;
10584
#else
10585
            bt->setText(text, btState);
10586
#endif
10587
        }
10588
    }
10589
#if TESTMODE == 1
10590
    setDone();
10591
#endif
10592
}
10593
 
10594
void TPageManager::doUTF(int port, vector<int>& channels, vector<string>& pars)
10595
{
10596
    DECL_TRACER("TPageManager::doTXT(int port, vector<int>& channels, vector<string>& pars)");
10597
 
10598
    if (pars.size() < 1)
10599
    {
10600
        MSG_ERROR("Expecting 1 parameters but got none! Ignoring command.");
10601
        return;
10602
    }
10603
 
10604
    TError::clear();
10605
    int btState = atoi(pars[0].c_str());
10606
    string text;
10607
 
10608
    if (pars.size() > 1)
10609
    {
10610
        for (size_t i = 1; i < pars.size(); ++i)
10611
        {
10612
            if (i > 1)
10613
                text += ",";
10614
 
10615
            text += pars[i];
10616
        }
10617
    }
10618
 
10619
    vector<TMap::MAP_T> map = findButtons(port, channels);
10620
 
10621
    if (TError::isError() || map.empty())
10622
        return;
10623
 
10624
    vector<Button::TButton *> buttons = collectButtons(map);
10625
 
10626
    if (buttons.size() > 0)
10627
    {
10628
        vector<Button::TButton *>::iterator mapIter;
10629
 
10630
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
10631
        {
10632
            Button::TButton *bt = *mapIter;
10633
 
10634
            if (btState == 0)       // All instances?
10635
            {
10636
                int bst = bt->getNumberInstances();
10637
 
10638
                for (int i = 0; i < bst; i++)
10639
                    bt->setText(text, i);
10640
            }
10641
            else
10642
                bt->setText(text, btState - 1);
10643
        }
10644
    }
10645
}
10646
 
10647
/**
10648
 * Simulates a touch/release/pulse at the given coordinate. If the push event
10649
 * is less then 0 or grater than 2 the command is ignored. It is also ignored
10650
 * if the x and y coordinate is out of range. The range must be between 0 and
10651
 * the maximum with and height.
10652
 */
10653
void TPageManager::doVTP (int, vector<int>&, vector<string>& pars)
10654
{
10655
    DECL_TRACER("TPageManager::doVTP (int, vector<int>&, vector<string>& pars)");
10656
 
10657
    if (pars.size() < 3)
10658
    {
10659
        MSG_ERROR("Expected 3 parameters but got only " << pars.size() << " parameters!");
10660
        return;
10661
    }
10662
 
10663
    int pushType = atoi(pars[0].c_str());
10664
    int x = atoi(pars[1].c_str());
10665
    int y = atoi(pars[2].c_str());
10666
 
10667
    if (pushType < 0 || pushType > 2)
10668
    {
10669
        MSG_ERROR("Invalid push type " << pushType << ". Ignoring command!");
10670
        return;
10671
    }
10672
 
10673
    if (x < 0 || x > mTSettings->getWidth() || y < 0 || y > mTSettings->getHeight())
10674
    {
10675
        MSG_ERROR("Illegal coordinates " << x << " x " << y << ". Ignoring command!");
10676
        return;
10677
    }
10678
 
10679
    if (pushType == 0 || pushType == 2)
10680
        mouseEvent(x, y, true);
10681
 
10682
    if (pushType == 1 || pushType == 2)
10683
        mouseEvent(x, y, false);
10684
}
10685
 
10686
 
10687
/**
10688
 * Set the keyboard passthru.
10689
 */
10690
void TPageManager::doKPS(int, vector<int>&, vector<string>& pars)
10691
{
10692
    DECL_TRACER("TPageManager::doKPS(int, vector<int>&, vector<string>& pars)");
10693
 
10694
    if (pars.size() < 1)
10695
    {
10696
        MSG_ERROR("Got no parameter. Ignoring command!");
10697
        return;
10698
    }
10699
 
10700
    int state = atoi(pars[0].c_str());
10701
 
10702
    if (state == 0)
10703
        mPassThrough = false;
10704
    else if (state == 5)
10705
        mPassThrough = true;
10706
}
10707
 
10708
void TPageManager::doVKS(int, vector<int>&, vector<string>& pars)
10709
{
10710
    DECL_TRACER("TPageManager::doVKS(int, vector<int>&, vector<string>& pars)");
10711
 
10712
    if (pars.size() < 1)
10713
    {
10714
        MSG_ERROR("Got no parameter. Ignoring command!");
10715
        return;
10716
    }
10717
 
10718
    if (_sendVirtualKeys)
10719
        _sendVirtualKeys(pars[0]);
10720
}
10721
 
10722
void TPageManager::doLPB(int port, vector<int>& channels, vector<string>& pars)
10723
{
10724
    DECL_TRACER("TPageManager::doLPB(int port, vector<int>& channels, vector<string>& pars)");
10725
 
10726
    if (pars.size() < 1)
10727
        return;
10728
 
10729
    TError::clear();
10730
    string passwd = pars[0];
10731
    vector<TMap::MAP_T> map = findButtons(port, channels);
10732
 
10733
    if (TError::isError() || map.empty())
10734
        return;
10735
 
10736
    vector<Button::TButton *> buttons = collectButtons(map);
10737
 
10738
    if (buttons.size() > 0)
10739
    {
10740
        vector<Button::TButton *>::iterator mapIter;
10741
 
10742
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
10743
        {
10744
            Button::TButton *bt = *mapIter;
10745
            bt->setUserName(passwd);
10746
        }
10747
    }
10748
}
10749
 
10750
void TPageManager::doLPC(int, vector<int>&, vector<string>&)
10751
{
10752
    DECL_TRACER("TPageManager::doLPC(int, vector<int>&, vector<string>&)");
10753
 
10754
    TConfig::clearUserPasswords();
10755
}
10756
 
10757
void TPageManager::doLPR(int, vector<int>&, vector<string>& pars)
10758
{
10759
    DECL_TRACER("TPageManager::doLPR(int, vector<int>&, vector<string>& pars)");
10760
 
10761
    if (pars.size() < 1)
10762
        return;
10763
 
10764
    string user = pars[0];
10765
    TConfig::clearUserPassword(user);
10766
}
10767
 
10768
void TPageManager::doLPS(int, vector<int>&, vector<string>& pars)
10769
{
10770
    DECL_TRACER("TPageManager::doLPS(int, vector<int>&, vector<string>& pars)");
10771
 
10772
    if (pars.size() < 2)
10773
        return;
10774
 
10775
    string user = pars[0];
10776
    string password;
10777
 
10778
    // In case the password contains one or more comma (,), the password is
10779
    // splitted. The following loop concatenates the password into one. Because
10780
    // the comma is lost, we must add it again.
10781
    for (size_t i = 0; i < pars.size(); ++i)
10782
    {
10783
        if (i > 0)
10784
            password += ",";
10785
 
10786
        password += pars[i];
10787
    }
10788
 
10789
    TConfig::setUserPassword(user, password);
10790
}
10791
 
10792
/*
10793
 * Set the page flip password. @PWD sets the level 1 password only.
10794
 */
10795
void TPageManager::doAPWD(int, vector<int>&, vector<string>& pars)
10796
{
10797
    DECL_TRACER("TPageManager::doPWD(int port, vector<int>&, vector<string>& pars)");
10798
 
10799
    if (pars.size() < 1)
10800
    {
10801
        MSG_ERROR("Got less then 1 parameter!");
10802
        return;
10803
    }
10804
 
10805
    string password;
10806
    // In case the password contains one or more comma (,), the password is
10807
    // splitted. The following loop concatenates the password into one. Because
10808
    // the comma is lost, we must add it again.
10809
    for (size_t i = 0; i < pars.size(); ++i)
10810
    {
10811
        if (i > 0)
10812
            password += ",";
10813
 
10814
        password += pars[i];
10815
    }
10816
 
10817
    TConfig::savePassword1(password);
10818
}
10819
 
10820
/*
10821
 * Set the page flip password. Password level is required and must be 1 - 4
10822
 */
10823
void TPageManager::doPWD(int, vector<int>&, vector<string>& pars)
10824
{
10825
    DECL_TRACER("TPageManager::doPWD(int, vector<int>&, vector<string>& pars)");
10826
 
10827
    if (pars.size() < 2)
10828
    {
10829
        MSG_ERROR("Got less then 2 parameters!");
10830
        return;
10831
    }
10832
 
10833
    int pwIdx = atoi(pars[0].c_str());
10834
    string password;
10835
    // In case the password contains one or more comma (,), the password is
10836
    // splitted. The following loop concatenates the password into one. Because
10837
    // the comma is lost, we must add it again.
10838
    for (size_t i = 1; i < pars.size(); ++i)
10839
    {
10840
        if (i > 1)
10841
            password += ",";
10842
 
10843
        password += pars[i];
10844
    }
10845
 
10846
    switch(pwIdx)
10847
    {
10848
        case 1: TConfig::savePassword1(password); break;
10849
        case 2: TConfig::savePassword2(password); break;
10850
        case 3: TConfig::savePassword3(password); break;
10851
        case 4: TConfig::savePassword4(password); break;
10852
    }
10853
}
10854
 
10855
/*
10856
 * Set the bitmap of a button to use a particular resource.
10857
 * Syntax:
10858
 *    "'^BBR-<vt addr range>,<button states range>,<resource name>'"
10859
 * Variable:
10860
 *    variable text address range = 1 - 4000.
10861
 *    button states range = 1 - 256 for multi-state buttons (0 = All states, for General buttons 1 = Off state and 2 = On state).
10862
 *    resource name = 1 - 50 ASCII characters.
10863
 * Example:
10864
 *    SEND_COMMAND Panel,"'^BBR-700,1,Sports_Image'"
10865
 *    Sets the resource name of the button to ’Sports_Image’.
10866
 */
10867
void TPageManager::doBBR(int port, vector<int>& channels, vector<string>& pars)
10868
{
10869
    DECL_TRACER("TPageManager::doBBR(int port, vector<int>& channels, vector<string>& pars)");
10870
 
10871
    if (pars.size() < 2)
10872
    {
10873
        MSG_ERROR("Expecting 2 parameters but got none! Ignoring command.");
10874
        return;
10875
    }
10876
 
10877
    TError::clear();
10878
    int btState = atoi(pars[0].c_str());
10879
    string resName = pars[1];
10880
 
10881
    vector<TMap::MAP_T> map = findButtons(port, channels);
10882
 
10883
    if (TError::isError() || map.empty())
10884
        return;
10885
 
10886
    vector<Button::TButton *> buttons = collectButtons(map);
10887
 
10888
    if (buttons.size() > 0)
10889
    {
10890
        vector<Button::TButton *>::iterator mapIter;
10891
 
10892
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
10893
        {
10894
            Button::TButton *bt = *mapIter;
10895
//            setButtonCallbacks(bt);
10896
 
10897
            if (btState == 0)       // All instances?
10898
            {
10899
                int bst = bt->getNumberInstances();
10900
                MSG_DEBUG("Setting BBR on all " << bst << " instances...");
10901
 
10902
                for (int i = 0; i < bst; i++)
10903
                    bt->setResourceName(resName, i);
10904
            }
10905
            else
10906
                bt->setResourceName(resName, btState - 1);
10907
 
10908
            if (bt->isVisible())
10909
                bt->refresh();
10910
            else if (_setVisible)
10911
                _setVisible(bt->getHandle(), false);
10912
        }
10913
    }
10914
}
10915
 
10916
/*
10917
 * Add new resources
10918
 * Adds any and all resource parameters by sending embedded codes and data.
10919
 * Since the embedded codes are preceded by a '%' character, any '%' character
10920
 * contained in* the URL must be escaped with a second '%' character (see
10921
 * example).
10922
 * The file name field (indicated by a %F embedded code) may contain special
10923
 * escape sequences as shown in the ^RAF, ^RMF.
10924
 * Syntax:
10925
 *    "'^RAF-<resource name>,<data>'"
10926
 * Variables:
10927
 *    resource name = 1 - 50 ASCII characters.
10928
 *    data = Refers to the embedded codes, see the ^RAF, ^RMF.
10929
 * Example:
10930
 *    SEND_COMMAND Panel,"'^RAF-New Image,%P0%HAMX.COM%ALab/Test%%5Ffile%Ftest.jpg'"
10931
 *    Adds a new resource.
10932
 *    The resource name is ’New Image’
10933
 *    %P (protocol) is an HTTP
10934
 *    %H (host name) is AMX.COM
10935
 *    %A (file path) is Lab/Test_f ile
10936
 *    %F (file name) is test.jpg.
10937
 *    Note that the %%5F in the file path is actually encoded as %5F.
10938
 */
10939
void TPageManager::doRAF(int, vector<int>&, vector<string>& pars)
10940
{
10941
    DECL_TRACER("TPageManager::doRAF(int port, vector<int>& channels, vector<string>& pars)");
10942
 
10943
    if (pars.size() < 2)
10944
    {
10945
        MSG_ERROR("Expecting 2 parameters but got none! Ignoring command.");
10946
        return;
10947
    }
10948
 
10949
    string name = pars[0];
10950
    string data = pars[1];
10951
 
10952
    vector<string> parts = StrSplit(data, "%");
10953
    RESOURCE_T res;
10954
 
10955
    if (parts.size() > 0)
10956
    {
10957
        vector<string>::iterator sIter;
10958
 
10959
        for (sIter = parts.begin(); sIter != parts.end(); sIter++)
10960
        {
10961
            const char *s = sIter->c_str();
10962
            string ss = *sIter;
10963
            MSG_DEBUG("Parsing \"" << ss << "\" with token << " << ss[0]);
10964
 
10965
            switch(*s)
10966
            {
10967
                case 'P':
10968
                    if (*(s+1) == '0')
10969
                        res.protocol = "HTTP";
10970
                    else
10971
                        res.protocol = "FTP";
10972
                    break;
10973
 
10974
                case 'U': res.user = sIter->substr(1); break;
10975
                case 'S': res.password = sIter->substr(1); break;
10976
                case 'H': res.host = sIter->substr(1); break;
10977
                case 'F': res.file = sIter->substr(1); break;
10978
                case 'A': res.path = sIter->substr(1); break;
10979
                case 'R': res.refresh = atoi(sIter->substr(1).c_str()); break;
10980
 
10981
                default:
10982
                    MSG_WARNING("Option " << sIter->at(0) << " is currently not implemented!");
10983
            }
10984
        }
10985
 
10986
        if (gPrjResources)
10987
            gPrjResources->addResource(name, res.protocol, res.host, res.path, res.file, res.user, res.password, res.refresh);
10988
    }
10989
}
10990
 
10991
void TPageManager::doRFR(int, vector<int>&, vector<string>& pars)
10992
{
10993
    DECL_TRACER("TPageManager::doRFR(int port, vector<int>& channels, vector<string>& pars)");
10994
 
10995
    if (pars.size() < 1)
10996
    {
10997
        MSG_ERROR("Expecting 1 parameter but got none! Ignoring command.");
10998
        return;
10999
    }
11000
 
11001
    string name = pars[0];
11002
    vector<TMap::MAP_T> map = findButtonByName(name);
11003
 
11004
    if (TError::isError() || map.empty())
11005
        return;
11006
 
11007
    vector<Button::TButton *> buttons = collectButtons(map);
11008
 
11009
    if (buttons.size() > 0)
11010
    {
11011
        vector<Button::TButton *>::iterator mapIter;
11012
 
11013
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
11014
        {
11015
            Button::TButton *bt = *mapIter;
11016
 
11017
            if (bt->isVisible())
11018
            {
11019
//                setButtonCallbacks(bt);
11020
                bt->refresh();
11021
            }
11022
        }
11023
    }
11024
}
11025
 
11026
/*
11027
 * Modify an existing resource
11028
 *
11029
 * Modifies any and all resource parameters by sending embedded codes and data.
11030
 * Since the embedded codes are preceded by a '%' character, any '%' character
11031
 * contained in the URL must be escaped with a second '%' character (see
11032
 * example).
11033
 * The file name field (indicated by a %F embedded code) may contain special
11034
 * escape sequences as shown in the ^RAF.
11035
 *
11036
 * Syntax:
11037
 * "'^RMF-<resource name>,<data>'"
11038
 * Variables:
11039
 *   • resource name = 1 - 50 ASCII characters
11040
 *   • data = Refers to the embedded codes, see the ^RAF, ^RMF.
11041
 * Example:
11042
 *   SEND_COMMAND Panel,"'^RMF-Sports_Image,%ALab%%5FTest/Images%Ftest.jpg'"
11043
 * Changes the resource ’Sports_Image’ file name to ’test.jpg’ and the path to
11044
 * ’Lab_Test/Images’.
11045
 * Note that the %%5F in the file path is actually encoded as %5F.
11046
 */
11047
void TPageManager::doRMF(int, vector<int>&, vector<string>& pars)
11048
{
11049
    DECL_TRACER("TPageManager::doRMF(int port, vector<int>& channels, vector<string>& pars)");
11050
 
11051
    if (pars.size() < 2)
11052
    {
11053
        MSG_ERROR("Expecting 2 parameters but got none! Ignoring command.");
11054
        return;
11055
    }
11056
 
11057
    string name = pars[0];
11058
    string data = pars[1];
11059
 
11060
    vector<string> parts = StrSplit(data, "%");
11061
    RESOURCE_T res;
11062
 
11063
    if (parts.size() > 0)
11064
    {
11065
        vector<string>::iterator sIter;
11066
 
11067
        for (sIter = parts.begin(); sIter != parts.end(); sIter++)
11068
        {
11069
            const char *s = sIter->c_str();
11070
            string ss = *sIter;
11071
            MSG_DEBUG("Parsing \"" << ss << "\" with token << " << ss[0]);
11072
 
11073
            switch(*s)
11074
            {
11075
                case 'P':
11076
                    if (*(s+1) == '0')
11077
                        res.protocol = "HTTP";
11078
                    else
11079
                        res.protocol = "FTP";
11080
                break;
11081
 
11082
                case 'U': res.user = sIter->substr(1); break;
11083
                case 'S': res.password = sIter->substr(1); break;
11084
                case 'H': res.host = sIter->substr(1); break;
11085
                case 'F': res.file = sIter->substr(1); break;
11086
                case 'A': res.path = sIter->substr(1); break;
11087
                case 'R': res.refresh = atoi(sIter->substr(1).c_str()); break;
11088
 
11089
                default:
11090
                    MSG_WARNING("Option " << sIter->at(0) << " is currently not implemented!");
11091
            }
11092
        }
11093
 
11094
        if (gPrjResources)
11095
            gPrjResources->setResource(name, res.protocol, res.host, res.path, res.file, res.user, res.password, res.refresh);
11096
    }
11097
}
11098
 
11099
/**
11100
 * Change the refresh rate for a given resource.
11101
 */
11102
void TPageManager::doRSR(int, vector<int>&, vector<string>& pars)
11103
{
11104
    DECL_TRACER("TPageManager::doRSR(int, vector<int>&, vector<string>& pars)");
11105
 
11106
    if (pars.size() < 2)
11107
    {
11108
        MSG_ERROR("Expecting 2 parameters but got none! Ignoring command.");
11109
        return;
11110
    }
11111
 
11112
    string resName = pars[0];
11113
    int resRefresh = atoi(pars[1].c_str());
11114
 
11115
    if (!gPrjResources)
11116
    {
11117
        MSG_ERROR("Missing the resource module. Ignoring command!");
11118
        return;
11119
    }
11120
 
11121
    RESOURCE_T res = gPrjResources->findResource(resName);
11122
 
11123
    if (res.name.empty() || res.refresh == resRefresh)
11124
        return;
11125
 
11126
    gPrjResources->setResource(resName, res.protocol, res.host, res.path, res.file, res.user, res.password, resRefresh);
11127
}
11128
 
11129
/**
11130
 * @brief TPageManager::doAKB - Pop up the keyboard icon
11131
 * Pop up the keyboard icon and initialize the text string to that specified.
11132
 * Keyboard string is set to null on power up and is stored until power is lost.
11133
 * The Prompt Text is optional.
11134
 */
11135
void TPageManager::doAKB(int, vector<int>&, vector<string> &pars)
11136
{
11137
    DECL_TRACER("TPageManager::doAKB(int, vector<int>&, vector<string> &pars)");
11138
 
11139
    if (pars.size() < 1)
11140
    {
11141
        MSG_ERROR("Expecting 2 parameters but got only " << pars.size() << "! Ignoring command.");
11142
        return;
11143
    }
11144
 
11145
    string initText = pars[0];
11146
    string promptText;
11147
 
11148
    if (pars.size() > 1)
11149
        promptText = pars[1];
11150
 
11151
    if (initText.empty())
11152
        initText = mAkbText;
11153
    else
11154
        mAkbText = initText;
11155
 
11156
    if (_callKeyboard)
11157
        _callKeyboard(initText, promptText, false);
11158
}
11159
 
11160
/**
11161
 * Pop up the keyboard icon and initialize the text string to that
11162
 * specified.
11163
 */
11164
void TPageManager::doAKEYB(int port, vector<int>& channels, vector<string>& pars)
11165
{
11166
    DECL_TRACER("TPageManager::doAKEYB(int port, vector<int>& channels, vector<string>& pars)");
11167
 
11168
    doAKB(port, channels, pars);
11169
}
11170
 
11171
void TPageManager::doAKEYP(int port, std::vector<int>& channels, std::vector<std::string>& pars)
11172
{
11173
    DECL_TRACER("TPageManager::doAKEYP(int port, std::vector<int>& channels, std::vector<std::string>& pars)");
11174
 
11175
    doAKP(port, channels, pars);
11176
}
11177
 
11178
/**
11179
 * Remove keyboard or keypad that was displayed using 'AKEYB', 'AKEYP', 'PKEYP',
11180
 * @AKB, @AKP, @PKP, @EKP, or @TKP commands.
11181
 */
11182
void TPageManager::doAKEYR(int, vector<int>&, vector<string>&)
11183
{
11184
    DECL_TRACER("TPageManager::doAKEYR(int, vector<int>&, vector<string>&)");
11185
 
11186
    if (_callResetKeyboard)
11187
        _callResetKeyboard();
11188
}
11189
 
11190
/**
11191
 * @brief TPageManager::doAKP - Pop up the keypad icon
11192
 * Pop up the keypad icon and initialize the text string to that specified.
11193
 * Keypad string is set to null on power up and is stored until power is lost.
11194
 * The Prompt Text is optional.
11195
 */
11196
void TPageManager::doAKP(int, std::vector<int>&, std::vector<std::string> &pars)
11197
{
11198
    DECL_TRACER("TPageManager::doAKP(int, vector<int>&, vector<string> &pars)");
11199
 
11200
    if (pars.size() < 1)
11201
    {
11202
        MSG_ERROR("Expecting 2 parameters but got only " << pars.size() << "! Ignoring command.");
11203
        return;
11204
    }
11205
 
11206
    string initText = pars[0];
11207
    string promptText;
11208
 
11209
    if (pars.size() > 1)
11210
        promptText = pars[1];
11211
 
11212
    if (initText.empty())
11213
        initText = mAkpText;
11214
    else
11215
        mAkpText = initText;
11216
 
11217
    if (_callKeypad)
11218
        _callKeypad(initText, promptText, false);
11219
}
11220
 
11221
/**
11222
 * Remove keyboard or keypad that was displayed using 'AKEYB', 'AKEYP', 'PKEYP',
11223
 * @AKB, @AKP, @PKP, @EKP, or @TKP commands.
11224
 */
11225
void TPageManager::doAKR(int port, vector<int>& channels, vector<string>& pars)
11226
{
11227
    DECL_TRACER("TPageManager::doAKR(int, vector<int>&, vector<string>&)");
11228
 
11229
    doAKEYR(port, channels, pars);
11230
}
11231
 
11232
void TPageManager::doABEEP(int, std::vector<int>&, vector<string>&)
11233
{
11234
    DECL_TRACER("TPageManager::doBEEP(int, std::vector<int>&, vector<string>&)");
11235
 
11236
    if (!_playSound)
11237
    {
11238
#if TESTMODE == 1
11239
        setAllDone();
11240
#endif
11241
        return;
11242
    }
11243
 
11244
    string snd = TConfig::getSystemPath(TConfig::SOUNDS) + "/" + TConfig::getSingleBeepSound();
11245
    TValidateFile vf;
11246
 
11247
    if (vf.isValidFile(snd))
11248
        _playSound(snd);
11249
#if TESTMODE == 1
11250
    else
11251
    {
11252
        MSG_PROTOCOL("Sound file invalid!");
11253
        setAllDone();
11254
    }
11255
#endif
11256
}
11257
 
11258
void TPageManager::doADBEEP(int, std::vector<int>&, vector<string>&)
11259
{
11260
    DECL_TRACER("TPageManager::doDBEEP(int, std::vector<int>&, vector<string>&)");
11261
 
11262
    if (!_playSound)
11263
        return;
11264
 
11265
    string snd = TConfig::getSystemPath(TConfig::SOUNDS) + "/" + TConfig::getDoubleBeepSound();
11266
    TValidateFile vf;
11267
 
11268
    if (vf.isValidFile(snd))
11269
        _playSound(snd);
11270
#if TESTMODE == 1
11271
    else
11272
    {
11273
        MSG_PROTOCOL("Sound file invalid!");
11274
        setAllDone();
11275
    }
11276
#endif
11277
}
11278
 
11279
void TPageManager::doBEEP(int, std::vector<int>&, vector<string>&)
11280
{
11281
    DECL_TRACER("TPageManager::doBEEP(int, std::vector<int>&, vector<string>&)");
11282
 
11283
    if (!_playSound)
11284
    {
11285
#if TESTMODE == 1
11286
        MSG_PROTOCOL("Method \"playSound()\" not initialized!");
11287
        setAllDone();
11288
#endif
11289
        return;
11290
    }
11291
 
11292
    string snd = TConfig::getSystemPath(TConfig::SOUNDS) + "/" + TConfig::getSingleBeepSound();
11293
    TValidateFile vf;
11294
    TSystemSound sysSound(TConfig::getSystemPath(TConfig::SOUNDS));
11295
 
11296
    if (sysSound.getSystemSoundState() && vf.isValidFile(snd))
11297
        _playSound(snd);
11298
#if TESTMODE == 1
11299
    else
11300
    {
11301
        if (!sysSound.getSystemSoundState())
11302
        {
11303
            MSG_PROTOCOL("Sound state disabled!")
11304
        }
11305
        else
11306
        {
11307
            MSG_PROTOCOL("Sound file invalid!");
11308
        }
11309
 
11310
        setAllDone();
11311
    }
11312
#endif
11313
}
11314
 
11315
void TPageManager::doDBEEP(int, std::vector<int>&, vector<string>&)
11316
{
11317
    DECL_TRACER("TPageManager::doDBEEP(int, std::vector<int>&, vector<string>&)");
11318
 
11319
    if (!_playSound)
11320
        return;
11321
 
11322
    string snd = TConfig::getSystemPath(TConfig::SOUNDS) + "/" + TConfig::getDoubleBeepSound();
11323
    TValidateFile vf;
11324
    TSystemSound sysSound(TConfig::getSystemPath(TConfig::SOUNDS));
11325
 
11326
    if (sysSound.getSystemSoundState() && vf.isValidFile(snd))
11327
        _playSound(snd);
11328
#if TESTMODE == 1
11329
    else
11330
    {
11331
        if (!sysSound.getSystemSoundState())
11332
        {
11333
            MSG_PROTOCOL("Sound state disabled!")
11334
        }
11335
        else
11336
        {
11337
            MSG_PROTOCOL("Sound file invalid!");
11338
        }
11339
 
11340
        setAllDone();
11341
    }
11342
#endif
11343
}
11344
 
11345
/**
11346
 * @brief Pop up the keypad icon and initialize the text string to that specified.
11347
 * Keypad string is set to null on power up and is stored until power is lost.
11348
 * The Prompt Text is optional.
11349
 */
11350
void TPageManager::doEKP(int port, std::vector<int>& channels, std::vector<std::string>& pars)
11351
{
11352
    DECL_TRACER("TPageManager::doEKP(int port, std::vector<int>& channels, std::vector<std::string>& pars)");
11353
 
11354
    doAKP(port, channels, pars);
11355
}
11356
 
11357
/**
11358
 * @brief Present a private keyboard.
11359
 * Pops up the keyboard icon and initializes the text string to that specified.
11360
 * Keyboard displays a '*' instead of the letters typed. The Prompt Text is optional.
11361
 */
11362
void TPageManager::doPKB(int, vector<int>&, vector<string>& pars)
11363
{
11364
    DECL_TRACER("TPageManager::doPKB(int, vector<int>&, vector<string>& pars)");
11365
 
11366
    if (pars.size() < 1)
11367
    {
11368
        MSG_ERROR("Expecting 2 parameters but got only " << pars.size() << "! Ignoring command.");
11369
        return;
11370
    }
11371
 
11372
    string initText = pars[0];
11373
    string promptText;
11374
 
11375
    if (pars.size() > 1)
11376
        promptText = pars[1];
11377
 
11378
    if (_callKeyboard)
11379
        _callKeyboard(initText, promptText, true);
11380
}
11381
 
11382
/**
11383
 * @brief Present a private keypad.
11384
 * Pops up the keypad icon and initializes the text string to that specified.
11385
 * Keypad displays a '*' instead of the numbers typed. The Prompt Text is optional.
11386
 */
11387
void TPageManager::doPKP(int, vector<int>&, vector<string>& pars)
11388
{
11389
    DECL_TRACER("TPageManager::doPKP(int, vector<int>&, vector<string>& pars)");
11390
 
11391
    if (pars.size() < 1)
11392
    {
11393
        MSG_ERROR("Expecting 2 parameters but got only " << pars.size() << "! Ignoring command.");
11394
        return;
11395
    }
11396
 
11397
    string initText = pars[0];
11398
    string promptText;
11399
 
11400
    if (pars.size() > 1)
11401
        promptText = pars[1];
11402
 
11403
    if (_callKeypad)
11404
        _callKeypad(initText, promptText, true);
11405
}
11406
 
11407
/**
11408
 * @brief Reset protected password command
11409
 * This command is used to reset the protected setup password to the factory
11410
 * default value.
11411
 */
11412
void TPageManager::doRPP(int, vector<int>&, vector<string>&)
11413
{
11414
    DECL_TRACER("TPageManager::doRPP(int, vector<int>&, vector<string>&)");
11415
 
11416
    TConfig::savePassword1("1988");
11417
}
11418
 
11419
/**
11420
 * Send panel to SETUP page.
11421
 */
11422
void TPageManager::doSetup(int, vector<int>&, vector<string>&)
11423
{
11424
    DECL_TRACER("TPageManager::doSetup(int, vector<int>&, vector<string>&)");
11425
 
11426
    if (_callShowSetup)
11427
        _callShowSetup();
11428
}
11429
 
11430
/**
11431
 * Shut down the App
11432
 */
11433
void TPageManager::doShutdown(int, vector<int>&, vector<string>&)
11434
{
11435
    DECL_TRACER("TPageManager::doShutdown(int, vector<int>&, vector<string>&)");
11436
 
11437
    MSG_PROTOCOL("Received shutdown ...");
11438
#ifdef __ANDROID__
11439
    stopNetworkState();
11440
#endif
11441
    prg_stopped = true;
11442
    killed = true;
11443
 
11444
    if (_shutdown)
11445
        _shutdown();
11446
}
11447
 
11448
void TPageManager::doSOU(int, vector<int>&, vector<string>& pars)
11449
{
11450
    DECL_TRACER("TPageManager::doSOU(int, vector<int>&, vector<string>& pars)");
11451
 
11452
    if (pars.size() < 1)
11453
    {
11454
        MSG_ERROR("@SOU: Expecting a sound file as parameter! Ignoring command.");
11455
        return;
11456
    }
11457
 
11458
    if (!_playSound)
11459
    {
11460
        MSG_ERROR("@SOU: Missing sound module!");
11461
        return;
11462
    }
11463
 
11464
    if (pars[0].empty() || strCaseCompare(pars[0], "None") == 0)
11465
        return;
11466
 
11467
    _playSound(pars[0]);
11468
}
11469
 
11470
void TPageManager::doMUT(int, vector<int>&, vector<string>& pars)
11471
{
11472
    DECL_TRACER("TPageManager::doMUT(int, vector<int>&, vector<string>& pars)");
11473
 
11474
    if (pars.size() < 1)
11475
    {
11476
        MSG_ERROR("^MUT: Expecting a state parameter! Ignoring command.");
11477
        return;
11478
    }
11479
 
11480
    bool mute = 0;
11481
 
11482
    if (pars[0] == "0")
11483
        mute = false;
11484
    else
11485
        mute = true;
11486
 
11487
    TConfig::setMuteState(mute);
11488
#if TESTMODE == 1
11489
    if (_gTestMode)
11490
    {
11491
        bool st = TConfig::getMuteState();
11492
        _gTestMode->setResult(st ? "1" : "0");
11493
    }
11494
 
11495
    __success = true;
11496
    setAllDone();
11497
#endif
11498
}
11499
 
11500
/**
11501
 * @brief Present a telephone keypad.
11502
 * Pops up the keypad icon and initializes the text string to that specified.
11503
 * The Prompt Text is optional.
11504
 */
11505
void TPageManager::doTKP(int port, vector<int>& channels, vector<string>& pars)
11506
{
11507
    DECL_TRACER("TPageManager::doTKP(int port, vector<int>& channels, vector<string>& pars)");
11508
 
11509
    // TODO: Implement a real telefone keypad.
11510
    doAKP(port, channels, pars);
11511
}
11512
 
11513
/**
11514
 * Popup the virtual keyboard
11515
 */
11516
void TPageManager::doVKB(int port, vector<int>& channels, vector<string>& pars)
11517
{
11518
    DECL_TRACER("TPageManager::doVKB(int port, vector<int>& channels, vector<string>& pars)");
11519
 
11520
    doAKP(port, channels, pars);
11521
}
11522
#ifndef _NOSIP_
11523
void TPageManager::sendPHN(vector<string>& cmds)
11524
{
11525
    DECL_TRACER("TPageManager::sendPHN(const vector<string>& cmds)");
11526
 
11527
    vector<int> channels;
11528
    doPHN(-1, channels, cmds);
11529
}
11530
 
11531
void TPageManager::actPHN(vector<string>& cmds)
11532
{
11533
    DECL_TRACER("TPageManager::actPHN(const vector<string>& cmds)");
11534
 
11535
    vector<int> channels;
11536
    doPHN(1, channels, cmds);
11537
}
11538
 
11539
void TPageManager::phonePickup(int id)
11540
{
11541
    DECL_TRACER("TPageManager::phonePickup(int id)");
11542
 
11543
    if (id < 0 || id >= 4)
11544
        return;
11545
 
11546
    if (mSIPClient)
11547
        mSIPClient->pickup(id);
11548
}
11549
 
11550
void TPageManager::phoneHangup(int id)
11551
{
11552
    DECL_TRACER("TPageManager::phoneHangup(int id)");
11553
 
11554
    if (id < 0 || id >= 4)
11555
        return;
11556
 
11557
    if (mSIPClient)
11558
        mSIPClient->terminate(id);
11559
}
11560
 
11561
/**
11562
 * @brief Phone commands.
11563
 * The phone commands could come from the master or are send to the master.
11564
 * If the parameter \p port is less then 0 (zero) a command is send to the
11565
 * master. In any other case the command came from the mater.
11566
 *
11567
 * @param port  This is used to signal if the command was sent by the master
11568
 *              or generated from the panel. If ths is less then 0, then the
11569
 *              method was called because of an event happen in the panel.
11570
 *              If this is grater or equal 0, then the event is comming from
11571
 *              the master.
11572
 * @param pars  This are parameters. The first parameter defines the action
11573
 *              to be done. According to the command this parameter may have a
11574
 *              different number of arguments.
11575
 */
11576
void TPageManager::doPHN(int port, vector<int>&, vector<string>& pars)
11577
{
11578
    DECL_TRACER("TPageManager::doPHN(int port, vector<int>&, vector<string>& pars)");
11579
 
11580
    if (pars.size() < 1)
11581
    {
11582
        MSG_ERROR("Expecting at least 1 parameter but got none! Ignoring command.");
11583
        return;
11584
    }
11585
 
11586
    string sCommand;
11587
    string cmd = toUpper(pars[0]);
11588
 
11589
    // Master to panel
11590
    if (port >= 0)
11591
    {
11592
        if (!mSIPClient)
11593
        {
11594
            MSG_ERROR("SIP client class was not initialized!")
11595
            return;
11596
        }
11597
 
11598
        if (cmd == "ANSWER")
11599
        {
11600
            if (pars.size() >= 2)
11601
            {
11602
                int id = atoi(pars[1].c_str());
11603
 
11604
                if (mSIPClient->getSIPState(id) == TSIPClient::SIP_HOLD)
11605
                    mSIPClient->resume(id);
11606
                else
11607
                    mSIPClient->pickup(id);
11608
            }
11609
        }
11610
        else if (cmd == "AUTOANSWER")
11611
        {
11612
            if (pars.size() >= 2)
11613
            {
11614
                if (pars[1].at(0) == '0')
11615
                    mPHNautoanswer = false;
11616
                else
11617
                    mPHNautoanswer = true;
11618
 
11619
                vector<string> cmds;
11620
                cmds = { "AUTOANSWER", to_string(mPHNautoanswer ? 1 : 0) };
11621
                sendPHN(cmds);
11622
            }
11623
        }
11624
        else if (cmd == "CALL")     // Initiate a call
11625
        {
11626
            if (pars.size() >= 2)
11627
                mSIPClient->call(pars[1]);
11628
        }
11629
        else if (cmd == "DTMF")     // Send tone modified codes
11630
        {
11631
            if (pars.size() >= 2)
11632
                mSIPClient->sendDTMF(pars[1]);
11633
        }
11634
        else if (cmd == "HANGUP")   // terminate a call
11635
        {
11636
            if (pars.size() >= 2)
11637
            {
11638
                int id = atoi(pars[1].c_str());
11639
                mSIPClient->terminate(id);
11640
            }
11641
        }
11642
        else if (cmd == "HOLD")     // Hold the line
11643
        {
11644
            if (pars.size() >= 2)
11645
            {
11646
                int id = atoi(pars[1].c_str());
11647
                mSIPClient->hold(id);
11648
            }
11649
        }
11650
        else if (cmd == "LINESTATE") // State of all line
11651
        {
11652
            mSIPClient->sendLinestate();
11653
        }
11654
        else if (cmd == "PRIVACY")  // Set/unset "do not disturb"
11655
        {
11656
            if (pars.size() >= 2)
11657
            {
11658
                bool state = (pars[1].at(0) == '1' ? true : false);
11659
                mSIPClient->sendPrivate(state);
11660
            }
11661
        }
11662
        else if (cmd == "REDIAL")   // Redials the last number
11663
        {
11664
            mSIPClient->redial();
11665
        }
11666
        else if (cmd == "TRANSFER") // Transfer call to provided number
11667
        {
11668
            if (pars.size() >= 3)
11669
            {
11670
                int id = atoi(pars[1].c_str());
11671
                string num = pars[2];
11672
 
11673
                if (mSIPClient->transfer(id, num))
11674
                {
11675
                    vector<string> cmds;
11676
                    cmds.push_back("TRANSFERRED");
11677
                    sendPHN(cmds);
11678
                }
11679
            }
11680
        }
11681
        else if (cmd == "IM")
11682
        {
11683
            if (pars.size() < 3)
11684
                return;
11685
 
11686
            string to = pars[1];
11687
            string msg = pars[2];
11688
            string toUri;
11689
 
11690
            if (to.find("sip:") == string::npos)
11691
                toUri = "sip:";
11692
 
11693
            toUri += to;
11694
 
11695
            if (to.find("@") == string::npos)
11696
                toUri += "@" + TConfig::getSIPproxy();
11697
 
11698
            mSIPClient->sendIM(toUri, msg);
11699
        }
11700
        else if (cmd == "SETUP")    // Some temporary settings
11701
        {
11702
            if (pars.size() < 2)
11703
                return;
11704
 
11705
            if (pars[1] == "DOMAIN" && pars.size() >= 3)
11706
                TConfig::setSIPdomain(pars[2]);
11707
            else if (pars[1] == "DTMFDURATION")
11708
            {
11709
                unsigned int ms = atoi(pars[2].c_str());
11710
                mSIPClient->setDTMFduration(ms);
11711
            }
11712
            else if (pars[1] == "ENABLE")   // (re)register user
11713
            {
11714
                TConfig::setSIPstatus(true);
11715
                mSIPClient->cleanUp();
11716
                mSIPClient->init();
11717
            }
11718
            else if (pars[1] == "DOMAIN" && pars.size() >= 3)
11719
                TConfig::setSIPdomain(pars[2]);
11720
            else if (pars[1] == "PASSWORD" && pars.size() >= 3)
11721
                TConfig::setSIPpassword(pars[2]);
11722
            else if (pars[1] == "PORT" && pars.size() != 3)
11723
                TConfig::setSIPport(atoi(pars[2].c_str()));
11724
            else if (pars[1] == "PROXYADDR" && pars.size() >= 3)
11725
                TConfig::setSIPproxy(pars[2]);
11726
            else if (pars[1] == "STUNADDR" && pars.size() >= 3)
11727
                TConfig::setSIPstun(pars[2]);
11728
            else if (pars[1] == "USERNAME" && pars.size() >= 3)
11729
                TConfig::setSIPuser(pars[2]);
11730
        }
11731
        else
11732
        {
11733
            MSG_ERROR("Unknown command ^PHN-" << cmd << " ignored!");
11734
        }
11735
    }
11736
    else   // Panel to master
11737
    {
11738
        vector<string>::iterator iter;
11739
 
11740
        for (iter = pars.begin(); iter != pars.end(); ++iter)
11741
        {
11742
            if (!sCommand.empty())
11743
                sCommand += ",";
11744
 
11745
            sCommand += *iter;
11746
        }
11747
 
11748
        sendPHNcommand(sCommand);
11749
    }
11750
}
11751
 
11752
void TPageManager::getPHN(int, vector<int>&, vector<string>& pars)
11753
{
11754
    DECL_TRACER("TPageManager::getPHN(int, vector<int>&, vector<string>& pars)");
11755
 
11756
    if (pars.size() < 1)
11757
    {
11758
        MSG_ERROR("Invalid number of arguments!");
11759
        return;
11760
    }
11761
 
11762
    string cmd = pars[0];
11763
 
11764
    if (cmd == "AUTOANSWER")
11765
        sendPHNcommand(cmd + "," + (mPHNautoanswer ? "1" : "0"));
11766
    else if (cmd == "LINESTATE")
11767
    {
11768
        if (!mSIPClient)
11769
            return;
11770
 
11771
        mSIPClient->sendLinestate();
11772
    }
11773
    else if (cmd == "MSGWAITING")
11774
    {
11775
        size_t num = mSIPClient->getNumberMessages();
11776
        sendPHNcommand(cmd + "," + (num > 0 ? "1" : "0") + "," + std::to_string(num) + "0,0,0");
11777
    }
11778
    else if (cmd == "PRIVACY")
11779
    {
11780
        if (mSIPClient->getPrivate())
11781
            sendPHNcommand(cmd + ",1");
11782
        else
11783
            sendPHNcommand(cmd + ",0");
11784
    }
11785
    else if (cmd == "REDIAL")
11786
    {
11787
        if (pars.size() < 2)
11788
            return;
11789
 
11790
        sendPHNcommand(cmd + "," + pars[1]);
11791
    }
11792
    else
11793
    {
11794
        MSG_WARNING("Unknown command " << cmd << " found!");
11795
    }
11796
}
11797
#endif  // _NOSIP_
11798
 
11799
/*
11800
 *  Hide all subpages in a subpage viewer button.
11801
 */
11802
void TPageManager::doSHA(int port, vector<int> &channels, vector<string> &pars)
11803
{
11804
    DECL_TRACER("TPageManager::doSHA(int port, vector<int> &channels, vector<string> &pars)");
11805
 
11806
    Q_UNUSED(pars);
11807
    vector<TMap::MAP_T> map = findButtons(port, channels);
11808
 
11809
    if (TError::isError() || map.empty())
11810
        return;
11811
 
11812
    vector<Button::TButton *> buttons = collectButtons(map);
11813
 
11814
    if (!buttons.empty())
11815
    {
11816
        vector<Button::TButton *>::iterator mapIter;
11817
 
11818
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
11819
        {
11820
            Button::TButton *bt = *mapIter;
11821
 
11822
            if (_hideAllSubViewItems)
11823
                _hideAllSubViewItems(bt->getHandle());
11824
        }
11825
    }
11826
}
11827
 
11828
void TPageManager::doSHD(int port, vector<int>& channels, vector<string>& pars)
11829
{
11830
    DECL_TRACER("TPageManager::doSHD(int port, vector<int>& channels, vector<string>& pars)");
11831
 
11832
    if (pars.size() < 1)
11833
        return;
11834
 
11835
    string name = pars[0];
11836
 
11837
    vector<TMap::MAP_T> map = findButtons(port, channels);
11838
 
11839
    if (TError::isError() || map.empty())
11840
        return;
11841
 
11842
    vector<Button::TButton *> buttons = collectButtons(map);
11843
 
11844
    if (!buttons.empty())
11845
    {
11846
        vector<Button::TButton *>::iterator mapIter;
11847
 
11848
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
11849
        {
11850
            Button::TButton *bt = *mapIter;
11851
 
11852
            vector<TSubPage *> subviews = createSubViewList(bt->getSubViewID());
11853
 
11854
            if (subviews.empty())
11855
                continue;
11856
 
11857
            vector<TSubPage *>::iterator itSub;
11858
 
11859
            for (itSub = subviews.begin(); itSub != subviews.end(); ++itSub)
11860
            {
11861
                TSubPage *sub = *itSub;
11862
 
11863
                if (sub && sub->getName() == name)
11864
                {
11865
                    if (_hideSubViewItem)
11866
                        _hideSubViewItem(bt->getHandle(), sub->getHandle());
11867
 
11868
                    break;
11869
                }
11870
            }
11871
        }
11872
    }
11873
}
11874
 
11875
void TPageManager::doSPD(int port, vector<int>& channels, vector<string>& pars)
11876
{
11877
    DECL_TRACER("TPageManager::doSPD(int port, vector<int>& channel, vector<string>& pars)");
11878
 
11879
    if (pars.size() < 1)
11880
        return;
11881
 
11882
    TError::clear();
11883
    int padding = atoi(pars[0].c_str());
11884
 
11885
    if (padding < 0 || padding > 100)
11886
        return;
11887
 
11888
    vector<TMap::MAP_T> map = findButtons(port, channels);
11889
 
11890
    if (TError::isError() || map.empty())
11891
        return;
11892
 
11893
    vector<Button::TButton *> buttons = collectButtons(map);
11894
 
11895
    if (!buttons.empty())
11896
    {
11897
        vector<Button::TButton *>::iterator mapIter;
11898
 
11899
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
11900
        {
11901
            Button::TButton *bt = *mapIter;
11902
 
11903
            if (_setSubViewPadding)
11904
                _setSubViewPadding(bt->getHandle(), padding);
11905
        }
11906
    }
11907
}
11908
 
11909
/*
11910
 * This command will perform one of three different operations based on the following conditions:
11911
 * 1. If the named subpage is hidden in the set associated with the viewer button it will be shown in the anchor position.
11912
 * 2. If the named subpage is not present in the set it will be added to the set and shown in the anchor position.
11913
 * 3. If the named subpage is already present in the set and is not hidden then the viewer button will move it to the anchor
11914
 * position. The anchor position is the location on the subpage viewer button specified by its weighting. This will either be
11915
 * left, center or right for horizontal subpage viewer buttons or top, center or bottom for vertical subpage viewer buttons.
11916
 * Surrounding subpages are relocated on the viewer button as needed to accommodate the described operations
11917
 */
11918
void TPageManager::doSSH(int port, vector<int> &channels, vector<string> &pars)
11919
{
11920
    DECL_TRACER("TPageManager::doSSH(int port, vector<int> &channels, vector<string> &pars)");
11921
 
11922
    if (pars.size() < 1)
11923
    {
11924
        MSG_ERROR("Expecting 1 parameter but got none! Ignoring command.");
11925
        return;
11926
    }
11927
 
11928
    TError::clear();
11929
    string name = pars[0];
11930
    int position = 0;   // optional
11931
    int time = 0;       // optional
11932
 
11933
    if (pars.size() > 1)
11934
        position = atoi(pars[1].c_str());
11935
 
11936
    if (pars.size() > 2)
11937
        time = atoi(pars[2].c_str());
11938
 
11939
    vector<TMap::MAP_T> map = findButtons(port, channels);
11940
 
11941
    if (TError::isError() || map.empty())
11942
        return;
11943
 
11944
    vector<Button::TButton *> buttons = collectButtons(map);
11945
 
11946
    if (!buttons.empty())
11947
    {
11948
        vector<Button::TButton *>::iterator mapIter;
11949
 
11950
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
11951
        {
11952
            Button::TButton *bt = *mapIter;
11953
            vector<TSubPage *> subviews = createSubViewList(bt->getSubViewID());
11954
 
11955
            if (subviews.empty() || !bt)
11956
                continue;
11957
 
11958
            vector<TSubPage *>::iterator itSub;
11959
 
11960
            for (itSub = subviews.begin(); itSub != subviews.end(); ++itSub)
11961
            {
11962
                TSubPage *sub = *itSub;
11963
 
11964
                if (sub && sub->getName() == name)
11965
                {
11966
                    if (_showSubViewItem)
11967
                        _showSubViewItem(sub->getHandle(), bt->getHandle(), position, time);
11968
 
11969
                    break;
11970
                }
11971
            }
11972
        }
11973
    }
11974
}
11975
 
11976
void TPageManager::doSTG(int port, vector<int>& channels, vector<string>& pars)
11977
{
11978
    DECL_TRACER("TPageManager::doSTG(int port, vector<int>& channels, vector<string>& pars)");
11979
 
11980
    if (pars.empty())
11981
    {
11982
        MSG_ERROR("Expecting 1 parameter but got none! Ignoring command.");
11983
        return;
11984
    }
11985
 
11986
    TError::clear();
11987
    string name = pars[0];
11988
    int position = 0;   // optional
11989
    int time = 0;       // optional
11990
 
11991
    if (pars.size() > 1)
11992
        position = atoi(pars[1].c_str());
11993
 
11994
    if (pars.size() > 2)
11995
        time = atoi(pars[2].c_str());
11996
 
11997
    vector<TMap::MAP_T> map = findButtons(port, channels);
11998
 
11999
    if (TError::isError() || map.empty())
12000
        return;
12001
 
12002
    vector<Button::TButton *> buttons = collectButtons(map);
12003
 
12004
    if (!buttons.empty())
12005
    {
12006
        vector<Button::TButton *>::iterator mapIter;
12007
 
12008
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
12009
        {
12010
            Button::TButton *bt = *mapIter;
12011
            vector<TSubPage *> subviews = createSubViewList(bt->getSubViewID());
12012
 
12013
            if (subviews.empty() || !bt)
12014
                continue;
12015
 
12016
            vector<TSubPage *>::iterator itSub;
12017
 
12018
            for (itSub = subviews.begin(); itSub != subviews.end(); ++itSub)
12019
            {
12020
                TSubPage *sub = *itSub;
12021
 
12022
                if (sub && sub->getName() == name)
12023
                {
12024
                    if (_toggleSubViewItem)
12025
                        _toggleSubViewItem(sub->getHandle(), bt->getHandle(), position, time);
12026
 
12027
                    break;
12028
                }
12029
            }
12030
        }
12031
    }
12032
}
12033
 
12034
void TPageManager::doLVD(int port, vector<int> &channels, vector<string> &pars)
12035
{
12036
    DECL_TRACER("TPageManager::doLVD(int port, vector<int> &channels, vector<string> &pars)");
12037
 
12038
    if (pars.size() < 1)
12039
    {
12040
        MSG_ERROR("Expecting one parameter but got none! Ignoring command.");
12041
        return;
12042
    }
12043
 
12044
    TError::clear();
12045
    string source = pars[0];
12046
    vector<string> configs;
12047
 
12048
    if (pars.size() > 1)
12049
    {
12050
        for (size_t i = 1; i < pars.size(); ++i)
12051
        {
12052
            string low = toLower(pars[i]);
12053
 
12054
            if (low.find_first_of("user=") != string::npos ||
12055
                low.find_first_of("pass=") != string::npos ||
12056
                low.find_first_of("csv=")  != string::npos ||
12057
                low.find_first_of("has_headers=") != string::npos)
12058
            {
12059
                configs.push_back(pars[i]);
12060
            }
12061
        }
12062
    }
12063
 
12064
    vector<TMap::MAP_T> map = findButtons(port, channels);
12065
 
12066
    if (TError::isError() || map.empty())
12067
        return;
12068
 
12069
    vector<Button::TButton *> buttons = collectButtons(map);
12070
 
12071
    if (buttons.size() > 0)
12072
    {
12073
        vector<Button::TButton *>::iterator mapIter;
12074
 
12075
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
12076
        {
12077
            Button::TButton *bt = *mapIter;
12078
            bt->setListSource(source, configs);
12079
        }
12080
    }
12081
 
12082
}
12083
 
12084
void TPageManager::doLVE(int port, vector<int> &channels, vector<string> &pars)
12085
{
12086
    DECL_TRACER("TPageManager::doLVE(int port, vector<int> &channels, vector<string> &pars)");
12087
 
12088
    if (pars.size() < 1)
12089
    {
12090
        MSG_ERROR("Expecting one parameter but got none! Ignoring command.");
12091
        return;
12092
    }
12093
 
12094
    TError::clear();
12095
    int num = atoi(pars[0].c_str());
12096
 
12097
    vector<TMap::MAP_T> map = findButtons(port, channels);
12098
 
12099
    if (TError::isError() || map.empty())
12100
        return;
12101
 
12102
    vector<Button::TButton *> buttons = collectButtons(map);
12103
 
12104
    if (buttons.size() > 0)
12105
    {
12106
        vector<Button::TButton *>::iterator mapIter;
12107
 
12108
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
12109
        {
12110
            Button::TButton *bt = *mapIter;
12111
            bt->setListViewEventNumber(num);
12112
        }
12113
    }
12114
 
12115
}
12116
 
12117
void TPageManager::doLVF(int port, vector<int> &channels, vector<string> &pars)
12118
{
12119
    DECL_TRACER("TPageManager::doLVF(int port, vector<int> &channels, vector<string> &pars)");
12120
 
12121
    if (pars.size() < 1)
12122
    {
12123
        MSG_ERROR("Expecting one parameter but got none! Ignoring command.");
12124
        return;
12125
    }
12126
 
12127
    TError::clear();
12128
    string filter;
12129
 
12130
    vector<string>::iterator iter;
12131
 
12132
    for (iter = pars.begin(); iter != pars.end(); ++iter)
12133
    {
12134
        if (filter.length() > 0)
12135
            filter += ",";
12136
 
12137
        filter += *iter;
12138
    }
12139
 
12140
    vector<TMap::MAP_T> map = findButtons(port, channels);
12141
 
12142
    if (TError::isError() || map.empty())
12143
        return;
12144
 
12145
    vector<Button::TButton *> buttons = collectButtons(map);
12146
 
12147
    if (buttons.size() > 0)
12148
    {
12149
        vector<Button::TButton *>::iterator mapIter;
12150
 
12151
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
12152
        {
12153
            Button::TButton *bt = *mapIter;
12154
            bt->setListSourceFilter(filter);
12155
        }
12156
    }
12157
}
12158
 
12159
void TPageManager::doLVL(int port, vector<int> &channels, vector<string> &pars)
12160
{
12161
    DECL_TRACER("TPageManager::doLVL(int port, vector<int> &channels, vector<string> &pars)");
12162
 
12163
    if (pars.size() < 1)
12164
    {
12165
        MSG_ERROR("Expecting one parameter but got none! Ignoring command.");
12166
        return;
12167
    }
12168
 
12169
    TError::clear();
12170
    bool hasColumns = false;
12171
    int columns = 0;
12172
    bool hasLayout = false;
12173
    int layout = 0;
12174
    bool hasComponent = false;
12175
    int component = 0;
12176
    bool hasCellHeight = false;
12177
    bool cellHeightPercent = false;
12178
    int cellheight = 0;
12179
    bool hasP1 = false;
12180
    int p1 = 0;
12181
    bool hasP2 = false;
12182
    int p2 = 0;
12183
    bool hasFilter = false;
12184
    bool filter = false;
12185
    bool hasFilterHeight = false;
12186
    bool filterHeightPercent = false;
12187
    int filterheight = 0;
12188
    bool hasAlphaScroll = false;
12189
    bool alphascroll = false;
12190
 
12191
    vector<string>::iterator iter;
12192
 
12193
    for (iter = pars.begin(); iter != pars.end(); ++iter)
12194
    {
12195
        string low = toLower(*iter);
12196
 
12197
        if (low.find("columns=") != string::npos ||
12198
            low.find("nc=") != string::npos ||
12199
            low.find("numcol=") != string::npos)
12200
        {
12201
            size_t pos = low.find("=");
12202
            string sCols = low.substr(pos + 1);
12203
            columns = atoi(sCols.c_str());
12204
            hasColumns = true;
12205
        }
12206
        else if (low.find("c=") != string::npos || low.find("comp=") != string::npos)
12207
        {
12208
            size_t pos = low.find("=");
12209
            string sComp = low.substr(pos + 1);
12210
            component |= atoi(sComp.c_str());
12211
            hasComponent = true;
12212
        }
12213
        else if (low.find("l=") != string::npos || low.find("layout=") != string::npos)
12214
        {
12215
            size_t pos = low.find("=");
12216
            string sLay = low.substr(pos + 1);
12217
            layout = atoi(sLay.c_str());
12218
            hasLayout = true;
12219
        }
12220
        else if (low.find("ch=") != string::npos || low.find("cellheight=") != string::npos)
12221
        {
12222
            size_t pos = low.find("=");
12223
            string sCh = low.substr(pos + 1);
12224
            cellheight = atoi(sCh.c_str());
12225
 
12226
            if (low.find("%") != string::npos)
12227
                cellHeightPercent = true;
12228
 
12229
            hasCellHeight = true;
12230
        }
12231
        else if (low.find("p1=") != string::npos)
12232
        {
12233
            size_t pos = low.find("=");
12234
            string sP1 = low.substr(pos + 1);
12235
            p1 = atoi(sP1.c_str());
12236
            hasP1 = true;
12237
        }
12238
        else if (low.find("p2=") != string::npos)
12239
        {
12240
            size_t pos = low.find("=");
12241
            string sP2 = low.substr(pos + 1);
12242
            p2 = atoi(sP2.c_str());
12243
            hasP2 = true;
12244
        }
12245
        else if (low.find("f=") != string::npos || low.find("filter=") != string::npos)
12246
        {
12247
            size_t pos = low.find("=");
12248
            string sFilter = low.substr(pos + 1);
12249
            filter = isTrue(sFilter);
12250
            hasFilter = true;
12251
        }
12252
        else if (low.find("fh=") != string::npos || low.find("filterheight=") != string::npos)
12253
        {
12254
            size_t pos = low.find("=");
12255
            string sFilter = low.substr(pos + 1);
12256
            filterheight = atoi(sFilter.c_str());
12257
 
12258
            if (low.find("%") != string::npos)
12259
                filterHeightPercent = true;
12260
 
12261
            hasFilterHeight = true;
12262
        }
12263
        else if (low.find("as=") != string::npos || low.find("alphascroll=") != string::npos)
12264
        {
12265
            size_t pos = low.find("=");
12266
            string sAlpha = low.substr(pos + 1);
12267
            alphascroll = isTrue(sAlpha);
12268
            hasAlphaScroll = true;
12269
        }
12270
    }
12271
 
12272
    vector<TMap::MAP_T> map = findButtons(port, channels);
12273
 
12274
    if (TError::isError() || map.empty())
12275
        return;
12276
 
12277
    vector<Button::TButton *> buttons = collectButtons(map);
12278
 
12279
    if (buttons.size() > 0)
12280
    {
12281
        vector<Button::TButton *>::iterator mapIter;
12282
 
12283
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
12284
        {
12285
            Button::TButton *bt = *mapIter;
12286
 
12287
            if (hasColumns)         bt->setListViewColumns(columns);
12288
            if (hasComponent)       bt->setListViewComponent(component);
12289
            if (hasLayout)          bt->setListViewLayout(layout);
12290
            if (hasCellHeight)      bt->setListViewCellheight(cellheight, cellHeightPercent);
12291
            if (hasP1)              bt->setListViewP1(p1);
12292
            if (hasP2)              bt->setListViewP2(p2);
12293
            if (hasFilter)          bt->setListViewColumnFilter(filter);
12294
            if (hasFilterHeight)    bt->setListViewFilterHeight(filterheight, filterHeightPercent);
12295
            if (hasAlphaScroll)     bt->setListViewAlphaScroll(alphascroll);
12296
        }
12297
    }
12298
}
12299
 
12300
void TPageManager::doLVM(int port, vector<int> &channels, vector<string> &pars)
12301
{
12302
    DECL_TRACER("TPageManager::doLVM(int port, vector<int> &channels, vector<string> &pars)");
12303
 
12304
    if (pars.size() < 1)
12305
    {
12306
        MSG_ERROR("Expecting one parameter but got none! Ignoring command.");
12307
        return;
12308
    }
12309
 
12310
    TError::clear();
12311
    map<string,string> mapField;
12312
 
12313
    vector<string>::iterator iter;
12314
 
12315
    for (iter = pars.begin(); iter != pars.end(); ++iter)
12316
    {
12317
        string left, right;
12318
        size_t pos = 0;
12319
 
12320
        if ((pos = iter->find("=")) != string::npos)
12321
        {
12322
            string left = iter->substr(0, pos);
12323
            left = toLower(left);
12324
            string right = iter->substr(pos + 1);
12325
 
12326
            if (left == "t1" || left == "t2" || left == "i1")
12327
                mapField.insert(pair<string,string>(left, right));
12328
        }
12329
    }
12330
 
12331
    vector<TMap::MAP_T> map = findButtons(port, channels);
12332
 
12333
    if (TError::isError() || map.empty())
12334
        return;
12335
 
12336
    vector<Button::TButton *> buttons = collectButtons(map);
12337
 
12338
    if (buttons.size() > 0)
12339
    {
12340
        vector<Button::TButton *>::iterator mapIter;
12341
 
12342
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
12343
        {
12344
            Button::TButton *bt = *mapIter;
12345
            bt->setListViewFieldMap(mapField);
12346
        }
12347
    }
12348
}
12349
 
12350
void TPageManager::doLVN(int port, vector<int> &channels, vector<string> &pars)
12351
{
12352
    DECL_TRACER("TPageManager::doLVN(int port, vector<int> &channels, vector<string> &pars)");
12353
 
12354
    if (pars.size() < 1)
12355
    {
12356
        MSG_ERROR("Expecting one parameter but got none! Ignoring command.");
12357
        return;
12358
    }
12359
 
12360
    TError::clear();
12361
    string command = pars[0];
12362
    bool select = false;
12363
 
12364
    if (pars.size() > 1)
12365
    {
12366
        if (isTrue(pars[1]))
12367
            select = true;
12368
    }
12369
 
12370
    vector<TMap::MAP_T> map = findButtons(port, channels);
12371
 
12372
    if (TError::isError() || map.empty())
12373
        return;
12374
 
12375
    vector<Button::TButton *> buttons = collectButtons(map);
12376
 
12377
    if (buttons.size() > 0)
12378
    {
12379
        vector<Button::TButton *>::iterator mapIter;
12380
 
12381
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
12382
        {
12383
            Button::TButton *bt = *mapIter;
12384
            bt->listViewNavigate(command, select);
12385
        }
12386
    }
12387
}
12388
 
12389
void TPageManager::doLVR(int port, vector<int> &channels, vector<string> &pars)
12390
{
12391
    DECL_TRACER("TPageManager::doLVR(int port, vector<int> &channels, vector<string> &pars)");
12392
 
12393
    TError::clear();
12394
    int interval = -1;
12395
    bool force = false;
12396
 
12397
    if (pars.size() > 0)
12398
        interval = atoi(pars[0].c_str());
12399
 
12400
    if (pars.size() > 1)
12401
        force = isTrue(pars[1]);
12402
 
12403
    vector<TMap::MAP_T> map = findButtons(port, channels);
12404
 
12405
    if (TError::isError() || map.empty())
12406
        return;
12407
 
12408
    vector<Button::TButton *> buttons = collectButtons(map);
12409
 
12410
    if (buttons.size() > 0)
12411
    {
12412
        vector<Button::TButton *>::iterator mapIter;
12413
 
12414
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
12415
        {
12416
            Button::TButton *bt = *mapIter;
12417
            bt->listViewRefresh(interval, force);
12418
        }
12419
    }
12420
}
12421
 
12422
void TPageManager::doLVS(int port, vector<int> &channels, vector<string> &pars)
12423
{
12424
    DECL_TRACER("TPageManager::doLVS(int port, vector<int> &channels, vector<string> &pars)");
12425
 
12426
    TError::clear();
12427
    vector<string> sortColumns;
12428
    Button::LIST_SORT sort = Button::LIST_SORT_NONE;
12429
    string override;
12430
 
12431
    if (pars.size() > 0)
12432
    {
12433
        vector<string>::iterator iter;
12434
 
12435
        for (iter = pars.begin(); iter != pars.end(); ++iter)
12436
        {
12437
            if (iter->find(";") == string::npos)
12438
                sortColumns.push_back(*iter);
12439
            else
12440
            {
12441
                vector<string> parts = StrSplit(*iter, ";");
12442
                sortColumns.push_back(parts[0]);
12443
 
12444
                if (parts[1].find("a") != string::npos || parts[1].find("A") != string::npos)
12445
                    sort = Button::LIST_SORT_ASC;
12446
                else if (parts[1].find("d") != string::npos || parts[1].find("D") != string::npos)
12447
                    sort = Button::LIST_SORT_DESC;
12448
                else if (parts[1].find("*") != string::npos)
12449
                {
12450
                    if (parts.size() > 2 && !parts[2].empty())
12451
                    {
12452
                        override = parts[2];
12453
                        sort = Button::LIST_SORT_OVERRIDE;
12454
                    }
12455
                }
12456
                else if (parts[1].find("n") != string::npos || parts[1].find("N") != string::npos)
12457
                    sort = Button::LIST_SORT_NONE;
12458
            }
12459
        }
12460
    }
12461
 
12462
    vector<TMap::MAP_T> map = findButtons(port, channels);
12463
 
12464
    if (TError::isError() || map.empty())
12465
        return;
12466
 
12467
    vector<Button::TButton *> buttons = collectButtons(map);
12468
 
12469
    if (buttons.size() > 0)
12470
    {
12471
        vector<Button::TButton *>::iterator mapIter;
12472
 
12473
        for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
12474
        {
12475
            Button::TButton *bt = *mapIter;
12476
            bt->listViewSortData(sortColumns, sort, override);
12477
        }
12478
    }
12479
}
12480
 
12481
void TPageManager::doTPCCMD(int, vector<int>&, vector<string>& pars)
12482
{
12483
    DECL_TRACER("TPageManager::doTPCCMD(int, vector<int>&, vector<string>& pars)");
12484
 
12485
    if (pars.size() < 1)
12486
    {
12487
        MSG_ERROR("Too few arguments for TPCCMD!");
12488
        return;
12489
    }
12490
 
12491
    string cmd = pars[0];
12492
 
12493
    if (strCaseCompare(cmd, "LocalHost") == 0)
12494
    {
12495
        if (pars.size() < 2 || pars[1].empty())
12496
        {
12497
            MSG_ERROR("The command \"LocalHost\" requires an additional parameter!");
12498
            return;
12499
        }
12500
 
12501
        TConfig::saveController(pars[1]);
12502
    }
12503
    else if (strCaseCompare(cmd, "LocalPort") == 0)
12504
    {
12505
        if (pars.size() < 2 || pars[1].empty())
12506
        {
12507
            MSG_ERROR("The command \"LocalPort\" requires an additional parameter!");
12508
            return;
12509
        }
12510
 
12511
        int port = atoi(pars[1].c_str());
12512
 
12513
        if (port > 0 && port < 65536)
12514
            TConfig::savePort(port);
12515
        else
12516
        {
12517
            MSG_ERROR("Invalid network port " << port);
12518
        }
12519
    }
12520
    else if (strCaseCompare(cmd, "DeviceID") == 0)
12521
    {
12522
        if (pars.size() < 2 || pars[1].empty())
12523
        {
12524
            MSG_ERROR("The command \"DeviceID\" requires an additional parameter!");
12525
            return;
12526
        }
12527
 
12528
        int id = atoi(pars[1].c_str());
12529
 
12530
        if (id >= 10000 && id < 30000)
12531
            TConfig::setSystemChannel(id);
12532
    }
12533
    else if (strCaseCompare(cmd, "ApplyProfile") == 0)
12534
    {
12535
        // We restart the network connection only
12536
        if (gAmxNet)
12537
            gAmxNet->reconnect();
12538
    }
12539
    else if (strCaseCompare(cmd, "QueryDeviceInfo") == 0)
12540
    {
12541
        string info = "DEVICEINFO-TPANELID," + TConfig::getPanelType();
12542
        info += ";HOSTNAME,";
12543
        char hostname[HOST_NAME_MAX];
12544
 
12545
        if (gethostname(hostname, HOST_NAME_MAX) != 0)
12546
        {
12547
            MSG_ERROR("Can't get host name: " << strerror(errno));
12548
            return;
12549
        }
12550
 
12551
        info.append(hostname);
12552
        info += ";UUID," + TConfig::getUUID();
12553
        sendGlobalString(info);
12554
    }
12555
    else if (strCaseCompare(cmd, "LockRotation") == 0)
12556
    {
12557
        if (pars.size() < 2 || pars[1].empty())
12558
        {
12559
            MSG_ERROR("The command \"LockRotation\" requires an additional parameter!");
12560
            return;
12561
        }
12562
 
12563
        if (strCaseCompare(pars[1], "true") == 0)
12564
            TConfig::setRotationFixed(true);
12565
        else
12566
            TConfig::setRotationFixed(false);
12567
    }
12568
    else if (strCaseCompare(cmd, "ButtonHit") == 0)
12569
    {
12570
        if (pars.size() < 2 || pars[1].empty())
12571
        {
12572
            MSG_ERROR("The command \"ButtonHit\" requires an additional parameter!");
12573
            return;
12574
        }
12575
 
12576
        if (strCaseCompare(pars[1], "true") == 0)
12577
            TConfig::saveSystemSoundState(true);
12578
        else
12579
            TConfig::saveSystemSoundState(false);
12580
    }
12581
    else if (strCaseCompare(cmd, "ReprocessTP4") == 0)
12582
    {
12583
        if (_resetSurface)
12584
            _resetSurface();
12585
    }
12586
}
12587
 
12588
void TPageManager::doTPCACC(int, vector<int>&, vector<string>& pars)
12589
{
12590
    DECL_TRACER("TPageManager::doTPCACC(int, vector<int>&, vector<string>& pars)");
12591
 
12592
    if (pars.size() < 1)
12593
    {
12594
        MSG_ERROR("Too few arguments for TPCACC!");
12595
        return;
12596
    }
12597
 
12598
    string cmd = pars[0];
12599
 
12600
    if (strCaseCompare(cmd, "ENABLE") == 0)
12601
    {
12602
        mInformOrientation = true;
12603
        sendOrientation();
12604
    }
12605
    else if (strCaseCompare(cmd, "DISABLE") == 0)
12606
    {
12607
        mInformOrientation = false;
12608
    }
12609
    else if (strCaseCompare(cmd, "QUERY") == 0)
12610
    {
12611
        sendOrientation();
12612
    }
12613
}
12614
 
12615
#ifndef _NOSIP_
12616
void TPageManager::doTPCSIP(int, vector<int>&, vector<string>& pars)
12617
{
12618
    DECL_TRACER("TPageManager::doTPCSIP(int port, vector<int>& channels, vector<string>& pars)");
12619
 
12620
    if (pars.empty())
12621
        return;
12622
 
12623
    string cmd = toUpper(pars[0]);
12624
 
12625
    if (cmd == "SHOW" && _showPhoneDialog)
12626
        _showPhoneDialog(true);
12627
    else if (!_showPhoneDialog)
12628
    {
12629
        MSG_ERROR("There is no phone dialog registered!");
12630
    }
12631
}
12632
#endif