Subversion Repositories Projects

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
746 rain-er 1
#!/usr/bin/perl
2
#!/usr/bin/perl -d:ptkdb
3
 
4
###############################################################################
5
#
6
# mkcockpit.pl -  MK Mission Cockpit - GUI
7
#
8
# Copyright (C) 2009  Rainer Walther  (rainerwalther-mail@web.de)
9
#
10
# Creative Commons Lizenz mit den Zusaetzen (by, nc, sa)
11
#
12
# Es ist Ihnen gestattet: 
13
#     * das Werk vervielfältigen, verbreiten und öffentlich zugänglich machen
14
#     * Abwandlungen bzw. Bearbeitungen des Inhaltes anfertigen
15
# 
16
# Zu den folgenden Bedingungen:
17
#     * Namensnennung.
18
#       Sie müssen den Namen des Autors/Rechteinhabers in der von ihm festgelegten Weise nennen.
19
#     * Keine kommerzielle Nutzung.
20
#       Dieses Werk darf nicht für kommerzielle Zwecke verwendet werden.
21
#     * Weitergabe unter gleichen Bedingungen.
22
#       Wenn Sie den lizenzierten Inhalt bearbeiten oder in anderer Weise umgestalten,
23
#       verändern oder als Grundlage für einen anderen Inhalt verwenden,
24
#       dürfen Sie den neu entstandenen Inhalt nur unter Verwendung von Lizenzbedingungen
25
#       weitergeben, die mit denen dieses Lizenzvertrages identisch oder vergleichbar sind.
26
# 
27
# Im Falle einer Verbreitung müssen Sie anderen die Lizenzbedingungen, unter welche dieses
28
# Werk fällt, mitteilen. Am Einfachsten ist es, einen Link auf diese Seite einzubinden.
29
# 
30
# Jede der vorgenannten Bedingungen kann aufgehoben werden, sofern Sie die Einwilligung
31
# des Rechteinhabers dazu erhalten.
32
# 
33
# Diese Lizenz lässt die Urheberpersönlichkeitsrechte unberührt.
34
# 
35
# Weitere Details zur Lizenzbestimmung gibt es hier:
36
#   Kurzform: http://creativecommons.org/licenses/by-nc-sa/3.0/de/
37
#   Komplett: http://creativecommons.org/licenses/by-nc-sa/3.0/de/legalcode
38
#
39
###############################################################################
40
# 2009-02-20 0.0.1 rw created
41
# 2009-04-01 0.1.0 rw RC1
42
# 2009-04-16 0.1.1 rw Bugfix, ALT= average of airsensor and Sat
43
# 2009-05-14 0.2.0 rw Waypoint Player
44
# 2009-05-17 0.2.1 rw Cursor-Steuerung fuer WP-Player. Cmdline-Parameter "-geometry"
45
# 2009-07-18 0.2.2 rw DE/EN multinational
46
#                     Target-Balloon with Distance, Tolerance and Holdtime
47
#                     Fix footprint "Ausreiser"
48
#                     JPEG and PNG maps supported
49
#                     Player for KML Files
50
# 2009-07-26 0.2.3 rw System Messages Balloon
51
# 2009-07-31 0.2.4 rw ODO Kilometerzähler
52
#                     Enter WP-Number from Keyboard
53
#                     Random WP-Player (Waypoint and Map)
54
#                     Check Airfield Border
55
#                     Draw Calibration points on map
56
# 2009-08-08 0.2.5 rw KML Recorder
57
#                     Text to speech
58
#                     Subroutines moved to libmkcockpit.pl
59
#                     Timer moved to libmktimer.pl
60
#                     Start Scenarion configuration
61
#                     Battery capacity estimation
62
#                     Read map definition from maps/map.xml
63
# 2009-08-23 0.2.6 rw Tracking-Antenna Icon
64
#                     Show Fox only in Player-Pause mode
65
#                     POI heading control
66
#                     Display scale
67
#                     Measuring-tool on left mouse button
68
#                     Display Operation Radius Border
69
#                     Read map definition from KML file (GE import)
70
#                     Include of local *.pm changed
71
#                     Copy x/y/Lat/Lon to Clipboard when pressing left mouse button
72
#                     Calculate size of map image
73
#                     track.pl - Commandline parameter added for COM ports
74
#                     don't use local perl libs any more
75
# 2009-10-18 0.2.7 rw Mk-Simulator
76
#                     Start tracker at program start. Coldstart at MK-calibration
77
#                     COM Port >9; PortSetSkip config
78
#                     Reset Flight-Time and ODO when clicking on OSD-value
79
# 2009-10-25 0.3.0 rw NC 0.17
80
#                     Read/Write KopterTool WPL Waypoint list
81
#                     Cfg Optionmenues
82
# 2010-02-09 0.4.0 rw Canvas - Popup focus improvement
83
#                     bugfix "WP hinzufügen und senden" in classic mode
84
#                     Grid on canvas
85
#                     joystick and 3D-Mouse
86
#                     remove main window status line
87
#                     Event engine
88
#                     Serial Channel
89
#                     External Control
90
#                     Expo, Dualrate
91
#                     Player Pause move relative to MAP or MK
92
#                     Load plugin directory
93
#                     Current, UsedCapacity, Power added
94
#                     RETURN turns off External-Control + Serial Channel
95
# 2010-02-15 0.4.1 rw F-Keys for Event
96
# 2010-03-20 0.4.2 rw Maestro Servo Controller
97
#
98
###############################################################################
99
 
100
$Version = "0.4.2 - 2010-03-20";
101
 
102
 
103
# change working directory to program path
104
my $Cwd = substr ($0, 0, rindex ($0, "mkcockpit.pl"));
105
chdir $Cwd;
106
 
107
# set path for local Perl libs
108
push @INC, $Cwd . "perl/lib";
109
 
110
use threads;            # http://search.cpan.org/~jdhedden/threads-1.72/threads.pm
111
                        # http://perldoc.perl.org/threads.html
112
use threads::shared;    # http://search.cpan.org/~jdhedden/threads-shared-1.28/shared.pm
113
use Thread::Queue;      # http://search.cpan.org/dist/Thread-Queue-2.11/lib/Thread/Queue.pm
114
use Tk;
115
use Tk::Balloon;
116
use Tk::Dialog;
117
use Tk::Notebook;
118
use Tk::JPEG;           # http://search.cpan.org/~srezic/Tk-804.028/JPEG/JPEG.pm
119
use Tk::PNG;            # http://search.cpan.org/~srezic/Tk-804.028/PNG/PNG.pm
120
use Tk::Tree;
121
use Math::Trig;
122
use Time::HiRes qw(usleep);  # http://search.cpan.org/~jhi/Time-HiRes-1.9719/HiRes.pm
123
use XML::Simple;             # http://search.cpan.org/dist/XML-Simple-2.18/lib/XML/Simple.pm
124
use Clipboard;               # http://search.cpan.org/~king/Clipboard-0.09/lib/Clipboard.pm
125
use Image::Size;             # http://search.cpan.org/~rjray/Image-Size-3.2/lib/Image/Size.pm
126
use Tk::BrowseEntry;         # http://search.cpan.org/~srezic/Tk-804.028/pod/BrowseEntry.pod
127
 
128
# Version setting
129
share (%Version);
130
$Version{'mkcockpit.pl'}  = $Version;
131
 
132
# Read configuration
133
$XmlConfigFile = "mkcockpit.xml";
134
$Cfg = XMLin($XmlConfigFile);
135
 
136
require "track.pl";        # Tracking antenna
137
require "mkcomm.pl";       # MK communication
138
require "logging.pl";      # CSV and GPX Logging
139
require "geserver.pl";     # Google Earth Server
140
require "$Cfg->{'map'}->{'MapDir'}/map.pl";   # Landkarte
141
require "libmap.pl";       # map subs
142
require "translate.pl";    # Übersetzungstable
143
require "tts.pl";          # Text to Speech
144
require "libmkcockpit.pl"; # Subroutines
145
require "libmksim.pl";     # MK Simulator
146
require "libcfgopt.pl";    # Option menu values
147
require "libmouse.pl";     # 3D Mouse
148
require "libjoystick.pl";  # joystick
149
 
150
# Commandline parameter
151
my %CmdLine = @ARGV;
152
 
153
# Aktuell gültige Karte
154
my %Map = %{$Maps{'Current'}};
155
 
156
# optional map specific Cfg setup from map definition
157
foreach $Key (keys %Map)
158
    {
159
    # Cfg:Section:Keyword
160
    if ( $Key =~ /^Cfg:(\S*):(\S*)/i )
161
        {
162
        $Section = $1;
163
        $Keyword = $2;
164
        $Cfg->{$Section}->{$Keyword} = $Map{$Key};
165
        }
166
    }
167
 
168
# Canvas size - get image size
169
my $ImgFile = "$Cfg->{'map'}->{'MapDir'}/$Map{'File'}";
170
($MapSizeX, $MapSizeY, my $ImgError) = imgsize ($ImgFile);
171
if ( $MapSizeX eq "" )
172
    {
173
    print "$ImgFile: $ImgError\n";
174
 
175
    # Try size information from map definition
176
    $MapSizeX  = $Map{'Size_X'};
177
    $MapSizeY  = $Map{'Size_Y'};
178
    }
179
 
180
 
181
# Thread fuer Kommunikation mit MK starten
182
# Output: %MkOsd, %MkTarget, %MkNcDebug, %Mk
183
# Input:  Thread-Queue: $MkSendQueue
184
$mk_thr = threads->create (\&MkCommLoop) -> detach();
185
 
186
# Start Logging Thread
187
$log_thr = threads->create (\&MkLogLoop) -> detach();
188
 
189
# Start GoogleEarth Thread
190
$ge_thr = threads->create (\&GeServer) -> detach();
191
 
192
# Start TTS Thread
193
$tts_thr = threads->create (\&TtsLoop) -> detach();
194
 
195
# Start Antenna tracker
196
if ( $Cfg->{'track'}->{'Active'} =~ /y/i )
197
    {
198
    $track_thr = threads->create (\&TrackAntennaGps)->detach();
199
    }
200
 
201
# 3D Mouse Thread
202
$mouse_thr = threads->create (\&Mouse3D) -> detach();
203
 
204
# Joystick Thread
205
$joystick_thr = threads->create (\&Joystick) -> detach();
206
 
207
 
208
#
209
# Player:
210
#    Waypoint-List:   @Waypoints
211
#    KML-Target-List: @KmlTargets
212
#
213
 
214
# Player state machine
215
$PlayerMode = 'Stop';       # Play, Stop, Pause, Home ...
216
$PlayerWptKmlMode = 'WPT';  # WPT, KML
217
$PlayerRandomMode = 'STD';  # STD, RND, MAP
218
$PlayerRecordMode = "";     # "", REC
219
$PlayerPauseMode  = "MAP";  # MAP, MK
220
$WpPlayerIndex = 0;
221
$WpPlayerHoldtime = -1;
222
$KmlPlayerIndex = 0;
223
$PlayerPause_Lat = "";
224
$PlayerPause_Lon = "";
225
 
226
# Point Of Interest (POI)
227
my $Poi_x = $MapSizeX/2-50;
228
my $Poi_y = $MapSizeY/2 ;
229
($Poi_Lat, $Poi_Lon) = &MapXY2Gps($Poi_x + 24, $Poi_y + 48);
230
 
231
# POI from Map configuration
232
if ( $Map{'Poi_Lat'} ne ""  and   $Map{'Poi_Lon'} ne "" )
233
    {
234
    $Poi_Lat = $Map{'Poi_Lat'};
235
    $Poi_Lon = $Map{'Poi_Lon'};
236
    ($Poi_x, $Poi_y) = &MapGps2XY($Poi_Lat, $Poi_Lon);
237
    $Poi_x = $Poi_x - 24;
238
    $Poi_y = $Poi_y - 48;
239
    }
240
$Poi_Mode = 0;     # POI Mode off
241
$TxExtOn = 0;      # Tx External-Control/SerialChannel off
242
 
243
# Event configuration
244
my $XmlEventConfigFile = $Cfg->{'StartScenario'}->{'EventFile'} || "event/mkevent.xml";
245
if ( ! -f $XmlEventConfigFile )
246
    {
247
    $XmlEventConfigFile = "event/" . $XmlEventConfigFile;
248
    }
249
if ( -f $XmlEventConfigFile )
250
    {
251
    $Event = XMLin($XmlEventConfigFile);
252
    }
253
 
254
if ( scalar keys %{$Event} == 0 )
255
    {
256
    # create new dummy event, if no XML or XML is empty
257
    &EventInit("Dummy", $Event);
258
    }
259
 
260
my %EventStat;    # internal state of event maschine
261
 
262
 
263
# load user plugins
264
opendir DIR, "plugin";
265
my @Plugin = readdir DIR;
266
closedir DIR;
267
@Plugin = grep /\.pl$/, @Plugin;
268
foreach my $File (@Plugin)
269
    {
270
    require "plugin/$File";
271
    }
272
 
273
 
274
# Hauptfenster
275
$main = new MainWindow;
276
$main->title ("MK Mission Cockpit - Version $Version");
277
 
278
if ( $CmdLine{'-geometry'} ne "" )
279
    {
280
    $main->geometry( "$CmdLine{'-geometry'}" );
281
    }
282
 
283
# pattern for dashed lines
284
my $stipple_bits = [];
285
foreach my $b (1..8)
286
    {
287
    push @$stipple_bits, pack ('b8', '1' x $b . '.' x (8 - $b));
288
    $main->DefineBitmap("stipple$b" => 8, 1, $stipple_bits->[$b-1]);
289
    }
290
 
291
# Catch delete window event and exit
292
$main->protocol( 'WM_DELETE_WINDOW' => sub
293
    {
294
    &CbExit();
295
    });
296
 
297
# disable main window Key-Bindings for F10
298
$main->bind('all', '<Key-F10>', undef);
299
 
300
#-----------------------------------------------------------------
301
# Menu
302
#-----------------------------------------------------------------
303
 
304
# Menu bar
305
my $menu_bar = $main->Menu;
306
$main->optionAdd("*tearOff", "false");
307
$main->configure ('-menu' => $menu_bar);
308
 
309
my $menu_file = $menu_bar->cascade('-label' => $Translate{'File'});
310
    $menu_file->command('-label' => $Translate{'Preferences'},
311
                        '-command' => [\&Configure, $XmlConfigFile, $Cfg, "CONFIG", ],
312
                       );
313
    $menu_file->command('-label' => $Translate{'ConfigEvent'},
314
                        '-command' => [\&Configure, $XmlEventConfigFile, $Event, "EVENT", ],
315
                       );
316
    $menu_file->separator;                                     
317
    $menu_file->command('-label' => $Translate{'Exit'},
318
                        '-command' => [\&CbExit ],
319
                        );
320
 
321
my $menu_debug = $menu_bar->cascade(-label => $Translate{'Debug'});
322
    $menu_debug->command('-label' => $Translate{'NcOsdDataset'},
323
                         '-command' => [\&DisplayHash, \%MkOsd, $Translate{'NcOsdDataset'}, "Display Refresh Heartbeat"],
324
                        );
325
    $menu_debug->command('-label' => $Translate{'NcTargetDataset'},
326
                         '-command' => [\&DisplayHash, \%MkTarget, $Translate{'NcTargetDataset'}, "Display Refresh Heartbeat"],
327
                        );
328
    $menu_debug->command('-label' => $Translate{'NcDebugDataset'},
329
                         '-command' => [\&DisplayHash, \%MkNcDebug, $Translate{'NcDebugDataset'}, "Display Refresh Heartbeat"],
330
                                        );             
331
    $menu_debug->command('-label' => $Translate{'NcOther'},
332
                         '-command' => [\&DisplayHash, \%Mk, $Translate{'NcOther'}, "Display Refresh Heartbeat"],
333
                                        );
334
    $menu_debug->command('-label' => $Translate{'TrackingDebugDataset'},
335
                         '-command' => [\&DisplayHash, \%MkTrack, $Translate{'TrackingDebugDataset'}, "Display Refresh Heartbeat"],
336
                        );
337
 
338
    $menu_debug->command('-label' => $Translate{'MapDebugDataset'},
339
                         '-command' => [\&DisplayHash, \%Map, $Translate{'MapDebugDataset'}, "Display"],
340
                        );
341
    $menu_debug->command('-label' => $Translate{'SystemDebug'},
342
                         '-command' => [\&DisplayHash, \%System, $Translate{'SystemDebug'}, "Display Refresh"],
343
                        );
344
    $menu_debug->separator;                                    
345
    $menu_debug->command('-label' => $Translate{'StickDebug'},
346
                         '-command' => [\&DisplayHash, \%Stick, $Translate{'StickDebug'}, "Display Refresh"],
347
                        );
348
    $menu_debug->command('-label' => $Translate{'SerialChannel'},
349
                         '-command' => [\&DisplayHash, \%MkSerialChannel, $Translate{'SerialChannel'}, "Display Refresh SerialChannel"],
350
                        );
351
    $menu_debug->command('-label' => $Translate{'ExternControl'},
352
                         '-command' => [\&DisplayHash, \%MkExternControl, $Translate{'ExternControl'}, "Display Refresh ExternControl"],
353
                        );
354
    $menu_debug->separator;                                    
355
    $menu_debug->command('-label' => $Translate{'MkDebugSim'},
356
                         '-command' => \&MkSim,
357
                        );
358
 
359
 
360
my $menu_help = $menu_bar->cascade(-label => $Translate{'Help'});
361
    $menu_help->command('-label' => 'Version',
362
                        '-command' => [\&DisplayHash, \%Version, $Translate{'Version'}, "Display"],
363
                       );
364
    $menu_help->separator;
365
    $menu_help->command('-label' => $Translate{'About'},
366
                        '-command' => sub
367
        {
368
        my $License = <<EOF;
369
Copyright (C) 2010  Rainer Walther (rainerwalther-mail\@web.de)
370
 
371
Creative Commons Lizenz mit den Zusaetzen (by, nc, sa)
372
 
373
See LICENSE.TXT
374
EOF
375
 
376
        my $DlgAbout = $frame_map->Dialog('-title' => $Translate{'AboutMissionCockpit'},
377
                                          '-text' => "$License",
378
                                          '-buttons' => ['OK'],
379
                                          '-bitmap' => 'info',
380
                                         );
381
        $DlgAbout->Show;
382
        });  
383
 
384
 
385
#-----------------------------------------------------------------
386
# Frames
387
#-----------------------------------------------------------------                        
388
 
389
#
390
# Frame: Map
391
#
392
 
393
$frame_map = $main->Frame( '-background' => 'lightgray',
394
                           '-relief' => 'sunken',
395
                           '-borderwidth' => 5,
396
                          ) -> pack('-side' => 'top',
397
                                    '-fill' => 'x',
398
                                    );
399
 
400
# Map Überschrift
401
$frame_map_top = $frame_map->Frame( -background => 'lightgray',
402
                                  ) -> pack( -side   => 'top',
403
                                             -anchor => 'w',
404
                                             -fill => 'x',
405
                                             -expand => 1,
406
                                           );
407
 
408
$frame_map_top->Label (-text       => "$Translate{'Map'}: $Map{'Name'} ($Map{'File'})",
409
                       -background => 'lightgray',
410
                       -relief     => 'flat',
411
                       ) -> pack( -side => 'left' );
412
 
413
 
414
# 10 placeholders for status texts in uppser status line. Field update in libmktimer
415
for ($i=0; $i<10; $i++)
416
    {
417
    $map_status_top[$i] = $frame_map_top->Label ( -text       => "",
418
                                                  -background => 'lightgray',
419
                                                  -anchor     => 'e',
420
                                                ) -> pack (-side => 'right',
421
                                                           -anchor => 'e',
422
                                                           -padx  => 1,
423
                                                          );
424
    }
425
 
426
# Map Statuszeile
427
$map_status = $frame_map->Frame( -background => 'lightgray',
428
                               ) -> pack( -side   => 'bottom',
429
                                          -anchor => 'w',
430
                                          -fill   => 'x',
431
                                          -expand => 1,
432
                                        );
433
$map_status_line = $map_status->Label ( -text => $Translate{'StatusLine'},
434
                                        -background => 'lightgray',
435
                                       ) -> pack (-side   => 'left',
436
                                                  -anchor => 'w',
437
                                                  -expand => 1,
438
                                                  );
439
 
440
# 10 placeholders for event status in lower status line. Field update in libmktimer
441
for ($i=0; $i<10; $i++)
442
    {
443
    $map_status_event[$i] = $map_status->Label ( -text       => "",
444
                                                 -background => 'lightgray',
445
                                                 -anchor     => 'e',
446
                                               ) -> pack (-side => 'right',
447
                                                          -anchor => 'e',
448
                                                          -padx  => 1,
449
                                                         );
450
    }
451
 
452
#
453
# Map Canvas
454
#
455
 
456
$map_canvas = $frame_map->Canvas( '-width'  => $MapSizeX,
457
                                  '-height' => $MapSizeY,
458
                                  '-cursor' => 'cross',
459
                                ) -> pack();
460
 
461
 
462
# Images and Icons on canvas
463
my @Icons = (
464
            # Image             Tag             File                                       Pos_x            Pos_y
465
            'Map',              'Map',          "$Cfg->{'map'}->{'MapDir'}/$Map{'File'}",  0,               0,
466
            'HeartbeatSmall',   'Heartbeat',    "$Cfg->{'mkcockpit'}->{'IconHeartSmall'}", $MapSizeX/4-10,  10,
467
            'HeartbeatLarge',   'Heartbeat',    "$Cfg->{'mkcockpit'}->{'IconHeartLarge'}", $MapSizeX/4-10,  -100,
468
            'Satellite-Photo',  'Satellite',    "$Cfg->{'mkcockpit'}->{'IconSatellite'}",  $MapSizeX-50,    -100,
469
            'Antenna-Photo',    'Track-Antenna',"$Cfg->{'track'}->{'IconAntenna'}",        0,               -50,
470
            'POI-Photo',        'POI'          ,"$Cfg->{'mkcockpit'}->{'IconPoi'}",        $Poi_x,          $Poi_y,
471
            'Waypoint-Photo',   'Waypoint',     "$Cfg->{'mkcockpit'}->{'IconWaypoint'}",   0,               -150,
472
            'Target-Photo',     'Target',       "$Cfg->{'mkcockpit'}->{'IconTarget'}",     0,               -100,
473
            'Fox-Photo',        'Fox',          "$Cfg->{'mkcockpit'}->{'IconFox'}",        $MapSizeX/2-100, $MapSizeY/2,
474
            'WpPlay-Foto',      'Wp-PlayPause', "$Cfg->{'waypoint'}->{'IconPlay'}",        $MapSizeX/2+150, $MapSizeY-48,
475
            'WpPause-Foto',     'Wp-PlayPause', "$Cfg->{'waypoint'}->{'IconPause'}",       $MapSizeX/2+150, -100,
476
            'WpStop-Foto',      'Wp-Stop',      "$Cfg->{'waypoint'}->{'IconStop'}",        $MapSizeX/2+200, $MapSizeY-48,
477
            'WpNext-Foto',      'Wp-Next',      "$Cfg->{'waypoint'}->{'IconNext'}",        $MapSizeX/2+50,  $MapSizeY-48,
478
            'WpPrev-Foto',      'Wp-Prev',      "$Cfg->{'waypoint'}->{'IconPrev'}",        $MapSizeX/2,     $MapSizeY-48,
479
            'WpFirst-Foto',     'Wp-First',     "$Cfg->{'waypoint'}->{'IconFirst'}",       $MapSizeX/2-50,  $MapSizeY-48,
480
            'WpLast-Foto',      'Wp-Last',      "$Cfg->{'waypoint'}->{'IconLast'}",        $MapSizeX/2+100, $MapSizeY-48,
481
            'WpHome-Foto',      'Wp-Home',      "$Cfg->{'waypoint'}->{'IconHome'}",        $MapSizeX/2-100, $MapSizeY-48,
482
            'WpRecord-Foto',    'Wp-Record',    "$Cfg->{'waypoint'}->{'IconRecord'}",      $MapSizeX/2-150, $MapSizeY-48,
483
            'WpRandomOff-Foto', 'Wp-WptRandom', "$Cfg->{'waypoint'}->{'IconRandomOff'}",   $MapSizeX/2-200, -100,
484
            'WpRandomOn-Foto',  'Wp-WptRandom', "$Cfg->{'waypoint'}->{'IconRandomOn'}",    $MapSizeX/2-200, $MapSizeY-48,
485
            'WpRandomMap-Foto', 'Wp-WptRandom', "$Cfg->{'waypoint'}->{'IconRandomMap'}",   $MapSizeX/2-200, -100,
486
            'WpWpt-Foto',       'Wp-WptKml',    "$Cfg->{'waypoint'}->{'IconWpt'}",         $MapSizeX/2-250, $MapSizeY-48,
487
            'WpKml-Foto',       'Wp-WptKml',    "$Cfg->{'waypoint'}->{'IconKml'}",         $MapSizeX/2-250, -100 ,
488
            );
489
my $i = 0;
490
for $Icon (0 .. $#Icons/5)
491
    {
492
    my $Image =  $Icons[$i++];
493
    my $Tag =    $Icons[$i++];
494
    my $File =   $Icons[$i++];
495
    my $Pos_x =  $Icons[$i++];
496
    my $Pos_y =  $Icons[$i++];
497
 
498
    $map_canvas->Photo( $Image,
499
                        -file => $File,
500
                      );
501
 
502
    $map_canvas->createImage( $Pos_x, $Pos_y,
503
                              -tags   => $Tag,
504
                              -anchor => 'nw',
505
                              -image  => $Image,
506
                            );
507
    }
508
 
509
 
510
# Calibration Points
511
$map_canvas->createLine ( $Map{'P1_x'}-8, $Map{'P1_y'},
512
                          $Map{'P1_x'}+8, $Map{'P1_y'},
513
                          $Map{'P1_x'},   $Map{'P1_y'},
514
                          $Map{'P1_x'},   $Map{'P1_y'}-8,
515
                          $Map{'P1_x'},   $Map{'P1_y'}+8,
516
                          '-tags'  => 'Calibration',
517
                          '-arrow' => 'none',
518
                          '-fill'  => 'red',
519
                          '-width' => 1,
520
                         );
521
$map_canvas->createLine ( $Map{'P2_x'}-8, $Map{'P2_y'},
522
                          $Map{'P2_x'}+8, $Map{'P2_y'},
523
                          $Map{'P2_x'},   $Map{'P2_y'},
524
                          $Map{'P2_x'},   $Map{'P2_y'}-8,
525
                          $Map{'P2_x'},   $Map{'P2_y'}+8,
526
                          '-tags'  => 'Calibration',
527
                          '-arrow' => 'none',
528
                          '-fill'  => 'red',
529
                          '-width' => 1,
530
                         );
531
 
532
# scale
533
my $x1 = $MapSizeX/2 +280;
534
my $x2 = $MapSizeX -30;
535
my $y1 = $MapSizeY - 20;
536
my $y2 = $MapSizeY - 15;
537
if ( $x2 - $x1 > 150 )
538
    {
539
    $x1 = $x2 - 150;
540
    }
541
 
542
$map_canvas->createLine ( $x1, $y1,
543
                          $x1, $y2,
544
                          $x2, $y2,
545
                          $x2, $y1,
546
                          '-tags'  => 'Scale',
547
                          '-arrow' => 'none',
548
                          '-fill'  => 'red',
549
                           '-fill' => $Cfg->{'mkcockpit'}->{'ColorScale'} || 'white',
550
                          '-width' => 1,
551
                         );
552
 
553
my ($Lat1, $Lon1) = &MapXY2Gps($x1, $y1);
554
my ($Lat2, $Lon2) = &MapXY2Gps($x2, $y2);
555
my ($Dist, $Bearing) = &MapGpsTo($Lat1, $Lon1, $Lat2, $Lon2 );
556
$Dist = sprintf ("%.2f m", $Dist);
557
$map_canvas->createText ( $x1 + ($x2 - $x1)/2 - 20, $y1 - ($y2 - $y1)/2,
558
                          '-tags' => 'Scale-Text',
559
                          '-text' => $Dist,
560
                          '-anchor' => 'w',
561
                          '-font' => '-*-Arial-Bold-R-Normal--*-120-*',
562
                          '-fill' => $Cfg->{'mkcockpit'}->{'ColorScale'} || 'white',
563
                          );
564
 
565
# border polygon
566
$map_canvas->createPolygon( @Map{'Border'},
567
                           '-tags' => 'Map-Border',
568
                           '-fill' => '',
569
                           '-outline' => $Cfg->{'mkcockpit'}->{'ColorAirfield'}, '-width' => 2,
570
                          );
571
$map_canvas->raise('Map-Border', 'Map');  # Border above Map
572
 
573
 
574
# Balloon attached to Canvas
575
$map_balloon = $frame_map->Balloon('-statusbar' => $status_line, );
576
$map_balloon->attach($map_canvas,
577
                     '-balloonposition' => 'mouse',
578
                     '-state' => 'balloon',
579
                     '-msg' => { 'MK-Arrow'               => $Translate{'Balloon-MK-Arrow'},
580
                                 'MK-Home-Line'           => $Translate{'Balloon-MK-Home-Line'},
581
                                 'MK-Home-Dist'           => $Translate{'Balloon-MK-Home-Dist'},
582
                                 'MK-Target-Line'         => $Translate{'Balloon-MK-Target-Line' },
583
                                 'MK-Target-Dist'         => $Translate{'Balloon-MK-Target-Dist'},
584
                                 'MK-Speed'               => $Translate{'Balloon-MK-Speed'},
585
                                 'Map-Variometer'         => $Translate{'Balloon-Map-Variometer' },
586
                                 'Map-Variometer-Pointer' => $Translate{'Balloon-Map-Variometer-Pointer'},
587
                                 'Map-Variometer-Skala'   => $Translate{'Balloon-Map-Variometer-Pointer'},
588
                                 'Fox'                    => $Translate{'Balloon-Fox'},
589
                                 'Heartbeat'              => $Translate{'Balloon-Heartbeat'},
590
                                 'Satellite'              => $Translate{'Balloon-Satellite'},
591
                                 'Waypoint'               => $Translate{'Balloon-Waypoint'},
592
                                 'Map-Border'             => $Translate{'Balloon-Map-Border'},
593
                                 'Waypoint-Connector'     => $Translate{'Balloon-Waypoint-Connector'},
594
                                 'Wp-PlayPause'           => $Translate{'Balloon-Wp-PlayPause'},
595
                                 'Wp-Stop'                => $Translate{'Balloon-Wp-Stop'},
596
                                 'Wp-First'               => $Translate{'Balloon-Wp-First'},
597
                                 'Wp-Last'                => $Translate{'Balloon-Wp-Last'},
598
                                 'Wp-Next'                => $Translate{'Balloon-Wp-Next'},
599
                                 'Wp-Prev'                => $Translate{'Balloon-Wp-Prev'},
600
                                 'Wp-Home'                => $Translate{'Balloon-Wp-Home'},
601
                                 'Wp-WptKml'              => $Translate{'Balloon-Wp-WptKml'},
602
                                 'Wp-WptRandom'           => $Translate{'Balloon-Wp-WptRandom'},
603
                                 'Wp-Record'              => $Translate{'Balloon-Wp-Record'},
604
                                 'Track-Antenna'          => $Translate{'Balloon-TrackAntenna'},
605
                                 'POI'                    => $Translate{'Balloon-Poi'},
606
                               },
607
                    );
608
 
609
#                                       
610
# Mouse button 1
611
#
612
 
613
# Button 1 Press
614
$map_canvas->CanvasBind("<Button-1>", sub
615
    {
616
    # print coords in status line
617
    my ($x, $y) = ($Tk::event->x, $Tk::event->y);
618
    my ($Lat, $Lon) = &MapXY2Gps($x, $y);
619
 
620
    $map_status_line->configure ('-text' => "Lat: $Lat  Lon: $Lon     x: $x  y: $y");
621
 
622
    # save Coords and GPS-Pos for Button-Motion and Release
623
    $Button1_x = $x;
624
    $Button1_y = $y;
625
    $Button1_Lat = $Lat;
626
    $Button1_Lon = $Lon;
627
 
628
    # copy Pixel-Coordinates to Clipboard
629
    Clipboard->copy ("x=$x\r\n" . "y=$y\r\n" . "Lat=$Lat\r\n" . "Lon=$Lon\r\n");
630
    });
631
 
632
# Button 1 Motion
633
$map_canvas->CanvasBind("<Button1-Motion>", sub
634
    {
635
    my ($x, $y) = ($Tk::event->x, $Tk::event->y);
636
    my $id      = $map_canvas->find('withtag', 'current');
637
 
638
    # delete old measuring line
639
    $map_canvas->delete('Map-Measure');
640
 
641
    my @Tags = $map_canvas->gettags($id);
642
    if ( ( $Tags[0] eq "Map"  or $Tags[0] eq "Map-Border") and
643
         $x ne $Button1_x  and  $y ne $Button1_y )
644
        {
645
        # button moved on Map
646
 
647
        # draw new measuring line
648
        $map_canvas->createLine ( $Button1_x, $Button1_y, $x, $y,
649
                                  '-tags' => 'Map-Measure',
650
                                  '-arrow' => 'none',
651
                                  '-fill' => 'white',
652
                                  '-width' => 1,
653
                         );
654
 
655
        # update status line
656
        my ($Lat, $Lon) = &MapXY2Gps($x, $y);
657
        my ($Dist, $Bearing) = &MapGpsTo($Button1_Lat, $Button1_Lon, $Lat, $Lon);
658
        $Dist = sprintf ("%.2f m", $Dist);
659
        $Bearing = sprintf ("%.2f degree", $Bearing);
660
 
661
        $map_status_line->configure ('-text' => "Dist: $Dist  Bearing: $Bearing");
662
        }
663
    });
664
 
665
# Button 1 Release
666
$map_canvas->CanvasBind("<Button1-ButtonRelease>", sub
667
    {
668
    my ($x, $y) = ($Tk::event->x, $Tk::event->y);
669
    my $id      = $map_canvas->find('withtag', 'current');
670
 
671
    # delete measuring line
672
    $map_canvas->delete('Map-Measure');
673
 
674
    my @Tags = $map_canvas->gettags($id);
675
    if ( ( $Tags[0] eq "Map"  or $Tags[0] eq "Map-Border") and
676
         $x ne $Button1_x  and  $y ne $Button1_y )
677
        {
678
        # button released on Map
679
 
680
        # update status line
681
        my ($Lat, $Lon) = &MapXY2Gps($x, $y);
682
        my ($Dist, $Bearing) = &MapGpsTo($Button1_Lat, $Button1_Lon, $Lat, $Lon);
683
        $Dist = sprintf ("%.2f m", $Dist);
684
        $Bearing = sprintf ("%.2f degree", $Bearing);
685
 
686
        $map_status_line->configure ('-text' => "Dist: $Dist  Bearing: $Bearing");
687
        }
688
    });
689
 
690
 
691
# Mouse button 1 for Fox
692
my $FoxOldx = 0;
693
my $FoxOldy = 0;
694
my $FoxTime = time;
695
&FoxHide();   # Show only in Player-Pause Mode
696
 
697
# Pick Fox
698
$map_canvas->bind('Fox' => '<Button-1>' => sub
699
    {
700
    # prepare to move Fox
701
    my ($x, $y) = ($Tk::event->x, $Tk::event->y);
702
    $FoxOldx = $x;
703
    $FoxOldy = $y;
704
    $FoxTime = time;
705
    });
706
 
707
# Move Fox
708
$map_canvas->bind('Fox' => '<Button1-Motion>' => sub
709
    {
710
    my ($x, $y) = ($Tk::event->x, $Tk::event->y);
711
    my $id      = $map_canvas->find('withtag', 'current');
712
 
713
    $map_canvas->move($id => $x - $FoxOldx, $y - $FoxOldy);
714
    $FoxOldx = $x;
715
    $FoxOldy = $y;
716
 
717
    if ( time > $FoxTime )
718
        {
719
        # wenn in Bewegung Koordinaten nur 1/s senden
720
        my ($x0, $y0, $x1, $y1) = $map_canvas->bbox ($id);
721
        $x = $x0 + ($x1 - $x0)/2;
722
        $y = $y1;
723
 
724
        ($PlayerPause_Lat, $PlayerPause_Lon) = &MapXY2Gps($x, $y);
725
        $FoxTime = time;
726
 
727
        $map_status_line->configure ('-text' => "$Translate{'TargetCoordSent'} -> Lat: $PlayerPause_Lat  Lon: $PlayerPause_Lon     x: $x  y: $y");
728
        }
729
    });
730
 
731
# Release Fox
732
$map_canvas->bind('Fox' => '<Button1-ButtonRelease>' => sub
733
    {
734
    my ($x, $y) = ($Tk::event->x, $Tk::event->y);
735
    my $id      = $map_canvas->find('withtag', 'current');
736
 
737
    my ($x0, $y0, $x1, $y1) = $map_canvas->bbox ($id);
738
    $x = $x0 + ($x1 - $x0)/2;
739
    $y = $y1;
740
 
741
    ($PlayerPause_Lat, $PlayerPause_Lon) = &MapXY2Gps($x, $y);
742
 
743
    # Show user that Waypoints in MK are cleared
744
    $WaypointsModified = 1;
745
    &WpRedrawLines();
746
 
747
    $map_status_line->configure ('-text' => "$Translate{'TargetCoordSent'} -> Lat: $PlayerPause_Lat  Lon: $PlayerPause_Lon     x: $x  y: $y");
748
    });
749
 
750
# Pick Waypoint
751
my $WpOldx;
752
my $WpOldy;
753
$map_canvas->bind('Waypoint' => '<Button-1>' => sub
754
    {
755
    # prepare to move
756
    my ($x, $y) = ($Tk::event->x, $Tk::event->y);
757
    $WpOldx = $x;
758
    $WpOldy = $y;
759
    });
760
 
761
# Move Waypoint
762
$map_canvas->bind('Waypoint' => '<Button1-Motion>' => sub
763
    {
764
    my ($x, $y) = ($Tk::event->x, $Tk::event->y);
765
    my $id      = $map_canvas->find('withtag', 'current');
766
 
767
    # move icon and Wp-Number
768
    my $WpIndex = &WpGetIndexFromId($id);
769
    if ( $WpIndex >= 0 )
770
        {
771
        my $Tag = $Waypoints[$WpIndex]{'Tag'};
772
        $map_canvas->move($Tag => $x - $WpOldx, $y - $WpOldy);
773
        }
774
 
775
    $WpOldx = $x;
776
    $WpOldy = $y;
777
    });
778
 
779
# Release Wp
780
$map_canvas->bind('Waypoint' => '<Button1-ButtonRelease>' => sub
781
    {
782
    my ($x, $y) = ($Tk::event->x, $Tk::event->y);
783
    my $id      = $map_canvas->find('withtag', 'current');
784
 
785
    # take coords from lower/middle icon position
786
    my ($x0, $y0, $x1, $y1) = $map_canvas->bbox ($id);
787
    $x = $x0 + ($x1 - $x0)/2;
788
    $y = $y1;
789
 
790
    # update Waypoint-Array
791
    my $WpIndex = &WpGetIndexFromId($id);
792
    if ( $WpIndex >= 0 )
793
            {
794
        # got it: set new coords
795
 
796
        my ($Lat, $Lon) = &MapXY2Gps($x, $y);
797
        my $Wp = $Waypoints[$WpIndex];
798
        $Wp->{'MapX'} = $x;
799
        $Wp->{'MapY'} = $y;
800
        $Wp->{'Pos_Lat'} = $Lat;
801
        $Wp->{'Pos_Lon'} = $Lon;
802
 
803
        # redraw connector-lines
804
        &WpRedrawLines();
805
 
806
        # red connectors: Wp still have to be sent to MK
807
        $map_canvas->itemconfigure('Waypoint-Connector',
808
                                           '-fill' => $Cfg->{'mkcockpit'}->{'ColorWpResend'},
809
                                  );
810
        $WaypointsModified = 1;
811
 
812
        my $WpNum = $WpIndex + 1;
813
        $map_status_line->configure ('-text' => "$Translate{'WpMoved'}: $WpNum -> Lat: $Lat  Lon: $Lon     x: $x  y: $y");
814
        }
815
    });
816
 
817
# Mouse button 1 for POI
818
my $PoiOldx = 0;
819
my $PoiOldy = 0;
820
&PoiHide();
821
 
822
# Pick Poi
823
$map_canvas->bind('POI' => '<Button-1>' => sub
824
    {
825
    # prepare to move Icon
826
    my ($x, $y) = ($Tk::event->x, $Tk::event->y);
827
    $PoiOldx = $x;
828
    $PoiOldy = $y;
829
    });
830
 
831
# Move POI
832
$map_canvas->bind('POI' => '<Button1-Motion>' => sub
833
    {
834
    my ($x, $y) = ($Tk::event->x, $Tk::event->y);
835
    my $id      = $map_canvas->find('withtag', 'current');
836
 
837
    $map_canvas->move($id => $x - $PoiOldx, $y - $PoiOldy);
838
    $PoiOldx = $x;
839
    $PoiOldy = $y;
840
    });
841
 
842
# Release POI
843
$map_canvas->bind('POI' => '<Button1-ButtonRelease>' => sub
844
    {
845
    my ($x, $y) = ($Tk::event->x, $Tk::event->y);
846
    my $id      = $map_canvas->find('withtag', 'current');
847
 
848
    my ($x0, $y0, $x1, $y1) = $map_canvas->bbox ($id);
849
    $x = $x0 + ($x1 - $x0)/2;
850
    $y = $y1;
851
 
852
    ($Poi_Lat, $Poi_Lon) = &MapXY2Gps($x, $y);
853
 
854
    $map_status_line->configure ('-text' => "$Translate{'PoiMoved'}: ->   Lat: $Poi_Lat  Lon: $Poi_Lon     x: $x  y: $y");
855
    });
856
 
857
 
858
# Reset Flight time
859
$map_canvas->bind('MK-OSD-Tim-Value' => '<Button-1>' => sub
860
    {
861
    $MkFlyingTime = 0;
862
    });
863
 
864
# Reset ODO
865
$map_canvas->bind('MK-OSD-Odo-Value' => '<Button-1>' => sub
866
    {
867
    $OdoMeter = 0;
868
    });
869
 
870
 
871
#
872
# Mouse button 3 context menu
873
#
874
my $map_menu = $map_canvas->Menu('-tearoff' => 0,
875
                                 '-title' =>'None',
876
                                 '-menuitems' =>
877
    [
878
     [Button => $Translate{'WpAddAndSend'},  -command => sub
879
        {
880
        # send Wp to MK         
881
        my ($Lat, $Lon) = &MapXY2Gps($MapCanvasX, $MapCanvasY);
882
        &MkFlyTo ( -lat => $Lat,
883
                   -lon => $Lon,
884
                   -mode => "Waypoint",
885
                   -index => scalar @Waypoints,
886
                 );
887
 
888
        # Add Wp to Waypoints list
889
        &WpAdd (-lat => $Lat,
890
                -lon => $Lon,
891
                -x   => $MapCanvasX,
892
                -y   => $MapCanvasY,
893
               );
894
 
895
        # switch player to Wp mode and redraw waypoints
896
        &PlayerWpt();
897
 
898
        $map_status_line->configure ('-text' => "$Translate{'WpSavedAndSent'} -> Lat: $Lat Lon: $Lon");
899
        }],
900
 
901
 
902
     [Button => $Translate{'WpProperties'},  -command => sub
903
        {
904
        # find Wp-Hash for selected icon/tag
905
        my $WpIndex = &WpGetIndexFromId($MapCanvasId);
906
        if ( $WpIndex >= 0 )
907
            {
908
            my $Wp = $Waypoints[$WpIndex];
909
            my $WpNum = $WpIndex + 1;
910
 
911
            &DisplayHash ($Wp, "$Translate{'WpProperties'} $WpNum", "Edit Waypoint Refresh");
912
 
913
            $map_status_line->configure ('-text' => "$Translate{'WpProperties'} $WpNum");
914
            }
915
        }],
916
 
917
     [Button => $Translate{'WpResendAll'},  -command => sub
918
        {
919
        &WpSendAll();
920
 
921
        $map_status_line->configure ('-text' => $Translate{'WpAllSent'});
922
        }],
923
 
924
      '',   # Separator
925
 
926
     [Button => $Translate{'WpLoadAndSend'},  -command => sub
927
        {
928
        my $WpFile = $main->getOpenFile('-defaultextension' => ".xml",
929
                                        '-filetypes'        =>
930
                                            [['Mission Cockpit',  '.xml' ],
931
                                             ['Mikrokopter Tool', '.wpl' ],
932
                                             ['All Files',     '*', ],
933
                                            ],
934
                                        '-initialdir' => $Cfg->{'waypoint'}->{'WpDir'},
935
                                        '-title' => $Translate{'WpLoad'},
936
                                       );
937
        if ( -f $WpFile )
938
            {
939
            &WpLoadFile ($WpFile);
940
 
941
            # send all Wp to MK
942
            &WpSendAll();
943
 
944
            # switch player to Wp mode and redraw waypoints
945
            $PlayerRandomMode  = 'STD';
946
            &PlayerWpt();
947
 
948
            $map_status_line->configure ('-text' => "$Translate{'WpLoadedAndSent'}: $WpFile");
949
            }
950
        }],    
951
 
952
     [Button => $Translate{'WpSave'},  -command => sub
953
        {
954
        my $WpFile = $main->getSaveFile('-defaultextension' => ".xml",
955
                                        '-filetypes'        =>
956
                                         [['Mission Cockpit',  '.xml' ],
957
                                          ['Mikrokopter Tool', '.wpl' ],
958
                                          ['All Files',     '*', ],
959
                                          ],
960
                                        '-initialdir' => $Cfg->{'waypoint'}->{'WpDir'},
961
                                        '-title' => $Translate{'WpSave'},
962
                                       );
963
 
964
        &WpSaveFile ($WpFile);
965
 
966
        $map_status_line->configure ('-text' => "$Translate{'WpSaved'}: $WpFile");
967
        }],
968
 
969
     '',   # Separator
970
 
971
     [Button => $Translate{'WpDelete'},  -command => sub
972
        {
973
        # find Wp-Hash for selected icon/tag
974
        my $WpIndex = &WpGetIndexFromId($MapCanvasId);
975
        if ( $WpIndex >= 0 )
976
            {
977
            &WpDelete ($WpIndex);
978
 
979
            # redraw connector-lines
980
            $WaypointsModified = 1;
981
            &WpRedrawLines();  
982
            &WpRedrawIcons();  # wg. Wp-Nummern
983
 
984
            my $WpNum = $WpIndex + 1;
985
            $map_status_line->configure ('-text' => "$Translate{'WpDeleted'}: $WpNum");
986
            }
987
        }],
988
 
989
     [Button => $Translate{'WpAllDeleteAndSend'},  -command => sub
990
        {
991
        &WpDeleteAll();
992
        &WpSendAll();
993
 
994
        $map_status_line->configure ('-text' => "$Translate{'WpAllDeleted'}: $WpIndex");
995
        }],
996
 
997
    '',   # Separator
998
 
999
     [Button => $Translate{'KmlLoadAndPlay'},  -command => sub
1000
        {
1001
        $KmlFile = $main->getOpenFile('-defaultextension' => ".kml",
1002
                                     '-filetypes'        =>
1003
                                         [['KML',           '.kml' ],
1004
                                          ['All Files',     '*', ],
1005
                                         ],
1006
                                     '-initialdir' => $Cfg->{'waypoint'}->{'KmlDir'},
1007
                                     '-title' => $Translate{'KmlLoad'},
1008
                                    );
1009
        if ( -f $KmlFile )
1010
            {
1011
            &KmlLoadFile($KmlFile);
1012
 
1013
            # switch player to KML mode and redraw track
1014
            &PlayerKml();
1015
 
1016
            $map_status_line->configure ('-text' => "$Translate{'KmlLoaded'}: $KmlFile" );
1017
            }
1018
 
1019
        }],
1020
    ]
1021
                                    );
1022
$map_canvas->CanvasBind("<Button-3>" => [ sub
1023
    {
1024
    $map_canvas->focus;
1025
    my($w, $x, $y) = @_;
1026
    ($MapCanvasX, $MapCanvasY) = ($Tk::event->x, $Tk::event->y);
1027
    $MapCanvasId = $map_canvas->find('withtag', 'current');
1028
    $map_menu->post($x, $y);
1029
    }, Ev('X'), Ev('Y') ] );
1030
 
1031
 
1032
# Mouse bindings
1033
$map_canvas->bind('Wp-PlayPause' => '<Button-1>' => \&CbPlayerPlayPause );
1034
$map_canvas->bind('Wp-Next'      => '<Button-1>' => \&CbPlayerNext );
1035
$map_canvas->bind('Wp-Prev'      => '<Button-1>' => \&CbPlayerPrev );
1036
$map_canvas->bind('Wp-First'     => '<Button-1>' => \&CbPlayerFirst );
1037
$map_canvas->bind('Wp-Last'      => '<Button-1>' => \&CbPlayerLast );
1038
$map_canvas->bind('Wp-Home'      => '<Button-1>' => \&CbPlayerHome );
1039
$map_canvas->bind('Wp-Stop'      => '<Button-1>' => \&CbPlayerStop );
1040
$map_canvas->bind('Wp-WptKml'    => '<Button-1>' => \&CbPlayerWptKml );
1041
$map_canvas->bind('Wp-WptRandom' => '<Button-1>' => \&CbPlayerWptRandom );
1042
$map_canvas->bind('Wp-Record'    => '<Button-1>' => \&CbPlayerRecord );
1043
 
1044
 
1045
# Focus Canvas, if any key pressed. Needed for the following key-bindings
1046
my $bBindFocus = 0;
1047
$main->bind('<Any-Enter>' => sub
1048
    {
1049
    if ($bBindFocus == 0)
1050
        {
1051
        # focus only once. Verhindern vom canvas-popup, wenn Config-Dialog aktiv ist.
1052
        # funktioniert so, habe aber keine Ahnung warum
1053
        $map_canvas->Tk::focus;
1054
        $bBindFocus = 1;
1055
        }
1056
    });
1057
 
1058
 
1059
# Disable default arrow-key bindings on canvas
1060
$main->bind('Tk::Canvas',"<$_>",undef)for qw /Left Right Up Down/;
1061
 
1062
# keyboard bindings
1063
$map_canvas->Tk::bind( '<Key-space>' , \&CbPlayerPlayPause );
1064
$map_canvas->Tk::bind( '<Key-n>'     , \&CbPlayerNext );
1065
$map_canvas->Tk::bind( '<Key-p>'     , \&CbPlayerPrev );
1066
$map_canvas->Tk::bind( '<Key-f>'     , \&CbPlayerFirst );
1067
$map_canvas->Tk::bind( '<Key-l>'     , \&CbPlayerLast );
1068
$map_canvas->Tk::bind( '<Key-h>'     , \&CbPlayerHome );
1069
$map_canvas->Tk::bind( '<Key-s>'     , \&CbPlayerStop );
1070
$map_canvas->Tk::bind( '<Key-w>'     , \&CbPlayerWptKml );
1071
$map_canvas->Tk::bind( '<Key-k>'     , \&CbPlayerWptKml );
1072
$map_canvas->Tk::bind( '<Key-r>'     , \&CbPlayerWptRandom );
1073
$map_canvas->Tk::bind( '<Key-a>'     , \&CbPlayerRecord );
1074
$map_canvas->Tk::bind( '<Key-m>'     , \&CbPlayerMute );
1075
$map_canvas->Tk::bind( '<Key-v>'     , \&CbPoi );
1076
$map_canvas->Tk::bind( '<Key-g>'     , \&CbGrid );
1077
$map_canvas->Tk::bind( '<Key-x>'     , \&CbPlayerPauseMode );
1078
$map_canvas->Tk::bind( '<Key-0>'     , [\&CbPlayerNum, "0"] );
1079
$map_canvas->Tk::bind( '<Key-1>'     , [\&CbPlayerNum, "1"] );
1080
$map_canvas->Tk::bind( '<Key-2>'     , [\&CbPlayerNum, "2"] );
1081
$map_canvas->Tk::bind( '<Key-3>'     , [\&CbPlayerNum, "3"] );
1082
$map_canvas->Tk::bind( '<Key-4>'     , [\&CbPlayerNum, "4"] );
1083
$map_canvas->Tk::bind( '<Key-5>'     , [\&CbPlayerNum, "5"] );
1084
$map_canvas->Tk::bind( '<Key-6>'     , [\&CbPlayerNum, "6"] );
1085
$map_canvas->Tk::bind( '<Key-7>'     , [\&CbPlayerNum, "7"] );
1086
$map_canvas->Tk::bind( '<Key-8>'     , [\&CbPlayerNum, "8"] );
1087
$map_canvas->Tk::bind( '<Key-9>'     , [\&CbPlayerNum, "9"] );
1088
$map_canvas->Tk::bind( '<Key-Left>'  , [\&CbPlayerMove, -1,  0] );
1089
$map_canvas->Tk::bind( '<Key-Right>' , [\&CbPlayerMove,  1,  0] );
1090
$map_canvas->Tk::bind( '<Key-Up>'    , [\&CbPlayerMove,  0,  1] );
1091
$map_canvas->Tk::bind( '<Key-Down>'  , [\&CbPlayerMove,  0, -1] );
1092
$map_canvas->Tk::bind( '<Key-Escape>', \&CbExit );
1093
$map_canvas->Tk::bind( '<Key-Return>', \&CbTxOnOff );
1094
 
1095
# Fct-Keys F1 .. F12
1096
for ($i=1; $i <= 12; $i++)
1097
    {
1098
    $map_canvas->Tk::bind( "<KeyPress-F$i>",   [\&CbFctKeyPress,   "$i"] );
1099
    $map_canvas->Tk::bind( "<KeyRelease-F$i>", [\&CbFctKeyRelease, "$i"] );
1100
    }
1101
$Stick{'FctKey'} = 0;
1102
 
1103
#
1104
# dynamic objecs on canvas
1105
#
1106
 
1107
# current MK position on canvas
1108
$MkPos_x = $MapSizeX/2;
1109
$MkPos_y = $MapSizeY/2;
1110
 
1111
# Line from MK to Home
1112
$map_canvas->createLine ( $MapSizeX/2, $MapSizeY/2, $MapSizeX/2, $MapSizeY/2,
1113
                          '-tags' => 'MK-Home-Line',
1114
                          '-arrow' => 'none',
1115
                          '-fill' => $Cfg->{'mkcockpit'}->{'ColorHomeLine'},
1116
                          '-width' => 3,
1117
                         );
1118
 
1119
# Text Entfernung positioniert an der Home-Linie
1120
$map_canvas->createText ( $MapSizeX/2 + 8, $MapSizeY/2 - 8,
1121
                          '-tags' => 'MK-Home-Dist',
1122
                          '-text' => '0 m',
1123
                          '-anchor' => 'w',
1124
                          '-font' => '-*-Arial-Bold-R-Normal--*-200-*',
1125
                          '-fill' => $Cfg->{'mkcockpit'}->{'ColorHomeDist'},
1126
                          );
1127
 
1128
# Line from MK to Target, draw invisible out of sight
1129
$map_canvas->createLine ( 0, -100, 0, -100,
1130
                          '-tags' => 'MK-Target-Line',
1131
                          '-arrow' => 'none',
1132
                          '-fill' => $Cfg->{'mkcockpit'}->{'ColorTargetLine'},
1133
                          '-width' => 3,
1134
                         );
1135
 
1136
# Text Entfernung positioniert an der Target-Linie
1137
$map_canvas->createText ( 0, -100,
1138
                          '-tags' => 'MK-Target-Dist',
1139
                          '-text' => '0 m',
1140
                          '-anchor' => 'w',
1141
                          '-font' => '-*-Arial-Bold-R-Normal--*-200-*',
1142
                          '-fill' => $Cfg->{'mkcockpit'}->{'ColorTargetDist'},
1143
                          );
1144
 
1145
# Line from MK to POI, draw invisible out of sight
1146
$map_canvas->createLine ( 0, -200, 0, -200,
1147
                          '-tags' => 'MK-POI-Line',
1148
                          '-arrow' => 'none',
1149
                          '-fill' => $Cfg->{'mkcockpit'}->{'ColorPoiLine'},
1150
                          '-stipple' => "stipple4",
1151
                          '-width' => 1,
1152
                         );
1153
$map_canvas->lower('MK-POI-Line', 'Target');
1154
 
1155
# MK Geschwindigkeits-Vektor
1156
$MapMkSpeedLen = 60;    # Länge Speed-Zeiger
1157
my $x0 = $MapSizeX/2;
1158
my $y0 = $MapSizeY/2;
1159
my $x1 = $MapSizeX/2;
1160
my $y1 = $MapSizeY/2 - $MapMkSpeedLen;
1161
$map_canvas->createLine ( $x0, $y0, $x1, $y1,
1162
                          '-tags' => 'MK-Speed',
1163
                          '-arrow' => 'last',
1164
                          '-arrowshape' => [10, 10, 3 ],
1165
                          '-fill' => $Cfg->{'mkcockpit'}->{'ColorSpeedVector'},
1166
                          '-width' => 4,
1167
                         );
1168
 
1169
# MK als Pfeilspitze einer Linie darstellen
1170
$MapMkLen = 25;
1171
my $x0 = $MapSizeX/2;
1172
my $y0 = $MapSizeY/2 + $MapMkLen/2;
1173
my $x1 = $MapSizeX/2;
1174
my $y1 = $MapSizeY/2 - $MapMkLen/2;
1175
$map_canvas->createLine ( $x0, $y0, $x1, $y1,
1176
                          '-tags' => 'MK-Arrow',
1177
                          '-arrow' => 'last',
1178
                          '-arrowshape' => [25, 30, 10 ],
1179
                          '-fill' => $Cfg->{'mkcockpit'}->{'ColorMkSatNo'},
1180
                          '-width' => 1
1181
                         );
1182
 
1183
# OSD Texte auf Karte anzeigen
1184
my @Texts = (
1185
            # Tag                 Text         Pos_x           Pos_y  Font
1186
            'MK-OSD-Tim-Label',   "TIM",       $MapSizeX/2 + 30,  20, '-*-Arial-Bold-R-Normal--*-150-*',
1187
            'MK-OSD-Tim-Value',   "00:00",     $MapSizeX/2 + 80,  20, '-*-Arial-Bold-R-Normal--*-270-*',
1188
            'MK-OSD-Bat-Label',   "BAT",       $MapSizeX/2 + 30,  50, '-*-Arial-Bold-R-Normal--*-150-*',
1189
            'MK-OSD-Bat-Value',   "0.0 V",     $MapSizeX/2 + 80,  50, '-*-Arial-Bold-R-Normal--*-270-*',
1190
            'MK-OSD-Cap-Label',   "CAP",       $MapSizeX/2 - 150, 20, '-*-Arial-Bold-R-Normal--*-150-*',
1191
            'MK-OSD-Cap-Value',   "0.00 Ah",   $MapSizeX/2 - 100, 20, '-*-Arial-Bold-R-Normal--*-270-*',
1192
            'MK-OSD-Cur-Label',   "CUR",       $MapSizeX/2 - 150, 50, '-*-Arial-Bold-R-Normal--*-150-*',
1193
            'MK-OSD-Cur-Value',   "0.0 A",     $MapSizeX/2 - 100, 50, '-*-Arial-Bold-R-Normal--*-270-*',
1194
            'MK-OSD-Pow-Label',   "POW",       $MapSizeX/2 - 150, 80, '-*-Arial-Bold-R-Normal--*-150-*',
1195
            'MK-OSD-Pow-Value',   "0.0 W",     $MapSizeX/2 - 100, 80, '-*-Arial-Bold-R-Normal--*-270-*',
1196
            'MK-OSD-Spd-Label',   "SPD",       10,                20, '-*-Arial-Bold-R-Normal--*-150-*',
1197
            'MK-OSD-Spd-Value',   "0.0 km/h",  60,                20, '-*-Arial-Bold-R-Normal--*-270-*',
1198
            'MK-OSD-Alt-Label',   "ALT",       10,                50, '-*-Arial-Bold-R-Normal--*-150-*',
1199
            'MK-OSD-Alt-Value',   "0 m",       60,                50, '-*-Arial-Bold-R-Normal--*-270-*',
1200
            'MK-OSD-Odo-Label',   "ODO",       10,                80, '-*-Arial-Bold-R-Normal--*-150-*',
1201
            'MK-OSD-Odo-Value',   "0.000 km",  60,                80, '-*-Arial-Bold-R-Normal--*-270-*',
1202
            'MK-OSD-Sat-Label',   "SAT",       $MapSizeX - 230,   20, '-*-Arial-Bold-R-Normal--*-150-*',
1203
            'MK-OSD-Sat-Value',   "0",         $MapSizeX - 180,   20, '-*-Arial-Bold-R-Normal--*-270-*',
1204
            'MK-OSD-Wp-Label',    "WPT",       $MapSizeX - 230,   50, '-*-Arial-Bold-R-Normal--*-150-*',
1205
            'MK-OSD-Wp-Value',    "0 / 0",     $MapSizeX - 180,   50, '-*-Arial-Bold-R-Normal--*-270-*',
1206
            'MK-OSD-Mode-Label',  "MOD",       $MapSizeX - 230,   80, '-*-Arial-Bold-R-Normal--*-150-*',
1207
            'MK-OSD-Mode-Value',  "",          $MapSizeX - 180,   80, '-*-Arial-Bold-R-Normal--*-270-*',
1208
            'MK-OSD-Rec-Value',   "",          $MapSizeX - 180,  110, '-*-Arial-Bold-R-Normal--*-200-*',
1209
            );
1210
my $i = 0;
1211
for $Text (0 .. $#Texts/5)
1212
    {
1213
    my $Tag =   $Texts[$i++];
1214
    my $Text =  $Texts[$i++];
1215
    my $Pos_x = $Texts[$i++];
1216
    my $Pos_y = $Texts[$i++];
1217
    my $Font =  $Texts[$i++];
1218
 
1219
    $map_canvas->createText ( $Pos_x, $Pos_y,
1220
                              '-tags' => $Tag,
1221
                              '-text' => $Text,
1222
                              '-font' => $Font,
1223
                              '-fill' => $Cfg->{'mkcockpit'}->{'ColorOsd'},
1224
                              '-anchor' => 'w',
1225
                             );
1226
 
1227
    }
1228
 
1229
 
1230
# Variometer on canvas
1231
my @Polygon;
1232
for ( $y = -100; $y <= 100; $y += 10)
1233
    {
1234
    my $Len = 5;
1235
    if ( ($y % 50) == 0 )
1236
        {
1237
        $Len = 10;
1238
        $map_canvas->createText ( $Len+5, $MapSizeY/2 + $y,
1239
                                  '-tags' => 'Map-Variometer-Skala',
1240
                                  '-text' => sprintf ("%3d", -$y / 10),
1241
                                  '-anchor' => 'w',
1242
                                  '-font' => '-*-Arial-Normal-R-Normal--*-150-*',
1243
                          '-fill' => $Cfg->{'mkcockpit'}->{'ColorVariometer'},
1244
                          );
1245
        }
1246
    push @Polygon, (   0, $MapSizeY/2 + $y);
1247
    push @Polygon, ($Len, $MapSizeY/2 + $y);
1248
    push @Polygon, (   0, $MapSizeY/2 + $y);
1249
    }
1250
 
1251
$map_canvas->createLine(@Polygon,
1252
                        '-tags' => 'Map-Variometer',
1253
                        '-fill' => $Cfg->{'mkcockpit'}->{'ColorVariometer'},
1254
                        '-width' => 2,
1255
                        '-arrow' => 'none',
1256
                       );
1257
# Vario Pointer
1258
$map_canvas->createPolygon( 5, $MapSizeY/2, 20, $MapSizeY/2+10, 20, $MapSizeY/2-10,
1259
                           '-tags' => 'Map-Variometer-Pointer',
1260
                           '-fill' => $Cfg->{'mkcockpit'}->{'ColorVariometerPointer'},
1261
                           '-outline' => 'black', '-width' => 1,
1262
                          );
1263
 
1264
# Crosshair
1265
$map_canvas->createLine ( 0, $MapSizeY/2, $MapSizeX, $MapSizeY/2,
1266
                          '-tags' => ['Map-Crosshair', 'Map-Crosshair-X'],
1267
                          '-arrow' => 'none',
1268
                          '-fill' => $Cfg->{'map'}->{'CrosshairColor'},
1269
                          '-width' => 1,
1270
                        );
1271
$map_canvas->createLine ( $MapSizeX/2, 0, $MapSizeX/2, $MapSizeY,
1272
                          '-tags' => ['Map-Crosshair', 'Map-Crosshair-Y'],
1273
                          '-arrow' => 'none',
1274
                          '-fill' => $Cfg->{'map'}->{'CrosshairColor'},
1275
                          '-width' => 1,
1276
                        );
1277
$map_canvas->lower('Map-Crosshair', 'Map');   # hide below map
1278
 
1279
 
1280
# Tracking Canvas
1281
 
1282
if ( $Cfg->{'track'}->{'Active'} =~ /y/i )
1283
    {
1284
    # Canvas size
1285
    $TrackSizeX  = 125;
1286
    $TrackSizeY  = 100;
1287
    $TrackOffY   = $TrackSizeY - $MapSizeY + $TrackSizeY/2;
1288
    $TrackPtrLen = 50;    # Länge Zeiger
1289
 
1290
    # draw in map-canvas
1291
    $track_canvas = $map_canvas;
1292
 
1293
    # Ziffernblatt
1294
    my $x0 = $TrackSizeX/2 - $TrackPtrLen;
1295
    my $y0 = $TrackSizeY   + $TrackPtrLen - $TrackOffY;
1296
    my $x1 = $TrackSizeX/2 + $TrackPtrLen;
1297
    my $y1 = $TrackSizeY   - $TrackPtrLen - $TrackOffY;
1298
    $track_canvas->createArc ( $x0, $y0, $x1, $y1,
1299
                               '-extent' => '359',
1300
                               '-start' => '0',
1301
                               '-style' => 'chord',
1302
                               '-outline' => 'gray', '-width' => '1',
1303
                             );
1304
 
1305
    # Skala Ziffernblatt
1306
    for ($i=0; $i<360; $i+=15)
1307
        {
1308
        my $x0 = $TrackSizeX/2 - ($TrackPtrLen - 20) * cos( deg2rad $i );
1309
        my $y0 = $TrackSizeY   - ($TrackPtrLen - 20) * sin( deg2rad $i ) - $TrackOffY;
1310
        my $x1 = $TrackSizeX/2 - ($TrackPtrLen - 28) * cos( deg2rad $i );
1311
        my $y1 = $TrackSizeY   - ($TrackPtrLen - 28) * sin( deg2rad $i ) - $TrackOffY;
1312
        $track_canvas->createLine ( $x0, $y0, $x1, $y1,
1313
                                   '-fill' => 'white',
1314
                                   '-width' => 1,
1315
                                  );
1316
        }
1317
 
1318
    # Skala Beschriftung Ziffernblatt
1319
    for ($i=-180; $i<180; $i+=45)
1320
        {
1321
        my $x0 = $TrackSizeX/2 - ($TrackPtrLen - 12) * cos( deg2rad $i+90 );
1322
        my $y0 = $TrackSizeY   - ($TrackPtrLen - 12) * sin( deg2rad $i+90 ) - $TrackOffY;
1323
        $track_canvas->createText ( $x0, $y0,
1324
                                   '-text' => $i,
1325
                                   '-fill' => 'white',
1326
                                  );
1327
        }
1328
 
1329
    # Zeiger Pan
1330
    my $x0 = $TrackSizeX/2;
1331
    my $y0 = $TrackSizeY - 0 - $TrackOffY;
1332
    my $x1 = $TrackSizeX/2;
1333
    my $y1 = $TrackSizeY - ($TrackPtrLen - 22) - $TrackOffY;
1334
    $track_canvas->createLine ( $x0, $y0, $x1, $y1,
1335
                                '-tags' => 'Track-Ptr-Pan',
1336
                                '-arrow' => 'last',
1337
                                '-arrowshape' => [20, 30, 5 ],
1338
                                '-fill' => 'red',
1339
                                '-width' => 8,
1340
                                );
1341
    # Zeiger Tilt
1342
    my $x0 = $TrackSizeX/2;
1343
    my $y0 = $TrackSizeY - 0 - $TrackOffY;
1344
    my $x1 = $TrackSizeX/2;
1345
    my $y1 = $TrackSizeY - ($TrackPtrLen - 22) - $TrackOffY;
1346
    $track_canvas->createLine ( $x0, $y0, $x1, $y1,
1347
                                '-tags' => 'Track-Ptr-Tilt',
1348
                                '-fill' => 'white',
1349
                                '-width' => 1,
1350
                              );
1351
 
1352
    # Zeiger Center
1353
    my $Dia = 7;
1354
    my $x0 = $TrackSizeX/2 - $Dia;
1355
    my $y0 = $TrackSizeY + $Dia - $TrackOffY;
1356
    my $x1 = $TrackSizeX/2 + $Dia;
1357
    my $y1 = $TrackSizeY   - $Dia - $TrackOffY;
1358
    $track_canvas->createArc ( $x0, $y0, $x1, $y1,
1359
                               '-extent' => '359',
1360
                               '-outline' => 'gray', '-width' => 1,
1361
                               '-fill' => 'gray',
1362
                             );
1363
    }
1364
 
1365
#
1366
# Load Start Scenario
1367
#
1368
 
1369
# Waypoint file
1370
my $CfgVal = $Cfg->{'StartScenario'}->{'WpFile'};
1371
if ( ! -f $CfgVal )
1372
    {
1373
    $CfgVal = $Cfg->{'waypoint'}->{'WpDir'} . "/" . $Cfg->{'StartScenario'}->{'WpFile'};
1374
    }
1375
if ( -f $CfgVal )
1376
    {
1377
    &WpLoadFile($CfgVal);
1378
 
1379
    # send all Wp to MK
1380
    &WpSendAll();
1381
    }
1382
 
1383
# KML file
1384
my $CfgVal = $Cfg->{'StartScenario'}->{'KmlFile'};
1385
if ( ! -f $CfgVal )
1386
    {
1387
    $CfgVal = $Cfg->{'waypoint'}->{'KmlDir'} . "/" . $Cfg->{'StartScenario'}->{'KmlFile'};
1388
    }
1389
if ( -f $CfgVal )
1390
    {
1391
    &KmlLoadFile($CfgVal);
1392
    }
1393
 
1394
# PLayer Mode
1395
my $CfgVal  = $Cfg->{'StartScenario'}->{'PlayerMode'};
1396
if ( $CfgVal =~ /Play/i )  { &PlayerPlay(); }
1397
if ( $CfgVal =~ /Pause/i ) { &PlayerPause(); }
1398
if ( $CfgVal =~ /Home/i )  { &PlayerHome(); }
1399
if ( $CfgVal =~ /Stop/i )  { &PlayerStop(); }
1400
 
1401
# Player Random Mode
1402
my $CfgVal  = $Cfg->{'StartScenario'}->{'PlayerRandomMode'};
1403
if ( $CfgVal eq "STD" ) { &PlayerRandomStd(); }
1404
if ( $CfgVal eq "RND" ) { &PlayerRandomRnd(); }
1405
if ( $CfgVal eq "MAP" ) { &PlayerRandomMap(); }
1406
 
1407
# PLayer Wpt/Kml Mode
1408
my $CfgVal  = $Cfg->{'StartScenario'}->{'PlayerWptKmlMode'};
1409
if ( $CfgVal eq "WPT" )  { &PlayerWpt(); }
1410
if ( $CfgVal eq "KML" )  { &PlayerKml(); }
1411
 
1412
# PLayer Pause Mode
1413
my $CfgVal  = $Cfg->{'StartScenario'}->{'PlayerPauseMode'};
1414
if ( $CfgVal eq "MAP" )  { &PlayerPauseMode("MAP"); }
1415
if ( $CfgVal eq "MK" )   { &PlayerPauseMode("MK"); }
1416
 
1417
# Audio TTS Mute
1418
my $CfgVal  = $Cfg->{'StartScenario'}->{'AudioMute'};
1419
if ( $CfgVal =~ /y/i )
1420
    {
1421
    $TtsMute = 1;    
1422
    }
1423
 
1424
# External-Contorl/Serial Channel Tx On/Off
1425
my $CfgVal  = $Cfg->{'StartScenario'}->{'TxExtOn'};
1426
if ( $CfgVal =~ /y/i )
1427
    {
1428
    $TxExtOn = 1;    
1429
    }
1430
 
1431
#
1432
# Timer
1433
#
1434
require "libmktimer.pl";
1435
 
1436
MainLoop();   # should never end
1437
 
1438
 
1439
#
1440
# GUI Call Back
1441
# 
1442
 
1443
# Player CallBack: Play/Pause button
1444
sub CbPlayerPlayPause()
1445
    {
1446
    if ( ($PlayerMode eq "Pause") or  ($PlayerMode eq "Stop") or  ($PlayerMode eq "Home") )
1447
        {
1448
        &PlayerPlay();
1449
        }
1450
    else
1451
        {
1452
        &PlayerPause();
1453
        }
1454
    }
1455
 
1456
 
1457
# Player CallBack: Next
1458
sub CbPlayerNext()
1459
    {
1460
    if ( $PlayerMode ne 'Stop' )
1461
        {
1462
        if ( $PlayerWptKmlMode eq 'WPT' )
1463
           {
1464
           &WpTargetNext();
1465
           }
1466
        if ( $PlayerWptKmlMode eq 'KML' )
1467
           {
1468
           &KmlTargetNext();
1469
           }
1470
        }
1471
    }
1472
 
1473
 
1474
# Player CallBack: Prev
1475
sub CbPlayerPrev()
1476
    {
1477
    if ( $PlayerMode ne 'Stop' )
1478
        {
1479
        if ( $PlayerWptKmlMode eq 'WPT' )
1480
           {
1481
           &WpTargetPrev();
1482
           }
1483
        if ( $PlayerWptKmlMode eq 'KML' )
1484
           {
1485
           &KmlTargetPrev();
1486
           }
1487
        }
1488
    }
1489
 
1490
 
1491
# Player CallBack: First
1492
sub CbPlayerFirst()
1493
    {
1494
    if ( $PlayerMode ne 'Stop' )
1495
        {
1496
        if ( $PlayerWptKmlMode eq 'WPT' )
1497
           {
1498
           &WpTargetFirst();
1499
           }
1500
        if ( $PlayerWptKmlMode eq 'KML' )
1501
           {
1502
           &KmlTargetFirst();
1503
           }
1504
        }
1505
    }
1506
 
1507
# Player CallBack: Last
1508
sub CbPlayerLast()
1509
    {
1510
    if ( $PlayerMode ne 'Stop' )
1511
        {
1512
        if ( $PlayerWptKmlMode eq 'WPT' )
1513
           {
1514
           &WpTargetLast();
1515
           }
1516
        if ( $PlayerWptKmlMode eq 'KML' )
1517
           {
1518
           &KmlTargetLast();
1519
           }
1520
        }
1521
    }
1522
 
1523
 
1524
# Player CallBack: Home
1525
sub CbPlayerHome()
1526
    {
1527
    if ( $PlayerMode ne 'Stop' )
1528
        {
1529
        &PlayerHome();
1530
        }
1531
    }
1532
 
1533
 
1534
# Player CallBack: Stop
1535
sub CbPlayerStop()
1536
    {
1537
    if ( $PlayerMode ne 'Stop' )
1538
        {
1539
        &PlayerStop();
1540
        }
1541
    }
1542
 
1543
 
1544
# Player CallBack: Move MK in Pause-Mode
1545
sub CbPlayerMove()
1546
    {
1547
    my ($Id, $DirX, $DirY) = @_;
1548
 
1549
    if ( $PlayerMode eq 'Pause'  and
1550
         $PlayerPause_Lat ne ""  and  $PlayerPause_Lon ne "" )
1551
        {
1552
        my $Dist = $Cfg->{'map'}->{'PauseMoveDist'} || 1;  # 1m default
1553
 
1554
        my $BearingTop = &MapAngel() - 90.0;
1555
        my $BearingKey = rad2deg atan2($DirX, $DirY);
1556
        my $Bearing = $BearingTop + $BearingKey;
1557
        if ( $PlayerPauseMode eq "MK" )
1558
            {
1559
            # MK Reference
1560
            $Bearing = $MkOsd{'CompassHeading'} + $BearingKey;
1561
            }
1562
 
1563
        ($PlayerPause_Lat, $PlayerPause_Lon) = &MapGpsAt($PlayerPause_Lat, $PlayerPause_Lon, $Dist, $Bearing);
1564
 
1565
        # restart crosshair display timer
1566
        $CrosshairTimerCnt = 0;
1567
        }
1568
    }
1569
 
1570
 
1571
# Player CallBack: Toggle WPT/KML button
1572
sub CbPlayerWptKml()
1573
    {
1574
 
1575
    if ( $PlayerWptKmlMode =~ /WPT/i )
1576
        {
1577
        &PlayerKml();
1578
        }
1579
    elsif ( $PlayerWptKmlMode =~ /KML/i )
1580
        {
1581
        &PlayerWpt();
1582
        }
1583
    }
1584
 
1585
 
1586
# Player CallBack: Toggle Random modes. STD -> RND -> MAP
1587
sub CbPlayerWptRandom()
1588
    {
1589
    if ( $PlayerRandomMode eq "STD" )
1590
        {
1591
        &PlayerRandomRnd();
1592
        }
1593
    elsif ( $PlayerRandomMode eq "RND" )
1594
        {
1595
        &PlayerRandomMap();
1596
        }
1597
    else
1598
        {
1599
        &PlayerRandomStd();
1600
        }
1601
    }
1602
 
1603
 
1604
# Player CallBack: Togglle Record KML
1605
sub CbPlayerRecord()
1606
    {
1607
    if ( $PlayerRecordMode =~ /REC/i )
1608
        {
1609
        &PlayerRecordOff();
1610
        }
1611
    elsif ( $PlayerRecordMode eq "" )
1612
        {
1613
        &PlayerRecordOn();
1614
        }
1615
    }
1616
 
1617
 
1618
# Player CallBack: Number Keys
1619
sub CbPlayerNum()
1620
    {
1621
    my ($Id, $Num) = @_;
1622
 
1623
    $CbPlayerKey = "$CbPlayerKey" . "$Num";
1624
    }
1625
 
1626
 
1627
# Player CallBack: mute TTS audio
1628
sub CbPlayerMute()
1629
    {
1630
    if ( $TtsMute )
1631
        {
1632
        &TtsMute(0);
1633
        }
1634
    else
1635
        {
1636
        &TtsMute(1);
1637
        }
1638
    }
1639
 
1640
# Switch POI Mode
1641
sub CbPoi()
1642
    {
1643
    if ( $PoiMode )
1644
        {
1645
        $PoiMode = 0;
1646
        &PoiHide();
1647
        }
1648
    else
1649
        {
1650
        $PoiMode = 1;
1651
        &PoiShow();
1652
        }
1653
    }
1654
 
1655
# Grid on canvas
1656
$GridIsOn = 0;
1657
sub CbGrid()
1658
    {
1659
    if ( $GridIsOn )
1660
        {
1661
        $GridIsOn = 0;
1662
        &GridHide();
1663
        }
1664
    else
1665
        {
1666
        $GridIsOn = 1;
1667
        &GridShow();
1668
        }
1669
    }
1670
 
1671
# Player Pause Mode
1672
sub CbPlayerPauseMode()
1673
    {
1674
    if ( $PlayerPauseMode eq "MAP" )
1675
        {
1676
        &PlayerPauseMode("MK");
1677
        }
1678
    else
1679
        {
1680
        &PlayerPauseMode("MAP");
1681
        }
1682
    }
1683
 
1684
# External-Control, SerialChannel On/Off
1685
sub CbTxOnOff()
1686
    {
1687
    if ( $TxExtOn == 1 )
1688
        {
1689
        $TxExtOn = 0;
1690
        }
1691
    else
1692
        {
1693
        $TxExtOn = 1;
1694
        }
1695
    }
1696
 
1697
 
1698
# Function Key Press
1699
sub CbFctKeyPress()
1700
    {
1701
    my ($Id, $Num) = @_;
1702
 
1703
    $Num --;
1704
    $Stick{'FctKey'} |= (1 << $Num);
1705
    }
1706
 
1707
 
1708
# Function Key Release
1709
sub CbFctKeyRelease()
1710
    {
1711
    my ($Id, $Num) = @_;
1712
 
1713
    $Num --;
1714
    $Stick{'FctKey'} ^= (1 << $Num);
1715
    }
1716
 
1717
 
1718
# CallBack: Exit Mission Cockpit
1719
sub CbExit()
1720
    {
1721
 
1722
    # stop 3D Mouse
1723
    &Mouse3DStop();
1724
 
1725
    # stop Joystick
1726
    &JoystickStop();
1727
 
1728
    # stop antenna tracking
1729
    $TrackQueue->enqueue( "IDLE" );
1730
 
1731
    # wait for tracker shutdown, with timeout
1732
    if ( $Cfg->{'track'}->{'Active'} =~ /y/i )
1733
        {
1734
        for ($i=0; $i < 5; $i++)
1735
            {
1736
            if ( $MkTrack{'State'} ne "Idle" )
1737
                {
1738
                sleep 1;
1739
                }
1740
            }
1741
        }
1742
 
1743
    exit;
1744
    }
1745
 
1746
 
1747
__END__