Subversion Repositories Projects

Rev

Details | Last modification | View Log | RSS feed

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