Migrate to GitLab

This commit is contained in:
Óscar García Amor 2022-07-08 12:03:47 +02:00
parent 695b2df63f
commit 4f2211dab8
No known key found for this signature in database
GPG Key ID: E18B2370D3D566EE
11 changed files with 264 additions and 231 deletions

View File

@ -1,154 +0,0 @@
version: 2.1
parameters:
memory-config:
type: string
default: "-Xmx3200m -Xms256m -XX:MaxMetaspaceSize=1g"
memory-config-debug:
type: string
default: "-Xmx3200m -Xms256m -XX:MaxMetaspaceSize=1g -verbose:gc -Xlog:gc*"
jobs:
build:
docker:
- image: cimg/android:2022.06.1
working_directory: ~/ultrasonic
environment:
JVM_OPTS: << pipeline.parameters.memory-config >>
JAVA_TOOL_OPTIONS: << pipeline.parameters.memory-config >>
GRADLE_OPTS: << pipeline.parameters.memory-config >>
steps:
- checkout
- restore_cache:
keys:
- v2-ultrasonic-{{ .Branch }}-{{ checksum "gradle/libs.versions.toml" }}
- v2-ultrasonic-{{ .Branch }}
- v2-ultrasonic
- run:
name: configure gradle.properties for CI building
command: |
sed -i '/^org.gradle.jvmargs/d' gradle.properties
sed -i 's/^org.gradle.daemon=true/org.gradle.daemon=false/g' gradle.properties
cat gradle.properties
- run:
name: checkstyle
command: ./gradlew -Pqc ktlintCheck
- run:
name: static analysis
command: ./gradlew -Pqc detekt
- run:
name: build debug
command: ./gradlew assembleDebug
- run:
name: unit-tests
command: |
./gradlew ciTest testDebugUnitTest
- run:
name: lint
command: ./gradlew :ultrasonic:lintRelease
- run:
name: build
command: ./gradlew buildRelease
- run:
name: assemble release
command: ./gradlew assembleRelease
- save_cache:
paths:
- ~/.gradle
key: v2-ultrasonic-{{ .Branch }}-{{ checksum "gradle/libs.versions.toml" }}
- store_artifacts:
path: ultrasonic/build/reports
destination: reports
- store_artifacts:
path: subsonic-api/build/reports
destination: reports
push_translations:
docker:
- image: cimg/python:3.6
working_directory: ~/ultrasonic
steps:
- checkout
- run:
name: install transifex client
command: |
python -m venv ~/venv
. ~/venv/bin/activate
pip install transifex-client
- run:
name: configure transifex client
command: echo $'[https://www.transifex.com]\nhostname = https://www.transifex.com\nusername = api\npassword = '"${TRANSIFEX_PASSWORD}"$'\n' > ~/.transifexrc
- run:
name: push changes in translation files
command: |
. ~/venv/bin/activate
tx push -s
generate_signed_apk:
docker:
- image: cimg/android:2022.06.1
working_directory: ~/ultrasonic
environment:
JVM_OPTS: << pipeline.parameters.memory-config >>
JAVA_TOOL_OPTIONS: << pipeline.parameters.memory-config >>
GRADLE_OPTS: << pipeline.parameters.memory-config >>
steps:
- checkout
- restore_cache:
keys:
- v2-ultrasonic-{{ .Branch }}-{{ checksum "gradle/libs.versions.toml" }}
- v2-ultrasonic-{{ .Branch }}
- v2-ultrasonic
- run:
name: decrypt ultrasonic-keystore
command: openssl aes-256-cbc -K ${ULTRASONIC_KEYSTORE_KEY} -iv ${ULTRASONIC_KEYSTORE_IV} -in ultrasonic-keystore.enc -out ultrasonic-keystore -d
- run:
name: build release apk
command: ./gradlew build assembleRelease
- run:
name: sign release apk
command: |
export PATH="${JAVA_HOME}/bin:${PATH}"
mkdir -p /tmp/ultrasonic-release
${ANDROID_HOME}/build-tools/32.0.0/zipalign -v 4 ultrasonic/build/outputs/apk/release/ultrasonic-release-unsigned.apk /tmp/ultrasonic-release/ultrasonic-${CIRCLE_TAG}.apk
${ANDROID_HOME}/build-tools/32.0.0/apksigner sign --verbose --ks ~/ultrasonic/ultrasonic-keystore --ks-pass pass:${ULTRASONIC_KEYSTORE_STOREPASS} --key-pass pass:${ULTRASONIC_KEYSTORE_KEYPASS} /tmp/ultrasonic-release/ultrasonic-${CIRCLE_TAG}.apk
${ANDROID_HOME}/build-tools/32.0.0/apksigner verify --verbose /tmp/ultrasonic-release/ultrasonic-${CIRCLE_TAG}.apk
- persist_to_workspace:
root: /tmp/ultrasonic-release
paths:
- ultrasonic-*.apk*
publish_github_signed_apk:
docker:
- image: cimg/go:1.18
steps:
- attach_workspace:
at: /tmp/ultrasonic-release
- run:
name: install ghr
command: go install -v github.com/tcnksm/ghr@latest
- run:
name: publish release on github tag
command: ghr -u ${CIRCLE_PROJECT_USERNAME} -r ${CIRCLE_PROJECT_REPONAME} ${CIRCLE_TAG} /tmp/ultrasonic-release
workflows:
version: 2
build_and_push_translations:
jobs:
- build
- push_translations:
requires:
- build
filters:
branches:
only:
- develop
- generate_signed_apk:
filters:
tags:
only: /^[0-9]+(\.[0-9]+)*(-beta\.[0-9]+)?/
branches:
ignore: /.*/
- publish_github_signed_apk:
requires:
- generate_signed_apk
filters:
tags:
only: /^[0-9]+(\.[0-9]+)*(-beta\.[0-9]+)?/
branches:
ignore: /.*/

View File

@ -1,15 +0,0 @@
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
version: 2
updates:
- package-ecosystem: "gradle" # See documentation for possible values
directory: "/" # Location of package manifests
schedule:
interval: "monthly"
ignore:
- dependency-name: "*"
update-types: ["version-update:semver-patch"]

116
.gitlab-ci.yml Normal file
View File

@ -0,0 +1,116 @@
default:
image: cimg/android:2022.06.1
cache:
key: ${CI_COMMIT_REF_SLUG}
paths:
- .gradle/
variables:
CACHE_FALLBACK_KEY: develop
MEMORY_CONFIG: "-Xmx3200m -Xms256m -XX:MaxMetaspaceSize=1g"
MEMORY_CONFIG_DEBUG: "-Xmx3200m -Xms256m -XX:MaxMetaspaceSize=1g -verbose:gc -Xlog:gc*"
JVM_OPTS: ${MEMORY_CONFIG}
JAVA_TOOL_OPTIONS: ${MEMORY_CONFIG}
GRADLE_OPTS: ${MEMORY_CONFIG}
PACKAGE_REGISTRY_URL: "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/ultrasonic/${CI_COMMIT_TAG}"
PACKAGE_APK: "ultrasonic-${CI_COMMIT_TAG}.apk"
PACKAGE_APK_IDSIG: "ultrasonic-${CI_COMMIT_TAG}.apk.idsig"
stages:
- Check
- Assemble
- Translations
- APK
- Publish
- Release
Check Style:
stage: Check
script: ./gradlew -Pqc ktlintCheck
Static Analysis:
stage: Check
script: ./gradlew -Pqc detekt
Lint:
stage: Check
script: ./gradlew :ultrasonic:lintRelease
Unit Tests:
stage: Check
script: ./gradlew ciTest testDebugUnitTest
Assemble Debug:
stage: Assemble
script: ./gradlew assembleDebug
Assemble Release:
stage: Assemble
script: ./gradlew assembleRelease
artifacts:
name: ultrasonic-release-unsigned-${CI_COMMIT_SHA}
paths:
- ultrasonic/build/outputs/apk/release/ultrasonic-release-unsigned.apk
Push Translations:
stage: Translations
image: cimg/python:3.6
script:
- python -m venv ~/venv
- . ~/venv/bin/activate
- pip install transifex-client
- echo $'[https://www.transifex.com]\nhostname = https://www.transifex.com\nusername = api\npassword = '"${TRANSIFEX_PASSWORD}"$'\n' > ~/.transifexrc
- tx push -s
rules:
- if: $CI_COMMIT_REF_NAME == "develop"
Generate Signed Develop APK:
stage: APK
script:
- openssl aes-256-cbc -K ${ULTRASONIC_KEYSTORE_KEY} -iv ${ULTRASONIC_KEYSTORE_IV} -in ultrasonic-keystore.enc -out ultrasonic-keystore -d
- mkdir -p ${CI_PROJECT_DIR}/ultrasonic-release
- ${ANDROID_HOME}/build-tools/*/zipalign -v 4 ultrasonic/build/outputs/apk/release/ultrasonic-release-unsigned.apk ${CI_PROJECT_DIR}/ultrasonic-release/ultrasonic-${CI_COMMIT_SHA}.apk
- ${ANDROID_HOME}/build-tools/*/apksigner sign --verbose --ks ${CI_PROJECT_DIR}/ultrasonic-keystore --ks-pass pass:${ULTRASONIC_KEYSTORE_STOREPASS} --key-pass pass:${ULTRASONIC_KEYSTORE_KEYPASS} ${CI_PROJECT_DIR}/ultrasonic-release/ultrasonic-${CI_COMMIT_SHA}.apk
- ${ANDROID_HOME}/build-tools/*/apksigner verify --verbose ${CI_PROJECT_DIR}/ultrasonic-release/ultrasonic-${CI_COMMIT_SHA}.apk
artifacts:
name: ultrasonic-${CI_COMMIT_SHA}
paths:
- ultrasonic-release/
rules:
- if: $CI_COMMIT_REF_NAME == "develop"
Generate Signed APK:
stage: APK
script:
- openssl aes-256-cbc -K ${ULTRASONIC_KEYSTORE_KEY} -iv ${ULTRASONIC_KEYSTORE_IV} -in ultrasonic-keystore.enc -out ultrasonic-keystore -d
- mkdir -p ${CI_PROJECT_DIR}/ultrasonic-release
- ${ANDROID_HOME}/build-tools/*/zipalign -v 4 ultrasonic/build/outputs/apk/release/ultrasonic-release-unsigned.apk ${CI_PROJECT_DIR}/ultrasonic-release/${PACKAGE_APK}
- ${ANDROID_HOME}/build-tools/*/apksigner sign --verbose --ks ${CI_PROJECT_DIR}/ultrasonic-keystore --ks-pass pass:${ULTRASONIC_KEYSTORE_STOREPASS} --key-pass pass:${ULTRASONIC_KEYSTORE_KEYPASS} ${CI_PROJECT_DIR}/ultrasonic-release/${PACKAGE_APK}
- ${ANDROID_HOME}/build-tools/*/apksigner verify --verbose ${CI_PROJECT_DIR}/ultrasonic-release/${PACKAGE_APK}
artifacts:
name: ultrasonic-${CI_COMMIT_TAG}
paths:
- ultrasonic-release/
rules:
- if: $CI_COMMIT_TAG
Publish Signed APK:
stage: Publish
image: curlimages/curl:latest
script:
- |
curl --header "JOB-TOKEN: ${CI_JOB_TOKEN}" --upload-file ultrasonic-release/${PACKAGE_APK} "${PACKAGE_REGISTRY_URL}/${PACKAGE_APK}"
- |
curl --header "JOB-TOKEN: ${CI_JOB_TOKEN}" --upload-file ultrasonic-release/${PACKAGE_APK_IDSIG} "${PACKAGE_REGISTRY_URL}/${PACKAGE_APK_IDSIG}"
rules:
- if: $CI_COMMIT_TAG
Release:
stage: Release
image: registry.gitlab.com/gitlab-org/release-cli:latest
script: |
release-cli create --name "Release ${CI_COMMIT_TAG}" --tag-name ${CI_COMMIT_TAG} \
--assets-link "{\"name\":\"${PACKAGE_APK}\",\"url\":\"${PACKAGE_REGISTRY_URL}/${PACKAGE_APK}\"}" \
--assets-link "{\"name\":\"${PACKAGE_APK_IDSIG}\",\"url\":\"${PACKAGE_REGISTRY_URL}/${PACKAGE_APK_IDSIG}\"}"
rules:
- if: $CI_COMMIT_TAG

View File

@ -0,0 +1,32 @@
## Motivation
Describe here what motivated you to make this enhancement request. What is
currently happening and what would you like to improve. If you have a stack
trace or any logs, please format them using Markdown triple backquote
notation.
### Proposal
Tell us in detail what you propose. How you want to achieve what you would
like to improve.
## System information
Include this section only if you consider that is relevant to this ticket,
otherwise you may remove it.
### Ultrasonic client
* **Ultrasonic version**: *version of the app*
* **Android version**: *Version of Android OS on the device*
* **Device info**: *Device manufacturer, model*
### Server
* **Server name**: *Airsonic, Ampache, Supysonic...*
* **Server version**: *version of server software*
* **Protocol used**: *http or https (self certificate, letsencrypt...)*
## Additional notes
Include any extra notes here. Otherwise you may remove this section.

View File

@ -0,0 +1,27 @@
## Proposal
Describe your proposed feature request here. Use this template only to
request a new feature that does not exist in Ultrasonic. If you are
requesting an enhancement to a current feature, please use the enhancement
template.
## System information
Include this section only if you consider that is relevant to this ticket,
otherwise you may remove it.
### Ultrasonic client
* **Ultrasonic version**: *version of the app*
* **Android version**: *Version of Android OS on the device*
* **Device info**: *Device manufacturer, model*
### Server
* **Server name**: *Airsonic, Ampache, Supysonic...*
* **Server version**: *version of server software*
* **Protocol used**: *http or https (self certificate, letsencrypt...)*
## Additional notes
Include any extra notes here. Otherwise you may remove this section.

View File

@ -1,9 +1,12 @@
# Contributing
Ultrasonic development is a community project, and contributions are welcomed.
Ultrasonic development is a community project, and contributions are
welcomed.
First, see if your issue havent been yet reported [here](https://github.com/ultrasonic/ultrasonic/issues),
then, please, first discuss the change you wish to make via [a new issue](https://github.com/ultrasonic/ultrasonic/issues/new).
First, see if your issue havent been yet reported
[here](https://gitlab.com/ultrasonic/ultrasonic/issues), then, please, first
discuss the change you wish to make via [a new
issue](https://gitlab.com/ultrasonic/ultrasonic/issues/new).
## Contributing Translations
@ -12,52 +15,62 @@ Interested in help to translate Ultrasonic? You can contribute in our
## Contributing Code
By default Pull Request should be opened against **develop** branch, PR against **master** branch should be used only
for critical bugfixes.
By default Pull Request should be opened against **develop** branch, PR
against **master** branch should be used only for critical bugfixes.
### Here are a few guidelines you should follow before submitting:
1. **License Acceptance:** All contributions must be licensed as [GNU GPLv3](LICENSE) to be accepted.
Use `git commit --signoff` to acknowledge this.
2. **No Breakage:** New features or changes to existing ones must not degrade the user experience.
3. **Coding standards:** best-practices should be followed, comment generously, and avoid "clever" algorithms.
Refactoring existing messes is great, but watch out for breakage.
4. **No large PR:** Try to limit the scope of PR only to the related issue, so it will be easier to review
and test.
1. **License Acceptance:** All contributions must be licensed as [GNU
GPLv3](LICENSE) to be accepted. Use `git commit --signoff` to acknowledge
this.
2. **No Breakage:** New features or changes to existing ones must not
degrade the user experience.
3. **Coding standards:** best-practices should be followed, comment
generously, and avoid "clever" algorithms. Refactoring existing messes is
great, but watch out for breakage.
4. **No large PR:** Try to limit the scope of PR only to the related issue,
so it will be easier to review and test.
### Pull Request Process
On each Pull Request Github runs a number of checks to make sure there are no problems.
On each Pull Request GitLab runs a number of checks to make sure there are
no problems.
#### Signed commits
Commits must be signed. [See here how to set it up](https://docs.github.com/en/authentication/managing-commit-signature-verification/signing-commits)
Commits must be signed. [See here how to set it
up](https://docs.gitlab.com/ee/user/project/repository/gpg_signed_commits/).
#### KtLint
This programm checks if the source code is formatted correctly.
You can run it yourself locally with
`./gradlew -Pqc ktlintFormat`
Running this command will fix common problems and will notify you of problems it couldn't fix automatically.
This programm checks if the source code is formatted correctly. You can run
it yourself locally with
```
./gradlew -Pqc ktlintFormat
```
Running this command will fix common problems and will notify you of
problems it couldn't fix automatically.
#### Detekt
Detekt is a static analyser. It helps to find potential bugs in our code.
You can run it yourself locally with
`./gradlew -Pqc detekt`
There is a "baseline" file, in which errors which have been in the code base before are noted.
Sometimes it is necessary to regenerate this file by running:
`./gradlew -Pqc detektBaseline`
You can run it yourself locally with
```
./gradlew -Pqc detekt
```
There is a "baseline" file, in which errors which have been in the code base
before are noted. Sometimes it is necessary to regenerate this file by
running:
```
./gradlew -Pqc detektBaseline
```
#### Lint
Lint looks for general problems in the code or unused resources etc.
You can run it with
`./gradlew -Pqc lintRelease`
If there is a need to regenerate the baseline, remove `ultrasonic/lint-baseline.xml` and rerun the command.
Lint looks for general problems in the code or unused resources etc. You can
run it with
```
./gradlew -Pqc lintRelease
```
If there is a need to regenerate the baseline, remove
`ultrasonic/lint-baseline.xml` and rerun the command.

View File

@ -1,15 +1,14 @@
# Ultrasonic
[![Build Status](https://circleci.com/gh/ultrasonic/ultrasonic/tree/develop.svg?style=shield&circle-token=:circle-token)](https://circleci.com/gh/ultrasonic)
[![Codecov branch](https://img.shields.io/codecov/c/github/ultrasonic/ultrasonic/develop.svg)]()
[![ktlint](https://img.shields.io/badge/code%20style-%E2%9D%A4-FF4081.svg)](https://ktlint.github.io/)
Ultrasonic is free and open-source music streaming Android client for [Subsonic](http://www.subsonic.org/) [API](http://www.subsonic.org/pages/api.jsp) (version 1.7.0 or higher) compatible servers.
Ultrasonic is free and open-source music streaming Android client for
[Subsonic][subsonic] [API][subapi] (version 1.7.0 or higher) compatible
servers.
## Help wanted
We currently don't have that much time to spend developing Subsonic, so any
contributions or active developers are always welcomed.
Have a look at [CONTRIBUTING.md](https://github.com/ultrasonic/ultrasonic/blob/develop/CONTRIBUTING.md) to get started.
Have a look at [CONTRIBUTING](CONTRIBUTING.md) to get started.
## Download
@ -17,24 +16,26 @@ App is available to download at following stores:
[<img src="https://play.google.com/intl/en_us/badges/images/generic/en-play-badge.png" alt="Get it on Google Play" height="70">](https://play.google.com/store/apps/details?id=org.moire.ultrasonic)
[<img src="https://f-droid.org/badge/get-it-on.png" alt="Get it on F-Droid" height="70">](https://f-droid.org/packages/org.moire.ultrasonic/)
[<img src="https://ultrasonic.github.io/assets/img/get-it-on-github.png" alt="Get it on GitHub" height="70">](https://github.com/ultrasonic/ultrasonic/releases)
[<img src="https://ultrasonic.gitlab.io/assets/img/get-it-on-gitlab.png" alt="Get it on GitLab" height="70">](https://gitlab.com/ultrasonic/ultrasonic/-/releases)
**Warning**: All three versions (Google Play, F-Droid and the APKs) are not
compatible (not signed by the same key)! You must uninstall one to install
the other, which will delete all your data.
the other, which will delete all your data.
If you want to use the version downloaded from F-Droid or from Github with **Android Auto**, you must enable Unknown Sources as it is described in [this wiki page](https://github.com/ultrasonic/ultrasonic/wiki/Using-Ultrasonic-with-Android-Auto).
If you want to use the version downloaded from F-Droid or from GitLab with
**Android Auto**, you must enable Unknown Sources as it is described in
[this wiki page][wikiaa].
## Bugs and issues
First, see if your issue havent been yet reported [here](https://github.com/ultrasonic/ultrasonic/issues),
otherwise open [a new issue](https://github.com/ultrasonic/ultrasonic/issues/new).
First, see if your issue havent been yet reported [here][issues], otherwise
open [a new issue][newissue].
### Known (not our) bugs
If you are using *Madsonic 5.1.X* several sections of Ultrasonic will not
work. This is caused by bad implementation of Subsonic API by Madsonic. For
more info about this you can read [this bug](https://github.com/ultrasonic/ultrasonic/issues/129).
more info about this you can read [this bug][madbug].
## Contributing
@ -42,16 +43,29 @@ See [CONTRIBUTING](CONTRIBUTING.md).
## Supported (tested) Subsonic API implementations
- [Subsonic](http://www.subsonic.org/pages/index.jsp)
- [Airsonic-Advanced](https://github.com/airsonic-advanced/airsonic-advanced)
- [Supysonic](https://github.com/spl0k/supysonic)
- [Ampache](https://ampache.org/)
- [Subsonic][subsonic]
- [Airsonic-Advanced][airsonic]
- [Supysonic][supysonic]
- [Ampache][ampache]
Other *Subsonic API* implementations should work as well as long as they follow API
[documentation](http://www.subsonic.org/pages/api.jsp).
Other *Subsonic API* implementations should work as well as long as they
follow API [documentation][subapi].
## License
This software is licensed under the terms of the GNU General Public License version 3 (GPLv3).
This software is licensed under the terms of the GNU General Public License
version 3 (GPLv3).
Full text of the license is available in the [LICENSE](LICENSE) file and [online](https://opensource.org/licenses/gpl-3.0.html).
Full text of the license is available in the [LICENSE](LICENSE) file and
[online][gpl3].
[wikiaa]: https://gitlab.com/ultrasonic/ultrasonic/-/wikis/Using-Ultrasonic-with-Android-Auto
[issues]: https://gitlab.com/ultrasonic/ultrasonic/-/issues
[newissue]: https://gitlab.com/ultrasonic/ultrasonic/-/issues/new
[madbug]: https://gitlab.com/ultrasonic/ultrasonic/-/issues/129
[subsonic]: http://www.subsonic.org/
[subapi]: http://www.subsonic.org/pages/api.jsp
[airsonic]: https://github.com/airsonic-advanced/airsonic-advanced
[supysonic]: https://github.com/spl0k/supysonic
[ampache]: https://ampache.org/
[gpl3]: https://opensource.org/licenses/gpl-3.0.html

View File

@ -13,6 +13,6 @@ Main features:
* Server chat
* And much more!!!
The source code is available with GPL license in Github: https://github.com/ultrasonic/ultrasonic
If you have any issue, please post in: https://github.com/ultrasonic/ultrasonic/issues
Play store icon designed by: http://www.flaticon.com/authors/sebastien-gabriel
The source code is available with GPL license in GitLab: https://gitlab.com/ultrasonic/ultrasonic
If you have any issue, please post in: https://gitlab.com/ultrasonic/ultrasonic/issues
Play store icon designed by: http://www.flaticon.com/authors/sebastien-gabriel

View File

@ -13,6 +13,6 @@ Características principales:
* Chat del servidor
* Y muchas mas!!!
El código esta disponible con licencia GPL en Github: https://github.com/ultrasonic/ultrasonic
Si tienes problemas puedes dejar tu petición en: https://github.com/ultrasonic/ultrasonic/issues
Icono diseñado por Sebastien Gabriel: http://www.flaticon.com/authors/sebastien-gabriel
El código esta disponible con licencia GPL en GitLab: https://gitlab.com/ultrasonic/ultrasonic
Si tienes problemas puedes dejar tu petición en: https://gitlab.com/ultrasonic/ultrasonic/issues
Icono diseñado por Sebastien Gabriel: http://www.flaticon.com/authors/sebastien-gabriel

View File

@ -401,8 +401,8 @@
<string name="about.webpage">Visit webpage</string>
<string name="about.report">Report a bug</string>
<string name="about.text"><b>Ultrasonic</b> is a free and open-source music streaming Android client for Subsonic API (version 1.7.0 or higher) compatible servers.\n\nWith <b>Ultrasonic</b> you can easily stream or download music from your home computer to your Android phone using your Subsonic compatible media server. The Subsonic server software requires additional configuration separate from Ultrasonic.\n\nBy default, Ultrasonic is not configured. Once you\'ve set up your own server, please change the server configuration so that it connects to your own computer.</string>
<string name="about.webpage.url" translatable="false">https://ultrasonic.github.io/</string>
<string name="about.report.url" translatable="false">https://github.com/ultrasonic/ultrasonic/issues</string>
<string name="about.webpage.url" translatable="false">https://ultrasonic.gitlab.io/</string>
<string name="about.report.url" translatable="false">https://gitlab.com/ultrasonic/ultrasonic/issues</string>
<plurals name="select_album_n_songs">
<item quantity="one">%d song</item>