Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,19 @@

## Unreleased

### Update notes

The project uses now a library to manage user directories on the different operating systems, the location was modified for Windows:

```cmd
# cmd
mkdir %APPDATA%\DakaraProject
move %APPDATA%\Dakara %APPDATA%\DakaraProject\dakara
# powershell
mkdir $env:APPDATA\DakaraProject
mv $env:APPDATA\Dakara $env:APPDATA\DakaraProject\dakara
```

### Added

- Fonts are automatically installed on Windows.
Expand Down
10 changes: 8 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,12 @@ It is strongly recommended to use the Dakara player within a virtual environment

### Install

Please ensure you have a recent enough version of `setuptools`:

```sh
pip install --upgrade "setuptools>=46.4.0"
```

Install the package with:

```sh
Expand Down Expand Up @@ -73,12 +79,12 @@ dakara-player create-config
python -m dakara_player create-config
```

and complete it with your values. The file is stored in your user space: `~/.config/dakara` on Linux or `$APPDATA\Dakara` on Windows.
and complete it with your values. The file is stored in your user space: `~/.config/dakara` on Linux, or `$APPDATA\DakaraProject\dakara` on Windows.

## Customization

The different text screens used when the player is idle, or before a song, can be customized, both for the background and the text template.
The program looks for custom files at startup in the user directory: `~/.local/share/dakara/player` on Linux or `$APPDATA\Dakara\player` on Windows.
The program looks for custom files at startup in the user directory: `~/.local/share/dakara/player` on Linux or `$APPDATA\DakaraProject\dakara\player` on Windows.
Backgrounds are located in the `backgrounds` subfolder, and text templates in the `templates` subfolder.
File names can be modified in the config file, see `player.templates` and `player.backgrounds`.

Expand Down
2 changes: 1 addition & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ package_dir =
packages = find:
# dependencies are pinned by interval
install_requires =
dakarabase>=1.4.0,<1.5.0
dakarabase>=1.4.2,<1.5.0
filetype>=1.0.10,<1.1.0
importlib-resources>=5.6.0,<5.7.0; python_version < '3.7'
Jinja2>=3.1.1,<3.2.0
Expand Down
30 changes: 24 additions & 6 deletions src/dakara_player/font.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import ctypes
import logging
import sys
import platform
from abc import ABC, abstractmethod

from path import Path
Expand All @@ -26,14 +26,16 @@ def get_font_loader_class():
Returns:
FontLoader: Specialized version of the font loader class.
"""
if "linux" in sys.platform:
system = platform.system()

if system == "Linux":
return FontLoaderLinux

if "win" in sys.platform:
if system == "Windows":
return FontLoaderWindows

raise NotImplementedError(
"This operating system ({}) is not currently supported".format(sys.platform)
"This operating system ({}) is not currently supported".format(system)
)


Expand Down Expand Up @@ -136,14 +138,30 @@ def __init__(self, *args, **kwargs):
# create list of fonts
self.fonts_loaded = {}

def get_system_font_path_list(self):
"""Retrieve the list of system fonts.

Returns:
list of path.Path: List of font paths.
"""
return list(self.FONT_DIR_SYSTEM.walkfiles())

def get_user_font_path_list(self):
"""Retrieve the list of user fonts.

Returns:
list of path.Path: List of font paths.
"""
return list(self.FONT_DIR_USER.expanduser().walkfiles())

def load(self):
"""Load the fonts."""
# ensure that the user font directory exists
self.FONT_DIR_USER.expanduser().mkdir_p()

# get system and user font files
system_font_path_list = list(self.FONT_DIR_SYSTEM.walkfiles())
user_font_path_list = list(self.FONT_DIR_USER.expanduser().walkfiles())
system_font_path_list = self.get_system_font_path_list()
user_font_path_list = self.get_user_font_path_list()

# load fonts
for font_file_path in self.get_font_path_iterator():
Expand Down
6 changes: 3 additions & 3 deletions src/dakara_player/media_player/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@
from functools import wraps
from threading import Timer

from dakara_base.directory import directories
from dakara_base.exceptions import DakaraError
from dakara_base.safe_workers import Worker
from path import Path

from dakara_player.audio import get_audio_files
from dakara_player.background import BackgroundLoader
from dakara_player.text import TextGenerator
from dakara_player.user_resources import get_user_directory
from dakara_player.version import __version__

TRANSITION_BG_NAME = "transition.png"
Expand Down Expand Up @@ -125,7 +125,7 @@ def init_worker(self, config, tempdir, warn_long_exit=True):
config_texts = config.get("templates") or {}
self.text_generator = TextGenerator(
package="dakara_player.resources.templates",
directory=get_user_directory().expand() / "templates",
directory=directories.user_data_dir / "player" / "templates",
filenames={
"transition": config_texts.get(
"transition_template_name", TRANSITION_TEXT_NAME
Expand All @@ -139,7 +139,7 @@ def init_worker(self, config, tempdir, warn_long_exit=True):
self.background_loader = BackgroundLoader(
destination=tempdir,
package="dakara_player.resources.backgrounds",
directory=get_user_directory().expand() / "backgrounds",
directory=directories.user_data_dir / "player" / "backgrounds",
filenames={
"transition": config_backgrounds.get(
"transition_background_name", TRANSITION_BG_NAME
Expand Down
10 changes: 6 additions & 4 deletions src/dakara_player/media_player/vlc.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

import json
import logging
import platform
import re
import sys

from dakara_base.exceptions import DakaraError
from dakara_base.safe_workers import safe
Expand Down Expand Up @@ -726,18 +726,20 @@ def set_window(self, id):
logger.debug("Using VLC default window")
return

if "linux" in sys.platform:
system = platform.system()

if system == "Linux":
logger.debug("Associating X window to VLC")
self.player.set_xwindow(id)
return

if "win" in sys.platform:
if system == "Windows":
logger.debug("Associating Win API window to VLC")
self.player.set_hwnd(id)
return

raise NotImplementedError(
"This operating system ({}) is not currently supported".format(sys.platform)
"This operating system ({}) is not currently supported".format(system)
)


Expand Down
22 changes: 2 additions & 20 deletions src/dakara_player/user_resources.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
"""Manage the user resource directory and files."""

import logging
import sys
from distutils.util import strtobool

try:
Expand All @@ -10,29 +9,12 @@
except ImportError:
from importlib_resources import path, contents

from dakara_base.directory import directories
from path import Path

logger = logging.getLogger(__name__)


def get_user_directory():
"""Get the user directory for resource files.

Returns:
path.Path: Path to the user directory, must be expanded to be used.

Raises:
NotImplementedError: If the current platform is not supported.
"""
if "linux" in sys.platform:
return Path("~") / ".local" / "share" / "dakara" / "player"

if "win" in sys.platform:
return Path("$APPDATA") / "Dakara" / "player"

raise NotImplementedError("Operating system not supported")


def copy_resource(resource, destination, force):
"""Copy the content of one resource directory.

Expand Down Expand Up @@ -75,7 +57,7 @@ def create_resource_files(force=False):
force (bool): If the user directory already contains the resource
directories and this flag is set, overwrite the directories.
"""
user_directory = get_user_directory().expand()
user_directory = directories.user_data_dir
user_directory.makedirs_p()

for directory in ["backgrounds", "templates"]:
Expand Down
10 changes: 5 additions & 5 deletions tests/unit/test_font.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import sys
import platform
from unittest import TestCase, skipUnless
from unittest.mock import call, patch

Expand All @@ -18,17 +18,17 @@ class GetFontLoaderClassTestCase(TestCase):
def test(self):
"""Test to get the correct font loader class for the platform."""
# call for Linux
with patch("dakara_player.font.sys.platform", "linux"):
with patch("dakara_player.font.platform.system", return_value="Linux"):
FontLoaderClass = get_font_loader_class()
self.assertEqual(FontLoaderClass, FontLoaderLinux)

# call for Windows
with patch("dakara_player.font.sys.platform", "win32"):
with patch("dakara_player.font.platform.system", return_value="Windows"):
FontLoaderClass = get_font_loader_class()
self.assertEqual(FontLoaderClass, FontLoaderWindows)

# call for uniplemented OS
with patch("dakara_player.font.sys.platform", "other"):
with patch("dakara_player.font.platform.system", return_value="other"):
with self.assertRaisesRegex(
NotImplementedError,
r"This operating system \(other\) is not currently supported",
Expand Down Expand Up @@ -110,7 +110,7 @@ def test_get_font_path_iterator(self, mocked_get_font_name_list, mocked_path):
self.assertListEqual(font_file_path_list, [self.font_path])


@skipUnless(sys.platform.startswith("linux"), "Can be tested on Linux only")
@skipUnless(platform.system() == "Linux", "Can be tested on Linux only")
class FontLoaderLinuxTestCase(FontLoaderTestCase):
"""Test the Linux font loader."""

Expand Down
24 changes: 12 additions & 12 deletions tests/unit/test_media_player_vlc.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,15 @@
from threading import Event
from time import sleep
from unittest import TestCase, skipIf
from unittest.mock import MagicMock, patch
from unittest.mock import MagicMock, PropertyMock, patch

try:
import vlc

except (ImportError, OSError):
vlc = None

from dakara_base.directory import AppDirsPath
from packaging.version import parse
from path import Path

Expand Down Expand Up @@ -1069,10 +1070,10 @@ def test_handle_paused(self, mocked_get_timing):
# assert the call
vlc_player.callbacks["paused"].assert_called_with(42, 25)

@patch("dakara_player.media_player.base.get_user_directory")
def test_custom_backgrounds(self, mocked_get_user_directory):
@patch.object(AppDirsPath, "user_data_dir", new_callable=PropertyMock)
def test_custom_backgrounds(self, mocked_user_data_dir):
"""Test to instanciate with custom backgrounds."""
mocked_get_user_directory.return_value = Path("custom")
mocked_user_data_dir.return_value = Path("directory")

# create object
tempdir = Path("temp")
Expand All @@ -1090,7 +1091,7 @@ def test_custom_backgrounds(self, mocked_get_user_directory):
mocked_background_loader_class.assert_called_with(
destination=tempdir,
package="dakara_player.resources.backgrounds",
directory=Path("custom") / "backgrounds",
directory=Path("directory") / "player" / "backgrounds",
filenames={
"transition": "custom_transition.png",
"idle": "custom_idle.png",
Expand Down Expand Up @@ -1169,8 +1170,8 @@ def test_set_window_none(self):
["DEBUG:dakara_player.media_player.vlc:Using VLC default window"],
)

@patch("dakara_player.media_player.vlc.sys.platform", "linux")
def test_set_window_linux(self):
@patch("dakara_player.media_player.vlc.platform.system", return_value="Linux")
def test_set_window_linux(self, mocked_system):
"""Test to use X window."""
with self.get_instance() as (vlc_player, _, _):
with self.assertLogs("dakara_player.media_player.vlc", "DEBUG") as logger:
Expand All @@ -1181,8 +1182,8 @@ def test_set_window_linux(self):
["DEBUG:dakara_player.media_player.vlc:Associating X window to VLC"],
)

@patch("dakara_player.media_player.vlc.sys.platform", "win32")
def test_set_window_windows(self):
@patch("dakara_player.media_player.vlc.platform.system", return_value="Windows")
def test_set_window_windows(self, mocked_system):
"""Test to use Win API window."""
with self.get_instance() as (vlc_player, _, _):
with self.assertLogs("dakara_player.media_player.vlc", "DEBUG") as logger:
Expand All @@ -1196,9 +1197,8 @@ def test_set_window_windows(self):
],
)

@patch("dakara_player.media_player.base.get_user_directory", autospec=True)
@patch("dakara_player.media_player.vlc.sys.platform", "other")
def test_set_window_other(self, mocked_get_user_directory):
@patch("dakara_player.media_player.vlc.platform.system", return_value="other")
def test_set_window_other(self, mocked_system):
"""Test to set window on unknown platform."""
with self.get_instance() as (vlc_player, _, _):
with self.assertRaises(NotImplementedError):
Expand Down
Loading