Philipp Hörist pushed to branch master at gajim / gajim

Commits:

2 changed files:

Changes:

  • gajim/common/helpers.py
    ... ... @@ -534,31 +534,8 @@ def play_sound_file(path_to_soundfile):
    534 534
         if path_to_soundfile is None:
    
    535 535
             return
    
    536 536
     
    
    537
    -    path_to_soundfile = str(path_to_soundfile)
    
    538
    -    if sys.platform == 'win32':
    
    539
    -        import winsound
    
    540
    -        try:
    
    541
    -            winsound.PlaySound(path_to_soundfile,
    
    542
    -                               winsound.SND_FILENAME|winsound.SND_ASYNC)
    
    543
    -        except Exception:
    
    544
    -            log.exception('Sound Playback Error')
    
    545
    -
    
    546
    -    elif sys.platform == 'darwin':
    
    547
    -        try:
    
    548
    -            from AppKit import NSSound
    
    549
    -        except ImportError:
    
    550
    -            log.exception('Sound Playback Error')
    
    551
    -            return
    
    552
    -
    
    553
    -        sound = NSSound.alloc()
    
    554
    -        sound.initWithContentsOfFile_byReference_(path_to_soundfile, True)
    
    555
    -        sound.play()
    
    556
    -
    
    557
    -    elif app.is_installed('GSOUND'):
    
    558
    -        try:
    
    559
    -            app.gsound_ctx.play_simple({'media.filename' : path_to_soundfile})
    
    560
    -        except GLib.Error as error:
    
    561
    -            log.error('Could not play sound: %s', error.message)
    
    537
    +    from gajim.common import sound
    
    538
    +    sound.play(path_to_soundfile)
    
    562 539
     
    
    563 540
     def get_connection_status(account: str) -> str:
    
    564 541
         if not app.account_is_available(account):
    

  • gajim/common/sound.py
    1
    +# This file is part of Gajim.
    
    2
    +#
    
    3
    +# Gajim is free software; you can redistribute it and/or modify
    
    4
    +# it under the terms of the GNU General Public License as published
    
    5
    +# by the Free Software Foundation; version 3 only.
    
    6
    +#
    
    7
    +# Gajim is distributed in the hope that it will be useful,
    
    8
    +# but WITHOUT ANY WARRANTY; without even the implied warranty of
    
    9
    +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    
    10
    +# GNU General Public License for more details.
    
    11
    +#
    
    12
    +# You should have received a copy of the GNU General Public License
    
    13
    +# along with Gajim.  If not, see <http://www.gnu.org/licenses/>.
    
    14
    +
    
    15
    +from __future__ import annotations
    
    16
    +
    
    17
    +from typing import Any
    
    18
    +from typing import Optional
    
    19
    +
    
    20
    +import sys
    
    21
    +import logging
    
    22
    +from pathlib import Path
    
    23
    +
    
    24
    +from gi.repository import Gio
    
    25
    +from gi.repository import GLib
    
    26
    +
    
    27
    +from gajim.common import app
    
    28
    +
    
    29
    +if sys.platform == 'win32':
    
    30
    +    import winsound
    
    31
    +
    
    32
    +elif sys.platform == 'darwin':
    
    33
    +    from AppKit import NSSound
    
    34
    +
    
    35
    +
    
    36
    +log = logging.getLogger('gajim.c.sound')
    
    37
    +
    
    38
    +
    
    39
    +class PlaySound:
    
    40
    +
    
    41
    +    def play(self, path: Path, loop: bool = False) -> None:
    
    42
    +        raise NotImplementedError
    
    43
    +
    
    44
    +    def stop(self) -> None:
    
    45
    +        raise NotImplementedError
    
    46
    +
    
    47
    +
    
    48
    +class PlatformWindows(PlaySound):
    
    49
    +
    
    50
    +    def play(self, path: Path, loop: bool = False) -> None:
    
    51
    +        flags = (winsound.SND_FILENAME |
    
    52
    +                 winsound.SND_ASYNC |
    
    53
    +                 winsound.SND_NODEFAULT)
    
    54
    +        if loop:
    
    55
    +            flags = flags | winsound.SND_LOOP
    
    56
    +
    
    57
    +        try:
    
    58
    +            winsound.PlaySound(str(path), flags)
    
    59
    +        except Exception:
    
    60
    +            log.exception('Sound Playback Error')
    
    61
    +
    
    62
    +    def stop(self) -> None:
    
    63
    +        try:
    
    64
    +            winsound.PlaySound(None, 0)
    
    65
    +        except Exception:
    
    66
    +            log.exception('Sound Playback Error')
    
    67
    +
    
    68
    +
    
    69
    +class PlatformMacOS(PlaySound):
    
    70
    +
    
    71
    +    def play(self, path: Path, loop: bool = False) -> None:
    
    72
    +        sound = NSSound.alloc()
    
    73
    +        sound.initWithContentsOfFile_byReference_(str(path), True)
    
    74
    +        sound.play()
    
    75
    +
    
    76
    +    def stop(self) -> None:
    
    77
    +        pass
    
    78
    +
    
    79
    +
    
    80
    +class PlatformUnix(PlaySound):
    
    81
    +
    
    82
    +    def __init__(self) -> None:
    
    83
    +        self._cancellable: Optional[Gio.Cancellable] = None
    
    84
    +
    
    85
    +    def play(self, path: Path, loop: bool = False) -> None:
    
    86
    +        if not app.is_installed('GSOUND'):
    
    87
    +            return
    
    88
    +
    
    89
    +        attrs = {'media.filename': str(path)}
    
    90
    +        self._cancellable = Gio.Cancellable()
    
    91
    +
    
    92
    +        if loop:
    
    93
    +            self._play_loop(attrs)
    
    94
    +        else:
    
    95
    +            try:
    
    96
    +                app.gsound_ctx.play_simple(attrs, self._cancellable)
    
    97
    +            except GLib.Error as error:
    
    98
    +                log.error('Could not play sound: %s', error.message)
    
    99
    +                self._cancellable = None
    
    100
    +
    
    101
    +    def _play_loop(self, attrs: dict[str, str]) -> None:
    
    102
    +        try:
    
    103
    +            app.gsound_ctx.play_full(attrs,
    
    104
    +                                     self._cancellable,
    
    105
    +                                     self._on_play_finished,
    
    106
    +                                     attrs)
    
    107
    +        except GLib.Error as error:
    
    108
    +            log.error('Could not play sound: %s', error.message)
    
    109
    +            self._cancellable = None
    
    110
    +
    
    111
    +    def _on_play_finished(self,
    
    112
    +                          _context: Any,
    
    113
    +                          res: Gio.AsyncResult,
    
    114
    +                          user_data: dict[str, str]) -> None:
    
    115
    +        try:
    
    116
    +            app.gsound_ctx.play_full_finish(res)
    
    117
    +        except GLib.Error as error:
    
    118
    +            quark = GLib.quark_try_string('g-io-error-quark')
    
    119
    +            if error.matches(quark, Gio.IOErrorEnum.CANCELLED):
    
    120
    +                return
    
    121
    +            log.error('Could not play sound: %s', error.message)
    
    122
    +
    
    123
    +        self._play_loop(user_data)
    
    124
    +
    
    125
    +    def stop(self) -> None:
    
    126
    +        if self._cancellable is None or self._cancellable.is_cancelled():
    
    127
    +            return
    
    128
    +        self._cancellable.cancel()
    
    129
    +        self._cancellable = None
    
    130
    +
    
    131
    +
    
    132
    +def _init_platform() -> PlaySound:
    
    133
    +    if sys.platform == 'win32':
    
    134
    +        return PlatformWindows()
    
    135
    +
    
    136
    +    if sys.platform == 'darwin':
    
    137
    +        return PlatformMacOS()
    
    138
    +
    
    139
    +    return PlatformUnix()
    
    140
    +
    
    141
    +_platform_player = _init_platform()
    
    142
    +
    
    143
    +def play(path: Path, loop: bool = False) -> None:
    
    144
    +    _platform_player.play(path, loop)
    
    145
    +
    
    146
    +def stop():
    
    147
    +    _platform_player.stop()