Merge branch 'master' into develop
This commit is contained in:
commit
8f261f96e9
49
CHANGELOG
49
CHANGELOG
|
@ -10,6 +10,55 @@ This changelog is viewable on the web at https://docs.funkwhale.audio/changelog.
|
||||||
|
|
||||||
.. towncrier
|
.. towncrier
|
||||||
|
|
||||||
|
0.19.1 (2018-06-28)
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
Upgrade instructions are available at
|
||||||
|
https://docs.funkwhale.audio/index.html
|
||||||
|
|
||||||
|
Enhancements:
|
||||||
|
|
||||||
|
- The currently playing track is now highlighted with an orange play icon (#832)
|
||||||
|
- Support for importing files with no album tag (#122)
|
||||||
|
- Redirect from / to /library when user is logged in (#864)
|
||||||
|
- Added a SUBSONIC_DEFAULT_TRANSCODING_FORMAT env var to support clients that don't provide the format parameter (#867)
|
||||||
|
- Added button to search for objects on Discogs (#368)
|
||||||
|
- Added copy-to-clipboard button with Subsonic password input (#814)
|
||||||
|
- Added opus to the list of supported mimetypes and extensions (#868)
|
||||||
|
- Aligned search headers with search results in the sidebar (#708)
|
||||||
|
- Clicking on the currently selected playlist in the Playlist popup will now close the popup (#807)
|
||||||
|
- Favorites radio will not be visible if the user does not have any favorites (#419)
|
||||||
|
|
||||||
|
|
||||||
|
Bugfixes:
|
||||||
|
|
||||||
|
- Ensure empty but optional fields in file metadata don't error during import (#850)
|
||||||
|
- Fix broken upload for specific files when using S3 storage (#857)
|
||||||
|
- Fixed broken translation on home and track detail page (#833)
|
||||||
|
- Fixed broken user admin for users with non-digit or letters in their username (#869)
|
||||||
|
- Fixed invalid file extension for transcoded tracks (#848)
|
||||||
|
- Fixed issue with French translation for "Start radio" (#849)
|
||||||
|
- Fixed issue with player changing height when hovering over the volume slider (#838)
|
||||||
|
- Fixed secondary menus truncated on narrow screens (#855)
|
||||||
|
- Fixed wrong og:image url when using S3 storage (#851)
|
||||||
|
- Hide pod statistics on about page if those are disabled (#835)
|
||||||
|
- Use ASCII filename before upload to S3 to avoid playback issues (#847)
|
||||||
|
|
||||||
|
|
||||||
|
Contributors to this release (commiters and reviewers):
|
||||||
|
|
||||||
|
- Ciarán Ainsworth
|
||||||
|
- Creak
|
||||||
|
- ealgase
|
||||||
|
- Eliot Berriot
|
||||||
|
- Esteban
|
||||||
|
- Freyja Wildes
|
||||||
|
- hellekin
|
||||||
|
- Johannes H.
|
||||||
|
- Mehdi
|
||||||
|
- Reg
|
||||||
|
|
||||||
|
|
||||||
0.19.0 (2019-05-16)
|
0.19.0 (2019-05-16)
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
|
|
|
@ -706,3 +706,6 @@ RSA_KEY_SIZE = 2048
|
||||||
CREATE_IMAGE_THUMBNAILS = env.bool("CREATE_IMAGE_THUMBNAILS", default=True)
|
CREATE_IMAGE_THUMBNAILS = env.bool("CREATE_IMAGE_THUMBNAILS", default=True)
|
||||||
# we rotate actor keys at most every two days by default
|
# we rotate actor keys at most every two days by default
|
||||||
ACTOR_KEY_ROTATION_DELAY = env.int("ACTOR_KEY_ROTATION_DELAY", default=3600 * 48)
|
ACTOR_KEY_ROTATION_DELAY = env.int("ACTOR_KEY_ROTATION_DELAY", default=3600 * 48)
|
||||||
|
SUBSONIC_DEFAULT_TRANSCODING_FORMAT = (
|
||||||
|
env("SUBSONIC_DEFAULT_TRANSCODING_FORMAT", default="mp3") or None
|
||||||
|
)
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
__version__ = "0.19.0"
|
__version__ = "0.19.1"
|
||||||
__version_info__ = tuple(
|
__version_info__ = tuple(
|
||||||
[
|
[
|
||||||
int(num) if num.isdigit() else num
|
int(num) if num.isdigit() else num
|
||||||
|
|
|
@ -247,10 +247,6 @@ class SubsonicViewSet(viewsets.GenericViewSet):
|
||||||
if not upload:
|
if not upload:
|
||||||
return response.Response(status=404)
|
return response.Response(status=404)
|
||||||
|
|
||||||
format = data.get("format", "raw")
|
|
||||||
if format == "raw":
|
|
||||||
format = None
|
|
||||||
|
|
||||||
max_bitrate = data.get("maxBitRate")
|
max_bitrate = data.get("maxBitRate")
|
||||||
try:
|
try:
|
||||||
max_bitrate = min(max(int(max_bitrate), 0), 320) or None
|
max_bitrate = min(max(int(max_bitrate), 0), 320) or None
|
||||||
|
@ -259,6 +255,16 @@ class SubsonicViewSet(viewsets.GenericViewSet):
|
||||||
|
|
||||||
if max_bitrate:
|
if max_bitrate:
|
||||||
max_bitrate = max_bitrate * 1000
|
max_bitrate = max_bitrate * 1000
|
||||||
|
|
||||||
|
format = data.get("format", "raw") or None
|
||||||
|
if max_bitrate and not format:
|
||||||
|
# specific bitrate requested, but no format specified
|
||||||
|
# so we use a default one, cf #867. This helps with clients
|
||||||
|
# that don't send the format parameter, such as DSub.
|
||||||
|
format = settings.SUBSONIC_DEFAULT_TRANSCODING_FORMAT
|
||||||
|
elif format == "raw":
|
||||||
|
format = None
|
||||||
|
|
||||||
return music_views.handle_serve(
|
return music_views.handle_serve(
|
||||||
upload=upload,
|
upload=upload,
|
||||||
user=request.user,
|
user=request.user,
|
||||||
|
|
|
@ -261,23 +261,48 @@ def test_stream_format(format, expected, logged_in_api_client, factories, mocker
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
"max_bitrate,expected", [(0, None), (192, 192000), (2000, 320000)]
|
"max_bitrate,format,default_transcoding_format,expected_bitrate,expected_format",
|
||||||
|
[
|
||||||
|
# no max bitrate, no format, so no transcoding should happen
|
||||||
|
(0, "", "ogg", None, None),
|
||||||
|
# same using "raw" format
|
||||||
|
(0, "raw", "ogg", None, None),
|
||||||
|
# specified bitrate, but no format, so fallback to default transcoding format
|
||||||
|
(192, "", "ogg", 192000, "ogg"),
|
||||||
|
# specified bitrate, but over limit
|
||||||
|
(2000, "", "ogg", 320000, "ogg"),
|
||||||
|
# specified format, we use that one
|
||||||
|
(192, "opus", "ogg", 192000, "opus"),
|
||||||
|
# No default transcoding format set and no format requested
|
||||||
|
(192, "", None, 192000, None),
|
||||||
|
],
|
||||||
)
|
)
|
||||||
def test_stream_bitrate(max_bitrate, expected, logged_in_api_client, factories, mocker):
|
def test_stream_transcode(
|
||||||
|
max_bitrate,
|
||||||
|
format,
|
||||||
|
default_transcoding_format,
|
||||||
|
expected_bitrate,
|
||||||
|
expected_format,
|
||||||
|
logged_in_api_client,
|
||||||
|
factories,
|
||||||
|
mocker,
|
||||||
|
settings,
|
||||||
|
):
|
||||||
|
settings.SUBSONIC_DEFAULT_TRANSCODING_FORMAT = default_transcoding_format
|
||||||
url = reverse("api:subsonic-stream")
|
url = reverse("api:subsonic-stream")
|
||||||
mocked_serve = mocker.patch.object(
|
mocked_serve = mocker.patch.object(
|
||||||
music_views, "handle_serve", return_value=Response()
|
music_views, "handle_serve", return_value=Response()
|
||||||
)
|
)
|
||||||
upload = factories["music.Upload"](playable=True)
|
upload = factories["music.Upload"](playable=True)
|
||||||
response = logged_in_api_client.get(
|
response = logged_in_api_client.get(
|
||||||
url, {"id": upload.track.pk, "maxBitRate": max_bitrate}
|
url, {"id": upload.track.pk, "maxBitRate": max_bitrate, "format": format}
|
||||||
)
|
)
|
||||||
|
|
||||||
mocked_serve.assert_called_once_with(
|
mocked_serve.assert_called_once_with(
|
||||||
upload=upload,
|
upload=upload,
|
||||||
user=logged_in_api_client.user,
|
user=logged_in_api_client.user,
|
||||||
format=None,
|
format=expected_format,
|
||||||
max_bitrate=expected,
|
max_bitrate=expected_bitrate,
|
||||||
proxy_media=True,
|
proxy_media=True,
|
||||||
)
|
)
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
Support for importing files with no album tag (#122)
|
|
|
@ -1 +0,0 @@
|
||||||
Added button to search for objects on Discogs (#368)
|
|
|
@ -1 +0,0 @@
|
||||||
Favorites radio will not be visible if the user does not have any favorites (#419)
|
|
|
@ -1 +0,0 @@
|
||||||
Aligned search headers with search results in the sidebar (#708)
|
|
|
@ -1 +0,0 @@
|
||||||
Clicking on the currently selected playlist in the Playlist popup will now close the popup (#807)
|
|
|
@ -1 +0,0 @@
|
||||||
Added copy-to-clipboard button with Subsonic password input (#814)
|
|
|
@ -1 +0,0 @@
|
||||||
The currently playing track is now highlighted with an orange play icon (#832)
|
|
|
@ -1 +0,0 @@
|
||||||
Fixed broken translation on home and track detail page (#833)
|
|
|
@ -1 +0,0 @@
|
||||||
Hide pod statistics on about page if those are disabled (#835)
|
|
|
@ -1 +0,0 @@
|
||||||
Fixed issue with player changing height when hovering over the volume slider (#838)
|
|
|
@ -1 +0,0 @@
|
||||||
Use ASCII filename before upload to S3 to avoid playback issues (#847)
|
|
|
@ -1 +0,0 @@
|
||||||
Fixed invalid file extension for transcoded tracks (#848)
|
|
|
@ -1 +0,0 @@
|
||||||
Fixed issue with French translation for "Start radio" (#849)
|
|
|
@ -1 +0,0 @@
|
||||||
Ensure empty but optional fields in file metadata don't error during import (#850)
|
|
|
@ -1 +0,0 @@
|
||||||
Fixed wrong og:image url when using S3 storage (#851)
|
|
|
@ -1 +0,0 @@
|
||||||
Fixed secondary menus truncated on narrow screens (#855)
|
|
|
@ -1 +0,0 @@
|
||||||
Fix broken upload for specific files when using S3 storage (#857)
|
|
|
@ -1 +0,0 @@
|
||||||
Redirect from / to /library when user is logged in (#864)
|
|
|
@ -1 +0,0 @@
|
||||||
Added opus to the list of supported mimetypes and extensions (#868)
|
|
|
@ -1 +0,0 @@
|
||||||
Fixed broken user admin for users with non-digit or letters in their username (#869)
|
|
|
@ -1,5 +1,6 @@
|
||||||
import argparse
|
import argparse
|
||||||
import requests
|
import requests
|
||||||
|
import os
|
||||||
|
|
||||||
GITLAB_URL = "https://dev.funkwhale.audio"
|
GITLAB_URL = "https://dev.funkwhale.audio"
|
||||||
GITLAB_PROJECT_ID = 17
|
GITLAB_PROJECT_ID = 17
|
||||||
|
@ -82,6 +83,14 @@ def get_translations_stats(translations):
|
||||||
return stats
|
return stats
|
||||||
|
|
||||||
|
|
||||||
|
def get_group_usernames(group):
|
||||||
|
url = GITLAB_URL + "/api/v4/groups/{}/members".format(group)
|
||||||
|
response = requests.get(url, headers={"PRIVATE-TOKEN": os.environ["PRIVATE_TOKEN"]})
|
||||||
|
response.raise_for_status()
|
||||||
|
data = response.json()
|
||||||
|
return [r["name"] for r in data]
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
parser = argparse.ArgumentParser()
|
parser = argparse.ArgumentParser()
|
||||||
parser.add_argument("ref_name")
|
parser.add_argument("ref_name")
|
||||||
|
@ -90,9 +99,15 @@ def main():
|
||||||
since = get_tag_date(args.last_tag)
|
since = get_tag_date(args.last_tag)
|
||||||
commits = get_commits(args.ref_name, since)
|
commits = get_commits(args.ref_name, since)
|
||||||
commits_stats = get_commit_stats(commits)
|
commits_stats = get_commit_stats(commits)
|
||||||
|
groups = [(588, "funkwhale/reviewers-python"), (589, "funkwhale/reviewers-front")]
|
||||||
|
reviewers = []
|
||||||
|
for id, _ in groups:
|
||||||
|
reviewers += get_group_usernames(id)
|
||||||
|
print("\nReviewers:\n")
|
||||||
|
for reviewer in reviewers:
|
||||||
|
print(reviewer)
|
||||||
commiter_names = commits_stats["commiters"].keys()
|
commiter_names = commits_stats["commiters"].keys()
|
||||||
print("Commiters:")
|
print("\nCommiters:\n")
|
||||||
for commiter in sorted(commits_stats["commiters"].keys(), key=lambda v: v.upper()):
|
for commiter in sorted(commits_stats["commiters"].keys(), key=lambda v: v.upper()):
|
||||||
print(commiter)
|
print(commiter)
|
||||||
translations = get_translations(since)
|
translations = get_translations(since)
|
||||||
|
@ -100,7 +115,7 @@ def main():
|
||||||
translators_ids = sorted(translations_stats["translators"].keys())
|
translators_ids = sorted(translations_stats["translators"].keys())
|
||||||
# There is no way to query user/author info via weblate API and we need the names…
|
# There is no way to query user/author info via weblate API and we need the names…
|
||||||
print(
|
print(
|
||||||
"Execute the following SQL query on the weblate server to get the translators names:"
|
"\nExecute the following SQL query on the weblate server to get the translators names:"
|
||||||
)
|
)
|
||||||
print("$ weblate dbshell")
|
print("$ weblate dbshell")
|
||||||
print(
|
print(
|
||||||
|
|
Loading…
Reference in New Issue