aboutsummarylogtreecommitdiffstats
path: root/wrapper.pl
blob: a62a5726d0681d99433ed5e93515773ad3639b3b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
#!/usr/bin/perl

# Autheur: Nicolas Guilloux
# Website: https://nicolasguilloux.eu/
# Email:   novares.x@gmail.com

# Thanks Kabouik for his help for the english translations
# Thanks Brother/Ilya#0013 and TheWolf#0985 for their help for the german translations

use strict;
use warnings;

use File::Basename;
use POSIX qw(locale_h);
use locale;

use version;

use Cwd 'abs_path';
use File::Basename;

# ------ Exit if the user is root ------- #
if( $> == 0 ) {
    print "Please do not launch this application with the super administrator account.\n\n";
    exit 1;
}

# ----------- Translations ------------ #

my %fr = (
    'bypass'            => "Vérification de compatibilité désactivée.",

    'fake-error'        => "Ceci est une fonction de debug affichant une fausse erreur pour tester les notifications. Blip.",
    'fake-warning'      => "Ceci est une fonction de debug affichant un faux avertissement pour tester les notifications. Blip.",

    'lang-en'           => "Langage forcé en anglais (en_US)",
    'lang-de'           => "Langage forcé en allemand (de_DE)",
    'lang-fr'           => "Langage forcé en français (fr_FR)",

    'vainfo-nvidia'     => "Votre carte graphique est de marque Nvidia. Ces cartes ne sont pas supportées par Shadow sur Linux. Il faut attendre une nouvelle version de l'application.",
    'vainfo-optimus'    => "Votre GPU est NVIDIA. L'application ne peut pas fonctionner sur ce GPU. Néanmoins, vous disposez de la technologie Optimus. Lancez le panneau de controle NVIDIA, allez dans la rubrique Prime profiles, choisissez le GPU Intel et relancez votre session.",
    'vainfo-missing'    => "La commande 'vainfo' n'a pas été trouvée, le support H.264 et H.265 par votre carte graphique ne peut pas être vérifié. Installez 'vainfo' (Ubuntu, Linux Mint, Debian) ou 'libva-utils' (Arch, Solus) puis relancez l'application.",
    'vainfo-bad'        => "Votre carte graphique ne supporte aucun encodage utilisé par Shadow. Vous devez changer votre carte graphique pour une compatible, ou vérifier vos drivers VA-API.",
    'vainfo-good'       => "Votre carte graphique ne supporte que le H.264. Vous ne pourrez pas utiliser le H.265 (HEVC).",
    'vainfo-fail'       => "Votre carte graphique n'est pas reconnue par la librarie VA-API. Veuillez vérifiez vos drivers VA-API avec la commande 'vainfo'.",

    'input-adding'      => "Ajout de l'utilisateur actuel au groupe input.",
    'input-added'       => "Le programme a tenté d'ajouter l'utilisateur courant au groupe \"input\". Si vous avez entré le mot de passe administrateur, veuillez redémarrer votre ordinateur ou votre session pour appliquer le changement.",

    'xorg-fail'         => "Votre environnement de bureau n'utilise pas Xorg mais est identifié comme",
    'xorg-fail2'        => "Veuillez changer l'environnement pour utiliser Xorg ou l'application ne pourra pas fonctionner.",
    'xorg-empty'        => "Impossible de vérifier si vous êtes bien sur Xorg.",

    'errors'            => "Les erreurs suivantes empêchent\nl'application Shadow de fonctionner",

    'hotkeys'           => bold("Raccourcis") . "
    • lshift-rctrl-esc:      Quitter
    • lshift-rctrl-space:    Activer/désactiver le mode plein écran
    • lshift-rctrl-g:        Activer/désactiver la capture du clavier et de la souris
    • lshift-rctrl-h:        Activer/désactiver le Shadow Mode"
);

my %en = (
    'bypass'            => "Bypassing the compatibility check.",

    'fake-error'        => "This is a debug feature showing a fake error to test notifications. Blip.",
    'fake-warning'      => "This is a debug feature showing a fake warning to test notifications. Blip.",

    'lang-en'           => "Language forced in english (en_US)",
    'lang-de'           => "Language forced in german (de_DE)",
    'lang-fr'           => "Language forced in french (fr_FR)",

    'vainfo-nvidia'     => "Your GPU brand is Nvidia. This brand is not supported by Shadow on Linux. You have to wait for a new release from Blade.",
    'vainfo-optimus'    => "Your currently using the NVIDIA GPU. You can't start the application with it, but your computer supports Prime. Start the NVIDIA control panel, select the Prime panel, choose the Intel GPU and restart your session.",
    'vainfo-missing'    => "'vainfo' not found, H.264 and H.265 support by your GPU could not be checked. Install 'vainfo' (Ubuntu, Linux Mint, Debian) or 'libva-utils' (Arch, Solus) and restart the application.",
    'vainfo-bad'        => "Your GPU does not support any encoding technology used by Shadow. You have to change you GPU or check your VA-API drivers to use this application.",
    'vainfo-good'       => "Your GPU supports only H.264. You will not be able to use H.265 (HEVC).",
    'vainfo-fail'       => "Your GPU is not recognized. Please check your hardware decoding drivers with the 'vainfo' command.",


    'input-adding'      => "Adding the current user to the input group.",
    'input-added'       => "The program tried to add the current user to the \"input\" group. If you entered the administrator password, please reboot or restart your session to apply the change.",

    'xorg-fail'         => "Your environnement is not Xorg but is identified as",
    'xorg-fail2'        => "Please switch to Xorg or you will not be able to start this application.",
    'xorg-empty'        => "Impossible to check if you are on Xorg or not.",

    'errors'            => "The following errors prevented the\nShadow application from running",

    'hotkeys'           => bold("Hotkeys") . "
    • lshift-rctrl-esc:      Exit
    • lshift-rctrl-space:    Toggle fullscreen or windowed
    • lshift-rctrl-g:        Toggle input grab
    • lshift-rctrl-h:        Toggle Shadow Mode"
);

my %de = (
    'bypass'            => "Umgehung der Kompatibilitätsprüfung.",

    'fake-error'        => "Dies ist eine Debug-Funktion, die einen gefälschten Fehler anzeigt, um Benachrichtigungen zu testen.",
    'fake-warning'      => "Dies ist eine Debug-Funktion, die eine gefälschte Warnung anzeigt, um Benachrichtigungen zu testen.",

    'lang-en'           => "Sprache erzwungen in english (en_US)",
    'lang-de'           => "Sprache erzwungen in german (de_DE)",
    'lang-fr'           => "Sprache erzwungen in french (fr_FR)",

    'vainfo-nvidia'     => "Ihre GPU-Marke ist Nvidia. Diese Marke wird von Shadow unter Linux nicht unterstützt. Sie müssen auf eine neue Version von Blade warten.",
    'vainfo-optimus'    => "Sie verwenden derzeit den NVIDIA Grafikprozessor. Sie können die Anwendung damit nicht starten, aber Ihr Computer unterstützt Prime. Starten Sie das NVIDIA Control Panel, wählen Sie das Prime Panel, wählen Sie den Intel Grafikprozessor und starten Sie Ihre Sitzung neu.",
    'vainfo-missing'    => "'vainfo' nicht gefunden werden, konnte die H.264- und H.265-Unterstützung durch Ihren Grafikprozessor nicht überprüft werden. Installieren Sie 'vainfo' (Ubuntu, Linux  Mint, Debian) oder 'libva-utils' (Arch, Solus) und starten Sie die Anwendung neu.",
    'vainfo-bad'        => "Ihr Grafikprozessor unterstützt keine von Shadow verwendete Kodierungstechnologie. Sie müssen Ihren Grafikprozessor wechseln oder Ihre VA-API-Treiber überprüfen, um diese Anwendung nutzen zu können.",
    'vainfo-good'       => "Ihr Grafikprozessor unterstützt nur H.264. Sie können H.265 (HEVC) nicht verwenden.",
    'vainfo-fail'       => "Ihre GPU wird nicht erkannt. Bitte überprüfen Sie Ihren Hardware-Dekodierungstreiber mit dem Befehl 'vainfo'.",

    'input-adding'      => "Füge den aktuellen Benutzer zur Eingabengruppe hinzu.",
    'input-added'       => "Das Programm hat versucht, den aktuellen Benutzer zur Gruppe \"input\" hinzuzufügen. Wenn Sie das Administratorkennwort eingegeben haben, starten Sie Ihre Sitzung neu, um die Änderung zu übernehmen.",

    'xorg-fail'         => "Die Umgebung wurde nicht als Xorg identifiziert, sondern als",
    'xorg-fail2'        => "Bitte wechseln Sie auf Xorg, ansonsten kann die Anwendung nicht gestartet werden.",
    'xorg-empty'        => "Es konnte nicht geprüft werden ob Xorg verwendet wird oder nicht.",

    'errors'            => " Folgende Fehler haben einen \nStart von Shadow verhindert",

    'hotkeys'           => bold("Tastenbelegung") . "
    • lshift-rctrl-esc:      Beenden
    • lshift-rctrl-space:    Wechsel Vollbild / Fenster
    • lshift-rctrl-g:        Eingaben fangen umschalten
    • lshift-rctrl-h:        Shadowmodus umschalten"
);

my $locale = setlocale(LC_CTYPE);
my %lang = %en;

if( index($locale, 'fr') != -1 ) {
    %lang = %fr;

} elsif( index($locale, 'de') != -1 ){
    %lang = %de;
}


# ----------- Functions ------------ #

# Create a notification
#
# @param String Title
# @param String Content
# @param Bool   (Optional) Question notification
sub alert {
    if( -f "/usr/bin/notify-send" ) {
        my $command = "notify-send \"$_[0]\" \"$_[1]\" -u critical -i shadow-beta";
        exec($command);
    }
}

###
# Display in bold
#
# @param Input string
#
# @return Bold formated string
sub bold {
    return "\033[1m$_[0]\033[0m";
}

# ----------- Variables ------------ #

# Messages variables
my $help = "Wrapper for Shadow Beta that checks your configuration and compatibility errors.

Usage: shadowbeta-linux-x86_64.AppImage [OPTIONS]
    --help             Show this help
    --version          Get the version of the AppImage
    --bypass-check     Bypass the compatibility check and directly run the Shadow launcher
    --clientsdl        Directly launch the ClientSDL renderer

    --force-en         Force the launcher in english for people with translation issues (en_US)
    --force-de         Force the launcher in german for people with translation issues (de_DE)
    --force-fr         Force the launcher in french for people with translation issues (fr_FR)

    --error            Show a fake error notification
    --warning          Show a fake warning notification
    --strace           Launch the application with 'strace -f' and save the result to /var/tmp/strace_shadowbeta
    --report           Upload a report of the configuration";

# Debug, errors and warnings
my $debug  = 0;
my $strace = 0;
my $langF  = '';

my $isAppImg = 0;
my @errors   = ();
my @warnings = ();

my $version = 'Standalone wrapper';

# -------- Update -------- #
if( -d 'opt' ) {
    # AppImage detection
    $isAppImg = 1;
    $version = 'Nightly build';

    if( -f 'shadow-appimage-version' ) {

        # Local version
        open(my $fh, '<:encoding(UTF-8)', 'shadow-appimage-version')
          or die "Could not open file 'shadow-appimage-version' $!";
        $version = <$fh>;
        chomp $version;

        $help = "AppImage $version. " . $help;

        if( substr($version, 0, 1) eq 'v' ) {
            # Distant version
            my $distantVersion = `curl https://gitlab.com/api/v4/projects/7962701/repository/tags | jq -r -c 'map(select(.release!=null))|.[0]|.["release"]|.["tag_name"]'`;
            chomp $distantVersion;

            # Update available
            if( version->parse($version) < version->parse($distantVersion) ) {
                print "\nNEW UPDATE AVAILABLE: $distantVersion\n";
                alert('New version of the AppImage', "\nA new version of the AppImage is available on the server ($distantVersion)\n");
            }
        }

    }
}

# -------- Arguments -------- #
for(my $i=0; $i < $#ARGV+1; $i++) {
    my $arg = $ARGV[$i];

    # Display help and stop the program
    if( $arg eq '--help' ) {
        print "\n$help\n\n";
        exit;
    }

    # Get the version of the AppImage
    if( $arg eq '--version' ) {
        print "$version\n";
        exit;
    }

    # Bypass the check and launch
    if( $arg eq '--bypass-check' ) {
        push @warnings, $lang{'bypass'};
        goto START_SHADOW;
    }

    # Start directly ClientSDL and stops
    if( $arg eq '--clientsdl' ) {
        if( $isAppImg ) {
            system('./opt/Shadow\ Beta/resources/app.asar.unpacked/native/linux/ClientSDL');
        } else {
            system('/opt/Shadow\ Beta/resources/app.asar.unpacked/native/linux/ClientSDL');
        }

        exit 0;
    }


    # Force the launcher in english
    if( $arg eq '--force-en' ) {
        $langF = 'LANG=en_US.utf8 ';
        push @warnings, $lang{'lang-en'}
    }

    # Force the launcher in german
    if( $arg eq '--force-de' ) {
        $langF = 'LANG=de_DE.utf8 ';
        push @warnings, $lang{'lang-de'}
    }

    # Force the launcher in english
    if( $arg eq '--force-fr' ) {
        $langF = 'LANG=fr_FR.utf8 ';
        push @warnings, $lang{'lang-fr'}
    }


    # Start Shadow with Strace
    if( $arg eq '--strace' ) {
        $strace = 1;
    }

    # Create a false error
    if( $arg eq '--error' ) {
        push @errors, $lang{'fake-error'};
    }

    # Create a false warning
    if( $arg eq '--warning' ) {
        push @warnings, $lang{'fake-warning'};
    }

    # Upload a report of the configuration
    if( $arg eq '--report' ) {
        if( $isAppImg ) {
            system( './report.pl --appimage');

        } else {
            system( '"' . dirname(abs_path($0)) . '/report.pl"');
        }

        exit 0;
    }

}


# -------- NVIDIA check -------- #
if( index(`lspci | grep 'VGA'`, 'NVIDIA') != -1 ) {

    # Intel iGPU detected
    if( index(`lspci | grep 'VGA'`, 'Intel') != -1 ) {

        # Currently on the NVIDIA GPU
        if( index(`nvidia-smi -L`, 'GPU ') != 1 ) {
            push @errors, $lang{'vainfo-optimus'};
        }

    # Only NVIDIA GPU available
    } else {
        push @errors, $lang{'vainfo-nvidia'};
    }
}

# -------- Vainfo -------- #
if( -f '/usr/bin/vainfo' ) {
    my $vainfo = `vainfo`;

    if( $vainfo ne '' ) {
        # The GPU doesn't support H264.
        if( index($vainfo, 'H264') == -1 ) {
            push @errors, $lang{'vainfo-bad'};
        }

        if( index($vainfo, 'H265') == -1 and index($vainfo, 'HEVC') == 1 ) {
            push @warnings, $lang{'vainfo-good'};
        }

    } else {
        push @errors, $lang{'vainfo-fail'};
    }

} else {
    push @warnings, $lang{'vainfo-missing'};
}


# -------- Input --------- #
my $groups = `groups \$USER`;

if( index($groups, 'input') == -1 ) {

    print "$lang{'input-adding'}\n";
    my $in = `pkexec gpasswd -a \$USER input`;

    push @errors, $lang{'input-added'};
}


# -------- Xorg check -------- #
my $env = `echo \$XDG_SESSION_TYPE`;
chomp $env;

if( $env ne 'x11') {
    if( $env ne '' ) {
        push @errors,  "$lang{'xorg-fail'} $env. $lang{'xorg-fail2'}";

    } else {
        push @warnings, $lang{'xorg-empty'}
    }

}


# -------- Kill ClientSDL ------ #
while( `pkill -e ClientSDL` ne '' ) {}


# -------- Start Shadow -------- #
START_SHADOW:
print "\n";

# Warnings
if( scalar @warnings > 0 ) {
    print bold('WARNING') . ":\n";
    foreach my $i (0 .. $#warnings) {
        print " • $warnings[$i]\n";
    }
    print "\n";
}

# Display errors
if( scalar @errors > 0 ) {

    my $str = "";
    foreach my $i (0 .. $#errors) {
        $str .= " • $errors[$i]\n";
    }

    print bold('ERROR') . ":\n$str\n";
    alert($lang{'errors'}, "\n$str");

    exit 1;

# Start Shadow
} else {
    print "$lang{'hotkeys'}\n\n";

    my $pathExec = '/opt/Shadow\ Beta/shadow-beta';

    if( $isAppImg ) {
        $pathExec = './opt/Shadow\ Beta/shadow-beta.wrapper';
    }

    # Start Shadow with Strace
    if( $strace ) {
        system("$langF strace -f $pathExec &> /var/tmp/strace_shadowbeta");

    	# Create the compressed archive in the user directory
    	system('tar -zcvf ~/strace_shadowbeta.tar.gz /var/tmp/strace_shadowbeta');

    	# Remove the uncompressed strace
    	system('rm /var/tmp/strace_shadowbeta');

    # Start Shadow
    } else {
        system("$langF $pathExec");
    }

    exit 0;
}