squentin / gmusicbrowser

jukebox for large collections of music
http://gmusicbrowser.org
GNU General Public License v3.0
197 stars 42 forks source link

Gtk3 and utf-8 filenames #210

Open ig3 opened 3 years ago

ig3 commented 3 years ago

I installed gmusicbrowser from git master onto Debian Bullseye (test). All was fine except when I tried to play files with non-ASCII characters in the filename, either from command line or thunar context menu (open with), in which case it failed to play the file, reporting 'unknown option'.

I traced to problem to failure of the file existence test in gmusicbrowser.pl line 440:

    elsif($arg=~m#^http://# || -e $arg) { push @files,$arg }

The test fails even when the file exists.

I was able to get this going by changing line 440 to:

    elsif($arg=~m#^http://# || -e Encode::encode('ISO-8859-1', $arg)) { push @files,$arg }

I would submit a PR except that I am not at all confident that this is an appropriate solution. I have very little understanding of when Perl does conversion between byte strings and utf-8 strings.

In testing, I found the problem is triggered by use Gtk3. When this is included in my test program, I see the same data and results of file existence test as in gmusicbrowser. Somehow Gtk3 causes values from shift from @ARGV (at line 398) to have utf-8 flag set but the value is not decoded utf-8 (which I think would be appropriate in my case) but rather, the resulting value is as if the original byte sequence were decoded as ISO-8859-1. While this is the case on my Linux system, the situation might be quite different on other platforms. As pointed out in When Unicode Does Not Happen, the possibilities are diverse.

Apologies for not having a better solution, but perhaps this will be of some use to you.

ig3 commented 3 years ago

A little more testing. It seems the transformation of @ARGV is explicit in Gtk3::init:

sub Gtk3::init {
  my $rest = Glib::Object::Introspection->invoke (
               $_GTK_BASENAME, undef, 'init',
               [$0, @ARGV]);
  @ARGV = @{$rest}[1 .. $#$rest]; # remove $0
  return;
}

I understand this calls some init function, but I don't know what init function so no idea what it does, other than it obviously decodes at least some elements of @ARGV, maybe all of them.

It might be gtk_init but that returns nothing and the invocation in Gtk3 returns an array reference, so maybe it is some other init function, or maybe the Perl binding does something.

In Gtk3 - Perl interface to the 3.x series of the gtk+ toolkit I see: Additionally, "Gtk3::init" and "Gtk3::init_check" automatically handle passing and updating @ARGV as appropriate.