Giter Site home page Giter Site logo

airsonic-advanced's Introduction

Airsonic-Advanced

Language grade: JavaScript Language grade: Java

What is Airsonic-Advanced?

Airsonic-Advanced is a more modern implementation of the Airsonic fork with several key performance and feature enhancements. It adds and supersedes several features in Airsonic.

What is Airsonic?

Airsonic is a free, web-based media streamer, providing ubiquitous access to your music. Use it to share your music with friends, or to listen to your own music while at work. You can stream to multiple players simultaneously, for instance to one player in your kitchen and another in your living room.

Airsonic is designed to handle very large music collections (hundreds of gigabytes). Although optimized for MP3 streaming, it works for any audio or video format that can stream over HTTP, for instance AAC and OGG. By using transcoder plug-ins, Airsonic supports on-the-fly conversion and streaming of virtually any audio format, including WMA, FLAC, APE, Musepack, WavPack and Shorten.

If you have constrained bandwidth, you may set an upper limit for the bitrate of the music streams. Airsonic will then automatically resample the music to a suitable bitrate.

In addition to being a streaming media server, Airsonic works very well as a local jukebox. The intuitive web interface, as well as search and index facilities, are optimized for efficient browsing through large media libraries. Airsonic also comes with an integrated Podcast receiver, with many of the same features as you find in iTunes.

Written in Java, Airsonic runs on most platforms, including Windows, Mac, Linux and Unix variants.

Screenshot

Feature Enhancements:

The following is an incomplete list of features that are enhanced from Airsonic:

  • More modern base frameworks and libraries
    • Spring Boot 2.x (instead of 1.x), Spring Framework 5.x (instead of 4.x). Plus all the additional dependency upgrades due to the base libaries being upgraded (including EhCache, upgraded SQL connectors etc.)
  • Security
    • A completely revamped credential system that actually stores credentials securely instead of openly. Includes encryption for credentials that need to be retrievable later (such as for third-party locations) and backwards compatibility. Also includes modern password hashing algorithms such as bcrypt, Argon for password storage.
  • Compliance: More compliant with web specs and utilizes frameworks to apply them instead of custom home-implemented solutions
    • RFC 7233 for Range headers
    • Send correct ETags and Last-Modified headers to aid in client-side caching
  • Performance enhancements
    • A more efficient and compliant streaming engine, utilizing piping and threading
    • Removal of pessimistic locking throughout the software in favor of more modern concurrency techniques
    • Upgraded internal database that uses connection pooling and uses MVCC control mode for dealing with concurrent updates
      • Massive throughput boost (100K media library scan times reduced from ~40 min to ~3 mins)
    • Much faster UI rendering for browsers, especially for massive playlists
    • Aggressively uses multi-threading and parallelization for most operations, including but not limited to:
      • Massively parallelized engine for media scanning (media scanning is done much much faster, ~8x)
      • Other various use cases utilizing async or parallel options via fork-join pools
    • Use of websockets to communicate with web-clients instead of polling
      • Much lighter on resource utilization as well as more dynamic
      • Does not have to keep running the same command client side again every 10 seconds to check statuses
      • Server pushes status updates when they're needed when something has changed
      • Web clients can update UIs immediately (live views)
      • Removal of DWR (10 year old technology used as an interface between the web-client and the server)
      • Provides status indicator whether client is connected to server
  • UI:
    • HTML5 compliant
      • Redesigned layout: Uses iframes instead of framesets and frames
    • Utilize a dedicated library (DataTables) to render tables
      • Deferred rendering and data manipulation outside the DOM allows much faster rendering (~10x-800x!)
        • The bigger the table, the more performance benefits it sees
        • Play queue that took about 800s to render in the browser, can now render in < 1s
      • Allow optional paging and accessible searching within tables
    • Customize generated cover art thumbnail quality
    • Ability to show and display more track fields in playlists, playqueue and file browse mode
    • Option to show header row for track fields
    • Sort tracks in browse mode (such as show most recently scanned files etc.)
    • Star and unstar from playqueue and media browser in bulk
    • Status charts/graphs are rendered on client-side using JS library, instead of on the server
  • Bugfixes:
    • Several race condition fixes
    • Consistency checks and refactors
    • Documentation fixes
  • Miscellaneous
    • Works with JDK17
    • Uses JSR 310 (Java time) instead of older Java packages for time/duration tracking
    • Uses Java's NIO for handling files instead of the older IO packages
    • More precise song duration calculation
    • Ability to pass properties via environment or system variables. You can but do not need to modify airsonic.properties to change preferences
    • Ability to use custom URLs to scrobble on ListenBrainz servers
    • Ability to use Repeat-One in play queues in web-clients
    • Sonos support: read documentation
    • Chromecast support: read details
    • Ability to upload to specified folders (via UploadsFolder property/parameter)
    • Ability to upload multiple files simultaneously
    • Ability to upload and extract more archive formats:
      • rar
      • 7z
      • tar
    • Ability to export Podcasts to OPML
    • Ability to import playlists with relative file paths (resolved relative to Playlists folder)
    • Support direct binary internet radio stream urls
    • Catalog multiple genres
    • Ability to specify custom log file location (via logging.file.name property/parameter)
    • Auto Bookmarks and Bookmark management
    • Ability to backup internal database, manually and on a schedule, including specifying how many backups to keep
    • Export and import data across installations and databases
  • Testing
    • Various fixes to make it compatible with multiple external DBs
    • Automated tests are performed against external DBs
      • Postgres
      • MySQL
      • MariaDB
    • Uses failsafe for integration testing instead of cucumber
  • Build and deployment
    • An updated Docker image with JRE 14 base layer.
      • Add support for XMP to support playing MOD files out of the box
    • Multiplatform builds, including for ARM v7 and ARM64
    • A more advanced build pipeline including automatic releases and deploys at merge
      • Allows people to grab the newest build without compiling from source as soon as features/enhancements are merged, instead of waiting for the next stable build (which may be months away)
    • Available on GHCR as well as Docker Hub
  • Stepbacks
    • The Java Jukebox has been removed, due to the third-party library not being kept up to date with modern JVMs. See PR #636.

The complete list of PRs that were used to enhance Airsonic can be seen on the PRs page. At some point an automatic changelog generator will be added to keep track.

Airsonic-Advanced will occasionally backport features introduced in the base Airsonic fork, but is generally much more modern and bleeding edge than Airsonic.

Usage

Airsonic-Advanced v10.6.x series (and its snapshots) are intercompatible with vanilla Airsonic 10.6.x series. This may not necessarily be the case with 11.x versions.

Also note that Airsonic-Advanced 11.x (and its snapshots) are breaking (non-backwards-compatible) version changes. You will not be able to revert back to 10.6.x after upgrading (the system does create a backup of the DB in case such revert is necessary, but it must be manually restored).

Airsonic-Advanced snapshots are generally pretty stable and recommended for use over the stable releases (which may be extremely outdated).

Stand-alone binaries

Airsonic-Advanced can be downloaded from GitHub.

The release signature may be verified using the public key.

You need a minimum Java Runtime Environment (JRE) of 1.8 for 10.6.x series, and 11 for 11.x onwards (including snapshots).

  • For 10.6.x releases -> Java 8
  • For 11.x releases and onwards -> Java 11

Airsonic-Advanced is run similarly to (and in lieu of) vanilla Airsonic.

Read the compatibility notes.

Docker

Docker releases are at DockerHub and GHCR. Docker releases are recently multiplatform, which means ARMv7 and ARM64 are also released to Dockerhub. However, automated testing for those archs is not currently done in the CI/CD pipeline (only Linux platform is tested).

Please note that for Docker images, the volume mounting points have changed and are different from Airsonic. Airsonic mount points are at /airsonic/* inside the container. Airsonic-Advanced tries to use the same volume locations as the default war image at /var/* in order to remain consistent if people want to switch between the containers and non-containers.

  • Music:/airsonic/music -> Music:/var/music
  • Podcasts:/airsonic/podcast -> Podcasts:/var/podcast
  • Playlists:/airsonic/playlists -> Playlists:/var/playlists
  • /airsonic/data -> /var/airsonic

Also note that the Docker image will by default run as user root (0), group root (0), and so any files created in the external volume will be owned as such. You may change the user running the internal process in one of two ways:

  • Specifying --user when invoking the docker run command, and providing it with one or both in the format uid:gid
  • Specifying the PUID or PGID environment variables to the container image when invoking the docker run command (-e PUID=uid -e PGID=gid)

Vanilla Airsonic can be downloaded from GitHub.

Please use the Airsonic documentation for instructions on running Airsonic. For the most part (currently) Airsonic-Advanced shares similar running instructions unless stated otherwise. Notable exceptions are available as comments or resolutions in the Issues page (please search).

Building/Compiling

You may compile the code yourself by using maven. One of the repositories does not have https, so you may need to allow that for maven. A custom settings.xml has been put in .mvn folder for this purpose. A sample invocation would be (in the root):

mvn clean compile package verify

The main binary would be in airsonic-main/target

Compatibility Notes:

The following properties are new in Airsonic-Advanced:

  • MediaScannerParallelism: (default: number of available processors + 1) The parallelism to use when scanning media
  • ClearFullScanSettingAfterScan: (default: false) Whether to clear FullScan setting after the next SUCCESSFUL scan (useful for doing full scan once and then reverting to default scan)

The following property names are different between Airsonic and Airsonic-Advanced:

  • UPNP_PORT -> UPnpPort
  • server.context-path -> server.servlet.context-path (Airsonic will use the latter from 11.0 onwards)
  • IgnoreFileTimestamps -> FullScan

Note that Airsonic-Advanced communicates with its Web UI via websockets. If you're behind a proxy, you need to enable websockets and allow UPGRADE http requests through the proxy. A sample configuration is posted here: nginx sample.

Additionally, if placed behind a proxy, the Airsonic server needs to forward headers, for which the following property is necessary (either in /path/to/airsonic-data/airsonic.properties or as a jvm argument):

  • After and including Edge Release 11.0.0-SNAPSHOT.20210117214044: server.forward-headers-strategy=native
  • Prior to Edge Release 11.0.0-SNAPSHOT.20210117214044: server.use-forward-headers=true

11.x series

Certain property names have been changed from 10.6 to recent snapshots of 11.0 and will be automigrated. When modifying properties, use the modern name.

  • DatabaseConfigEmbedDriver -> spring.datasource.driver-class-name
  • DatabaseConfigEmbedUrl -> spring.datasource.url
  • DatabaseConfigEmbedUsername -> spring.datasource.username
  • DatabaseConfigEmbedPassword -> spring.datasource.password
  • DatabaseConfigJNDIName -> spring.datasource.jndi-name
  • DatabaseMysqlMaxlength -> spring.liquibase.parameters.mysqlVarcharLimit
  • DatabaseUsertableQuote -> spring.liquibase.parameters.userTableQuote

The following property names have been changed from 10.6 to recent snapshots of 11.0 and will NOT be automigrated. Make sure you switch the property names if you use them.

Other properties are obsolete and have been removed:

  • DatabaseConfigType
  • DatabaseUsertableQuote (now self-managed)

First migration to 11.x will create a backup DB next to the DB folder. It will be marked as db.backup.<timestamp>. Use this folder as the DB if a revert to an older major version is needed (11.0 -> 10.6.0).

History

The original Subsonic is developed by Sindre Mehus. Subsonic was open source through version 6.0-beta1, and closed-source from then onwards.

Libresonic was created and maintained by Eugene E. Kashpureff Jr. It originated as an unofficial ("Kang") of Subsonic which did not contain the Licensing code checks present in the official builds. With the announcement of Subsonic's closed-source future, a decision was made to make a full fork and rebrand to Libresonic.

Around July 2017, it was discovered that Eugene had different intentions/goals for the project than some contributors had. Although the developers were hesitant to create a fork as it would fracture/confuse the community even further, it was deemed necessary in order to preserve a community-focused fork. To reiterate this more clearly:

Airsonic's goal is to provide a full-featured, stable, self-hosted media server based on the Subsonic codebase that is free, open source, and community driven.

Around November 2019, Airsonic-Advanced was forked off the base Airsonic fork due to differences in pace and review of development. Several key features of the framework were outdated, and attempts to upgrade them occasionally took upto a year. Airsonic-Advanced tries a modern implementation and bleeding edge approach to development, and is thus usually ahead of the base fork in dependencies and features.

Pull Requests are always welcome. All Pull Requests are reviewed before being merged to ensure we continue to meet our goals.

License

Airsonic-Advanced and Airsonic are free software and licensed under the GNU General Public License version 3. The code in this repository (and associated binaries) are free of any "license key" or other restrictions. If you wish to thank the maintainer of this repository, please consider a donation to the Electronic Frontier Foundation.

The Subsonic source code was released under the GPLv3 through version 6.0-beta1. Beginning with 6.0-beta2, source is no longer provided. Binaries of Subsonic are only available under a commercial license. There is a Subsonic Premium service which adds functionality not available in Airsonic. Subsonic also offers RPM, Deb, Exe, and other pre-built packages that Airsonic currently does not.

The cover zooming feature is provided by jquery.fancyzoom, released under MIT License.

The icons are from the amazing feather project, and are licensed under MIT license.

Community

Bugs/feature requests/discussions pertaining to Airsonic-Advanced may be raised as issues within GitHub on the Airsonic-Advanced project page.

Vanilla Airsonic itself has several places outside of GitHub for community discussion, questions, etc:

Note that the Matrix room and IRC channel are bridged together.

airsonic-advanced's People

Contributors

akpdw avatar bajansen avatar csobsidian avatar ctedgar avatar davis-a avatar dependabot[bot] avatar eharris avatar eugenekay avatar eusmilis avatar faeb35 avatar fxthomas avatar harawata avatar heyarne avatar ibmibmibm avatar jooola avatar jvoisin avatar kagemomiji avatar muff1nman avatar noitemname avatar nvllsvm avatar plastikman avatar prschopf avatar randomnicode avatar sindremehus avatar tari avatar tesshucom avatar the-exterminator avatar weblate avatar yetangitu avatar zifnab06 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

airsonic-advanced's Issues

Opening album of last played song instead of home site

Problem description

When I recently played some songs and opening Airsonic Advanced and then just entering the URL of Airsonic (aka refresh), Airsonic opens the album of the last played song.
I would expect to get the home site instead.
Not sure if this is a issue or a feature though ;-)

Steps to reproduce

  1. Play any song
  2. Press F5 or open a new tab and browse to Airsonic
  3. Your getting the album of the last played song instead of the home page

System information

  • Airsonic version: Edge Release 10.6.0-SNAPSHOT.20200414043004
  • Operating system: Windows Server 2012
  • Java version: Java(TM) SE Runtime Environment (build 1.8.0_241-b07)
  • Proxy server: IIS
  • Client: Tested in Firefox
  • Language: English

Add to playlist showing twice

Problem description

If you are browsing a playlist or an album in the background. When I then mark a track in the playing queue and select "Add to playlist" in the player queue. Im getting the "Add to playlist" popup twice. Once in the player queue and one time in the background where I have the playlist or the album.

Steps to reproduce

  1. Open album to see the song list
  2. Play some songs in the queue
  3. Select song in the queue
  4. Mark one song
  5. Select "Add to playlist" from the dropdown in the queue
  6. You'll see the "Add to playlist" popup twice.

System information

  • Airsonic version: Edge Release 10.6.0-SNAPSHOT.20200414043004
  • Operating system: Windows Server 2012
  • Java version: Java(TM) SE Runtime Environment (build 1.8.0_241-b07)
  • Proxy server: IIS
  • Client: Tested in Firefox
  • Language: English

Player is broken

Problem description

Just installed this to replace the original Airsonic. After uploading, scanning everything and restoring the original settings, I can't play anything, nothing gets added to the queue and the Settings tab "Players" always gives me a 404 Bad Gateway (and logs me out).

Am running it with a docker compose file almost equal to the one I had with the original Airsonic, routing trafic to Traefik 2.0.

Steps to reproduce

Really just try to play anything, add something to the queue, and go to the "Players" tab

System information

  • Airsonic version: 11.0.0-SNAPSHOT.20200429045733 – April 29, 2020 at 4:57:33 AM GMT
  • Operating system: Ubuntu Server 18.04
  • Java version: java 11.0.7
  • Proxy server: It's in a network proxy for Traefik 2.0
  • Client: Latest Firefox
  • Language: English

Additional Information

This is what the log shows after trying to play a track:

2020-04-29 14:00:54.491  INFO --- o.a.p.s.CacheConfiguration$CacheLogger   : Cache Key: /var/music/Albums/Alaska & Nucleus/1998 - Project Two _ Persistence of Vision | EventType: CREATED | Old value: null | New value: 1998 - Project Two _ Persistence of Vision
2020-04-29 14:03:23.131  INFO --- o.a.p.service.PodcastService             : Starting scheduled Podcast refresh.
2020-04-29 14:03:23.133  INFO --- o.a.p.service.PodcastService             : Completed scheduled Podcast refresh.
Inconsistency detected by ld.so: dl-lookup.c: 112: check_match: Assertion `version->filename == NULL || ! _dl_name_match_p (version->filename, map)' failed!
LOGBACK: No context given for c.q.l.core.rolling.SizeAndTimeBasedRollingPolicy@1636050357

Fail on startup

Hello
Ive tried installing you latest war and have problem on startup
2020-02-24 20:47:34.186 INFO --- l.executor.jvm.JdbcExecutor : SELECT * FROM public.databasechangelog ORDER BY DATEEXECUTED ASC, ORDEREXECUTED ASC 2020-02-24 20:47:34.376 INFO --- l.executor.jvm.JdbcExecutor : CREATE TABLE public.user_credentials (username VARCHAR NOT NULL, app_username VA RCHAR NOT NULL, credential VARCHAR NOT NULL, encoder VARCHAR NOT NULL, app VARCHAR NOT NULL, created TIMESTAMP WITHOUT TIME ZONE DEFAULT NOW() NOT NULL, upda ted TIMESTAMP WITHOUT TIME ZONE DEFAULT NOW() NOT NULL, expiration TIMESTAMP WITHOUT TIME ZONE, comment VARCHAR, CONSTRAINT uc_u_fk FOREIGN KEY (username) RE FERENCES public."user"(username) ON DELETE CASCADE) 2020-02-24 20:47:34.383 INFO --- liquibase.changelog.ChangeSet : Table user_credentials created 2020-02-24 20:47:34.400 INFO --- l.executor.jvm.JdbcExecutor : insert into user_credentials (username, app_username, credential, encoder, app, comment) select u.username, u.username, case when u.password like 'enc:%' then substr(u.password, 5, length(u.password) - 4) else u.password end, case when u.password like 'enc:%' then 'legacyhex' else 'legacynoop' end, 'AIRSONIC', 'Initial legacy migration' from user u 2020-02-24 20:47:34.417 ERROR --- liquibase.changelog.ChangeSet : Change Set classpath:liquibase/10.6/user-credentials.xml::add-user-credentials:: anon failed. Error: ERREUR: la colonne u.username n'existe pas Position : 110 [Failed SQL: (0) insert into user_credentials (username, app_username, credential, encoder, app, comment) select u.username, u.username, case when u.password like 'enc:%' then substr(u.password, 5, length(u.password) - 4) else u.password end, case when u.password like 'enc:%' then 'legacyhex' else 'legacynoop' end, 'AIRSONIC', 'Initial legacy migration' from user u] 2020-02-24 20:47:34.432 INFO --- l.l.StandardLockService : Successfully released change log lock 2020-02-24 20:47:34.434 WARN --- ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt : org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'themeSource': Unsatisfied dependency expressed through met hod 'setSettingsService' parameter 0; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'se ttingsService': Unsatisfied dependency expressed through field 'internetRadioDao'; nested exception is org.springframework.beans.factory.UnsatisfiedDependenc yException: Error creating bean with name 'internetRadioDao': Unsatisfied dependency expressed through field 'daoHelper'; nested exception is org.springframe work.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'daoHelper': Unsatisfied dependency expressed through field 'jdbcTemplate'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'liquibase' defined in class path resource [org/ai rsonic/player/spring/DatabaseConfiguration.class]: Invocation of init method failed; nested exception is liquibase.exception.MigrationFailedException: Migrat ion failed for change set classpath:liquibase/10.6/user-credentials.xml::add-user-credentials::anon: Reason: liquibase.exception.DatabaseException: ERREUR: la colonne u.username n'existe pas Position : 110 [Failed SQL: (0) insert into user_credentials (username, app_username, credential, encoder, app, comment) select u.username, u.username, case when u.password like 'enc:%' then substr(u.password, 5, length(u.password) - 4) else u.password end, case when u.password like 'enc:%' then 'legacyhex' else 'legacynoop' end, 'AIRSONIC', 'Initial legacy migration' from user u]
Standalone install

System debian 9
Java : OPEN JDK 11
postgres PostgreSQL 9.6.15

Perhaps Bug ??

Problem description

Only seen this in airsonic.log
`2020-03-09 19:34:00.189 ERROR --- o.s.w.s.s.s.DefaultHandshakeHandler : Handshake failed due to invalid Upgrade header: null
2020-03-09 19:34:06.026 ERROR --- o.a.p.s.LoggingExceptionResolver : 127.0.0.1: An exception occurred while loading http://music.cloud-dorel.ml/websocket/718/mcvcgorq/xhr_streaming?t=

org.springframework.http.converter.HttpMessageNotWritableException: No converter for [class java.util.LinkedHashMap] with preset Content-Type 'application/javascript;charset=UTF-8'
at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:309) ~[spring-webmvc-5.2.4.RELEASE.jar!/:5.2.4.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.HttpEntityMethodProcessor.handleReturnValue(HttpEntityMethodProcessor.java:226) ~[spring-webmvc-5.2.4.RELEASE.jar!/:5.2.4.RELEASE]
at org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite.handleReturnValue(HandlerMethodReturnValueHandlerComposite.java:82) ~[spring-web-5.2.4.RELEASE.jar!/:5.2.4.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:124) ~[spring-webmvc-5.2.4.RELEASE.jar!/:5.2.4.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:879) ~[spring-webmvc-5.2.4.RELEASE.jar!/:5.2.4.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:793) ~[spring-webmvc-5.2.4.RELEASE.jar!/:5.2.4.RELEASE]
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-5.2.4.RELEASE.jar!/:5.2.4.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040) ~[spring-webmvc-5.2.4.RELEASE.jar!/:5.2.4.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943) ~[spring-webmvc-5.2.4.RELEASE.jar!/:5.2.4.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.2.4.RELEASE.jar!/:5.2.4.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909) ~[spring-webmvc-5.2.4.RELEASE.jar!/:5.2.4.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:523) ~[jakarta.servlet-api-4.0.3.jar!/:4.0.3]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) ~[spring-webmvc-5.2.4.RELEASE.jar!/:5.2.4.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:590) ~[jakarta.servlet-api-4.0.3.jar!/:4.0.3]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) ~[tomcat-embed-core-9.0.31.jar!/:9.0.31]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.31.jar!/:9.0.31]
at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:712) ~[tomcat-embed-core-9.0.31.jar!/:9.0.31]
at org.apache.catalina.core.ApplicationDispatcher.doInclude(ApplicationDispatcher.java:580) ~[tomcat-embed-core-9.0.31.jar!/:9.0.31]
at org.apache.catalina.core.ApplicationDispatcher.include(ApplicationDispatcher.java:516) ~[tomcat-embed-core-9.0.31.jar!/:9.0.31]
at org.apache.catalina.core.StandardHostValve.custom(StandardHostValve.java:388) ~[tomcat-embed-core-9.0.31.jar!/:9.0.31]
at org.apache.catalina.core.StandardHostValve.status(StandardHostValve.java:253) ~[tomcat-embed-core-9.0.31.jar!/:9.0.31]
at org.apache.catalina.core.StandardHostValve.throwable(StandardHostValve.java:348) ~[tomcat-embed-core-9.0.31.jar!/:9.0.31]
at org.apache.catalina.core.AsyncContextImpl.setErrorState(AsyncContextImpl.java:449) ~[tomcat-embed-core-9.0.31.jar!/:9.0.31]
at org.apache.catalina.connector.CoyoteAdapter.asyncDispatch(CoyoteAdapter.java:176) ~[tomcat-embed-core-9.0.31.jar!/:9.0.31]
at org.apache.coyote.AbstractProcessor.dispatch(AbstractProcessor.java:237) ~[tomcat-embed-core-9.0.31.jar!/:9.0.31]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:59) ~[tomcat-embed-core-9.0.31.jar!/:9.0.31]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868) ~[tomcat-embed-core-9.0.31.jar!/:9.0.31]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1639) ~[tomcat-embed-core-9.0.31.jar!/:9.0.31]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) ~[tomcat-embed-core-9.0.31.jar!/:9.0.31]
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) ~[na:na]
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) ~[na:na]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-embed-core-9.0.31.jar!/:9.0.31]
at java.base/java.lang.Thread.run(Thread.java:834) ~[na:na]
`

Steps to reproduce

Don't know

System information

Airsonic version: 10.6.0-SNAPSHOT.20200302045745**

Operating system: *Debian 10.

Java version: java 11.0.5.

Proxy server: *NGINX

Client: Chrome.

Language: French

Database migration issues from old Airsonic

Problem description

I used to run Airsonic, but I want to try out Airsonic-advanced. I've always run Airsonic inside a Docker container, with the built in database. With Airsonic-advanced I've moved to MariaDB. After starting the DB and Airsonic-advanced container it starts to migrate the old database to MariaDB, this take a few minutes and then it's done. After it's done migrating, only the default admin user exists and none of the old users. The music data seems to be there, but the album thumbnail view in the middle is empty and if you try to click anything in the left side bar you get the following error:

Error 	Internal Server Error
Message 	PreparedStatementCallback; SQL [insert into media_file (path, folder, type, format, title, album, artist, album_artist, disc_number, track_number, year, genre, bit_rate, variable_bit_rate, duration, file_size, width, height, cover_art_path, parent_path, play_count, last_played, comment, created, changed, last_scanned, children_last_updated, present, version, mb_release_id, mb_recording_id) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)]; (conn=9) Duplicate entry '/var/music/somefolder/2017-05 - PURGE EP' for key 'idx_media_file_path'; nested exception is java.sql.SQLIntegrityConstraintViolationException: (conn=9) Duplicate entry '/var/music/somefolder/2017-05 - PURGE EP' for key 'idx_media_file_path'
Path 	/main.view
Time 	Sun Mar 08 16:51:58 GMT 2020
Exception 	
Java version 	AdoptOpenJDK 11.0.6
Operating system 	Linux 4.4.59+
Server 	Apache Tomcat/9.0.31
Memory 	Used 191 of 250 MB
Stack trace 	
                

                        org.springframework.dao.DuplicateKeyException: PreparedStatementCallback; SQL [insert into media_file (path, folder, type, format, title, album, artist, album_artist, disc_number, track_number, year, genre, bit_rate, variable_bit_rate, duration, file_size, width, height, cover_art_path, parent_path, play_count, last_played, comment, created, changed, last_scanned, children_last_updated, present, version, mb_release_id, mb_recording_id) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)]; (conn=9) Duplicate entry '/var/music/somefolder/2017-05 - PURGE EP' for key 'idx_media_file_path'; nested exception is java.sql.SQLIntegrityConstraintViolationException: (conn=9) Duplicate entry '/var/music/somefolder/2017-05 - PURGE EP' for key 'idx_media_file_path'
	at org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator.doTranslate(SQLErrorCodeSQLExceptionTranslator.java:243)
	at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:72)
	at org.springframework.jdbc.core.JdbcTemplate.translateException(JdbcTemplate.java:1443)
	at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:633)
	at org.springframework.jdbc.core.JdbcTemplate.update(JdbcTemplate.java:862)
	at org.springframework.jdbc.core.JdbcTemplate.update(JdbcTemplate.java:917)
	at org.springframework.jdbc.core.JdbcTemplate.update(JdbcTemplate.java:927)
	at org.airsonic.player.dao.AbstractDao.update(AbstractDao.java:90)
	at org.airsonic.player.dao.MediaFileDao.createOrUpdateMediaFile_aroundBody0(MediaFileDao.java:193)
	at org.airsonic.player.dao.MediaFileDao$AjcClosure1.run(MediaFileDao.java:1)
	at org.springframework.transaction.aspectj.AbstractTransactionAspect.ajc$around$org_springframework_transaction_aspectj_AbstractTransactionAspect$1$2a73e96cproceed(AbstractTransactionAspect.aj:66)
	at org.springframework.transaction.aspectj.AbstractTransactionAspect$AbstractTransactionAspect$1.proceedWithInvocation(AbstractTransactionAspect.aj:72)
	at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:366)
	at org.springframework.transaction.aspectj.AbstractTransactionAspect.ajc$around$org_springframework_transaction_aspectj_AbstractTransactionAspect$1$2a73e96c(AbstractTransactionAspect.aj:70)
	at org.airsonic.player.dao.MediaFileDao.createOrUpdateMediaFile(MediaFileDao.java:139)
	at org.airsonic.player.dao.MediaFileDao$$FastClassBySpringCGLIB$$15ad9359.invoke(<generated>)
	at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:769)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:747)
	at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:139)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:747)
	at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:366)
	at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:99)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:747)
	at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:689)
	at org.airsonic.player.dao.MediaFileDao$$EnhancerBySpringCGLIB$$fcdf95f7.createOrUpdateMediaFile(<generated>)
	at org.airsonic.player.service.MediaFileService.lambda$9(MediaFileService.java:383)
	at java.base/java.util.stream.ReferencePipeline$3$1.accept(Unknown Source)
	at java.base/java.util.stream.ReferencePipeline$2$1.accept(Unknown Source)
	at java.base/java.util.Spliterators$ArraySpliterator.forEachRemaining(Unknown Source)
	at java.base/java.util.stream.AbstractPipeline.copyInto(Unknown Source)
	at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(Unknown Source)
	at java.base/java.util.stream.ReduceOps$ReduceTask.doLeaf(Unknown Source)
	at java.base/java.util.stream.ReduceOps$ReduceTask.doLeaf(Unknown Source)
	at java.base/java.util.stream.AbstractTask.compute(Unknown Source)
	at java.base/java.util.concurrent.CountedCompleter.exec(Unknown Source)
	at java.base/java.util.concurrent.ForkJoinTask.doExec(Unknown Source)
	at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.helpCC(Unknown Source)
	at java.base/java.util.concurrent.ForkJoinPool.externalHelpComplete(Unknown Source)
	at java.base/java.util.concurrent.ForkJoinTask.tryExternalHelp(Unknown Source)
	at java.base/java.util.concurrent.ForkJoinTask.externalAwaitDone(Unknown Source)
	at java.base/java.util.concurrent.ForkJoinTask.doInvoke(Unknown Source)
	at java.base/java.util.concurrent.ForkJoinTask.invoke(Unknown Source)
	at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateParallel(Unknown Source)
	at java.base/java.util.stream.AbstractPipeline.evaluate(Unknown Source)
	at java.base/java.util.stream.ReferencePipeline.collect(Unknown Source)
	at org.airsonic.player.service.MediaFileService.updateChildren(MediaFileService.java:390)
	at org.airsonic.player.service.MediaFileService.getChildrenOf(MediaFileService.java:195)
	at org.airsonic.player.service.MediaFileService.getChildrenOf(MediaFileService.java:174)
	at org.airsonic.player.controller.MainController.handleRequestInternal(MainController.java:91)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
	at java.base/java.lang.reflect.Method.invoke(Unknown Source)
	at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190)
	at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138)
	at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:106)
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:879)
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:793)
	at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040)
	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943)
	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
	at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:503)
	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:590)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.airsonic.player.security.JWTRequestParameterProcessingFilter.doFilter(JWTRequestParameterProcessingFilter.java:62)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.airsonic.player.filter.MetricsFilter.doFilter(MetricsFilter.java:30)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.airsonic.player.filter.RequestEncodingFilter.doFilter(RequestEncodingFilter.java:45)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.airsonic.player.filter.ParameterDecodingFilter.doFilter(ParameterDecodingFilter.java:57)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.airsonic.player.filter.BootstrapVerificationFilter.doFilter(BootstrapVerificationFilter.java:56)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:320)
	at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:126)
	at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:90)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
	at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:118)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
	at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:137)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
	at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:111)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
	at org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter.doFilter(RememberMeAuthenticationFilter.java:158)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
	at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:158)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
	at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
	at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:200)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
	at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:200)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
	at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:116)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
	at org.springframework.security.web.csrf.CsrfFilter.doFilterInternal(CsrfFilter.java:117)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
	at org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:92)
	at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:77)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
	at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
	at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
	at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:215)
	at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:178)
	at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:358)
	at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:271)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:94)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
	at org.apache.catalina.valves.RemoteIpValve.invoke(RemoteIpValve.java:747)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
	at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:367)
	at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868)
	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1639)
	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
	at java.base/java.lang.Thread.run(Unknown Source)
Caused by: java.sql.SQLIntegrityConstraintViolationException: (conn=9) Duplicate entry '/var/music/somefolder/2017-05 - PURGE EP' for key 'idx_media_file_path'
	at org.mariadb.jdbc.internal.util.exceptions.ExceptionMapper.get(ExceptionMapper.java:235)
	at org.mariadb.jdbc.internal.util.exceptions.ExceptionMapper.getException(ExceptionMapper.java:171)
	at org.mariadb.jdbc.MariaDbStatement.executeExceptionEpilogue(MariaDbStatement.java:248)
	at org.mariadb.jdbc.ClientSidePreparedStatement.executeInternal(ClientSidePreparedStatement.java:230)
	at org.mariadb.jdbc.ClientSidePreparedStatement.execute(ClientSidePreparedStatement.java:157)
	at org.mariadb.jdbc.ClientSidePreparedStatement.executeUpdate(ClientSidePreparedStatement.java:192)
	at com.zaxxer.hikari.pool.ProxyPreparedStatement.executeUpdate(ProxyPreparedStatement.java:61)
	at com.zaxxer.hikari.pool.HikariProxyPreparedStatement.executeUpdate(HikariProxyPreparedStatement.java)
	at org.springframework.jdbc.core.JdbcTemplate.lambda$update$0(JdbcTemplate.java:867)
	at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:617)
	... 159 more
Caused by: java.sql.SQLException: Duplicate entry '/var/music/somefolder/2017-05 - PURGE EP' for key 'idx_media_file_path'
	at org.mariadb.jdbc.internal.protocol.AbstractQueryProtocol.readErrorPacket(AbstractQueryProtocol.java:1594)
	at org.mariadb.jdbc.internal.protocol.AbstractQueryProtocol.readPacket(AbstractQueryProtocol.java:1453)
	at org.mariadb.jdbc.internal.protocol.AbstractQueryProtocol.getResult(AbstractQueryProtocol.java:1415)
	at org.mariadb.jdbc.internal.protocol.AbstractQueryProtocol.executeQuery(AbstractQueryProtocol.java:289)
	at org.mariadb.jdbc.ClientSidePreparedStatement.executeInternal(ClientSidePreparedStatement.java:221)
	... 165 more

Steps to reproduce

  1. Stop old Airsonic server
  2. Copy over old Airsonic directory to new place
  3. Create new DB container
  4. Start Airsonic-Advanced with the old data
  5. Wait for database migration to finish
  6. Login with default credentials

System information

  • Airsonic version: the version listed on the About page
    Airsonic-advanced docker, latest version as of writing (10.6.0-SNAPSHOT.20200308063819)
  • Operating system: the operating system you're running Airsonic on.
    Linux, not sure which kernel, using Docker-Compose v3
    Linux, what distribution; Windows or Mac, what version?
  • Java version: the Java version you are using to run Airsonic.
    The one included in the Docker, seems to be AdoptOpenJDK 11.0.6
  • Proxy server: if running Airsonic behind a proxy, what server and
    version? Otherwise,
    Behind a reverse proxy, same setup as old Airsonic.
  • Client: what browser and version you use to access the Airsonic web
    interface, or the name and version of another app you're using.

    Firefox 73.0.1
  • Language: which langauge/internationalization is in use
    English

Additional notes

If any additional information is needed please let me know.

Attempted script load does not respect context_path setting

Problem description

The script sockjs-client-1.4.0.min.js is not fetched while respecting the context_path, attempting to load it at https://mydomain.com/script/sockjs-client-1.4.0.min.js instead of https://mydomain.com/music/script/sockjs-client-1.4.0.min.js using a context_path setting of /music

Steps to reproduce

  1. Log in to airsonic-advanced

System information

  • 10.6.0-SNAPSHOT.20200414043004
  • docker on unraid
  • java 11.0.6
  • nginx 1.16.1
  • Firefox 74.0.1
  • English

Additional notes

Makes two attempts to load. Have not noticed any loss of functionality; however, loading a resource without respecting the context_path setting triggers the http basic auth at mydomain.com twice every time I log in.

per-user podcasts

I posted this feature request on airsonic already (airsonic/airsonic#1624) but it may seem interesting here as well:

Problem description

Podcasts are managed on an application perspective. Different from access to media folders, which can be enabled per user, all users of the application have access to all podcast subscriptions. It would be nice, if different subscriptions could be registered per user, i.e. user A has access to his private podcast subscriptions and user B doesn't see those of user A.

System information

  • Airsonic version: 10.6.0-RELEASE
  • Operating system: official docker image
  • Java version: as proved by official docker image
  • Proxy server: nginx ssl proxy (v. 1.17.9)
  • Client: firefox (v. 75.0), dsub (v. 5.4.4)
  • Language: english

Container crash when clicking settings button in player panel

Problem description

Attempting to use the settings icon in the player panel causes container crash requiring restart.

Steps to reproduce

  1. Click the settings icon in the player panel
  2. 502 error in center frame
  3. Be unable to load anything until container is restarted

System information

  • 10.6.0-SNAPSHOT.20200414043004
  • docker on unraid
  • java 11.0.6
  • nginx 1.16.1
  • Firefox 74.0.1
  • English

Additional notes

Container log (this error usually appears twice in a row):
Inconsistency detected by ld.so: dl-lookup.c: 112: check_match: Assertion version->filename == NULL || ! _dl_name_match_p (version->filename, map)' failed!`

Browser console (appears immediately following clicking that icon):

Whoops! Lost connection to https://mydomain.com/music/websocket stomp-4.0.8.min.js:9:2502
Disconnected 
Object { type: "close", bubbles: false, cancelable: false, timeStamp: 1587025226100, wasClean: false, code: 1006, reason: "permanent" }
index:131:29
Error Whoops! Lost connection to https://mydomain.com/music/websocket

This also occurs when not behind a reverse proxy, although a simple "unable to connect" appears in the center frame instead of a 502. Similar behavior but including for completeness.

example: nginx local block configuration using websockets for airsonic-advanced

This is related to the websockets closed issue.

Since I had the same issue and I came up configuring nginx in the following way:

        ###
        # airsonic-advanced
        ###

    location /airsonic {
        proxy_set_header Upgrade           $http_upgrade;
        proxy_set_header Connection        "Upgrade";
        proxy_http_version 1.1;
        proxy_set_header X-Real-IP         $remote_addr;
        proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto https;
        proxy_set_header X-Forwarded-Host  $host;
        proxy_set_header X-Forwarded-Port  $server_port;
        proxy_set_header Host              $host;
        proxy_max_temp_file_size           0;
        proxy_pass                         http://192.168.178.90:8070;
        proxy_redirect                     http:// https://;
        proxy_buffering off;
        proxy_request_buffering off;
        
        client_max_body_size 0;

        access_log      /var/log/nginx/airsonic_access.log;
        error_log       /var/log/nginx/airsonic_error.log;
       #access_log      off;
    }

This config give the best output results and no warning or errors on chrome inspect console.

remarks: airsonic-advanced is not running on the same nginx server. airsonic-advanced running on 192.168.178.90:8070

Maybe could be from any help to others ussing the websockets used by airsonic advanced.

Updated: 25.01.2021 - added proxy_set_header Origin '';
Updated: 27.09.2021 - deleted the added line on 25.01.2021 proxy_set_header Origin ''; See #145 (comment)
Updated: 05.10.2021 - added proxy_set_header X-Forwarded-Port $server_port; since nginx could listen in other ports than 443, see #635
Updated: 12.12.2021 - changed proxy_set_header Host $http_host; to proxy_set_header Host $host; and proxy_set_header Host $http_host; to proxy_set_header Host $host; See #145 (comment)

Flac song stops and restart

Hello

Problem description

When i listen for flac files , it regurlalrly stops and restart afeter few seconds
I can see this error in console

Failed to load resource: net::ERR_CONTENT_LENGTH_MISMATCH

Steps to reproduce

just listen for flac files

System information

  • Airsonic version: 10.6.0-SNAPSHOT.20200302045745**

  • Operating system: *Debian 10.

  • Java version: java 11.0.5.

  • Proxy server: *NGINX

  • Client: Chrome.

  • Language: French

Additional notes

No Transcoding set up for flac

Include any extra notes here. Otherwise you may remove this section.

Playing Queue: Play next song with arrow key skips one song

Problem description

When I'm playing some songs in the playing queue and I use the arrow key on the keyboard to skip a track, it doesn't play the next track, it plays the song after the next track.

Steps to reproduce

  1. Play some songs
  2. Press arrow right on the keyboard

System information

  • Airsonic version: Edge Release 10.6.0-SNAPSHOT.20200414043004
  • Operating system: Windows Server 2012
  • Java version: Java(TM) SE Runtime Environment (build 1.8.0_241-b07)
  • Proxy server: IIS
  • Client: Tested in Firefox
  • Language: English

"Show X entries" not saved and in wrong order

Problem description

Like in the playing queue or when opening an album you get the following option:
grafik
Two things with this drop down:

  1. Is there a place, where I can set a default value for that? Or should this be saved automatically when changing the value? For me it always goes back to 40.
  2. 40 is on the bottom instead after 20 and before 50.

System information

  • Airsonic version: Edge Release 10.6.0-SNAPSHOT.20200414043004
  • Operating system: Windows Server 2012
  • Java version: Java(TM) SE Runtime Environment (build 1.8.0_241-b07)
  • Proxy server: IIS
  • Client: Tested in Firefox
  • Language: English

Getting horizontal scrollbar when opening player queue

Problem description

I'm using Firefox with the "Tree Style Tab" extension. This extension shows me all the opened tabs on the left side of the browser. So my websites are not having the fill width.
I just started to try airsonic-advanced and realized, that I get a horizontal scroll bar, when I open the player queue. When I close the sidebar of the browser extension all is working find.

Steps to reproduce

  1. Install "Tree Style Tab" extension.
  2. Open player queue
  3. You'll see the scrollbar

Edit:
The issue seems to go away, when I zoom out with the browser and then zoom in again.

Stable Release 10.6.0

There seem to be enough changes and stability now to merit a stable release.

Thereafter we can move to 11.0 snapshots and merge breaking changes to upgrade old stuff to modern counterparts.

If there are no outstanding bugs/issues in the next few days for the current prerelease, it'll get promoted to stable.

Stuck on first scan while first start after upgrade to Airsonic-Advanced

Problem description

I just updated from Airsonic to Aisonic-Advanced. I removed every file except the internal database. When starting Airsonic-Advanced for the first time it seams to do a complete full rescan of my medias (which takes very long for my 112000 mp3 files). When updating the genres (according to the log) it stuck for about 25 minutes and cosuming the power of one cpu (25% CPU, I have 4 cores). During this 25 minutes I was not able to access the Airsonic website. I always got a timeout when loading the page. Before updating the genres and while scanning the medias I was able to access the website without any issue.
After doing this whole thing several times and finally waiting patiently enough it came over this and finished this step. I think updating the genre isn't running on a own thread.

Steps to reproduce

  1. Take a copy of a big airsonic database.
  2. Start airsonic-advanced for the first time.
  3. Wait until media scan has finished and genres are updating

System information

System information

  • Airsonic version: Edge Release 10.6.0-SNAPSHOT.20200414043004
  • Operating system: Windows Server 2012
  • Java version: Java(TM) SE Runtime Environment (build 1.8.0_241-b07)
  • Proxy server: IIS
  • Client: Tested in Firefox
  • Language: English

Additional notes

2020-04-16 21:14:38.406 INFO --- o.a.p.s.MediaScannerService : Scanned media library with 115751 entries.
2020-04-16 21:14:46.213 INFO --- o.a.p.s.MediaScannerService : Scanned media library with 115855 entries.
2020-04-16 21:14:46.230 INFO --- o.a.p.s.MediaScannerService : Persisting albums
2020-04-16 21:14:46.291 INFO --- o.a.p.s.MediaScannerService : Persisting artists
2020-04-16 21:14:46.353 INFO --- o.a.p.s.MediaScannerService : Marking present files
2020-04-16 21:14:46.353 INFO --- o.a.p.s.MediaScannerService : Persisting genres
2020-04-16 21:14:47.931 INFO --- o.a.p.s.MediaScannerService : Updating genres
2020-04-16 21:40:31.175 INFO --- o.a.p.s.MediaScannerService : Marking non-present files.
2020-04-16 21:40:31.207 INFO --- o.a.p.s.MediaScannerService : File marking complete
2020-04-16 21:40:31.254 INFO --- o.a.p.s.MediaScannerService : Genre persistence complete
2020-04-16 21:40:32.238 INFO --- o.a.p.s.MediaScannerService : Marking non-present albums.
2020-04-16 21:40:32.238 INFO --- o.a.p.s.MediaScannerService : Album persistence complete
2020-04-16 21:40:32.316 INFO --- o.a.p.s.MediaScannerService : Marking non-present artists.
2020-04-16 21:40:32.316 INFO --- o.a.p.s.MediaScannerService : Artist persistence complete
2020-04-16 21:40:32.316 INFO --- o.a.p.s.MediaScannerService : Completed media library scan.
2020-04-16 21:40:34.066 INFO --- o.a.p.s.MediaScannerService : Media library scan took 3948s
2020-04-16 21:40:34.066 INFO --- o.a.p.service.PlaylistService : Starting playlist import.
2020-04-16 21:40:34.066 INFO --- o.a.p.service.PlaylistService : Completed playlist import.

Add support for CSP

Problem description

No *sonic server is CSP compliant, which makes users vulnerable to a number of XSS attacks. This was detailed in a vanilla airsonic issue and it looked as if some work had started with a milestone for 11.0.0 release. However, given the age of the vanilla codebase and ubiquity of inline scripts and styles this is understandably a nontrivial project.

Here is the vanilla airsonic issue: airsonic #909 (feature planned for 11.0.0 release) with additional details. Inline 'eval' is less common and could be a comparative low hanging fruit.

Steps to reproduce

  1. Don't allow inline scripts, eval, or styles using a CSP header like:

frame-ancestors 'self'; base-uri 'self'; default-src 'self'; form-action 'self'; font-src 'self'; img-src 'self' https://lastfm.freetls.fastly.net; object-src 'none'; script-src 'self'; style-src 'self';

  1. Menus and player disappear, most functionality is lost. Addition of inline scripts, eval, and styles are required:

frame-ancestors 'self'; base-uri 'self'; default-src 'self'; form-action 'self'; font-src 'self'; img-src 'self' https://lastfm.freetls.fastly.net; object-src 'none'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline';

System information

  • 11.0.0-SNAPSHOT.20200430000326
  • docker on unraid
  • java 14.0.1
  • nginx 1.16.1
  • Firefox 74.0.1
  • English

Additional notes

None

Milliseconds displayed in track length

Problem description

In the queue some tune lengths are shown with milliseconds.
See screenshot below :

Screenshot_20200417_145612

I play only FLACs. This doesn't happen with all albums, so I guess this is simply how metadata are saved in my files.
Not sure if this is a bug or a feature, but I find it a bit confusing. Any chance to avoid that much details ?

Steps to reproduce

  1. Add some tunes to the queue

System information

  • Airsonic version: 10.6.0-SNAPSHOT.20200417044128 (same with previous versions)
  • Operating system: Armbian Buster
  • Java version: Openjdk 8
  • Proxy server: Nginx
  • Client: Firefox / Ubuntu
  • Language: EN

Standalone with external database (mariadb) help needed

Hi there!

I am trying to run airsonic-advanced standalone with an external database (mariadb) and the correct "driver" ... mariadb-java-client-2.6.0.jar
Running with the local database everything runs great!
Running within tomcat9 (I have to admit; there I am running the "classical" version of airsonic) it also works with the external MariaDB while using mariadb-java-client-2.6.0.jar..

But I cant' get it running standalone using mariaDB ...

Amy help is highly appreciated :)

Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'themeSource': Unsatisfied dependency expressed through method 'setSettingsService' parameter 0; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'settingsService': Unsatisfied dependency expressed through field 'internetRadioDao'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'internetRadioDao': Unsatisfied dependency expressed through field 'daoHelper'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'daoHelper': Unsatisfied dependency expressed through field 'jdbcTemplate'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'liquibase' defined in class path resource [org/airsonic/player/spring/DatabaseConfiguration.class]: Invocation of init method failed; nested exception is liquibase.exception.ValidationFailedException:

Pb on loading some picture

Problem description

i load an artist page and have this message in console
Refused to load the image 'https://lastfm.freetls.fastly.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png' because it violates the following Content Security Policy directive: "img-src 'self' *.akamaized.net".*

In artist information no picture

Steps to reproduce

Try to load an artist page

System information

  • Airsonic version: *10.6.0-SNAPSHOT.20200302045745

  • Operating system: *Debian 10

  • Java version: OpenJdK 11.

  • Proxy server: *NGINX

  • Client: *Chrome

  • Language: French

Additional notes

If you want i cant give an acces to my airsonic

Can't rearrange play queue with auto-hide enabled

I cannot re-arrange items in the play queue on Airsonic web when the queue auto-hide feature is enabled. If I disable auto-hide, I can drag a track to a different position in the queue. I am using Firefox.

Running v11.0.0-SNAPSHOT.20200430193915

Mousecursor not showing link on actions in album view

Problem description

When I open an album and move over the list of songs, I would expect to get a hand as curser, when hovering over the buttons like the star, play, play next... Instead I still have the usual pointer.
When I open a playlist I get the hand as cursor when hovering on the whole row (probably related to the possibility to move the songs around to change the order).

Steps to reproduce

  1. Open an album
  2. Hover over the button icons in the list of songs

System information

  • Airsonic version: Edge Release 10.6.0-SNAPSHOT.20200414043004
  • Operating system: Windows Server 2012
  • Java version: Java(TM) SE Runtime Environment (build 1.8.0_241-b07)
  • Proxy server: IIS
  • Client: Tested in Firefox
  • Language: English

Can't change admin user password

Problem description

This may be a silly question, but I can't see how to change the admin password in the web UI.

Steps to reproduce

  1. Settings > User > Admin, there's no password change input boxes?

System information

  • Airsonic version: 11.0.0-SNAPSHOT.20200430000326 – April 30, 2020 at 10:03:26 AM AEST

Multi-select download of podcasts frequently fails

Problem description

Single select downloads of podcasts work as expected; however, selecting two or more and clicking "download selected" either does nothing or throws a 400 internal error when three or more are selected.

Steps to reproduce

  1. Add a podcast
  2. Select more than one episode
  3. Click 'download selected'
  4. Download does not start (exactly two or three) or (usually) fails in frame (4+)

System information

  • 10.6.0-SNAPSHOT.20200414043004
  • docker on unraid
  • java 11.0.6
  • nginx 1.16.1
  • Firefox 74.0.1
  • English

Additional notes

Log of 4+ failure attached. Nothing in console or logs for the "nothing happens" failures. Tested with multiple podcasts (Welcome to Nightvale, This American Life, Darknet Diaries, Reply All, others) that all downloaded OK with vanilla airsonic regardless of number.
multiselect_four_or_more_trace.txt

redirection to domain.tld/airsonic doesn't work anymore

Problem description

I'm using the following java command to start airsonic:

/usr/bin/java -Xmx700m -Dairsonic.home=/media/sda/airsonic/config -Dserver.context-path=/airsonic -Dserver.host=0.0.0.0 -Dserver.port=8070 -Djava.awt.headless=true -Dserver.use-forward-headers=true -verbose:gc -jar /media/sda/airsonic/airsonic.war --illegal-access=warn

but the redirection to domain.tld/airsonic it doesn't work. The redirection using the normal airsonic.war work without any issues.

Question: how should be managed the redirection -Dserver.context-path=/airsonic now, since this doesn't seems to work anymore with the airsocnic-advanced ?

System information

  • Airsonic version: 10.6.0-SNAPSHOT.20200217215259 – February 17, 2020 at 10:52:59 PM CET
  • Operating system: Ubuntu 19.10 (GNU/Linux 5.3.0-29-generic x86_64)
  • Java version: zulu13.29.9-ca-jdk13.0.2-linux_amd64 / OpenJDK11U-jre_x64_linux_openj9_11.0.6_10_openj9-0.18.1 / OpenJDK13U-jre_x64_linux_openj9_13.0.2_8_openj9-0.18.0.tar
  • Proxy server: nginx nginx/1.17.8
location /airsonic {
      proxy_set_header X-Real-IP         $remote_addr;
      proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
      proxy_set_header X-Forwarded-Proto https;
      proxy_set_header X-Forwarded-Host  $http_host;
      proxy_set_header Host              $http_host;
      proxy_max_temp_file_size           0;
      proxy_pass                         http://192.168.178.90:8070;
      proxy_redirect                     http:// https://;


      client_max_body_size 0;

      #access_log      /var/log/nginx/airsonic_access.log;
      error_log       /var/log/nginx/airsonic_error.log;
      access_log      off;
  }
  • Client: Chrome Version 80.0.3987.106 (Offizieller Build) (64-Bit)

  • Language: UTF8

Additional notes

on startup following warnings apper:

2020-02-18 17:44:43.264  INFO --- o.a.p.service.SettingsService            : Removing obsolete property [PortForwardingPublicPort]
2020-02-18 17:44:43.277  INFO --- o.a.p.service.SettingsService            : Removing obsolete property [PortForwardingLocalPort]
2020-02-18 17:44:43.278  INFO --- o.a.p.service.SettingsService            : Removing obsolete property [DownsamplingCommand]
2020-02-18 17:44:43.279  INFO --- o.a.p.service.SettingsService            : Removing obsolete property [DownsamplingCommand2]
2020-02-18 17:44:43.279  INFO --- o.a.p.service.SettingsService            : Removing obsolete property [DownsamplingCommand3]
2020-02-18 17:44:43.280  INFO --- o.a.p.service.SettingsService            : Removing obsolete property [AutoCoverBatch]
2020-02-18 17:44:43.280  INFO --- o.a.p.service.SettingsService            : Removing obsolete property [MusicMask]
2020-02-18 17:44:43.280  INFO --- o.a.p.service.SettingsService            : Removing obsolete property [VideoMask]
2020-02-18 17:44:43.281  INFO --- o.a.p.service.SettingsService            : Removing obsolete property [CoverArtMask]
2020-02-18 17:44:43.281  INFO --- o.a.p.service.SettingsService            : Removing obsolete property [HlsCommand]
2020-02-18 17:44:43.282  INFO --- o.a.p.service.SettingsService            : Removing obsolete property [HlsCommand2]
2020-02-18 17:44:43.282  INFO --- o.a.p.service.SettingsService            : Removing obsolete property [JukeboxCommand]
2020-02-18 17:44:43.282  INFO --- o.a.p.service.SettingsService            : Removing obsolete property [CoverArtFileTypes]
2020-02-18 17:44:43.283  INFO --- o.a.p.service.SettingsService            : Removing obsolete property [UrlRedirectCustomHost]
2020-02-18 17:44:43.283  INFO --- o.a.p.service.SettingsService            : Removing obsolete property [CoverArtLimit]
2020-02-18 17:44:43.284  INFO --- o.a.p.service.SettingsService            : Removing obsolete property [StreamPort]
2020-02-18 17:44:43.284  INFO --- o.a.p.service.SettingsService            : Removing obsolete property [PortForwardingEnabled]
2020-02-18 17:44:43.284  INFO --- o.a.p.service.SettingsService            : Removing obsolete property [RewriteUrl]
2020-02-18 17:44:43.284  INFO --- o.a.p.service.SettingsService            : Removing obsolete property [UrlRedirectCustomUrl]
2020-02-18 17:44:43.285  INFO --- o.a.p.service.SettingsService            : Removing obsolete property [UrlRedirectContextPath]
2020-02-18 17:44:43.285  INFO --- o.a.p.service.SettingsService            : Removing obsolete property [UrlRedirectFrom]
2020-02-18 17:44:43.285  INFO --- o.a.p.service.SettingsService            : Removing obsolete property [UrlRedirectionEnabled]
2020-02-18 17:44:43.286  INFO --- o.a.p.service.SettingsService            : Removing obsolete property [UrlRedirectType]
2020-02-18 17:44:43.286  INFO --- o.a.p.service.SettingsService            : Removing obsolete property [Port]
2020-02-18 17:44:43.286  INFO --- o.a.p.service.SettingsService            : Removing obsolete property [HttpsPort]
2020-02-18 17:44:43.287  INFO --- o.a.p.service.SettingsService            : Removing obsolete property [MediaLibraryStatistics]
2020-02-18 17:44:43.287  INFO --- o.a.p.service.SettingsService            : Removing obsolete property [LastScanned]

I observe the following issue as well:

2020-02-18 17:27:22.737 WARN --- o.d.impl.DefaultPageNormalizer : Missing /WEB-INF/web.xml

Bug in scrobbling creds

thx
I test today and it's fine only if i store my password in plain-text which is not very secure
each time i have tested something else , i obtain
2020-03-02 20:11:37.340 WARN --- o.a.p.s.s.LastFMScrobbler : Failed to scrobble song 'À vouloir toucher Dieu…' at Last.fm. Wrong username or password.

Originally posted by @dorel14 in #110 (comment)

Playing Queue: Marking song with star scrolls to top

Problem description

When I'm playing some songs in the playing queue and I mark a song with a star, the queue always scrolls to top. It's not really an issue, but it's anyoing to me, as I usualy also add the same song to a playlist afterwards. Then I have to scoll down again and find the song.

Steps to reproduce

  1. Play some songs
  2. Mark one of the songs with a star

System information

  • Airsonic version: Edge Release 10.6.0-SNAPSHOT.20200414043004
  • Operating system: Windows Server 2012
  • Java version: Java(TM) SE Runtime Environment (build 1.8.0_241-b07)
  • Proxy server: IIS
  • Client: Tested in Firefox
  • Language: English

Login is not remembered overnight

I think a login timeout setting would be useful, possibly on a per-user basis. I'm not sure what it's coded to currently, but I find I have to login again after a period of inactivity (when accessing from a desktop web browser).

IIRC, original Airsonic used to log you out after some period of inactivity, but when I last used it, it would leave me logged in all day (unless I found a bug). I would prefer it log me out after some period, but the current setting is too short, imo.

Link area on user icon to big

Problem description

In the header there's a link on my username/icon which brings me to my personal settings. I already got many times unintended to this page, as the link is not just there on the username/icon (tested with Firefox), it's also on the space between search - username/icon and between connected username/icon.

Steps to reproduce

  1. Hover over the header with your mouse and you will see ;-)

System information

  • Airsonic version: Edge Release 10.6.0-SNAPSHOT.20200414043004
  • Operating system: Windows Server 2012
  • Java version: Java(TM) SE Runtime Environment (build 1.8.0_241-b07)
  • Proxy server: IIS
  • Client: Tested in Firefox
  • Language: English

Playing Queue: Moving song is scrolling up afterwards

Problem description

When I play some songs in the playing queue and move a song around and release the mouse button afterwords, the playing queue always scrolls to the top of the list.
This happens to me very often unintended: I click on song without actually having the intention to move it. When I click and release the mousebutton, the playing queue scrolls to the top.
This is very annoying if you like to play a song, but didn't exactly clicked on the link of the title to play the certain song. If you missed it by just a pixel it scrolls you up to the top and you can search the song again.

Steps to reproduce

  1. Play some songs in the playing queue
  2. Scroll down
  3. Click on a random song (and move it [optional]) -> Don't click on the title or album
  4. Release mouse button

System information

  • Airsonic version: Edge Release 10.6.0-SNAPSHOT.20200414043004
  • Operating system: Windows Server 2012
  • Java version: Java(TM) SE Runtime Environment (build 1.8.0_241-b07)
  • Proxy server: IIS
  • Client: Tested in Firefox
  • Language: English

Playing Queue: Shortcut "Q" not working to open

Problem description

If I'm having some songs in the playing queue and browsing around I very often use the keyboard shortcut (key Q) to open/close the queue. Unfortunately only closing is possible.

Steps to reproduce

  1. Play some songs
  2. Press Q on the keyboard

System information

  • Airsonic version: Edge Release 10.6.0-SNAPSHOT.20200414043004
  • Operating system: Windows Server 2012
  • Java version: Java(TM) SE Runtime Environment (build 1.8.0_241-b07)
  • Proxy server: IIS
  • Client: Tested in Firefox
  • Language: English

NoSuchFileException on service start if podcast episode is missing

I'm running Stable Release 10.6.0, but I have the same problem with the 2 subsequent releases as well.

Airsonic crashes on service start if a podcast episode file is missing (no such file exception). The process continues to run, but I cannot access the interface in my browser. I get a "page can't be displayed" error in Firefox. Dev console shows a get request made to /login, but no response code from the server.

I didn't manually delete the file in question. I confirmed the file is missing. I assume Airsonic is deleting the file because I have it set to only keep 10 or so.

Deleting the folder for the particular podcast, e.g. /Podcasts/Podcast title/ allows me access Airsonic in the browser again.

Here is the relevant log output:

2020-04-24 16:43:10.550 WARN --- o.a.p.service.MediaFileService : Could not retrieve children for /media/mp3/Podcasts/Behind the Bastards/HSW71630825051.mp3.java.nio.file.NoSuchFileException: /media/mp3/Podcasts/Behind the Bastards/HSW71630825051.mp3 at java.base/sun.nio.fs.UnixException.translateToIOException(UnixException.java:92) ~[na:na] at java.base/sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:111) ~[na:na] at java.base/sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:116) ~[na:na] at java.base/sun.nio.fs.UnixFileSystemProvider.newDirectoryStream(UnixFileSystemProvider.java:428) ~[na:na] at java.base/java.nio.file.Files.newDirectoryStream(Files.java:465) ~[na:na] at java.base/java.nio.file.Files.list(Files.java:3527) ~[na:na] at org.airsonic.player.service.MediaFileService.createMediaFile(MediaFileService.java:498) [classes!/:10.6.0-SNAPSHOT] at org.airsonic.player.service.MediaFileService.checkLastModified(MediaFileService.java:164) [classes!/:10.6.0-SNAPSHOT] at org.airsonic.player.service.MediaFileService.getMediaFile_aroundBody0(MediaFileService.java:107) [classes!/:10.6.0-SNAPSHOT] at org.airsonic.player.service.MediaFileService$AjcClosure1.run(MediaFileService.java:1) [classes!/:10.6.0-SNAPSHOT] at org.springframework.cache.aspectj.AbstractCacheAspect.ajc$around$org_springframework_cache_aspectj_AbstractCacheAspect$1$2bc714b5proceed(AbstractCacheAspect.aj:64) [spring-aspects-5.2.5.RELEASE.jar!/:5.2.5.RELEASE] at org.springframework.cache.aspectj.AbstractCacheAspect$AbstractCacheAspect$1.invoke(AbstractCacheAspect.aj:71) [spring-aspects-5.2.5.RELEASE.jar!/:5.2.5.RELEASE] at org.springframework.cache.interceptor.CacheAspectSupport.execute(CacheAspectSupport.java:351) [spring-context-5.2.5.RELEASE.jar!/:5.2.5.RELEASE] at org.springframework.cache.aspectj.AbstractCacheAspect.ajc$around$org_springframework_cache_aspectj_AbstractCacheAspect$1$2bc714b5(AbstractCacheAspect.aj:80) [spring-aspects-5.2.5.RELEASE.jar!/:5.2.5.RELEASE] at org.airsonic.player.service.MediaFileService.getMediaFile(MediaFileService.java:99) [classes!/:10.6.0-SNAPSHOT] at org.airsonic.player.service.MediaFileService.getMediaFile(MediaFileService.java:88) [classes!/:10.6.0-SNAPSHOT] at org.airsonic.player.service.MediaFileService.getMediaFile(MediaFileService.java:132) [classes!/:10.6.0-SNAPSHOT] at org.airsonic.player.service.PodcastService.lambda$9(PodcastService.java:251) [classes!/:10.6.0-SNAPSHOT] at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:195) ~[na:na] at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1492) ~[na:na] at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484) ~[na:na] at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474) ~[na:na] at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:913) ~[na:na] at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) ~[na:na] at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:578) ~[na:na] at org.airsonic.player.service.PodcastService.addMediaFileIdToEpisodes(PodcastService.java:258) [classes!/:10.6.0-SNAPSHOT] at org.airsonic.player.service.PodcastService.getEpisodes(PodcastService.java:212) [classes!/:10.6.0-SNAPSHOT] at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:195) ~[na:na] at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:195) ~[na:na] at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1492) ~[na:na] at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484) ~[na:na] at java.base/java.util.stream.ForEachOps$ForEachTask.compute(ForEachOps.java:290) ~[na:na] at java.base/java.util.concurrent.CountedCompleter.exec(CountedCompleter.java:746) ~[na:na] at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:290) ~[na:na] at java.base/java.util.concurrent.ForkJoinTask.doInvoke(ForkJoinTask.java:408) ~[na:na] at java.base/java.util.concurrent.ForkJoinTask.invoke(ForkJoinTask.java:736) ~[na:na] at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateParallel(ForEachOps.java:159) ~[na:na] at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateParallel(ForEachOps.java:173) ~[na:na] at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:233) ~[na:na] at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:497) ~[na:na] at org.airsonic.player.service.PodcastService.init(PodcastService.java:120) [classes!/:10.6.0-SNAPSHOT] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na] at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na] at java.base/java.lang.reflect.Method.invoke(Method.java:564) ~[na:na] at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleElement.invoke(InitDestroyAnnotationBeanPostProcessor.java:389) ~[spring-beans-5.2.5.RELEASE.jar!/:5.2.5.RELEASE] at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleMetadata.invokeInitMethods(InitDestroyAnnotationBeanPostProcessor.java:333) ~[spring-beans-5.2.5.RELEASE.jar!/:5.2.5.RELEASE] at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:157) ~[spring-beans-5.2.5.RELEASE.jar!/:5.2.5.RELEASE] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:416) ~[spring-beans-5.2.5.RELEASE.jar!/:5.2.5.RELEASE] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1788) ~[spring-beans-5.2.5.RELEASE.jar!/:5.2.5.RELEASE] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:595) ~[spring-beans-5.2.5.RELEASE.jar!/:5.2.5.RELEASE] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:517) ~[spring-beans-5.2.5.RELEASE.jar!/:5.2.5.RELEASE] at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:323) ~[spring-beans-5.2.5.RELEASE.jar!/:5.2.5.RELEASE] at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222) ~[spring-beans-5.2.5.RELEASE.jar!/:5.2.5.RELEASE] at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:321) ~[spring-beans-5.2.5.RELEASE.jar!/:5.2.5.RELEASE] at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) ~[spring-beans-5.2.5.RELEASE.jar!/:5.2.5.RELEASE] at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:882) ~[spring-beans-5.2.5.RELEASE.jar!/:5.2.5.RELEASE] at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:878) ~[spring-context-5.2.5.RELEASE.jar!/:5.2.5.RELEASE] at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:550) ~[spring-context-5.2.5.RELEASE.jar!/:5.2.5.RELEASE] at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:141) ~[spring-boot-2.2.6.RELEASE.jar!/:2.2.6.RELEASE] at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:747) ~[spring-boot-2.2.6.RELEASE.jar!/:2.2.6.RELEASE] at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397) ~[spring-boot-2.2.6.RELEASE.jar!/:2.2.6.RELEASE] at org.springframework.boot.SpringApplication.run(SpringApplication.java:315) ~[spring-boot-2.2.6.RELEASE.jar!/:2.2.6.RELEASE] at org.springframework.boot.builder.SpringApplicationBuilder.run(SpringApplicationBuilder.java:140) ~[spring-boot-2.2.6.RELEASE.jar!/:2.2.6.RELEASE] at org.airsonic.player.Application.main(Application.java:78) ~[classes!/:10.6.0-SNAPSHOT] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na] at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na] at java.base/java.lang.reflect.Method.invoke(Method.java:564) ~[na:na] at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:48) ~[airsonic.war:10.6.0-SNAPSHOT] at org.springframework.boot.loader.Launcher.launch(Launcher.java:87) ~[airsonic.war:10.6.0-SNAPSHOT] at org.springframework.boot.loader.Launcher.launch(Launcher.java:51) ~[airsonic.war:10.6.0-SNAPSHOT] at org.springframework.boot.loader.WarLauncher.main(WarLauncher.java:58) ~[airsonic.war:10.6.0-SNAPSHOT]

Duration minutes of podcasts displayed wrong

Problem description

Duration minutes of podcasts displayed wrong.
When I browse to the podcast section, open a certain podcast and look through the list of episodes the duration of minutes is calucalted wrong.
grafik

Seems like hours are not subtracted from the minutes.

Duration showing in Windows Explorer.
grafik

Steps to reproduce

  1. Download some podcast episodes
  2. Open the list of episodes
  3. See the duration

System information

  • Airsonic version: Edge Release 10.6.0-SNAPSHOT.20200424035525
  • Operating system: Windows Server 2012
  • Java version: Java(TM) SE Runtime Environment (build 1.8.0_241-b07)
  • Proxy server: IIS
  • Client: Tested in Firefox
  • Language: English

Ui Issue on left side (artist names)

Problem description

On left column the arrow which permit to hide all artist beginning by a letter doesn't work anymore

Steps to reproduce

Click on the arrow near the A lettter on left side

System information

  • Airsonic version: 10.6.0-SNAPSHOT.20200408045448 – 8 avril 2020 à 04:54:48 UTC

  • Operating system: Debian 10

  • Java version: OpenJDK 11

  • Proxy server: Nginx

  • Client: Chrome

  • Language: French

Can't create new playlist with fresh Database

When running Airsonic Advanced, starting with a fresh database I'm getting the following error, when clicking on "Create new playlist".

Tested with version: 11.0.0-SNAPSHOT.20200501175424
Database: HSQLDB

2020-05-01 19:47:51.235 ERROR --- .WebSocketAnnotationMethodMessageHandler : Unhandled exception from message handler method

org.springframework.dao.DataIntegrityViolationException: PreparedStatementCallback; integrity constraint violation: NOT NULL check constraint; SYS_CT_10506 table: PLAYLIST column: DURATION_SECONDS; nested exception is java.sql.SQLIntegrityConstraintViolationException: integrity constraint violation: NOT NULL check constraint; SYS_CT_10506 table: PLAYLIST column: DURATION_SECONDS
	at org.springframework.jdbc.support.SQLExceptionSubclassTranslator.doTranslate(SQLExceptionSubclassTranslator.java:87) ~[spring-jdbc-5.2.5.RELEASE.jar:5.2.5.RELEASE]
	at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:72) ~[spring-jdbc-5.2.5.RELEASE.jar:5.2.5.RELEASE]
	at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:81) ~[spring-jdbc-5.2.5.RELEASE.jar:5.2.5.RELEASE]
	at org.springframework.jdbc.core.JdbcTemplate.translateException(JdbcTemplate.java:1443) ~[spring-jdbc-5.2.5.RELEASE.jar:5.2.5.RELEASE]
	at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:633) ~[spring-jdbc-5.2.5.RELEASE.jar:5.2.5.RELEASE]
	at org.springframework.jdbc.core.JdbcTemplate.update(JdbcTemplate.java:893) ~[spring-jdbc-5.2.5.RELEASE.jar:5.2.5.RELEASE]
	at org.springframework.jdbc.core.simple.AbstractJdbcInsert.executeInsertAndReturnKeyHolderInternal(AbstractJdbcInsert.java:433) ~[spring-jdbc-5.2.5.RELEASE.jar:5.2.5.RELEASE]
	at org.springframework.jdbc.core.simple.AbstractJdbcInsert.doExecuteAndReturnKeyHolder(AbstractJdbcInsert.java:394) ~[spring-jdbc-5.2.5.RELEASE.jar:5.2.5.RELEASE]
	at org.springframework.jdbc.core.simple.SimpleJdbcInsert.executeAndReturnKeyHolder(SimpleJdbcInsert.java:137) ~[spring-jdbc-5.2.5.RELEASE.jar:5.2.5.RELEASE]
	at org.airsonic.player.dao.AbstractDao.insert(AbstractDao.java:293) ~[classes/:na]
	at org.airsonic.player.dao.PlaylistDao.createPlaylist(PlaylistDao.java:92) ~[classes/:na]
	at org.airsonic.player.dao.PlaylistDao$$FastClassBySpringCGLIB$$e2635819.invoke(<generated>) ~[classes/:na]
	at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) ~[spring-core-5.2.5.RELEASE.jar:5.2.5.RELEASE]
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:771) ~[spring-aop-5.2.5.RELEASE.jar:5.2.5.RELEASE]
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.2.5.RELEASE.jar:5.2.5.RELEASE]
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749) ~[spring-aop-5.2.5.RELEASE.jar:5.2.5.RELEASE]
	at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:139) ~[spring-tx-5.2.5.RELEASE.jar:5.2.5.RELEASE]
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.2.5.RELEASE.jar:5.2.5.RELEASE]
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749) ~[spring-aop-5.2.5.RELEASE.jar:5.2.5.RELEASE]
	at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:691) ~[spring-aop-5.2.5.RELEASE.jar:5.2.5.RELEASE]
	at org.airsonic.player.dao.PlaylistDao$$EnhancerBySpringCGLIB$$b1e49dcd.createPlaylist(<generated>) ~[classes/:na]
	at org.airsonic.player.service.PlaylistService.createPlaylist(PlaylistService.java:151) ~[classes/:na]
	at org.airsonic.player.ajax.PlaylistWSController.createEmptyPlaylist(PlaylistWSController.java:75) ~[classes/:na]
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
	at java.base/java.lang.reflect.Method.invoke(Method.java:564) ~[na:na]
	at org.springframework.messaging.handler.invocation.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:171) ~[spring-messaging-5.2.5.RELEASE.jar:5.2.5.RELEASE]
	at org.springframework.messaging.handler.invocation.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:120) ~[spring-messaging-5.2.5.RELEASE.jar:5.2.5.RELEASE]
	at org.springframework.messaging.handler.invocation.AbstractMethodMessageHandler.handleMatch(AbstractMethodMessageHandler.java:565) ~[spring-messaging-5.2.5.RELEASE.jar:5.2.5.RELEASE]
	at org.springframework.messaging.simp.annotation.support.SimpAnnotationMethodMessageHandler.handleMatch(SimpAnnotationMethodMessageHandler.java:511) ~[spring-messaging-5.2.5.RELEASE.jar:5.2.5.RELEASE]
	at org.springframework.messaging.simp.annotation.support.SimpAnnotationMethodMessageHandler.handleMatch(SimpAnnotationMethodMessageHandler.java:94) ~[spring-messaging-5.2.5.RELEASE.jar:5.2.5.RELEASE]
	at org.springframework.messaging.handler.invocation.AbstractMethodMessageHandler.handleMessageInternal(AbstractMethodMessageHandler.java:520) ~[spring-messaging-5.2.5.RELEASE.jar:5.2.5.RELEASE]
	at org.springframework.messaging.handler.invocation.AbstractMethodMessageHandler.handleMessage(AbstractMethodMessageHandler.java:454) ~[spring-messaging-5.2.5.RELEASE.jar:5.2.5.RELEASE]
	at org.springframework.messaging.support.ExecutorSubscribableChannel$SendTask.run(ExecutorSubscribableChannel.java:144) ~[spring-messaging-5.2.5.RELEASE.jar:5.2.5.RELEASE]
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130) ~[na:na]
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630) ~[na:na]
	at java.base/java.lang.Thread.run(Thread.java:832) ~[na:na]
Caused by: java.sql.SQLIntegrityConstraintViolationException: integrity constraint violation: NOT NULL check constraint; SYS_CT_10506 table: PLAYLIST column: DURATION_SECONDS
	at org.hsqldb.jdbc.JDBCUtil.sqlException(Unknown Source) ~[hsqldb-2.5.0.jar:2.5.0]
	at org.hsqldb.jdbc.JDBCUtil.sqlException(Unknown Source) ~[hsqldb-2.5.0.jar:2.5.0]
	at org.hsqldb.jdbc.JDBCPreparedStatement.fetchResult(Unknown Source) ~[hsqldb-2.5.0.jar:2.5.0]
	at org.hsqldb.jdbc.JDBCPreparedStatement.executeUpdate(Unknown Source) ~[hsqldb-2.5.0.jar:2.5.0]
	at com.zaxxer.hikari.pool.ProxyPreparedStatement.executeUpdate(ProxyPreparedStatement.java:61) ~[HikariCP-3.4.2.jar:na]
	at com.zaxxer.hikari.pool.HikariProxyPreparedStatement.executeUpdate(HikariProxyPreparedStatement.java) ~[HikariCP-3.4.2.jar:na]
	at org.springframework.jdbc.core.JdbcTemplate.lambda$update$1(JdbcTemplate.java:894) ~[spring-jdbc-5.2.5.RELEASE.jar:5.2.5.RELEASE]
	at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:617) ~[spring-jdbc-5.2.5.RELEASE.jar:5.2.5.RELEASE]
	... 33 common frames omitted
Caused by: org.hsqldb.HsqlException: integrity constraint violation: NOT NULL check constraint; SYS_CT_10506 table: PLAYLIST column: DURATION_SECONDS
	at org.hsqldb.error.Error.error(Unknown Source) ~[hsqldb-2.5.0.jar:2.5.0]
	at org.hsqldb.Table.enforceRowConstraints(Unknown Source) ~[hsqldb-2.5.0.jar:2.5.0]
	at org.hsqldb.Table.generateAndCheckData(Unknown Source) ~[hsqldb-2.5.0.jar:2.5.0]
	at org.hsqldb.Table.insertSingleRow(Unknown Source) ~[hsqldb-2.5.0.jar:2.5.0]
	at org.hsqldb.StatementDML.insertRowSet(Unknown Source) ~[hsqldb-2.5.0.jar:2.5.0]
	at org.hsqldb.StatementInsert.getResult(Unknown Source) ~[hsqldb-2.5.0.jar:2.5.0]
	at org.hsqldb.StatementDMQL.execute(Unknown Source) ~[hsqldb-2.5.0.jar:2.5.0]
	at org.hsqldb.Session.executeCompiledStatement(Unknown Source) ~[hsqldb-2.5.0.jar:2.5.0]
	at org.hsqldb.Session.execute(Unknown Source) ~[hsqldb-2.5.0.jar:2.5.0]
	... 39 common frames omitted

Edit: Same issue when try to import a playlist
Failed to import playlist "PreparedStatementCallback; integrity constraint violation: NOT NULL check constraint; SYS_CT_10506 table: PLAYLIST column: DURATION_SECONDS; nested exception is java.sql.SQLIntegrityConstraintViolationException: integrity constraint violation: NOT NULL check constraint; SYS_CT_10506 table: PLAYLIST column: DURATION_SECONDS".

Padding between tracks in queue

Is there an option to adjust the (vertical) padding between songs in the queue, or could there be an option for this? I find songs in the queue are spaced too far apart. The padding between tracks in a playlist looks better to me (there's less space between them).

If no one else is seeing this, I can add a photo to demonstrate what I mean.

Problem with last FM scrobbling

Hello
i've downloaded and install latest .war and after listening for some song , i've found this in logs
2020-02-28 15:33:15.329 WARN --- o.a.p.s.s.LastFMScrobbler : Failed to scrobble song 'À vouloir toucher Dieu…' at Last.fm. Unknown response: <html><head

i didn't had this with 10.5

Can not play music with external players

Problem description

I am unable to use external (m3u) players.

The web player does work, but I get no download for a m3u file when using external players. This did work in upstream Airsonic.

Steps to reproduce

  1. Change the player to "External player" or "External player with playlist" in Settings->Players
  2. Play any song
  3. Observe that there is no m3u file being downloaded

System information

  • Airsonic version: 10.6.0-SNAPSHOT.20200406055614
  • Operating system: Debian 10.3
  • Java version:
$ java --version
openjdk 11.0.6 2020-01-14
OpenJDK Runtime Environment (build 11.0.6+10-post-Debian-1deb10u1)
OpenJDK 64-Bit Server VM (build 11.0.6+10-post-Debian-1deb10u1, mixed mode, sharing)
  • Proxy server: nginx, configured for websockets
  • Client: Tried in Chrome and Firefox
  • Language: English US

Layout issue with play queue slider

Hi,

I just noticed a (new) layout issue that might be related to your recent fixes to the top iframe.

When the current queue is slided down, there is a useless right sidebar in the browser:

1

When the queue is slided up, things get worse since I need to scroll down the right sidebar in order to get play controls to show up:

2

Please tell me if the screenshots are not clear enough (I obfuscated most of it...)

Passwords are not usable unless all other credentials for a user are removed from a PostgreSQL database

Problem description

A user (I have only tried this with the default admin user but it seems likely that this will also happen with other users) can not sign in with new credentials after changing them. Only the first supplied credential (in the case of the admin user that password is admin) is usable to successfully sign in. I am using a PostgreSQL database.

Steps to reproduce

  1. Change the default users' password
  2. Observe that a new row in the user_credentials table has been created
  3. Attempt to sign in with the changed password
  4. Observe that the newly supplied password fails
  5. Attempt to sign in with the old password
  6. Observe that sign-on was successful.

System information

  • Airsonic version: 10.6.0-SNAPSHOT.20200406055614
  • Operating system: Debian 10.3
  • Java version:
$ java --version
openjdk 11.0.6 2020-01-14
OpenJDK Runtime Environment (build 11.0.6+10-post-Debian-1deb10u1)
OpenJDK 64-Bit Server VM (build 11.0.6+10-post-Debian-1deb10u1, mixed mode, sharing)
  • Proxy server: nginx, configured for websockets
  • Client: N/A as this is a server issue
  • Language: N/A for aforementioned reason

Additional notes

A workaround would be to remove all rows from user_credentials except for the row containing the newly created password.

Illegal reflective access by org.jaudiotagger.audio.mp3.MP3File (jar:file:/media/sda/airsonic/airsonic.war!/WEB-

Problem description

I'm using the following java command to start airsonic:

/usr/local/src/jdk-11.0.6+10-jre/bin/java -Xmx700m -Dairsonic.home=/media/sda/airsonic/config -Dserver.servlet.contextPath=/airsonic -Dserver.host=0.0.0.0 -Dserver.port=8070 -Djava.awt.headless=true -Dserver.use-forward-headers=true -jar /media/sda/airsonic/airsonic.war --illegal-access=warn

I'm seeing the following WARNING on logfile:

Mär 21 12:02:07 apollo java[16610]: 2020-03-21 12:02:07.436  INFO --- o.a.p.s.CacheConfiguration$CacheLogger   : Cache Key: /media/sda/airsonic/links/musica/HTC Techno/Techno - Sesiones/DJ SEJO CUENCA REMEMBER 90'S/0. DJ SEJO CUENCA presents RECOPILATORIOS REMEMBER 90'S IN SESSION.mp3 | EventType: CREATED | Old value: null | New value: 0. DJ SEJO CUENCA presents RECOPILATORIOS REMEMBER 90'S IN SESSION
Mär 21 12:02:07 apollo java[16610]: WARNING: An illegal reflective access operation has occurred
Mär 21 12:02:07 apollo java[16610]: WARNING: Illegal reflective access by org.jaudiotagger.audio.mp3.MP3File (jar:file:/media/sda/airsonic/airsonic.war!/WEB-INF/lib/jaudiotagger-2.2.5.jar!/) to method sun.nio.ch.DirectBuffer.cleaner()
Mär 21 12:02:07 apollo java[16610]: WARNING: Please consider reporting this to the maintainers of org.jaudiotagger.audio.mp3.MP3File
Mär 21 12:02:07 apollo java[16610]: WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
Mär 21 12:02:07 apollo java[16610]: WARNING: All illegal access operations will be denied in a future release

System information

  • Airsonic version: 10.6.0-SNAPSHOT.20200319171336 – March 19, 2020 at 6:13:36 PM CET

  • Operating system: Ubuntu 19.10 (GNU/Linux 5.3.0-29-generic x86_64)

  • Java version: OpenJDK11U-jre_x64_linux_openj9_11.0.6_10_openj9-0.18.1

  • Proxy server: nginx nginx/1.17.8

  • Client: Chrome Version 80.0.3987.106 (Offizieller Build) (64-Bit)

  • Language: UTF8

Additional notes

on startup following warnings apper:

2020-02-18 17:44:43.264  INFO --- o.a.p.service.SettingsService            : Removing obsolete property [PortForwardingPublicPort]
2020-02-18 17:44:43.277  INFO --- o.a.p.service.SettingsService            : Removing obsolete property [PortForwardingLocalPort]
2020-02-18 17:44:43.278  INFO --- o.a.p.service.SettingsService            : Removing obsolete property [DownsamplingCommand]
2020-02-18 17:44:43.279  INFO --- o.a.p.service.SettingsService            : Removing obsolete property [DownsamplingCommand2]
2020-02-18 17:44:43.279  INFO --- o.a.p.service.SettingsService            : Removing obsolete property [DownsamplingCommand3]
2020-02-18 17:44:43.280  INFO --- o.a.p.service.SettingsService            : Removing obsolete property [AutoCoverBatch]
2020-02-18 17:44:43.280  INFO --- o.a.p.service.SettingsService            : Removing obsolete property [MusicMask]
2020-02-18 17:44:43.280  INFO --- o.a.p.service.SettingsService            : Removing obsolete property [VideoMask]
2020-02-18 17:44:43.281  INFO --- o.a.p.service.SettingsService            : Removing obsolete property [CoverArtMask]
2020-02-18 17:44:43.281  INFO --- o.a.p.service.SettingsService            : Removing obsolete property [HlsCommand]
2020-02-18 17:44:43.282  INFO --- o.a.p.service.SettingsService            : Removing obsolete property [HlsCommand2]
2020-02-18 17:44:43.282  INFO --- o.a.p.service.SettingsService            : Removing obsolete property [JukeboxCommand]
2020-02-18 17:44:43.282  INFO --- o.a.p.service.SettingsService            : Removing obsolete property [CoverArtFileTypes]
2020-02-18 17:44:43.283  INFO --- o.a.p.service.SettingsService            : Removing obsolete property [UrlRedirectCustomHost]
2020-02-18 17:44:43.283  INFO --- o.a.p.service.SettingsService            : Removing obsolete property [CoverArtLimit]
2020-02-18 17:44:43.284  INFO --- o.a.p.service.SettingsService            : Removing obsolete property [StreamPort]
2020-02-18 17:44:43.284  INFO --- o.a.p.service.SettingsService            : Removing obsolete property [PortForwardingEnabled]
2020-02-18 17:44:43.284  INFO --- o.a.p.service.SettingsService            : Removing obsolete property [RewriteUrl]
2020-02-18 17:44:43.284  INFO --- o.a.p.service.SettingsService            : Removing obsolete property [UrlRedirectCustomUrl]
2020-02-18 17:44:43.285  INFO --- o.a.p.service.SettingsService            : Removing obsolete property [UrlRedirectContextPath]
2020-02-18 17:44:43.285  INFO --- o.a.p.service.SettingsService            : Removing obsolete property [UrlRedirectFrom]
2020-02-18 17:44:43.285  INFO --- o.a.p.service.SettingsService            : Removing obsolete property [UrlRedirectionEnabled]
2020-02-18 17:44:43.286  INFO --- o.a.p.service.SettingsService            : Removing obsolete property [UrlRedirectType]
2020-02-18 17:44:43.286  INFO --- o.a.p.service.SettingsService            : Removing obsolete property [Port]
2020-02-18 17:44:43.286  INFO --- o.a.p.service.SettingsService            : Removing obsolete property [HttpsPort]
2020-02-18 17:44:43.287  INFO --- o.a.p.service.SettingsService            : Removing obsolete property [MediaLibraryStatistics]
2020-02-18 17:44:43.287  INFO --- o.a.p.service.SettingsService            : Removing obsolete property [LastScanned]

Playlist weird web reactions when passing the mouse over it.

Problem description

I'm using the following java command to start airsonic:

/usr/bin/java -Xmx700m -Dairsonic.home=/media/sda/airsonic/config -Dserver.context-path=/airsonic -Dserver.host=0.0.0.0 -Dserver.port=8070 -Djava.awt.headless=true -Dserver.use-forward-headers=true -verbose:gc -jar /media/sda/airsonic/airsonic.war --illegal-access=warn

Maybe you already noticed it. Moving the mouse over the playlist section, produces weird quick movement. See the animated gif.

System information

  • Airsonic version: `

  • 10.6.0-SNAPSHOT.20200406171011 – April 6, 2020 at 7:10:11 PM CEST`

  • Operating system: Ubuntu 19.10 (GNU/Linux 5.3.0-29-generic x86_64)

  • Java version: zulu13.29.9-ca-jdk13.0.2-linux_amd64 / OpenJDK11U-jre_x64_linux_openj9_11.0.6_10_openj9-0.18.1 / OpenJDK13U-jre_x64_linux_openj9_13.0.2_8_openj9-0.18.0.tar

  • Proxy server: nginx nginx/1.17.8

  • Client: Version 80.0.3987.163 (Offizieller Build) (64-Bit)

  • Language: UTF8

As usual, thanks for your intensive work.

Alt Animated Gif

Default admin password still works after changing

Problem description

Can still log into the admin account with the default password of "admin", ever after changing the password.

Steps to reproduce

  1. Login as admin with default password
  2. Go to Settings > Users >Select user >admin
  3. Tick Add Credentials
  4. Enter password twice
  5. Click Save
  6. Log out
  7. Log in with admin and password of "admin"

System information

  • Airsonic version: 10.6.0-SNAPSHOT.20200411233507
  • Operating system: Docker
  • Client: Firefox

Additional notes

Can log in with the new password as well as the default admin password.

Airsonic service won't start

I had issues with some of the newer snapshots not working, the webserver and player application never start (but the service does). The log always ended with the DLNA server shutting down, and nothing after that (and no fatal exceptions).

Anyway, with the latest version 11.0.0-SNAPSHOT.20200425031103, the airsonic service is now failing to start with an exit code 1.

systemctl status airsonic:

 Apr 25 10:24:16 Fractal systemd[1]: airsonic.service: User lookup succeeded: uid=970 gid=970
 Apr 25 10:24:16 Fractal systemd[1391419]: airsonic.service: Executing: /usr/bin/java -Xmx700m -Dairsonic.home=/var/airsonic -Dserver.context-path=/airsonic -Dserver.port=8080 -D>
 Apr 25 10:24:17 Fractal systemd[1]: airsonic.service: Failed to read oom_kill field of memory.events cgroup attribute: No such file or directory
 Apr 25 10:24:17 Fractal systemd[1]: airsonic.service: Child 1391419 belongs to airsonic.service.
 Apr 25 10:24:17 Fractal systemd[1]: airsonic.service: Main process exited, code=exited, status=1/FAILURE
 Apr 25 10:24:17 Fractal systemd[1]: airsonic.service: Failed with result 'exit-code'.
 Apr 25 10:24:17 Fractal systemd[1]: airsonic.service: Service will not restart (restart setting)
 Apr 25 10:24:17 Fractal systemd[1]: airsonic.service: Changed running -> failed
 Apr 25 10:24:17 Fractal systemd[1]: airsonic.service: Unit entered failed state.
 Apr 25 10:24:17 Fractal systemd[1]: airsonic.service: Control group is empty.

That looks possibly specific to my machine, but I'm unable to reboot currently. It will have to wait until rdiff-backup is finished running later today.

Can't run/debug Airsonic-Advanced with IntelliJ

Problem description

Hi buddies,
I would like start to contribute to Airsonic-Advanced (I'm quit a beginner, so don't expect to much). To do that I followed these instructions to build and run/debug Airsonic-Advanced.
https://airsonic.github.io/docs/developer/intellij/#use-embedded-spring-boot
I can run Airsonic -> Lifecycle -> package and this finishes without any error, but some warnings. So all good so far. But when I start the run/debug config "Application" I'm getting the following error. Something seems to be wrong with my Spring Boot config, but I can't figure out what it is.

Java HotSpot(TM) 64-Bit Server VM warning: Options -Xverify:none and -noverify were deprecated in JDK 13 and will likely be removed in a future release.
15:39:56.672 [main] DEBUG org.springframework.boot.context.logging.ClasspathLoggingApplicationListener - Application failed to start with classpath: unknown
15:39:56.691 [main] ERROR org.springframework.boot.SpringApplication - Application run failed
java.lang.ExceptionInInitializerError: null
	at org.airsonic.player.service.SettingsService.<clinit>(SettingsService.java:155)
	at org.airsonic.player.spring.LoggingFileOverrideListener.onApplicationEvent(LoggingFileOverrideListener.java:20)
	at org.airsonic.player.spring.LoggingFileOverrideListener.onApplicationEvent(LoggingFileOverrideListener.java:15)
	at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:172)
	at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:165)
	at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:139)
	at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:127)
	at org.springframework.boot.context.event.EventPublishingRunListener.environmentPrepared(EventPublishingRunListener.java:76)
	at org.springframework.boot.SpringApplicationRunListeners.environmentPrepared(SpringApplicationRunListeners.java:53)
	at org.springframework.boot.SpringApplication.prepareEnvironment(SpringApplication.java:345)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:308)
	at org.springframework.boot.builder.SpringApplicationBuilder.run(SpringApplicationBuilder.java:140)
	at org.airsonic.player.Application.main(Application.java:81)
Caused by: javax.validation.ValidationException: HV000183: Unable to initialize 'javax.el.ExpressionFactory'. Check that you have the EL dependencies on the classpath, or use ParameterMessageInterpolator instead
	at org.hibernate.validator.messageinterpolation.ResourceBundleMessageInterpolator.buildExpressionFactory(ResourceBundleMessageInterpolator.java:116)
	at org.hibernate.validator.messageinterpolation.ResourceBundleMessageInterpolator.<init>(ResourceBundleMessageInterpolator.java:47)
	at org.hibernate.validator.internal.engine.ConfigurationImpl.getDefaultMessageInterpolator(ConfigurationImpl.java:474)
	at org.hibernate.validator.internal.engine.ConfigurationImpl.getDefaultMessageInterpolatorConfiguredWithClassLoader(ConfigurationImpl.java:650)
	at org.hibernate.validator.internal.engine.ConfigurationImpl.getMessageInterpolator(ConfigurationImpl.java:397)
	at org.hibernate.validator.internal.engine.ValidatorFactoryImpl.<init>(ValidatorFactoryImpl.java:183)
	at org.hibernate.validator.HibernateValidator.buildValidatorFactory(HibernateValidator.java:38)
	at org.hibernate.validator.internal.engine.ConfigurationImpl.buildValidatorFactory(ConfigurationImpl.java:364)
	at javax.validation.Validation.buildDefaultValidatorFactory(Validation.java:103)
	at org.airsonic.player.util.Util.<clinit>(Util.java:202)
	... 13 common frames omitted
Caused by: java.lang.NoClassDefFoundError: javax/el/ELManager
	at org.hibernate.validator.messageinterpolation.ResourceBundleMessageInterpolator.buildExpressionFactory(ResourceBundleMessageInterpolator.java:108)
	... 22 common frames omitted

Process finished with exit code 1

I also tried to build and run the vanilla Airsonic. There I was sucessfull.

What can I do to get over this? What did I miss?

System information

  • Airsonic version: Edge Release 10.6.0-SNAPSHOT.20200424035525
  • Operating system: Windows 10
  • Java version: jdk-14.0.1
  • IntelliJ version: 2020.1

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.