Subversion Repositories tpanel

Rev

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