-
Notifications
You must be signed in to change notification settings - Fork 7
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Albums start showing up as blank after clicking through other ones #85
Comments
I can reproduce this with a gonic server. Its not just after going through other albums, going [..] one level and back in triggers it. Removing the if check from: Lines 341 to 343 in 4a8428b
makes the problem go away, but that's going to cause problems for whatever case necessitated that in the first place. As for what's causing this:
|
I think this is a dupe of #82. I'm working on it. It's ultimately related to the fact that Subsonic -- and stmps in turn -- look at music in two conflicting ways: as a filesystem, and as a tree of things organized by metadata. As you've found, some API calls return incomplete data if the filesystem structure doesn't match the tags. I can replicate this, and it'll be resolved when I fix #82. |
This would be a dupe, yeah. But just to clarify, its not incomplete data, just the Response type is different. Matching tags wouldn't affect anything since its a completely different object. The song entities are there, just in a different substruct. Logging the value of the Would just changing how the cache indexes responses help, since the key is already a string? Combining the id with some identifier of the endpoint might resolve this. Everything else should keep working as is, and any case where the server might respond with 2 different views, the object would be saved according to the endpoint. So |
First, this is a good observation, and it changes how I'm thinking about the solution. It comes at a good time, too, because I dropped this for other Life Events a couple of months ago and have forgotten where I was with this. Second, let me say issues like this are why we might prioritize #39. The bespoke Subsonic client in stmps is really kludgey, stuffing a bunch of different responses into one struct in a union-type-but-not-really thing. It's not particularly type safe, and error prone (tomAto, tomAHto). Third, as I mention in #82, there's also a disturbing amount of indirectly linked information in stmps, which you have also observed. Better encapsulation might help, but it'd be a large refactoring, and there's already one going on. I think I'm not going to try to address that in this issue, and will simply try to implement the least invasive fix in the hopes of a quick merge. Right now, I'm thinking that if we make a fresh call and get empty information that would overwrite non-empty data, we don't do that. This may necessitate a dirty or source bit, to handle the edge case where information really is removed on the server side, but I suspect that's so edge we can ignore it for now. |
So, there's a lot to unpack here. First, there's this concept of a "parent ID" which is not clearly defined in the API. Is it a directory ID? An album ID? Could be either! Compounded by the fact that we shove every response into the same struct type, it leads to confusion -- and, in particular, something I did in conflating the IDs in the directoryCache with album IDs. So I'm starting to clean this up; GetAlbum() won't return a SubsonicResponse, but an Album. We do, after all, have an Album type. As we do have Directory type, and all of the other specific types for which we currently return SubsonicResponses when we Get() them. The only truly ugly thing here is SubsonicEntity, which the OpenSubsonic API uses as a generic catch-all for "things on the server". However, I'm increasingly thinking we need to bite the bullet and implement #39. The bespoke Subsonic API we have really is a mess. I'm going to see if I can fix this with minimum fuss, but any further bugs or API changes, honestly, we just need to switch to a specialized library. @spezifisch I know you're busy with other things, but what are your thoughts here? |
I would assume "parent" means the parent directory, given the "Child" object also has an "albumId" variable. But the opensubsonic docs state the parent is "The id of the parent (folder/album)". The worst part is the "parent" attribute is optional for the response. |
I've come to the conclusion that the UI is a lie, and we need to rethink the model. The Browser tab says it's listing Artists in the first column, and either Songs or Albums in the second. But that's not what is going on in the program; it's working on Directories, which can be anything but a song. It's not built from the music metadata, but from the directory structure. A directory can be a folder with some loose songs and a subdirectory with an album, and in the UI, this is what was being shown. If that's what it said was being shown, that would be fine, but it isn't: stmps claims what's in the left column is Artists, and what's in the right is Songs or Albums (but never both). Over time, as features have been added - mostly the ones I've added, which tend to focus on the metadata - this issue has been exacerbated and now the model is breaking. There are two options here:
In case 2, instead of fetching Directories as stmps currently does, it'd fetch Artists, and put those in column 1. When an Artist is selected, it'd fetch the Artist's Albums and put that in column 2. No loose files -- songs are always under albums. Selecting an Album shows Songs. Then the titles are true, and we can always know what state we're in, which is impossible with Subsonic Directories (which are, after all, dumb folders). We still need a Directory browser, because no library of any size has entirely clean metadata; there may be songs without Artist or Album set, in which case, they are invisible. But I argue this should be a fallback, not the default, which is what stmps (and stmp before it) does. |
Your comment came in as I was writting my essay. To be clear, Subsonic Directories have no semantics. They're folders. They have a parent ID, the root of which tree is just the root; in gonic, it's "al-1". Entities in Directories are also not typed; there's a flag that says whether it's itself a directory or not, and if not, we can assume it's a song, but if you fetch directory "al-1" from gonic, you get a bunch of other directories and any loose songs, and there's nothing to tell you whether any child is an album or artist. BTW, pre-fork stmp behaves the same way. Browse and select an artist and then click "[..]", and you get the same content that's in the "artist" column. This has been broken since before @spezifisch forked the project, because it's based on browsing directories and pretending it's browsing metadata. |
I pushed a new branch, based off main, that has a major refactoring which changes the browser to be entirely metadata-based. While I believe that Navidrome users may not see a difference in visible content, gonic users will. Gonic draws a clear distinction between "Directories" and "Artists"/"Albums". Directories, and the related API calls, reflect the filesystem structure; Artists & Album API calls reflect the music metadata tags. The OpenSubsonic documentation itself conflates Directories and Artists/Albums: an Artist ID is also a valid Directory ID, and Navidrome's implementation is therefore more "correct." The author of gonic, disagrees with this and the implementation behaves consequently differently. For example, consider a filesystem:
where the song "Iron Man" is correctly tagged with artist and album. Navidrome and gonic will present two different views of this. This has been a source of some odd behaviors in stmp (and then stmps, which inherited the model). stmp's "Browser" page calls the left column "artist" and the right "song" or "album"; however, underneath it is accessing all of the content through the Index and Directory API, which means in gonic the left column is merely the top-level folders of the filesystem, and the right is whatever subdirectory filesystem is being navigated (with the context being determined by whether the current directory has a "parent" or not, an unreliable measure). Navidrome is a little more consistent with the API documentation which claims that "Index" returns "Authors" but also in the "Directory" calls claims that IDs returned by Index can be used to reference filesystem entries. Fundamentally, the OpenSubsonic API, and Navidrome, assume a strictly ordered filesystem layout: the audio directory contains Authors, and each Author directory contains Albums, and Albums contain songs. If your library follows this strictly, and the server assigns IDs to things under this assumption (as Navidrome does), then it doesn't matter which API calls you use. However, if your library has files at the top audio directory, or maybe directly under author directories, or maybe you have some albums that are at the top level and are not under an author directory... things get messy with Navidrome. gonic handles the latter case better, but it also does not conform to the API spec because IDs are not fungible between the Index/Directory views and the metadata (tag) Author/Album/Song view. Personally, I believe that many libraryies of any significant size are not going to be 100% clean, and that gonic's approach is in this case better. I also believe that servers should follow the API spec, and both can't be true. Consider my "Amy Grant/Black Sabbath" example above. So: I'm in the process of doing two things that are major renovations. The first is this new branch "metadata-based-browser", which completely removed all code accessing the Index and Directory API calls by the browser page. The columns are now populated entirely by the Artist and Album API calls, which (per the spec) are built by metadata in the song files and not by the directory structure. The downside is that files will not be accessible if the IDv3/Vorbis tags are not clean; if a file is missing an ARTIST tag, it'll never show up, because the tree now (truly) starts with Artists. The second step will be implemeting a browser view that only uses Index and Directory API calls. It'll basically be a filesystem browser, which is really what those APIs provide. This will allow you to access those poorly-tagged files. When I do this, I'm also going to add a feature that highlights files with missing structural tags (author & album) so you can use stmps to identify files that need their metadata sanitized. I'm not going too far with this, because fixing metadata isn't stmps' job, but combined with the search function I think it'll be helpful enough. I would appreciate any testing people are willing to do. If you grab that branch, you'll get the main branch plus my changes related to this feature. This should also address #82/#85. It may also have bugs, since I haven't thoroughly tested all features; however, since it mainly affects the browser page, in a way it's constrained and should not impact other pages. |
There's another new branch: xxxserxxx. It contains all of my outstanding PRs, including the metadata refactor. This branch has a bug that prevents fully browsing Navidrome servers; I know why, it's just too late for me to fix it tonight. These enhancements include:
I'll be pulling in other people's PRs as soon as I address a couple of things, which I'll do in the next few days:
Then I'll pull in other outstanding PRs. Finally, in no particular order, I would like to address the following items, none of which are a huge amount of work:
Again, feedback on the |
Problems I've noticed so far on your branch:
|
Thanks @mahmed2000. The first two are probably related to the refactoring. The last one I'm going to guess is how it behaves on the other branch: the loading happens in a thread, and there's no user interaction interruption in either branch. I've been aware of it, but haven't prioritized it. Although I didn't mention it, I've decided that my implementation of playlist population is inconsistent with the rest of the UI: it proactively deeply populates playlist data into memory, whereas in all other cases, stmps pulls data only as users browse. In one way, it makes the user experience more snappy once the data is cached; in another, it adds complexity and uses more memory. There are three solutions:
#1 is fraught. It has the same problem as #4, in that there's no way to detect server-side changes, and I worry about memory use. #4 is, I think, impractical for the reasons I listed. #3 increasingly bothers me aesthetically -- it's a drastic departure from how the rest of stmps operates, and really is a lot of added complexity. Therefore, unless a hue and cry is raised, I'm going to factor out all of that background loading, and make playlists behave like any other tree data. |
@mahmed2000 #1 is fixed. |
@mahmed2000 #2 is fixed |
So, I did a better job on the threading than I thought, and user events should be interrupting the search properly. In any case, I can't get either my gonic or Navidrome to respond so slowly that I can trigger the issue you're seeing with your search issue. I believe it's happening, but I can't reproduce it. I'm going to backburner it and knock out some other more critical usability issues, such as the (now) missing directory browsing functionality. Directory browsing is probably not as important on Navidrome, but the way gonic is implemented, it's critical to get at files that aren't well-tagged. I'm now moving this conversation to a different ticket. This set of changes is relatively large, and @spezifisch is going to be overwhelmed by them; I want to track the branch progress in a dedicated tracker. |
i don't really know how to properly describe this issue, so here's a screen recording:
recording.mp4
bisected it down to be a regression from 0754fdf, sadly
The text was updated successfully, but these errors were encountered: