Subversion Repositories tpanel

Rev

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