Subversion Repositories tpanel

Rev

Rev 462 | Details | Compare with Previous | Last modification | View Log | RSS feed

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