Subversion Repositories Projects

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
550 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
#
64
###############################################################################
65
 
66
$Version = "0.2.5 - 2009-08-08";
67
 
68
use threads;            # http://search.cpan.org/~jdhedden/threads-1.72/threads.pm
69
                        # http://perldoc.perl.org/threads.html
70
use threads::shared;    # http://search.cpan.org/~jdhedden/threads-shared-1.28/shared.pm
71
use Thread::Queue;      # http://search.cpan.org/dist/Thread-Queue-2.11/lib/Thread/Queue.pm
72
use Tk;
73
use Tk::Balloon;
74
use Tk::Dialog;
75
use Tk::Notebook;
76
use Tk::JPEG;           # http://search.cpan.org/~srezic/Tk-804.028/JPEG/JPEG.pm
77
use Tk::PNG;            # http://search.cpan.org/~srezic/Tk-804.028/PNG/PNG.pm
78
use Math::Trig;
79
use Time::HiRes qw(usleep);  # http://search.cpan.org/~jhi/Time-HiRes-1.9719/HiRes.pm
80
use XML::Simple;             # http://search.cpan.org/dist/XML-Simple-2.18/lib/XML/Simple.pm
81
 
82
# change working directory to program path
83
my $Cwd = substr ($0, 0, rindex ($0, "mkcockpit.pl"));
84
chdir $Cwd;
85
 
86
# set path for local Perl libs
87
push @INC, $Cwd . "perl/lib", $Cwd . "perl/site/lib";
88
 
89
# Version setting
90
share (%Version);
91
$Version{'mkcockpit.pl'}  = $Version;
92
 
93
# Read configuration
94
 
95
$XmlConfigFile = "mkcockpit.xml";
96
$Cfg = XMLin($XmlConfigFile);
97
 
98
require "track.pl";        # Tracking antenna
99
require "mkcomm.pl";       # MK communication
100
require "logging.pl";      # CSV and GPX Logging
101
require "geserver.pl";     # Google Earth Server
102
require "$Cfg->{'map'}->{'MapDir'}/map.pl";   # Landkarte
103
require "libmap.pl";       # map subs
104
require "translate.pl";    # Übersetzungstable
105
require "tts.pl";          # Text to Speech
106
require "libmkcockpit.pl"; # Subroutines
107
 
108
 
109
# Commandline parameter
110
my %CmdLine = @ARGV;
111
 
112
# Thread fuer Kommunikation mit MK starten
113
# Output: %MkOsd, %MkTarget, %MkNcDebug, %Mk
114
# Input:  Thread-Queue: $MkSendQueue
115
$mk_thr = threads->create (\&MkCommLoop) -> detach();
116
 
117
# Start Logging Thread
118
$log_thr = threads->create (\&MkLogLoop) -> detach();
119
 
120
# Start GoogleEarth Thread
121
$ge_thr = threads->create (\&GeServer) -> detach();
122
 
123
# Start TTS Thread
124
$tts_thr = threads->create (\&TtsLoop) -> detach();
125
 
126
#
127
# Player:
128
#    Waypoint-List:   @Waypoints
129
#    KML-Target-List: @KmlTargets
130
#
131
 
132
# Player state machine
133
$PlayerMode = 'Stop';       # Play, Stop, Pause, Home ...
134
$PlayerWptKmlMode = 'WPT';  # WPT, KML
135
$PlayerRandomMode = 'STD';  # STD, RND, MAP
136
$PlayerRecordMode = "";     # "", REC
137
$WpPlayerIndex = 0;
138
$WpPlayerHoldtime = -1;
139
$KmlPlayerIndex = 0;
140
$PlayerPause_Lat = "";
141
$PlayerPause_Lon = "";
142
 
143
# Aktuell gültige Karte
144
my %Map = %{$Maps{'Current'}};
145
 
146
 
147
# Hauptfenster
148
$main = new MainWindow;
149
$main->title ("MK Mission Cockpit - Version $Version");
150
 
151
if ( $CmdLine{'-geometry'} ne "" )
152
    {
153
    $main->geometry( "$CmdLine{'-geometry'}" );
154
    }
155
 
156
 
157
#-----------------------------------------------------------------
158
# Menu
159
#-----------------------------------------------------------------
160
 
161
# Menu bar
162
my $menu_bar = $main->Menu;
163
$main->optionAdd("*tearOff", "false");
164
$main->configure ('-menu' => $menu_bar);
165
 
166
my $menu_file = $menu_bar->cascade('-label' => $Translate{'File'});
167
    $menu_file->command('-label' => $Translate{'Preferences'},
168
                        '-command' => [\&Configure],
169
                       );
170
    $menu_file->separator;                                     
171
    $menu_file->command('-label' => $Translate{'Exit'},
172
                        '-command' => [\&CbExit ],
173
                        );
174
 
175
my $menu_debug = $menu_bar->cascade(-label => $Translate{'Debug'});
176
    $menu_debug->command('-label' => $Translate{'NcOsdDataset'},
177
                         '-command' => [\&DisplayHash, \%MkOsd, $Translate{'NcOsdDataset'}, "Display Refresh Heartbeat"],
178
                        );
179
    $menu_debug->command('-label' => $Translate{'NcTargetDataset'},
180
                         '-command' => [\&DisplayHash, \%MkTarget, $Translate{'NcTargetDataset'}, "Display Refresh Heartbeat"],
181
                        );
182
    $menu_debug->command('-label' => $Translate{'NcDebugDataset'},
183
                         '-command' => [\&DisplayHash, \%MkNcDebug, $Translate{'NcDebugDataset'}, "Display Refresh Heartbeat"],
184
                                        );             
185
    $menu_debug->command('-label' => $Translate{'NcOther'},
186
                         '-command' => [\&DisplayHash, \%Mk, $Translate{'NcOther'}, "Display Refresh Heartbeat"],
187
                                        );
188
    $menu_debug->separator;                                    
189
    $menu_debug->command('-label' => $Translate{'TrackingDebugDataset'},
190
                         '-command' => [\&DisplayHash, \%MkTrack, $Translate{'TrackingDebugDataset'}, "Display Refresh Heartbeat"],
191
                        );
192
    #$menu_debug->command('-label' => $Translate{'MapDebugDataset'}, 
193
    #                     '-command' => [\&DisplayHash, \%Map, $Translate{'MapDebugDataset'}, "Display"],
194
    #                    );
195
 
196
my $menu_help = $menu_bar->cascade(-label => $Translate{'Help'});
197
    $menu_help->command('-label' => 'Version',
198
                        '-command' => [\&DisplayHash, \%Version, $Translate{'Version'}, "Display"],
199
                       );
200
    $menu_help->separator;
201
    $menu_help->command('-label' => $Translate{'About'},
202
                        '-command' => sub
203
        {
204
        my $License = <<EOF;
205
Copyright (C) 2009  Rainer Walther (rainerwalther-mail\@web.de)
206
 
207
Creative Commons Lizenz mit den Zusaetzen (by, nc, sa)
208
 
209
See LICENSE.TXT
210
EOF
211
 
212
        my $DlgAbout = $frame_map->Dialog('-title' => $Translate{'AboutMissionCockpit'},
213
                                          '-text' => "$License",
214
                                          '-buttons' => ['OK'],
215
                                          '-bitmap' => 'info',
216
                                         );
217
        $DlgAbout->Show;
218
        });  
219
 
220
 
221
# Hauptfenster Statuszeile
222
$frame_status = $main->Frame( '-background' => 'lightgray',
223
                         ) -> pack('-side' => 'bottom',
224
                                   '-anchor' => 'w',
225
                                   '-fill' => 'none',
226
                                   '-expand' => 'y',
227
                                    );
228
$status_line = $frame_status->Label ('-text' => $Translate{'StatusLine'},
229
                                    ) -> pack ('-side' => 'bottom',
230
                                               );
231
 
232
 
233
#-----------------------------------------------------------------
234
# Frames
235
#-----------------------------------------------------------------                        
236
 
237
#
238
# Frame: Map
239
#
240
 
241
$frame_map = $main->Frame( '-background' => 'lightgray',
242
                           '-relief' => 'sunken',
243
                           '-borderwidth' => 5,
244
                          ) -> pack('-side' => 'top',
245
                                    '-fill' => 'x',
246
                                    );
247
 
248
# Map Überschrift
249
$frame_map_top = $frame_map->Frame() -> pack( '-side' => 'top',
250
                                              '-expand' => 'x',
251
                                              '-anchor' => 'w',
252
                                            );
253
 
254
$frame_map_top->Label ('-text' => "$Translate{'Map'}: $Map{'Name'} ($Map{'File'})",
255
                       '-background' => 'lightgray',
256
                       '-relief' => 'flat',
257
                       ) -> pack( '-side' => 'left' );
258
 
259
# Map Statuszeile
260
$map_status = $frame_map->Frame( '-background' => 'lightgray',
261
                               ) -> pack('-side' => 'bottom',
262
                                         '-anchor' => 'w',
263
                                         '-fill' => 'none',
264
                                         '-expand' => 'y',
265
                                        );
266
$map_status_line = $map_status->Label ( '-text' => $Translate{'StatusLine'},
267
                                        '-background' => 'lightgray',
268
                                       ) -> pack ('-side' => 'bottom',);
269
 
270
#
271
# Map Canvas
272
#
273
 
274
# Canvas size
275
$MapSizeX  = $Map{'Size_X'};
276
$MapSizeY  = $Map{'Size_Y'};
277
 
278
$map_canvas = $frame_map->Canvas( '-width'  => $MapSizeX,
279
                                  '-height' => $MapSizeY,
280
                                  '-cursor' => 'cross',
281
                                ) -> pack();
282
 
283
# Images and Icons on canvas
284
my @Icons = (
285
            # Image             Tag             File                                       Pos_x            Pos_y
286
            'Map',              'Map',          "$Cfg->{'map'}->{'MapDir'}/$Map{'File'}",  0,               0,
287
            'HeartbeatSmall',   'Heartbeat',    "$Cfg->{'mkcockpit'}->{'IconHeartSmall'}", $MapSizeX/4,     10,
288
            'HeartbeatLarge',   'Heartbeat',    "$Cfg->{'mkcockpit'}->{'IconHeartLarge'}", $MapSizeX/4,     -100,
289
            'Satellite-Photo',  'Satellite',    "$Cfg->{'mkcockpit'}->{'IconSatellite'}",  $MapSizeX-300,   -100,
290
            'Waypoint-Photo',   'Waypoint',     "$Cfg->{'mkcockpit'}->{'IconWaypoint'}",   0,               -150,
291
            'Target-Photo',     'Target',       "$Cfg->{'mkcockpit'}->{'IconTarget'}",     0,               -100,
292
            'Fox-Photo',        'Fox',          "$Cfg->{'mkcockpit'}->{'IconFox'}",        $MapSizeX/2-100, $MapSizeY/2,
293
            'WpPlay-Foto',      'Wp-PlayPause', "$Cfg->{'waypoint'}->{'IconPlay'}",        $MapSizeX/2+150, $MapSizeY-48,
294
            'WpPause-Foto',     'Wp-PlayPause', "$Cfg->{'waypoint'}->{'IconPause'}",       $MapSizeX/2+150, -100,
295
            'WpStop-Foto',      'Wp-Stop',      "$Cfg->{'waypoint'}->{'IconStop'}",        $MapSizeX/2+200, $MapSizeY-48,
296
            'WpNext-Foto',      'Wp-Next',      "$Cfg->{'waypoint'}->{'IconNext'}",        $MapSizeX/2+50,  $MapSizeY-48,
297
            'WpPrev-Foto',      'Wp-Prev',      "$Cfg->{'waypoint'}->{'IconPrev'}",        $MapSizeX/2,     $MapSizeY-48,
298
            'WpFirst-Foto',     'Wp-First',     "$Cfg->{'waypoint'}->{'IconFirst'}",       $MapSizeX/2-50,  $MapSizeY-48,
299
            'WpLast-Foto',      'Wp-Last',      "$Cfg->{'waypoint'}->{'IconLast'}",        $MapSizeX/2+100, $MapSizeY-48,
300
            'WpHome-Foto',      'Wp-Home',      "$Cfg->{'waypoint'}->{'IconHome'}",        $MapSizeX/2-100, $MapSizeY-48,
301
            'WpRecord-Foto',    'Wp-Record',    "$Cfg->{'waypoint'}->{'IconRecord'}",      $MapSizeX/2-150, $MapSizeY-48,
302
            'WpRandomOff-Foto', 'Wp-WptRandom', "$Cfg->{'waypoint'}->{'IconRandomOff'}",   $MapSizeX/2-200, -100,
303
            'WpRandomOn-Foto',  'Wp-WptRandom', "$Cfg->{'waypoint'}->{'IconRandomOn'}",    $MapSizeX/2-200, $MapSizeY-48,
304
            'WpRandomMap-Foto', 'Wp-WptRandom', "$Cfg->{'waypoint'}->{'IconRandomMap'}",   $MapSizeX/2-200, -100,
305
            'WpWpt-Foto',       'Wp-WptKml',    "$Cfg->{'waypoint'}->{'IconWpt'}",         $MapSizeX/2-250, $MapSizeY-48,
306
            'WpKml-Foto',       'Wp-WptKml',    "$Cfg->{'waypoint'}->{'IconKml'}",         $MapSizeX/2-250, -100 ,
307
            );
308
my $i = 0;
309
for $Icon (0 .. $#Icons/5)
310
    {
311
    my $Image =  $Icons[$i++];
312
    my $Tag =    $Icons[$i++];
313
    my $File =   $Icons[$i++];
314
    my $Pos_x =  $Icons[$i++];
315
    my $Pos_y =  $Icons[$i++];
316
 
317
    $map_canvas->Photo( $Image,
318
                        '-file' => $File,
319
                      );
320
    $map_canvas->createImage( $Pos_x, $Pos_y,
321
                              '-tags'   => $Tag,
322
                              '-anchor' => 'nw',
323
                              '-image'  => $Image,
324
                            );
325
    }
326
 
327
# Calibration Points
328
$map_canvas->createLine ( $Map{'P1_x'}-8, $Map{'P1_y'},
329
                          $Map{'P1_x'}+8, $Map{'P1_y'},
330
                          $Map{'P1_x'},   $Map{'P1_y'},
331
                          $Map{'P1_x'},   $Map{'P1_y'}-8,
332
                          $Map{'P1_x'},   $Map{'P1_y'}+8,
333
                          '-tags'  => 'Calibration',
334
                          '-arrow' => 'none',
335
                          '-fill'  => 'red',
336
                          '-width' => 1,
337
                         );
338
$map_canvas->createLine ( $Map{'P2_x'}-8, $Map{'P2_y'},
339
                          $Map{'P2_x'}+8, $Map{'P2_y'},
340
                          $Map{'P2_x'},   $Map{'P2_y'},
341
                          $Map{'P2_x'},   $Map{'P2_y'}-8,
342
                          $Map{'P2_x'},   $Map{'P2_y'}+8,
343
                          '-tags'  => 'Calibration',
344
                          '-arrow' => 'none',
345
                          '-fill'  => 'red',
346
                          '-width' => 1,
347
                         );
348
 
349
# border polygon
350
$map_canvas->createPolygon( @Map{'Border'},
351
                           '-tags' => 'Map-Border',
352
                           '-fill' => '',
353
                           '-outline' => $Cfg->{'mkcockpit'}->{'ColorAirfield'}, '-width' => 2,
354
                          );
355
$map_canvas->raise('Map-Border', 'Map');  # Border above Map
356
 
357
 
358
# Balloon attached to Canvas
359
$map_balloon = $frame_map->Balloon('-statusbar' => $status_line, );
360
$map_balloon->attach($map_canvas,
361
                     '-balloonposition' => 'mouse',
362
                     '-state' => 'balloon',
363
                     '-msg' => { 'MK-Arrow'               => $Translate{'Balloon-MK-Arrow'},
364
                                 'MK-Home-Line'           => $Translate{'Balloon-MK-Home-Line'},
365
                                 'MK-Home-Dist'           => $Translate{'Balloon-MK-Home-Dist'},
366
                                 'MK-Target-Line'         => $Translate{'Balloon-MK-Target-Line' },
367
                                 'MK-Target-Dist'         => $Translate{'Balloon-MK-Target-Dist'},
368
                                 'MK-Speed'               => $Translate{'Balloon-MK-Speed'},
369
                                 'Map-Variometer'         => $Translate{'Balloon-Map-Variometer' },
370
                                 'Map-Variometer-Pointer' => $Translate{'Balloon-Map-Variometer-Pointer'},
371
                                 'Map-Variometer-Skala'   => $Translate{'Balloon-Map-Variometer-Pointer'},
372
                                 'Fox'                    => $Translate{'Balloon-Fox'},
373
                                 'Heartbeat'              => $Translate{'Balloon-Heartbeat'},
374
                                 'Satellite'              => $Translate{'Balloon-Satellite'},
375
                                 'Waypoint'               => $Translate{'Balloon-Waypoint'},
376
                                 'Map-Border'             => $Translate{'Balloon-Map-Border'},
377
                                 'Waypoint-Connector'     => $Translate{'Balloon-Waypoint-Connector'},
378
                                 'Wp-PlayPause'           => $Translate{'Balloon-Wp-PlayPause'},
379
                                 'Wp-Stop'                => $Translate{'Balloon-Wp-Stop'},
380
                                 'Wp-First'               => $Translate{'Balloon-Wp-First'},
381
                                 'Wp-Last'                => $Translate{'Balloon-Wp-Last'},
382
                                 'Wp-Next'                => $Translate{'Balloon-Wp-Next'},
383
                                 'Wp-Prev'                => $Translate{'Balloon-Wp-Prev'},
384
                                 'Wp-Home'                => $Translate{'Balloon-Wp-Home'},
385
                                 'Wp-WptKml'              => $Translate{'Balloon-Wp-WptKml'},
386
                                 'Wp-WptRandom'           => $Translate{'Balloon-Wp-WptRandom'},
387
                                 'Wp-Record'              => $Translate{'Balloon-Wp-Record'},
388
                               },
389
                    );
390
 
391
#                                       
392
# Mouse button 1
393
#
394
 
395
$map_canvas->CanvasBind("<Button-1>", sub
396
    {
397
    # print coords in status line
398
    my ($x, $y) = ($Tk::event->x, $Tk::event->y);
399
    my ($Lat, $Lon) = &MapXY2Gps($x, $y);
400
    $map_status_line->configure ('-text' => "Lat: $Lat  Lon: $Lon     x: $x  y: $y");
401
    });
402
 
403
# Mouse button 1 for Fox
404
my $FoxOldx = 0;
405
my $FoxOldy = 0;
406
 
407
# Pick Fox
408
$map_canvas->bind('Fox' => '<Button-1>' => sub
409
    {
410
    # prepare to move Fox
411
    my ($x, $y) = ($Tk::event->x, $Tk::event->y);
412
    $FoxOldx = $x;
413
    $FoxOldy = $y;
414
    $FoxTime = time;
415
    });
416
 
417
# Move Fox
418
$map_canvas->bind('Fox' => '<Button1-Motion>' => sub
419
    {
420
    my ($x, $y) = ($Tk::event->x, $Tk::event->y);
421
    my $id      = $map_canvas->find('withtag', 'current');
422
 
423
    $map_canvas->move($id => $x - $FoxOldx, $y - $FoxOldy);
424
    $FoxOldx = $x;
425
    $FoxOldy = $y;
426
 
427
    if ( time > $FoxTime )
428
        {
429
          # wenn in Bewegung Koordinaten nur 1/s senden
430
        my ($x0, $y0, $x1, $y1) = $map_canvas->bbox ($id);
431
        $x = $x0 + ($x1 - $x0)/2;
432
        $y = $y1;
433
 
434
        my ($Lat, $Lon) = &MapXY2Gps($x, $y);
435
        &MkFlyTo ( '-lat' => $Lat,
436
                   '-lon' => $Lon,
437
                   '-mode' => "Target",
438
                 );
439
        $FoxTime = time;
440
 
441
        $map_status_line->configure ('-text' => "$Translate{'TargetCoordSent'} -> Lat: $Lat  Lon: $Lon     x: $x  y: $y");
442
        }
443
    });
444
 
445
# Release Fox
446
$map_canvas->bind('Fox' => '<Button1-ButtonRelease>' => sub
447
    {
448
    my ($x, $y) = ($Tk::event->x, $Tk::event->y);
449
    my $id      = $map_canvas->find('withtag', 'current');
450
 
451
    my ($x0, $y0, $x1, $y1) = $map_canvas->bbox ($id);
452
    $x = $x0 + ($x1 - $x0)/2;
453
    $y = $y1;
454
 
455
    my ($Lat, $Lon) = &MapXY2Gps($x, $y);
456
    &MkFlyTo ( '-lat' => $Lat,
457
               '-lon' => $Lon,
458
               '-mode' => "Target",
459
             );
460
 
461
    # Show user that Waypoints in MK are cleared
462
    $WaypointsModified = 1;
463
    &WpRedrawLines();
464
 
465
    $map_status_line->configure ('-text' => "$Translate{'TargetCoordSent'} -> Lat: $Lat  Lon: $Lon     x: $x  y: $y");
466
    });
467
 
468
# Pick Waypoint
469
my $WpOldx;
470
my $WpOldy;
471
$map_canvas->bind('Waypoint' => '<Button-1>' => sub
472
    {
473
    # prepare to move
474
    my ($x, $y) = ($Tk::event->x, $Tk::event->y);
475
    $WpOldx = $x;
476
    $WpOldy = $y;
477
    });
478
 
479
# Move Waypoint
480
$map_canvas->bind('Waypoint' => '<Button1-Motion>' => sub
481
    {
482
    my ($x, $y) = ($Tk::event->x, $Tk::event->y);
483
    my $id      = $map_canvas->find('withtag', 'current');
484
 
485
    # move icon and Wp-Number
486
    my $WpIndex = &WpGetIndexFromId($id);
487
    if ( $WpIndex >= 0 )
488
        {
489
        my $Tag = $Waypoints[$WpIndex]{'Tag'};
490
        $map_canvas->move($Tag => $x - $WpOldx, $y - $WpOldy);
491
        }
492
 
493
    $WpOldx = $x;
494
    $WpOldy = $y;
495
    });
496
 
497
# Release Wp
498
$map_canvas->bind('Waypoint' => '<Button1-ButtonRelease>' => sub
499
    {
500
    my ($x, $y) = ($Tk::event->x, $Tk::event->y);
501
    my $id      = $map_canvas->find('withtag', 'current');
502
 
503
    # take coords from lower/middle icon position
504
    my ($x0, $y0, $x1, $y1) = $map_canvas->bbox ($id);
505
    $x = $x0 + ($x1 - $x0)/2;
506
    $y = $y1;
507
 
508
    # update Waypoint-Array
509
    my $WpIndex = &WpGetIndexFromId($id);
510
    if ( $WpIndex >= 0 )
511
            {
512
        # got it: set new coords
513
 
514
        my ($Lat, $Lon) = &MapXY2Gps($x, $y);
515
        my $Wp = $Waypoints[$WpIndex];
516
        $Wp->{'MapX'} = $x;
517
        $Wp->{'MapY'} = $y;
518
        $Wp->{'Pos_Lat'} = $Lat;
519
        $Wp->{'Pos_Lon'} = $Lon;
520
 
521
        # redraw connector-lines
522
        &WpRedrawLines();
523
 
524
        # red connectors: Wp still have to be sent to MK
525
        $map_canvas->itemconfigure('Waypoint-Connector',
526
                                           '-fill' => $Cfg->{'mkcockpit'}->{'ColorWpResend'},
527
                                  );
528
        $WaypointsModified = 1;
529
 
530
        my $WpNum = $WpIndex + 1;
531
        $map_status_line->configure ('-text' => "$Translate{'WpMoved'}: $WpNum -> Lat: $Lat  Lon: $Lon     x: $x  y: $y");
532
        }
533
    });
534
 
535
#
536
# Mouse button 3 context menu
537
#
538
my $map_menu = $map_canvas->Menu('-tearoff' => 0,
539
                                 '-title' =>'None',
540
                                 '-menuitems' =>
541
    [
542
     [Button => $Translate{'WpAddAndSend'},  -command => sub
543
        {
544
        # send Wp to MK         
545
        ($Lat, $Lon) = &MapXY2Gps($Wp_x, $Wp_y);
546
        &MkFlyTo ( '-lat' => $Lat,
547
                   '-lon' => $Lon,
548
                   '-mode' => "Waypoint"
549
                 );
550
 
551
        # Add Wp to Waypoints list
552
        &WpAdd ($MapCanvasX, $MapCanvasY);
553
 
554
        # switch player to Wp mode and redraw waypoints
555
        &PlayerWpt();
556
 
557
        $map_status_line->configure ('-text' => "$Translate{'WpSavedAndSent'} -> Lat: $Lat Lon: $Lon");
558
        }],
559
 
560
 
561
     [Button => $Translate{'WpProperties'},  -command => sub
562
        {
563
        # find Wp-Hash for selected icon/tag
564
        my $WpIndex = &WpGetIndexFromId($MapCanvasId);
565
        if ( $WpIndex >= 0 )
566
            {
567
            my $Wp = $Waypoints[$WpIndex];
568
            my $WpNum = $WpIndex + 1;
569
 
570
            &DisplayHash ($Wp, "$Translate{'WpProperties'} $WpNum", "Edit Waypoint Refresh");
571
 
572
            $map_status_line->configure ('-text' => "$Translate{'WpProperties'} $WpNum");
573
            }
574
        }],
575
 
576
     [Button => $Translate{'WpResendAll'},  -command => sub
577
        {
578
        &WpSendAll();
579
 
580
        $map_status_line->configure ('-text' => $Translate{'WpAllSent'});
581
        }],
582
 
583
      '',   # Separator
584
 
585
     [Button => $Translate{'WpLoadAndSend'},  -command => sub
586
        {
587
        my $WpFile = $main->getOpenFile('-defaultextension' => ".xml",
588
                                        '-filetypes'        =>
589
                                            [['Waypoints',     '.xml' ],
590
                                             ['All Files',     '*', ],
591
                                            ],
592
                                        '-initialdir' => $Cfg->{'waypoint'}->{'WpDir'},
593
                                        '-title' => $Translate{'WpLoad'},
594
                                       );
595
        if ( -f $WpFile )
596
            {
597
            &WpLoadFile ($WpFile);
598
 
599
            # send all Wp to MK
600
            &WpSendAll();
601
 
602
            # switch player to Wp mode and redraw waypoints
603
            $PlayerRandomMode  = 'STD';
604
            &PlayerWpt();
605
 
606
            $map_status_line->configure ('-text' => "$Translate{'WpLoadedAndSent'}: $WpFile");
607
            }
608
        }],    
609
 
610
     [Button => $Translate{'WpSave'},  -command => sub
611
        {
612
        my $WpFile = $main->getSaveFile('-defaultextension' => ".xml",
613
                                        '-filetypes'        =>
614
                                          [['Waypoints',     '.xml' ],
615
                                           ['All Files',     '*', ],
616
                                          ],
617
                                        '-initialdir' => $Cfg->{'waypoint'}->{'WpDir'},
618
                                        '-title' => $Translate{'WpSave'},
619
                                       );
620
 
621
        &WpSaveFile ($WpFile);
622
 
623
        $map_status_line->configure ('-text' => "$Translate{'WpSaved'}: $WpFile");
624
        }],
625
 
626
     '',   # Separator
627
 
628
     [Button => $Translate{'WpDelete'},  -command => sub
629
        {
630
        # find Wp-Hash for selected icon/tag
631
        my $WpIndex = &WpGetIndexFromId($MapCanvasId);
632
        if ( $WpIndex >= 0 )
633
            {
634
            &WpDelete ($WpIndex);
635
 
636
            # redraw connector-lines
637
            $WaypointsModified = 1;
638
            &WpRedrawLines();  
639
            &WpRedrawIcons();  # wg. Wp-Nummern
640
 
641
            my $WpNum = $WpIndex + 1;
642
            $map_status_line->configure ('-text' => "$Translate{'WpDeleted'}: $WpNum");
643
            }
644
        }],
645
 
646
     [Button => $Translate{'WpAllDeleteAndSend'},  -command => sub
647
        {
648
        undef @Waypoints;
649
        $WpPlayerIndex = 0;
650
        $WpPlayerHoldtime = -1;
651
 
652
        # remove all Wp-Icons and Wp-Number on canvas
653
        &WpHide();
654
 
655
        &WpSendAll();
656
 
657
        $map_status_line->configure ('-text' => "$Translate{'WpAllDeleted'}: $WpIndex");
658
        }],
659
 
660
    '',   # Separator
661
 
662
     [Button => $Translate{'KmlLoadAndPlay'},  -command => sub
663
        {
664
        $KmlFile = $main->getOpenFile('-defaultextension' => ".kml",
665
                                     '-filetypes'        =>
666
                                         [['KML',           '.kml' ],
667
                                          ['All Files',     '*', ],
668
                                         ],
669
                                     '-initialdir' => $Cfg->{'waypoint'}->{'KmlDir'},
670
                                     '-title' => $Translate{'KmlLoad'},
671
                                    );
672
        if ( -f $KmlFile )
673
            {
674
            &KmlLoadFile($KmlFile);
675
 
676
            # switch player to KML mode and redraw track
677
            &PlayerKml();
678
 
679
            $map_status_line->configure ('-text' => "$Translate{'KmlLoaded'}: $KmlFile" );
680
            }
681
 
682
        }],
683
 
684
    '',   # Separator
685
 
686
     [Button => $Translate{'WpFlyImmediately'},  -command => sub
687
        {
688
        &MkFlyTo ( '-x' => $MapCanvasX,
689
                   '-y' => $MapCanvasY,
690
                   '-mode' => "Target"
691
                 );
692
 
693
        # redraw connector-lines
694
        $WaypointsModified = 1;
695
        &WpRedrawLines();  
696
 
697
        $map_status_line->configure ('-text' => "$Translate{'TargetCoordSent'} -> Lat: $Lat  Lon: $Lon     x: $MapCanvasX  y: $MapCanvasY");
698
        }],
699
    ]
700
                                    );
701
$map_canvas->CanvasBind("<Button-3>" => [ sub
702
    {
703
    $map_canvas->focus;
704
    my($w, $x, $y) = @_;
705
    ($MapCanvasX, $MapCanvasY) = ($Tk::event->x, $Tk::event->y);
706
    $MapCanvasId = $map_canvas->find('withtag', 'current');
707
    $map_menu->post($x, $y);
708
    }, Ev('X'), Ev('Y') ] );
709
 
710
 
711
# Mouse bindings
712
$map_canvas->bind('Wp-PlayPause' => '<Button-1>' => \&CbPlayerPlayPause );
713
$map_canvas->bind('Wp-Next'      => '<Button-1>' => \&CbPlayerNext );
714
$map_canvas->bind('Wp-Prev'      => '<Button-1>' => \&CbPlayerPrev );
715
$map_canvas->bind('Wp-First'     => '<Button-1>' => \&CbPlayerFirst );
716
$map_canvas->bind('Wp-Last'      => '<Button-1>' => \&CbPlayerLast );
717
$map_canvas->bind('Wp-Home'      => '<Button-1>' => \&CbPlayerHome );
718
$map_canvas->bind('Wp-Stop'      => '<Button-1>' => \&CbPlayerStop );
719
$map_canvas->bind('Wp-WptKml'    => '<Button-1>' => \&CbPlayerWptKml );
720
$map_canvas->bind('Wp-WptRandom' => '<Button-1>' => \&CbPlayerWptRandom );
721
$map_canvas->bind('Wp-Record'    => '<Button-1>' => \&CbPlayerRecord );
722
 
723
 
724
# Focus Canvas, if any key pressed. Needed for the following key-bindings
725
$main->bind('<Any-Enter>' => sub { $map_canvas->Tk::focus });
726
 
727
# Disable default arrow-key bindings on canvas
728
$main->bind('Tk::Canvas',"<$_>",undef)for qw /Left Right Up Down/;
729
 
730
# keyboard bindings
731
$map_canvas->Tk::bind( '<Key-space>' , \&CbPlayerPlayPause );
732
$map_canvas->Tk::bind( '<Key-n>'     , \&CbPlayerNext );
733
$map_canvas->Tk::bind( '<Key-p>'     , \&CbPlayerPrev );
734
$map_canvas->Tk::bind( '<Key-f>'     , \&CbPlayerFirst );
735
$map_canvas->Tk::bind( '<Key-l>'     , \&CbPlayerLast );
736
$map_canvas->Tk::bind( '<Key-h>'     , \&CbPlayerHome );
737
$map_canvas->Tk::bind( '<Key-s>'     , \&CbPlayerStop );
738
$map_canvas->Tk::bind( '<Key-w>'     , \&CbPlayerWptKml );
739
$map_canvas->Tk::bind( '<Key-k>'     , \&CbPlayerWptKml );
740
$map_canvas->Tk::bind( '<Key-r>'     , \&CbPlayerWptRandom );
741
$map_canvas->Tk::bind( '<Key-a>'     , \&CbPlayerRecord );
742
$map_canvas->Tk::bind( '<Key-m>'     , \&CbPlayerMute );
743
$map_canvas->Tk::bind( '<Key-0>'     , [\&CbPlayerNum, "0"] );
744
$map_canvas->Tk::bind( '<Key-1>'     , [\&CbPlayerNum, "1"] );
745
$map_canvas->Tk::bind( '<Key-2>'     , [\&CbPlayerNum, "2"] );
746
$map_canvas->Tk::bind( '<Key-3>'     , [\&CbPlayerNum, "3"] );
747
$map_canvas->Tk::bind( '<Key-4>'     , [\&CbPlayerNum, "4"] );
748
$map_canvas->Tk::bind( '<Key-5>'     , [\&CbPlayerNum, "5"] );
749
$map_canvas->Tk::bind( '<Key-6>'     , [\&CbPlayerNum, "6"] );
750
$map_canvas->Tk::bind( '<Key-7>'     , [\&CbPlayerNum, "7"] );
751
$map_canvas->Tk::bind( '<Key-8>'     , [\&CbPlayerNum, "8"] );
752
$map_canvas->Tk::bind( '<Key-9>'     , [\&CbPlayerNum, "9"] );
753
$map_canvas->Tk::bind( '<Key-Left>'  , [\&CbPlayerMove, -1,  0] );
754
$map_canvas->Tk::bind( '<Key-Right>' , [\&CbPlayerMove,  1,  0] );
755
$map_canvas->Tk::bind( '<Key-Up>'    , [\&CbPlayerMove,  0,  1] );
756
$map_canvas->Tk::bind( '<Key-Down>'  , [\&CbPlayerMove,  0, -1] );
757
$map_canvas->Tk::bind( '<Key-Escape>', \&CbExit );
758
 
759
 
760
#
761
# dynamic objecs on canvas
762
#
763
 
764
# current MK position on canvas
765
$MkPos_x = $MapSizeX/2;
766
$MkPos_y = $MapSizeY/2;
767
 
768
# Line from MK to Home
769
$map_canvas->createLine ( $MapSizeX/2, $MapSizeY/2, $MapSizeX/2, $MapSizeY/2,
770
                          '-tags' => 'MK-Home-Line',
771
                          '-arrow' => 'none',
772
                          '-fill' => $Cfg->{'mkcockpit'}->{'ColorHomeLine'},
773
                          '-width' => 3,
774
                         );
775
 
776
# Text Entfernung positioniert an der Home-Linie
777
$map_canvas->createText ( $MapSizeX/2 + 8, $MapSizeY/2 - 8,
778
                          '-tags' => 'MK-Home-Dist',
779
                          '-text' => '0 m',
780
                          '-anchor' => 'w',
781
                          '-font' => '-*-Arial-Bold-R-Normal--*-200-*',
782
                          '-fill' => $Cfg->{'mkcockpit'}->{'ColorHomeDist'},
783
                          );
784
 
785
# Line from MK to Target, draw invisible out of sight
786
$map_canvas->createLine ( 0, -100, 0, -100,
787
                          '-tags' => 'MK-Target-Line',
788
                          '-arrow' => 'none',
789
                          '-fill' => $Cfg->{'mkcockpit'}->{'ColorTargetLine'},
790
                          '-width' => 3,
791
                         );
792
 
793
# Text Entfernung positioniert an der Target-Linie
794
$map_canvas->createText ( 0, -100,
795
                          '-tags' => 'MK-Target-Dist',
796
                          '-text' => '0 m',
797
                          '-anchor' => 'w',
798
                          '-font' => '-*-Arial-Bold-R-Normal--*-200-*',
799
                          '-fill' => $Cfg->{'mkcockpit'}->{'ColorTargetDist'},
800
                          );
801
 
802
# MK Geschwindigkeits-Vektor
803
$MapMkSpeedLen = 60;    # Länge Speed-Zeiger
804
my $x0 = $MapSizeX/2;
805
my $y0 = $MapSizeY/2;
806
my $x1 = $MapSizeX/2;
807
my $y1 = $MapSizeY/2 - $MapMkSpeedLen;
808
$map_canvas->createLine ( $x0, $y0, $x1, $y1,
809
                          '-tags' => 'MK-Speed',
810
                          '-arrow' => 'last',
811
                          '-arrowshape' => [10, 10, 3 ],
812
                          '-fill' => $Cfg->{'mkcockpit'}->{'ColorSpeedVector'},
813
                          '-width' => 4,
814
                         );
815
 
816
# MK als Pfeilspitze einer Linie darstellen
817
$MapMkLen = 25;
818
my $x0 = $MapSizeX/2;
819
my $y0 = $MapSizeY/2 + $MapMkLen/2;
820
my $x1 = $MapSizeX/2;
821
my $y1 = $MapSizeY/2 - $MapMkLen/2;
822
$map_canvas->createLine ( $x0, $y0, $x1, $y1,
823
                          '-tags' => 'MK-Arrow',
824
                          '-arrow' => 'last',
825
                          '-arrowshape' => [25, 30, 10 ],
826
                          '-fill' => $Cfg->{'mkcockpit'}->{'ColorMkSatNo'},
827
                          '-width' => 1
828
                         );
829
 
830
# OSD Texte auf Karte anzeigen
831
my @Texts = (
832
            # Tag                 Text         Pos_x           Pos_y  Font
833
            'MK-OSD-Tim-Label',   "TIM",       $MapSizeX/2 - 40,  20, '-*-Arial-Bold-R-Normal--*-150-*',
834
            'MK-OSD-Tim-Value',   "00:00",     $MapSizeX/2,       20, '-*-Arial-Bold-R-Normal--*-270-*',
835
            'MK-OSD-Tim-Left',    "",          $MapSizeX/2 + 90,  20, '-*-Arial-Bold-R-Normal--*-270-*',
836
            'MK-OSD-Bat-Label',   "BAT",       $MapSizeX/2 - 40,  50, '-*-Arial-Bold-R-Normal--*-150-*',
837
            'MK-OSD-Bat-Value',   "0.0 V",     $MapSizeX/2,       50, '-*-Arial-Bold-R-Normal--*-270-*',
838
          # 'MK-OSD-Bat-Level',   "",          $MapSizeX/2 + 90,  50, '-*-Arial-Bold-R-Normal--*-270-*',
839
            'MK-OSD-Spd-Label',   "SPD",       10,                20, '-*-Arial-Bold-R-Normal--*-150-*',
840
            'MK-OSD-Spd-Value',   "0.0 km/h",  60,                20, '-*-Arial-Bold-R-Normal--*-270-*',
841
            'MK-OSD-Alt-Label',   "ALT",       10,                50, '-*-Arial-Bold-R-Normal--*-150-*',
842
            'MK-OSD-Alt-Value',   "0 m",       60,                50, '-*-Arial-Bold-R-Normal--*-270-*',
843
            'MK-OSD-Odo-Label',   "ODO",       10,                80, '-*-Arial-Bold-R-Normal--*-150-*',
844
            'MK-OSD-Odo-Value',   "0.000 km",  60,                80, '-*-Arial-Bold-R-Normal--*-270-*',
845
            'MK-OSD-Sat-Label',   "SAT",       $MapSizeX - 230,   20, '-*-Arial-Bold-R-Normal--*-150-*',
846
            'MK-OSD-Sat-Value',   "0",         $MapSizeX - 180,   20, '-*-Arial-Bold-R-Normal--*-270-*',
847
            'MK-OSD-Wp-Label',    "WPT",       $MapSizeX - 230,   50, '-*-Arial-Bold-R-Normal--*-150-*',
848
            'MK-OSD-Wp-Value',    "0 / 0",     $MapSizeX - 180,   50, '-*-Arial-Bold-R-Normal--*-270-*',
849
            'MK-OSD-Mode-Label',  "MOD",       $MapSizeX - 230,   80, '-*-Arial-Bold-R-Normal--*-150-*',
850
            'MK-OSD-Mode-Value',  "",          $MapSizeX - 180,   80, '-*-Arial-Bold-R-Normal--*-270-*',
851
            'MK-OSD-Rec-Value',   "",          $MapSizeX - 180,  110, '-*-Arial-Bold-R-Normal--*-200-*',
852
            );
853
my $i = 0;
854
for $Text (0 .. $#Texts/5)
855
    {
856
    my $Tag =   $Texts[$i++];
857
    my $Text =  $Texts[$i++];
858
    my $Pos_x = $Texts[$i++];
859
    my $Pos_y = $Texts[$i++];
860
    my $Font =  $Texts[$i++];
861
 
862
    $map_canvas->createText ( $Pos_x, $Pos_y,
863
                              '-tags' => $Tag,
864
                              '-text' => $Text,
865
                              '-font' => $Font,
866
                              '-fill' => $Cfg->{'mkcockpit'}->{'ColorOsd'},
867
                              '-anchor' => 'w',
868
                             );
869
 
870
    }
871
 
872
 
873
# Variometer on canvas
874
my @Polygon;
875
for ( $y = -100; $y <= 100; $y += 10)
876
    {
877
    my $Len = 5;
878
    if ( ($y % 50) == 0 )
879
        {
880
        $Len = 10;
881
        $map_canvas->createText ( $Len+5, $MapSizeY/2 + $y,
882
                                  '-tags' => 'Map-Variometer-Skala',
883
                                  '-text' => sprintf ("%3d", -$y / 10),
884
                                  '-anchor' => 'w',
885
                                  '-font' => '-*-Arial-Normal-R-Normal--*-150-*',
886
                          '-fill' => $Cfg->{'mkcockpit'}->{'ColorVariometer'},
887
                          );
888
        }
889
    push @Polygon, (   0, $MapSizeY/2 + $y);
890
    push @Polygon, ($Len, $MapSizeY/2 + $y);
891
    push @Polygon, (   0, $MapSizeY/2 + $y);
892
    }
893
 
894
$map_canvas->createLine(@Polygon,
895
                        '-tags' => 'Map-Variometer',
896
                        '-fill' => $Cfg->{'mkcockpit'}->{'ColorVariometer'},
897
                        '-width' => 2,
898
                        '-arrow' => 'none',
899
                       );
900
# Vario Pointer
901
$map_canvas->createPolygon( 5, $MapSizeY/2, 20, $MapSizeY/2+10, 20, $MapSizeY/2-10,
902
                           '-tags' => 'Map-Variometer-Pointer',
903
                           '-fill' => $Cfg->{'mkcockpit'}->{'ColorVariometerPointer'},
904
                           '-outline' => 'black', '-width' => 1,
905
                          );
906
 
907
# Tracking Canvas
908
 
909
if ( $Cfg->{'track'}->{'Active'} =~ /y/i )
910
    {
911
    # Canvas size
912
    $TrackSizeX  = 125;
913
    $TrackSizeY  = 100;
914
    $TrackOffY   = $TrackSizeY - $MapSizeY + 20;
915
    $TrackPtrLen = 50;    # Länge Zeiger
916
 
917
    # draw in map-canvas
918
    $track_canvas = $map_canvas;
919
 
920
    # Ziffernblatt
921
    my $x0 = $TrackSizeX/2 - $TrackPtrLen;
922
    my $y0 = $TrackSizeY + $TrackPtrLen - $TrackOffY;
923
    my $x1 = $TrackSizeX/2 + $TrackPtrLen;
924
    my $y1 = $TrackSizeY   - $TrackPtrLen - $TrackOffY;
925
    $track_canvas->createArc ( $x0, $y0, $x1, $y1,
926
                               '-extent' => '200',
927
                               '-start' => '-10',
928
                               '-style' => 'chord',
929
                               '-outline' => 'gray', '-width' => '1',
930
                             );
931
 
932
    # Skala Ziffernblatt
933
    for ($i=0; $i<=180; $i+=15)
934
        {
935
        my $x0 = $TrackSizeX/2 - ($TrackPtrLen - 20) * cos( deg2rad $i );
936
        my $y0 = $TrackSizeY   - ($TrackPtrLen - 20) * sin( deg2rad $i ) - $TrackOffY;
937
        my $x1 = $TrackSizeX/2 - ($TrackPtrLen - 28) * cos( deg2rad $i );
938
        my $y1 = $TrackSizeY   - ($TrackPtrLen - 28) * sin( deg2rad $i ) - $TrackOffY;
939
        $track_canvas->createLine ( $x0, $y0, $x1, $y1,
940
                                   '-fill' => 'white',
941
                                   '-width' => 1,
942
                                  );
943
        }
944
 
945
    # Skala Beschriftung Ziffernblatt
946
    for ($i=0; $i<=180; $i+=45)
947
        {
948
        my $x0 = $TrackSizeX/2 - ($TrackPtrLen - 12) * cos( deg2rad $i );
949
        my $y0 = $TrackSizeY   - ($TrackPtrLen - 12) * sin( deg2rad $i ) - $TrackOffY;
950
        $track_canvas->createText ( $x0, $y0,
951
                                   '-text' => $i - 90,
952
                                   '-fill' => 'white',
953
                                  );
954
        }
955
 
956
    # Ziffernblatt Beschriftung Einheit
957
    my $x0 = $TrackSizeX/2;
958
    my $y0 = $MapSizeY -6;
959
    $track_canvas->createText ( $x0, $y0,
960
                                '-text' => "Antenne Winkel",
961
                                '-justify' => 'center',
962
                                '-fill' => 'white',
963
                                );
964
 
965
    # Zeiger
966
    my $x0 = $TrackSizeX/2;
967
    my $y0 = $TrackSizeY - 0 - $TrackOffY;
968
    my $x1 = $TrackSizeX/2;
969
    my $y1 = $TrackSizeY - ($TrackPtrLen - 22) - $TrackOffY;
970
    $track_ptr_id= $track_canvas->createLine ( $x0, $y0, $x1, $y1,
971
                                               '-tags' => 'Track-Ptr',
972
                                               '-arrow' => 'last',
973
                                               '-arrowshape' => [20, 30, 5 ],
974
                                               '-fill' => 'red',
975
                                               '-width' => 8,
976
                                              );
977
    # Zeiger Center
978
    my $Dia = 7;
979
    my $x0 = $TrackSizeX/2 - $Dia;
980
    my $y0 = $TrackSizeY + $Dia - $TrackOffY;
981
    my $x1 = $TrackSizeX/2 + $Dia;
982
    my $y1 = $TrackSizeY   - $Dia - $TrackOffY;
983
    $track_canvas->createArc ( $x0, $y0, $x1, $y1,
984
                               '-extent' => '359',
985
                               '-outline' => 'gray', '-width' => 1,
986
                               '-fill' => 'gray',
987
                             );
988
    }
989
 
990
#
991
# Load Start Scenario
992
#
993
 
994
# Waypoint file
995
my $CfgVal = $Cfg->{'StartScenario'}->{'WpFile'};
996
if ( ! -f $CfgVal )
997
    {
998
    $CfgVal = $Cfg->{'waypoint'}->{'WpDir'} . "/" . $Cfg->{'StartScenario'}->{'WpFile'};
999
    }
1000
if ( -f $CfgVal )
1001
    {
1002
    &WpLoadFile($CfgVal);
1003
 
1004
    # send all Wp to MK
1005
    &WpSendAll();
1006
    }
1007
 
1008
# KML file
1009
my $CfgVal = $Cfg->{'StartScenario'}->{'KmlFile'};
1010
if ( ! -f $CfgVal )
1011
    {
1012
    $CfgVal = $Cfg->{'waypoint'}->{'KmlDir'} . "/" . $Cfg->{'StartScenario'}->{'KmlFile'};
1013
    }
1014
if ( -f $CfgVal )
1015
    {
1016
    &KmlLoadFile($CfgVal);
1017
    }
1018
 
1019
# PLayer Mode
1020
my $CfgVal  = $Cfg->{'StartScenario'}->{'PlayerMode'};
1021
if ( $CfgVal =~ /Play/i )  { &PlayerPlay(); }
1022
if ( $CfgVal =~ /Pause/i ) { &PlayerPause(); }
1023
if ( $CfgVal =~ /Home/i )  { &PlayerHome(); }
1024
if ( $CfgVal =~ /Stop/i )  { &PlayerStop(); }
1025
 
1026
# Player Random Mode
1027
my $CfgVal  = $Cfg->{'StartScenario'}->{'PlayerRandomMode'};
1028
if ( $CfgVal eq "STD" ) { &PlayerRandomStd(); }
1029
if ( $CfgVal eq "RND" ) { &PlayerRandomRnd(); }
1030
if ( $CfgVal eq "MAP" ) { &PlayerRandomMap(); }
1031
 
1032
# PLayer Wpt/Kml Mode
1033
my $CfgVal  = $Cfg->{'StartScenario'}->{'PlayerWptKmlMode'};
1034
if ( $CfgVal eq "WPT" )  { &PlayerWpt(); }
1035
if ( $CfgVal eq "KML" )  { &PlayerKml(); }
1036
 
1037
# Audio TTS Mute
1038
my $CfgVal  = $Cfg->{'StartScenario'}->{'AudioMute'};
1039
if ( $CfgVal =~ /y/i )
1040
    {
1041
    $TtsMute = 1;    
1042
    }
1043
 
1044
 
1045
#
1046
# Timer
1047
#
1048
require "libmktimer.pl";
1049
 
1050
 
1051
MainLoop();   # should never end
1052
 
1053
 
1054
#
1055
# GUI Call Back
1056
# 
1057
 
1058
# Player CallBack: Play/Pause button
1059
sub CbPlayerPlayPause()
1060
    {
1061
    if ( ($PlayerMode eq "Pause") or  ($PlayerMode eq "Stop") or  ($PlayerMode eq "Home") )
1062
        {
1063
        &PlayerPlay();
1064
        }
1065
    else
1066
        {
1067
        &PlayerPause();
1068
        }
1069
    }
1070
 
1071
 
1072
# Player CallBack: Next
1073
sub CbPlayerNext()
1074
    {
1075
    if ( $PlayerMode ne 'Stop' )
1076
        {
1077
        if ( $PlayerWptKmlMode eq 'WPT' )
1078
           {
1079
           &WpTargetNext();
1080
           }
1081
        if ( $PlayerWptKmlMode eq 'KML' )
1082
           {
1083
           &KmlTargetNext();
1084
           }
1085
        }
1086
    }
1087
 
1088
 
1089
# Player CallBack: Prev
1090
sub CbPlayerPrev()
1091
    {
1092
    if ( $PlayerMode ne 'Stop' )
1093
        {
1094
        if ( $PlayerWptKmlMode eq 'WPT' )
1095
           {
1096
           &WpTargetPrev();
1097
           }
1098
        if ( $PlayerWptKmlMode eq 'KML' )
1099
           {
1100
           &KmlTargetPrev();
1101
           }
1102
        }
1103
    }
1104
 
1105
 
1106
# Player CallBack: First
1107
sub CbPlayerFirst()
1108
    {
1109
    if ( $PlayerMode ne 'Stop' )
1110
        {
1111
        if ( $PlayerWptKmlMode eq 'WPT' )
1112
           {
1113
           &WpTargetFirst();
1114
           }
1115
        if ( $PlayerWptKmlMode eq 'KML' )
1116
           {
1117
           &KmlTargetFirst();
1118
           }
1119
        }
1120
    }
1121
 
1122
# Player CallBack: Last
1123
sub CbPlayerLast()
1124
    {
1125
    if ( $PlayerMode ne 'Stop' )
1126
        {
1127
        if ( $PlayerWptKmlMode eq 'WPT' )
1128
           {
1129
           &WpTargetLast();
1130
           }
1131
        if ( $PlayerWptKmlMode eq 'KML' )
1132
           {
1133
           &KmlTargetLast();
1134
           }
1135
        }
1136
    }
1137
 
1138
 
1139
# Player CallBack: Home
1140
sub CbPlayerHome()
1141
    {
1142
    if ( $PlayerMode ne 'Stop' )
1143
        {
1144
        &PlayerHome();
1145
        }
1146
    }
1147
 
1148
 
1149
# Player CallBack: Stop
1150
sub CbPlayerStop()
1151
    {
1152
    if ( $PlayerMode ne 'Stop' )
1153
        {
1154
        &PlayerStop();
1155
        }
1156
    }
1157
 
1158
 
1159
# Player CallBack: Move MK in Pause-Mode
1160
sub CbPlayerMove()
1161
    {
1162
    my ($Id, $DirX, $DirY) = @_;
1163
 
1164
    if ( $PlayerMode eq 'Pause'  and
1165
         $PlayerPause_Lat ne ""  and  $PlayerPause_Lon ne "" )
1166
        {
1167
        my $Dist = $Cfg->{'waypoint'}->{'PauseMoveDist'} || 1;  # 1m default
1168
 
1169
        my $BearingTop = &MapAngel() - 90.0;
1170
        my $BearingKey = rad2deg atan2($DirX, $DirY);
1171
        my $Bearing = $BearingTop + $BearingKey;
1172
 
1173
        ($PlayerPause_Lat, $PlayerPause_Lon) = &MapGpsAt($PlayerPause_Lat, $PlayerPause_Lon, $Dist, $Bearing)
1174
        }
1175
    }
1176
 
1177
 
1178
# Player CallBack: Toggle WPT/KML button
1179
sub CbPlayerWptKml()
1180
    {
1181
 
1182
    if ( $PlayerWptKmlMode =~ /WPT/i )
1183
        {
1184
        &PlayerKml();
1185
        }
1186
    elsif ( $PlayerWptKmlMode =~ /KML/i )
1187
        {
1188
        &PlayerWpt();
1189
        }
1190
    }
1191
 
1192
 
1193
# Player CallBack: Toggle Random modes. STD -> RND -> MAP
1194
sub CbPlayerWptRandom()
1195
    {
1196
    if ( $PlayerRandomMode eq "STD" )
1197
        {
1198
        &PlayerRandomRnd();
1199
        }
1200
    elsif ( $PlayerRandomMode eq "RND" )
1201
        {
1202
        &PlayerRandomMap();
1203
        }
1204
    else
1205
        {
1206
        &PlayerRandomStd();
1207
        }
1208
    }
1209
 
1210
 
1211
# Player CallBack: Togglle Record KML
1212
sub CbPlayerRecord()
1213
    {
1214
    if ( $PlayerRecordMode =~ /REC/i )
1215
        {
1216
        &PlayerRecordOff();
1217
        }
1218
    elsif ( $PlayerRecordMode eq "" )
1219
        {
1220
        &PlayerRecordOn();
1221
        }
1222
    }
1223
 
1224
 
1225
# Player CallBack: Number Keys
1226
sub CbPlayerNum()
1227
    {
1228
    my ($Id, $Num) = @_;
1229
 
1230
    $CbPlayerKey = "$CbPlayerKey" . "$Num";
1231
    }
1232
 
1233
 
1234
# Player CallBack: mute TTS audio
1235
sub CbPlayerMute()
1236
    {
1237
    if ( $TtsMute )
1238
        {
1239
        $TtsMute = 0;
1240
        }
1241
    else
1242
        {
1243
        $TtsMute = 1;
1244
        }
1245
    }
1246
 
1247
# CallBack: Exit Mission Cockpit
1248
sub CbExit()
1249
    {
1250
    # stop tracking antenna thread
1251
    $TrackQueue->enqueue( "EXIT" );
1252
 
1253
    exit;
1254
    }
1255
 
1256
 
1257
#
1258
# subroutines moved to libmkcockpit.pl
1259
# Timer moved to libmktimer.pl
1260
#
1261
 
1262
 
1263
__END__