Replies: 17 comments 29 replies
-
The diff: master...jsmtux:separate_ui I have some initial concerns about naming conventions, but they'd be better suited in a proper PR. |
Beta Was this translation helpful? Give feedback.
-
Placing this here for inspiration #1911 :) |
Beta Was this translation helpful? Give feedback.
-
Tagging @LMMS/developers. |
Beta Was this translation helpful? Give feedback.
-
First of all, thank you for your interest and efforts on LMMS. |
Beta Was this translation helpful? Give feedback.
-
Hi LMMS developers, I've been doing quite some work in the past few days and would like your feedback. As I've been reading in this and other discussions, there is a lot of interest in heavily refactoring the core library of LMMS. I had a feeling that my initial plans for the GUI separation wouldn't effectively enable you to do this properly. Because of this, I'll extend my scope to provide an interface for core as well as for the GUI part: As you can see in the diagram above, both GUI and Core are now separated into interface and implementation modules. The Core implementation needs to make use of the GUI interface so that it can for example show messages or request updates. The Core interface will have almost no dependencies, whilst the Core implementation will depend on all the relevant sound libraries. On the interface side, the division is quite similar. Interface has a very limited set of dependencies and each of the implementations will decide what they need. For the QWidgets implementation we'll depend on Qt Widget library. Of course, both GUI implementations will need to call elements from the Core Interface, but that doesn't mean they can now access all core or care about its dependencies. As you can imagine, this is quite some more work, but I think it does belong in this package. Thanks to this separation, it will now be possible to change the Core implementation completely, as long as the interface remains the same. Moreover, it will be much clearer when implementing the headless gui to see what I should be calling or doing, since I won't be needing to scan throughout the whole core codebase, just only the relevant interfaces. Moreover, I'd say this whole exercise will simplify the linking process. Since now we'll be mostly linking against interfaces and not real implementations, many of the fixes in the CMake files around this will hopefully become redundant and the process more robust. I created the core_header_separation branch on top of the previously shared separate_ui one. As it is, only the lmms_headless target is currently building but it effectively shows the plans I've tried to explain and progress I've been doing. I'll appreciate any feedback or comment Cheers! |
Beta Was this translation helpful? Give feedback.
-
Hi Guys, It has been a while, partly because of having less time to spend on this project, but mostly because of this starting to get a bit complex whilst trying to separate core and UI. As explained above, I wanted to expose a series of interfaces from the core to the outside. This way, UI won't need to have more knowledge about core's implementation, allowing for neater API and remove compile time dependencies. However, because of the long inheritance chains we have in LMMS, it was getting increasingly harder to create proper interfaces and only expose what I need. After a lot of failed attempts, I think I found the way to go and wanted to open the conversation about it here. The biggest change I need to incorporate is to remove the As you can see there, The option I am trying to implement, and you can have a look at it in my branch refactor_model_out_2, is that I was very happy to see that this new implementation makes the code much better. Before, This change, on top of improving the code as exposed above, will allow us to do things like the following: Which allows creating a proper interface to Let me know about your opinions or suggestions. |
Beta Was this translation helpful? Give feedback.
-
Hey @jsmtux, it's been some time since this discussion was taken a look at. It seems you have done some admirable work here, so I just wanted to check on its status. I did have some questions (not fully understanding why inheriting |
Beta Was this translation helpful? Give feedback.
-
Hi guys, After quite a few months of work, I finally have something meaningful to share. You can have a look at the src/core/interface folder in my core_interfaces_ready to see how the final interfaces could look like. In its current state, the code is quite useless as I still didn't take a decision on how to handle the plugin separation, and the lmms target is not able to fully link because of this. However, I think it is already useful to share because it shows how all the existing functionality in the QWidgets GUI can be implemented with a minimal set of interfaces exposed in the core library. I will now try to share a summary of the whole change, and how I think this can be useful to LMMS project. Process followed to get hereAs you can read earlier in this thread, the first step I took was to separate Once this was done, I removed dependencies from The real fun began when I tried removing the dependencies from
Especially at first, mainly because of long inheritance chains, this was not that straightforward. When I found a big roadblock in the process I stashed the changes and went back to the last working commit. Then made the necessary changes, tested it, and rebased the interface separation on top of it, reducing the number of changes in that commit. As I said, the head of the branch cannot be fully built, but everything until that point can be compiled and tested, with most of the bundled songs and samples working and the interface being quite usable. Finally, after following the cycle for months, this is the first time that the code QWidgets code compiles. I am quite happy to share this update with as it shows quite well what my vision for the future architecture is. I don't expect it will take me that a long time to fix things enough to run again, but I felt it was a big enough achievement to update you about. Possibilities enabled by this changesThe exposed interfaces show a vertical slice of all the LMMS functionalities. If we were to tidy them up a bit and document them, we would get a much better understanding of the inner workings of the software, and envision new ways of simplifying and extending it. A developer working with the core library won't need to care about how their changes would affect the GUI, as long as the external interfaces are kept the same. Someone implementing a new gui, or extending an existing one, wouldn't need to have any knowledge of the inner workings of LMMS, just know the available interfaces, as with any other library. This would even allow for different LMMS versions to exist. The same base library can be shared by the main software and from a reduced version for Android devices, for instance. With careful versioning of the interfaces, improvements to the core would arrive to all versions seamlessly. How to continue from hereI understand that, even if I got everything working again and rebased on top of master, it will be quite a big undertaking to get this integrated into LMMS. Even so, I'd say we'd be able to find a sort of organized, low risk approach. The first step is, I think, to agree on the end goal. It will be very helpful if you could start having a look at the branch and comment on it. There are countless improvements that can be made to the interfaces, and some of the intermediate steps I took could be simplified or improved. Once the end goal is agreed upon, we could start integrating one by one each change, and split up the bigger ones to make them manageable, making sure everything works before continuing to the next integration. The commit where the interfaces get hidden is huge, because at the moment I was developing it it was much simpler to hide all at once. Now that we know what we'll be needing from each class, we can start creating the interfaces in separate testable commits and only restrict the access to core once most of the interfaces are in place. The other part of the project (the more exciting one, I guess), is to take the exposed interfaces and produce working alternative GUI implementations. Getting the command line one to do useful processing will greatly improve our testing capabilities. Getting a sample QML working for the most basic tasks would probably be a very good demonstration of the new architecture. This can be achieved in parallel to the integration, but it might not be the highest priority. A less desireable alternativeThere is another way of going along with this, that in my opinion is not how we should go about it, but can have some advantages anyway. The biggest part of the changes is about getting the existing QWidgets interface working. In the future, as we improve the interfaces, keeping the GUI in sync with it will also take most of the effort. The alternative would be something like an "LMMS 2", where we would start by deleting the QWidgets implementation and from there rebuild the GUI in QML without needing to care about all this legacy. This alternative has two big disadvantages, the first being the constant need to rebase from main LMMS to get the latest improvements to the core and the second being that this "LMMS 2" would be unusable for months, and would take even longer to reach feature parity with the legacy version. Final wordsIn any case, please have a look that the changes and let me know your opinion on them and your thoughts about their integration. Thanks |
Beta Was this translation helpful? Give feedback.
-
Hi Guys, After my previous post didn't have much response, I felt I hadn't properly explained the opportunities that were enabled by exposing the interfaces in a clean and separate way from the core application. I hope the demo that follows will better show my intentions 😉 lmms_demo.mp4As you could expect, it is all pretty bare bones, with only kicker and triple oscillator plugins enabled, defaulting to quite a simple project file, little interaction and only works on macOS. Most of these issues, though could be easily fixed, I'll happily receive your comments on what you'd be more interested on. Now for the good news, you can read or get the code right now at my qt_6_qml_poc branch, it works using Qt6.6 and the QML code it needs is very small and quite self explanatory. The reason I am most happy about is that, even though a huge effort remains, most of it is pretty mechanical. In the near future I expect to have an in depth write about how this was achieved and how to contribute, for the moment I'll enjoy my holidays. Cheers! |
Beta Was this translation helpful? Give feedback.
-
I thought of something some time ago and mentioned it in the discord but forgot to mention it here. What i would like to say is that it makes some sense for a 3 way split rather than a mere core-gui seperation (atleast according to me). The first layer, ie the "core" can be just the base audio engine and the bare OS agnostic layer. This should be completely free of qt. The second layer, ie the "interface" can contain the necessary qt stuff needed to work and also the OS/platform specific layers. This layer can also help with qml integration as there might still need to be some non gui qt for some time. The third layer shall be for gui. The core and gui can call into the interface for any communication. This approach might add a middle layer but overall, i feel this approach might improve seperation of concerns. What do you think of ths? |
Beta Was this translation helpful? Give feedback.
-
Hi all, First I would like to thank all the LMMS developers for giving me inspiration and many rewarding hours I've spent composing and hacking through your code. It was a while ago I created a local branch in LMMS version 1.13 and implemented a method of Dynamic Transposition described at tectral.com. Now I decided to re-implemented it in the most recent version of LMMS but found the current version to be quite different from what it was back then and a direct merging of the branch was not possible. And here I found this chat about a possible GUI re-implementation which seems to make sense. So, my question is if this would be more appropriate to fork my project from this new branch. Also, I was wondering where can I learn about how the micro-tonality option was implemented in LMMS. The reason is that dynamic transposition is essentially a "just intonation" scale with an extra transposition track which determines in what key the music is played in each measure. So, I could use micro-tonality for that. Back then I implemented it directly using fractional frequencies. Andrei |
Beta Was this translation helpful? Give feedback.
-
May I ask if you are planning to open a PR for your branch any time soon? As a fellow new contributor, I've been following what you're doing with quite a bit of interest, and hope to see your impressive efforts get more attention. |
Beta Was this translation helpful? Give feedback.
-
Is it possible to mix classic QWidgets with QML? If that was the case then another approach might be to do the reorganization with regards to the interfaces, merge them into master and then to switch one element after the other to QML. I think something like this might be more feasible than a "big bang" approach where everything would have to be switched/reimplemented before it is merged back into master. |
Beta Was this translation helpful? Give feedback.
-
Hi guys, I haven't had much time lately to work on LMMS, but still did do quite some progress I wanted to share 2024-04-01.17-06-05.mp4As you can see, the list of projects is now displayed, the active song can be switched and there is some interaction possible with the pattern tracks. If anyone wants to try it, you'd need to install the base qt6 and qtquick development libraries and execute: Lots of things crash at the moment, like opening a song with a Let me know what you think Cheers! |
Beta Was this translation helpful? Give feedback.
-
Hi LMMS team. I come bringing some good news 🎉 . The first is that I feel this exploratory process I am doing is now complete. Once I had a promising separation of core and GUI I continued working on this Qt6 QML prototype to prove its usefulness. As one of the advantages of QML is seamless Android support, I decided I would tackle that to support this exercise. Now that an Android prototype is complete, I think it is time for me to try to formally merge some of my changes. I'll try in the coming weeks to get some PR that at least starts by modifying some of the compilation options. Now to the fun stuff: lmms_android_demo.1.mp4As always, you can find the changes to the code in my branch qt_6_qml_android_poc As you can see some things do work, more or less the same as in the prototype for desktop. The main missing thing is currently AudioFileProcessor sample loading, somehow it is not finding the files. And of course the UI is too big 😅. The main step for getting this to work was cross compiling the necessary libraries, for some of them it was a bit painful. The ones I used were:
Then, for the audio I needed to write an (AAudio)[https://developer.android.com/ndk/guides/audio/aaudio/aaudio] backend. It is a very nice framework that supports high performance and low latency audio. I didn't use it to its fullest yet, but even so it works quite nicely, even in debug builds. Another painful part had to do with storage permissions, as newer Android are quite strict there. In the end I packed everything as resources and wrote a Java Activity that gets them and writes them to the application folder. Finally, Android does not support shared memory across processes, which of course means no VST support. I added some dummy VST handler and some ifdefs in the code. It is a bit dirty. So that's it, let me know what you think |
Beta Was this translation helpful? Give feedback.
-
You can use vcpkg to deal with cross compiling those libraries instead of dealing with the hassle yourself. I hope you will find the necessary resources. Don't hesitate to ask help if stuck. For Qt, i believe you can use the official installer for Android libraries too. |
Beta Was this translation helpful? Give feedback.
-
So, as shared in a previous update, I've decided to start to find a way to merge the changes for the prototype. If you have a look at the prototype branch, you'll see it is a huge change we cannot expect anyone to review unless it is split into very small, atomic increments. The one problem that splitting could have is that we lose track of what we're trying to accomplish, so I'll first try to document the end goal and then will expose the first chunk of changes, that I think you'll be able to quickly review so we can at least be on the same page to discuss what is ok and what could be improved. End goalThe end goal for this separation is:
Current changeThe change I'd like now to submit for consideration is, I think, the minimum first step. There are no code changes here at all. The only changes are include files moved between folders. The CMake changes are only for setting new include directories. I don't expect the output binaries to change in any significant way. What I did is
Even if this change does little, it will enable lots of other small increments. For example, we could now start moving most of the files under You can see the PR at #7341 Thanks in advance for your comments! |
Beta Was this translation helpful? Give feedback.
-
tl;dr : I created a branch that has separated the UI from the core code of lmms and would like help to test, improve it and eventually merge.
Hi all,
First of all would like to express my gratitude for such a nice open source application, I always try to use open source software in my day to day, and I feel this is the best music making software available in that category. Because of this, and since I've worked in the past in similar GUI applications, I would like to share how I feel it could be improved, and the steps I already took to make that happen.
I think for any newcomer to the software, the first impression is that the UI is quite dated and inflexible. More important, after having a look at open issues and discussions, there are lots of improvements that cannot be achieved because of the way the UI code is intertwined with the core functionality.
A few weeks ago I started a proof of concept for separating the UI from the rest, with the aim of being able to compile the core of the app without the Widgets dependency. The first step was to make the ui a separate compile unit. If you look at the current CMake scripts, they just gather all sources and compile them together, making it impossible for them to have different dependencies.
Then, I started taking all the UI header files out of the 'include' folder and put them into the UI folder. This way, I could make sure that core was not calling any of them. After this was done, I needed to slightly modify the plugins to indicate they were QWidget plugins, as each one of them contains UI information.
With this, I managed to create a core library that is used by a new target, lmms_headless, that produces an executable that can be invoked from command line and has no QWidget dependencies, and the previous lmms executable. Even if it mostly works, I've only modified files compiled as a default in a Linux system. There are obvious things that don't fully work like the open/save dialogs, but it is already possible to test lots of the functionality.
I'll continue working on this on my spare time, but it would be fantastic to get help testing the software and making sure all targets and options compile and work, so that it could eventually be merged. You can find it here.
My current plans for the future include moving the rest of the headers out of the include folder to keep them close to the cpp files. Possibly only expose interfaces to outside units, like plugins. And finally create a proof of concept for a QML implementation, which would look more modern and work on mobile targets.
Please, let me know your thoughts on this proposal.
Beta Was this translation helpful? Give feedback.
All reactions