Repository: beetbox/beets

Issue:
play: Configuration option to include a UTF-8-BOM (and possibly use .m3u8 extension)
### Problem
Currently, the play plugin's generated m3u files don't behave with foobar2000 if they have special characters (i.e. [en dash](https://unicode-table.com/en/2013/) "–"). If I modify the m3u file to have an m3u8 extension and add the appropriate [BOM](https://en.wikipedia.org/wiki/Byte_order_mark), it works just fine.

Running this command in verbose (`-vv`) mode:

```sh
λ beet -vv play -a 009                                                                         
user configuration: C:\Users\mikey\AppData\Roaming\beets\config.yaml                           
data directory: C:\Users\mikey\AppData\Roaming\beets                                           
plugin paths:                                                                                  
Sending event: pluginload                                                                      
library database: D:\beets.db                                                                  
library directory: D:\Music                                                                    
Sending event: library_opened                                                                  
Playing 1 album.                                                                               
play: executing command: foobar2000 ['C:\\Users\\mikey\\AppData\\Local\\Temp\\tmp911i_r7f.m3u']
                                                                                               
```

Led to this problem:

```
Foobar can't find the files specified in the m3u file.
```
The file path attempting to be played is "D:\Music\Compilations\Monstercat 009 – Reunion"


### Setup

* OS: Windows 10 Pro 1803
* Python version: 3.6.4
* beets version: 1.4.6
* Turning off plugins made problem go away (yes/no): N/A

My configuration (output of `beet config`) is:

```yaml
directory: D:\\Music
library: D:\\beets.db

plugins: chroma fetchart mbsync fromfilename web play

import:
    move: yes
    write: yes

replace:
    '[\\/]': _
    ^\.: _
    '[\x00-\x1f]': _
    '[<>:"\?\*\|]': _
    \.$: _
    \s+$: ''
    ^\s+: ''
    ^-: _
play:
    command: foobar2000
    use_folders: no
    relative_to:
    raw: no
    warning_threshold: 100
sort_item: album+ disc+ track+ artist+
fetchart:
    auto: yes
    minwidth: 0
    maxwidth: 0
    enforce_ratio: no
    cautious: no
    cover_names:
    - cover
    - front
    - art
    - album
    - folder
    sources:
    - filesystem
    - coverart
    - itunes
    - amazon
    - albumart
    google_key: REDACTED
    google_engine: 001442825323518660753:hrh5ch1gjzm
    fanarttv_key: REDACTED
    store_source: no
web:
    host: 127.0.0.1
    port: 8337
    cors: ''
    reverse_proxy: no
    include_paths: no
chroma:
    auto: yes
```



Discussion:
Interesting! Yes, we do write non-ASCII filenames to these files. Do you know whether it’s a Foobar-specific quirk that it doesn’t support Unicode for ordinary `.m3u` files, or is this some manner of pseudo-standard we can read about somewhere? If it’s the former, maybe we should make it a configuration option. If it’s more universal, maybe the `.m3u8` behavior should be the default.
It seems to be a Foobar and Winamp problem. The default m3u files work in mpv, VLC, and MPC-BE.  
It doesn't seem to be a super common problem, and file extension doesn't seem to matter (if the BOM is present the files work in Winamp and Foobar).

Having it as a configuration option would probably be the way to go, with a warning about foobar/winamp in the wiki.
Cool; thanks for investigating. Let’s turn this into a feature request for such a flag.

Resolving patch:
diff --git a/beetsplug/play.py b/beetsplug/play.py
--- a/beetsplug/play.py
+++ b/beetsplug/play.py
@@ -65,6 +65,7 @@ def __init__(self):
             'relative_to': None,
             'raw': False,
             'warning_threshold': 100,
+            'bom': False,
         })
 
         self.register_listener('before_choose_candidate',
@@ -185,7 +186,12 @@ def _exceeds_threshold(self, selection, command_str, open_args,
     def _create_tmp_playlist(self, paths_list):
         """Create a temporary .m3u file. Return the filename.
         """
+        utf8_bom = config['play']['bom'].get(bool)
         m3u = NamedTemporaryFile('wb', suffix='.m3u', delete=False)
+
+        if utf8_bom:
+            m3u.write(b'\xEF\xBB\xBF')
+
         for item in paths_list:
             m3u.write(item + b'\n')
         m3u.close()


Test patch: