From a4d4c49de97543719964714a55065b3f463b9b6e Mon Sep 17 00:00:00 2001 From: Sagi Dayan Date: Tue, 16 Jan 2024 17:21:35 +0200 Subject: [PATCH] initial commit Signed-off-by: Sagi Dayan --- .gitignore | 2 + .golangci.yml | 76 ++++ LICENSE | 674 ++++++++++++++++++++++++++++++ Makefile | 33 ++ README.md | 91 ++++ assets/screenshot-miniplayer.png | Bin 0 -> 117433 bytes assets/screenshot.png | Bin 0 -> 103752 bytes go.mod | 28 ++ go.sum | 83 ++++ internal/client/artwork_cache.go | 97 +++++ internal/client/client.go | 163 ++++++++ internal/common/shuffle.go | 21 + internal/config/colors.go | 21 + internal/config/config.go | 123 ++++++ internal/playback/controller.go | 223 ++++++++++ internal/playback/desktop.go | 10 + internal/playback/mpris.go | 249 +++++++++++ internal/playback/queue.go | 84 ++++ internal/tui/tui.go | 124 ++++++ internal/tui/views/albums.go | 73 ++++ internal/tui/views/artists.go | 70 ++++ internal/tui/views/button.go | 21 + internal/tui/views/help.go | 113 +++++ internal/tui/views/layout.go | 398 ++++++++++++++++++ internal/tui/views/login.go | 73 ++++ internal/tui/views/main.go | 616 +++++++++++++++++++++++++++ internal/tui/views/player.go | 117 ++++++ internal/tui/views/playlists.go | 63 +++ internal/tui/views/queue.go | 81 ++++ internal/tui/views/status_line.go | 98 +++++ internal/tui/views/view.go | 15 + main.go | 42 ++ renovate.json | 6 + 33 files changed, 3888 insertions(+) create mode 100644 .gitignore create mode 100644 .golangci.yml create mode 100644 LICENSE create mode 100644 Makefile create mode 100644 README.md create mode 100644 assets/screenshot-miniplayer.png create mode 100644 assets/screenshot.png create mode 100644 go.mod create mode 100644 go.sum create mode 100644 internal/client/artwork_cache.go create mode 100644 internal/client/client.go create mode 100644 internal/common/shuffle.go create mode 100644 internal/config/colors.go create mode 100644 internal/config/config.go create mode 100644 internal/playback/controller.go create mode 100644 internal/playback/desktop.go create mode 100644 internal/playback/mpris.go create mode 100644 internal/playback/queue.go create mode 100644 internal/tui/tui.go create mode 100644 internal/tui/views/albums.go create mode 100644 internal/tui/views/artists.go create mode 100644 internal/tui/views/button.go create mode 100644 internal/tui/views/help.go create mode 100644 internal/tui/views/layout.go create mode 100644 internal/tui/views/login.go create mode 100644 internal/tui/views/main.go create mode 100644 internal/tui/views/player.go create mode 100644 internal/tui/views/playlists.go create mode 100644 internal/tui/views/queue.go create mode 100644 internal/tui/views/status_line.go create mode 100644 internal/tui/views/view.go create mode 100644 main.go create mode 100644 renovate.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e9418d0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +build/ +vendor/ diff --git a/.golangci.yml b/.golangci.yml new file mode 100644 index 0000000..8b44f70 --- /dev/null +++ b/.golangci.yml @@ -0,0 +1,76 @@ +# This file contains all available configuration options +# with their default values. + +# options for analysis running +run: + # default concurrency is a available CPU number + concurrency: 4 + + # timeout for analysis, e.g. 30s, 5m, default is 1m + timeout: 10m + + # exit code when at least one issue was found, default is 1 + issues-exit-code: 1 + + # include test files or not, default is true + tests: true + + # which dirs to skip: issues from them won't be reported; + # can use regexp here: generated.*, regexp is applied on full path; + # default value is empty list, but default dirs are skipped independently + # from this option's value (see skip-dirs-use-default). + skip-dirs: + - bin + - deploy + - docs + - examples + - hack + - packaging + - reports + +# output configuration options +output: + # colored-line-number|line-number|json|tab|checkstyle|code-climate, default is "colored-line-number" + format: colored-line-number + + # print lines of code with issue, default is true + print-issued-lines: true + + # print linter name in the end of issue text, default is true + print-linter-name: true + + # make issues output unique by line, default is true + uniq-by-line: true + +issues: + # List of regexps of issue texts to exclude, empty list by default. + # But independently from this option we use default exclude patterns, + # it can be disabled by `exclude-use-default: false`. To list all + # excluded by default patterns execute `golangci-lint run --help` + exclude: + - 'declaration of "err" shadows declaration at' + +linters: + enable: + - megacheck + - govet + - gocyclo + - gofmt + - gosec + - megacheck + - unconvert + - gci + - goimports + - exportloopref + +linters-settings: + govet: + check-shadowing: true + + settings: + printf: + funcs: + - Infof + - Warnf + - Errorf + - Fatalf diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..f288702 --- /dev/null +++ b/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..9a411f3 --- /dev/null +++ b/Makefile @@ -0,0 +1,33 @@ +BINARY_NAME=subsonic-tui +BUILD_FOLDER=build + + +.PHONY: build +build: + GOARCH=amd64 GOOS=darwin go build -o ${BUILD_FOLDER}/${BINARY_NAME}-darwin main.go + GOARCH=amd64 GOOS=linux go build -o ${BUILD_FOLDER}/${BINARY_NAME}-linux main.go + GOARCH=amd64 GOOS=windows go build -o ${BUILD_FOLDER}/${BINARY_NAME}-windows main.go + +run: build + ./${BINARY_NAME} + +clean: + go clean + rm ${BINARY_NAME}-darwin + rm ${BINARY_NAME}-linux + rm ${BINARY_NAME}-windows + +test: + go test ./... + +test_coverage: + go test ./... -coverprofile=coverage.out + +dep: + go mod download + +vet: + go vet + +lint: + golangci-lint run --enable-all diff --git a/README.md b/README.md new file mode 100644 index 0000000..6a919a7 --- /dev/null +++ b/README.md @@ -0,0 +1,91 @@ +# Subsonic TUI + +**NOTE ⚠ !!: This is under heavy development! Do not fork just yet. Im still force pushing to main!** + +A Subsonic client and player written in go. + +subsonictui (Name in progress) is a simple and easy to use player for Linux, Mac and (yes...) Windows. + +

+ Screenshot + Screenshot mini player +

+ +> Note: Screenshots blurred for (I dont know) copyright issues? + +## Features + + - [x] Browse Artists/Albums/Playlists + - [x] Artist view + - [x] Playlist view + - [x] Miniplayer on small screen + - [x] Album view + - [x] Search + - [x] Playback + - [x] Scrobble (configurable) + - [x] Play album + - [x] Shuffle album + - [x] Add album to queue + - [x] Add song to queue + - [x] Play Next/Prev + - [x] Stop/Pause + - [x] Generate artist radio + - [x] Generate song radio + - [-] Desktop integration + - [x] Linux (MPRIS) + - [ ] Windows + - [ ] MacOS + - [ ] Playlist management + - [ ] Add song to playlist + - [ ] Create playlist from queue + + +## Keybindings +| Key(s) | Action | +|------------------------------------------------------------------------------|-------------------------------------------------| +| ` | Focus on Main pane | +| 1 | Focus on Atrists pane | +| 2 | Focus on Albums pane | +| 3 | Focus on Playlists pane | +| 4 | Focus on Queue pane | +| Arrow keys or h j k l | Navigation in a pane. Shift for switching panes | +| g | Jump to first item in a list of a pane | +| G | Jump to last item in a list of a pane | +| n | Next song | +| N | Prev song | +| q | Exit | +| r | While on a song - Start Song radio | +| s | Playback - Stop | +| p | Playback - Toggle Play/Pause | +| c | Stop, clear queue | +| / | Search | +| ? | Help | + +## Config +`subsonictui` stores a config file at: +- Linux: `$HOME/.config/subsonictui/config.yaml` +- macOS: `$HOME/Library/Application Support/subsonictui/config.yaml` +- Windows: `C:\\Users\%USER%\AppData\Roaming\subsonictui\config.yaml` + + +## Development +### Build Dependencies +subsonictui uses [Beep](https://github.com/faiface/beep), that uses [OTO](https://github.com/hajimehoshi/oto) under the hood, so you will need OTO dependencies. +Mainly on Linux you will need `alsa-devel`. + +To Build the project: +``` +$ make build +``` + +## Special Thanks +subsonictui is built on top of a few projects. I would like to thank them here + - [go-subsonic](https://github.com/delucks/go-subsonic) + - [OTO](https://github.com/hajimehoshi/oto) + - [Beep](https://github.com/faiface/beep) + - [tview](https://github.com/rivo/tview) + - [tcell](https://github.com/gdamore/tcell) + - [MPRIS server](https://github.com/quarckster/go-mpris-server) + +Thank you for creating wondeful software that everyone can use. Including myself. + diff --git a/assets/screenshot-miniplayer.png b/assets/screenshot-miniplayer.png new file mode 100644 index 0000000000000000000000000000000000000000..e81e64509f865275e98a3500fc55eb3823d96de5 GIT binary patch literal 117433 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≶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 GGywp}vB5w9 literal 0 HcmV?d00001 diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..8cedf7f --- /dev/null +++ b/go.mod @@ -0,0 +1,28 @@ +module git.dayanhub.com/sagi/subsonic-tui + +go 1.21.5 + +require ( + github.com/creasty/defaults v1.7.0 + github.com/delucks/go-subsonic v0.0.0-20220915164742-2744002c4be5 + github.com/gdamore/tcell/v2 v2.7.4 + github.com/godbus/dbus/v5 v5.1.0 + github.com/gopxl/beep v1.4.0 + github.com/quarckster/go-mpris-server v1.0.3 + github.com/rivo/tview v0.0.0-20240307173318-e804876934a1 + gopkg.in/yaml.v3 v3.0.1 +) + +require ( + github.com/ebitengine/oto/v3 v3.1.1 // indirect + github.com/ebitengine/purego v0.6.1 // indirect + github.com/gdamore/encoding v1.0.1 // indirect + github.com/hajimehoshi/go-mp3 v0.3.4 // indirect + github.com/lucasb-eyer/go-colorful v1.2.0 // indirect + github.com/mattn/go-runewidth v0.0.15 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/rivo/uniseg v0.4.7 // indirect + golang.org/x/sys v0.18.0 // indirect + golang.org/x/term v0.18.0 // indirect + golang.org/x/text v0.14.0 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..1f053de --- /dev/null +++ b/go.sum @@ -0,0 +1,83 @@ +github.com/creasty/defaults v1.7.0 h1:eNdqZvc5B509z18lD8yc212CAqJNvfT1Jq6L8WowdBA= +github.com/creasty/defaults v1.7.0/go.mod h1:iGzKe6pbEHnpMPtfDXZEr0NVxWnPTjb1bbDy08fPzYM= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/delucks/go-subsonic v0.0.0-20220915164742-2744002c4be5 h1:RuuxidatioSKGOiBzL1mTY4X22DQD8weEbS3iRLHnAg= +github.com/delucks/go-subsonic v0.0.0-20220915164742-2744002c4be5/go.mod h1:vnbEuj6Z20PLcHB4rrLQAOXGMjtULfMGhRVSFPcSdUo= +github.com/ebitengine/oto/v3 v3.1.1 h1:utFNkSF4yXqA7VhMg7oHp3OSdz3vuzJQ42rCDnd8pc8= +github.com/ebitengine/oto/v3 v3.1.1/go.mod h1:bQM4zk9glIVjTynn8X0Lp1zngTlZltFFfzJvx543vdA= +github.com/ebitengine/purego v0.6.1 h1:sjN8rfzbhXQ59/pE+wInswbU9aMDHiwlup4p/a07Mkg= +github.com/ebitengine/purego v0.6.1/go.mod h1:ah1In8AOtksoNK6yk5z1HTJeUkC1Ez4Wk2idgGslMwQ= +github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg= +github.com/gdamore/encoding v1.0.1 h1:YzKZckdBL6jVt2Gc+5p82qhrGiqMdG/eNs6Wy0u3Uhw= +github.com/gdamore/encoding v1.0.1/go.mod h1:0Z0cMFinngz9kS1QfMjCP8TY7em3bZYeeklsSDPivEo= +github.com/gdamore/tcell/v2 v2.7.4 h1:sg6/UnTM9jGpZU+oFYAsDahfchWAFW8Xx2yFinNSAYU= +github.com/gdamore/tcell/v2 v2.7.4/go.mod h1:dSXtXTSK0VsW1biw65DZLZ2NKr7j0qP/0J7ONmsraWg= +github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= +github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/gopxl/beep v1.4.0 h1:pJERVDZMJkf49R1g/tV9DhVct4xNRuTlyMnMa53gGsc= +github.com/gopxl/beep v1.4.0/go.mod h1:gGVz7MJKlfHrmkzr0wSLGNyY7oisM6rFWJnaLjNxEwA= +github.com/hajimehoshi/go-mp3 v0.3.4 h1:NUP7pBYH8OguP4diaTZ9wJbUbk3tC0KlfzsEpWmYj68= +github.com/hajimehoshi/go-mp3 v0.3.4/go.mod h1:fRtZraRFcWb0pu7ok0LqyFhCUrPeMsGRSVop0eemFmo= +github.com/hajimehoshi/oto/v2 v2.3.1/go.mod h1:seWLbgHH7AyUMYKfKYT9pg7PhUu9/SisyJvNTT+ASQo= +github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= +github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= +github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= +github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/quarckster/go-mpris-server v1.0.3 h1:ef6d3DpxlORtdEBHnhQ/j3gS0Z3+YUfXeJhC9L9DZvA= +github.com/quarckster/go-mpris-server v1.0.3/go.mod h1:2b4IdrpnEoEfU+6fQKjYhAgdvsiz4JxmTpDAUrMJVO4= +github.com/rivo/tview v0.0.0-20240307173318-e804876934a1 h1:bWLHTRekAy497pE7+nXSuzXwwFHI0XauRzz6roUvY+s= +github.com/rivo/tview v0.0.0-20240307173318-e804876934a1/go.mod h1:02iFIz7K/A9jGCvrizLPvoqr4cEIx7q54RH5Qudkrss= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/rivo/uniseg v0.4.3/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= +github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220712014510-0a85c31ab51e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= +golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= +golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8= +golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/internal/client/artwork_cache.go b/internal/client/artwork_cache.go new file mode 100644 index 0000000..c3049e6 --- /dev/null +++ b/internal/client/artwork_cache.go @@ -0,0 +1,97 @@ +package client + +import ( + "fmt" + "image" + "image/jpeg" + "os" + "path" +) + +type artcache struct { + artPaths map[string]string + cacheDir string +} + +var ArtCache *artcache + +func (c *artcache) saveArt(id string, img image.Image) *string { + path := c.GetPath(id) + if path != nil { + return path + } + + path = c.saveImage(id, img) + if path != nil { + c.artPaths[id] = *path + } + return path +} + +func (c *artcache) saveImage(id string, img image.Image) *string { + filePath := c.filepath(id) + f, err := os.Create(filePath) + + defer func() { + _ = f.Close() + }() + + if err != nil { + return nil + } + err = jpeg.Encode(f, img, nil) + if err != nil { + return nil + } + return &filePath +} + +func (c *artcache) GetPath(id string) *string { + if path, ok := c.artPaths[id]; ok { + return &path + } + return nil +} + +func (c *artcache) GetImage(id string) *image.Image { + path := c.GetPath(id) + if path == nil { + return nil + } + + f, err := os.Open(*path) + if err != nil { + return nil + } + + defer func() { + _ = f.Close() + }() + + img, err := jpeg.Decode(f) + if err != nil { + return nil + } + return &img +} + +func (c *artcache) filepath(id string) string { + return path.Join(c.cacheDir, fmt.Sprintf("%s.jpg", id)) +} + +func (c *artcache) Destroy() { + os.RemoveAll(c.cacheDir) +} + +func init() { + tmpDir := os.TempDir() + cacheDir := path.Join(tmpDir, fmt.Sprintf("subsonic-tui-%d", os.Getpid())) + err := os.Mkdir(cacheDir, 0777) + if err != nil { + panic("Failed to create cacheDir") + } + ArtCache = &artcache{ + cacheDir: cacheDir, + artPaths: make(map[string]string), + } +} diff --git a/internal/client/client.go b/internal/client/client.go new file mode 100644 index 0000000..2115e82 --- /dev/null +++ b/internal/client/client.go @@ -0,0 +1,163 @@ +package client + +import ( + "fmt" + "image" + "io" + "net/http" + "sync" + + "git.dayanhub.com/sagi/subsonic-tui/internal/common" + "github.com/delucks/go-subsonic" +) + +type Client struct { + client subsonic.Client +} + +func NewClient(baseURL string) *Client { + var client subsonic.Client = subsonic.Client{ + Client: &http.Client{}, + ClientName: "subsonic-tui", + BaseUrl: baseURL, + PasswordAuth: true, + } + + return &Client{ + client: client, + } +} + +func (c *Client) Authenticate(username, password string) error { + c.client.User = username + return c.client.Authenticate(password) +} + +func (c *Client) GetUser() (*subsonic.User, error) { + return c.client.GetUser(c.client.User) +} + +func (c *Client) GetPlaylists() ([]*subsonic.Playlist, error) { + return c.client.GetPlaylists(map[string]string{}) +} + +func (c *Client) GetPlaylist(ID string) (*subsonic.Playlist, error) { + return c.client.GetPlaylist(ID) +} + +func (c *Client) GetArtists() ([]*subsonic.ArtistID3, error) { + indexes, err := c.client.GetArtists(map[string]string{}) + if err != nil { + return nil, err + } + artists := []*subsonic.ArtistID3{} + for _, i := range indexes.Index { + artists = append(artists, i.Artist...) + } + + return artists, nil +} + +func (c *Client) GetAlbums() ([]*subsonic.AlbumID3, error) { + return c.client.GetAlbumList2("alphabeticalByName", map[string]string{ + "size": "500", + }) +} + +func (c *Client) GetArtist(ID string) (*subsonic.ArtistID3, error) { + return c.client.GetArtist(ID) +} + +func (c *Client) GetArtistInfo(ID string) (*subsonic.ArtistInfo2, error) { + return c.client.GetArtistInfo2(ID, map[string]string{ + "count": "20", + }) +} + +func (c *Client) GetAlbum(ID string) (*subsonic.AlbumID3, error) { + return c.client.GetAlbum(ID) +} + +func (c *Client) GetCoverArt(ID string) (image.Image, error) { + if img := ArtCache.GetImage(ID); img != nil { + return *img, nil + } + img, err := c.client.GetCoverArt(ID, map[string]string{ + //"size": "64", + }) + if err != nil { + return nil, err + } + ArtCache.saveArt(ID, img) + return img, err +} + +func (c *Client) GetSimilarSongs(artistID string, maxSongs int) ([]*subsonic.Child, error) { + max := fmt.Sprintf("%d", maxSongs) + return c.client.GetSimilarSongs2(artistID, map[string]string{ + "count": max, + }) +} + +func (c *Client) Stream(ID string) (io.Reader, error) { + return c.client.Stream(ID, map[string]string{ + "format": "mp3", + }) +} + +func (c *Client) Scrobble(ID string) error { + return c.client.Scrobble(ID, map[string]string{}) +} + +func (c *Client) GetTopSongs(name string, max int) ([]*subsonic.Child, error) { + count := fmt.Sprintf("%d", max) + return c.client.GetTopSongs(name, map[string]string{ + "count": count, + }) +} + +func (c *Client) Search(query string) (*subsonic.SearchResult3, error) { + return c.client.Search3(query, map[string]string{ + "artistCount": "20", + "songCount": "20", + "albumCount": "20", + }) +} + +func (c *Client) GetExperimentalArtistRadio(artistId3 *subsonic.ArtistID3, info *subsonic.ArtistInfo2, max int) ([]*subsonic.Child, error) { + var wg sync.WaitGroup + ID := artistId3.ID + similarArtists := info.SimilarArtist + songs := []*subsonic.Child{} + similarArtistsSongs := 10 + thisArtistFactor := 3 + portion := len(info.SimilarArtist) * similarArtistsSongs * thisArtistFactor + wg.Add(2) + go func() { + s, _ := c.GetSimilarSongs(ID, portion) + songs = append(songs, s...) + wg.Done() + }() + go func() { + s, _ := c.GetTopSongs(artistId3.Name, similarArtistsSongs) + songs = append(songs, s...) + wg.Done() + }() + common.ShuffleSlice(similarArtists) + for _, a := range similarArtists { + wg.Add(1) + artist := a + go func() { + s, _ := c.GetSimilarSongs(artist.ID, similarArtistsSongs) + songs = append(songs, s...) + wg.Done() + }() + } + wg.Wait() + if max > len(songs) { + max = len(songs) + } + songs = songs[:max] + common.ShuffleSlice(songs) + return songs, nil +} diff --git a/internal/common/shuffle.go b/internal/common/shuffle.go new file mode 100644 index 0000000..82d420f --- /dev/null +++ b/internal/common/shuffle.go @@ -0,0 +1,21 @@ +package common + +import ( + "crypto/rand" + "math/big" + "reflect" +) + +func ShuffleSlice(slice interface{}) { + rv := reflect.ValueOf(slice) + swap := reflect.Swapper(slice) + + length := rv.Len() + for i := length - 1; i > 0; i-- { + j, err := rand.Int(rand.Reader, big.NewInt(int64(i+1))) + if err != nil { + panic("Shuffle error") + } + swap(i, int(j.Int64())) + } +} diff --git a/internal/config/colors.go b/internal/config/colors.go new file mode 100644 index 0000000..5442938 --- /dev/null +++ b/internal/config/colors.go @@ -0,0 +1,21 @@ +package config + +import ( + "github.com/gdamore/tcell/v2" +) + +const ( + ColorBackground = tcell.ColorDefault + ColorSelectedBoarder = tcell.ColorRed + ColorBluredBoarder = tcell.ColorWhite + ColorText = tcell.ColorWhite + ColorTextAccent = tcell.ColorYellow + ColorPlaybackProgressElapsed = tcell.ColorLightCyan + ColorPlaybackProgressRemaining = tcell.ColorBlack + ColorQueuePlayedBg = tcell.ColorBlack + ColorQueuePlayingBg = tcell.ColorDarkRed + ColorButtonBg = tcell.ColorBlue + ColorButtonTxt = tcell.ColorBlack + ColorButtonSelectedBg = tcell.ColorYellow + ColorButtonSelectedTxt = tcell.ColorDarkRed +) diff --git a/internal/config/config.go b/internal/config/config.go new file mode 100644 index 0000000..7d10602 --- /dev/null +++ b/internal/config/config.go @@ -0,0 +1,123 @@ +package config + +import ( + "encoding/base64" + "fmt" + "os" + "path" + "strings" + + "github.com/creasty/defaults" + "gopkg.in/yaml.v3" +) + +var configPath string + +type _config struct { + Username string `yaml:"username"` + Password string `yaml:"password"` + URL string `yaml:"url"` + EnableScrobble bool `yaml:"enable_scrobble" default:"false"` + MaxRadioSongs int `yaml:"max_radio_songs" default:"50"` + ExperimentalRadioAlgo bool `yaml:"experimental_radio_algo" default:"false"` +} + +var configStruct *_config + +func init() { + userConfigDir, err := os.UserConfigDir() + configDir := path.Join(userConfigDir, "subsonictui") + configPath = path.Join(configDir, "config.yaml") + + if err != nil { + fmt.Printf("[ERROR] Failed to fetch user config directory. %e\n", err) + os.Exit(1) + } + if _, err := os.Stat(configDir); os.IsNotExist(err) { + err := os.MkdirAll(configDir, 0700) + if err != nil { + panic(err) + } + } + var configFile *os.File + if _, err := os.Stat(configPath); os.IsNotExist(err) { + configFile, err = os.Create(configPath) + defer func() { + err := configFile.Close() + if err != nil { + panic(err) + } + }() + if err != nil { + fmt.Printf("[ERROR] Failed to create config file @ %s. %e\n", configPath, err) + os.Exit(1) + } + } + configStruct, err = loadConfig() + if err != nil { + fmt.Printf("[ERROR] Failed to load config file @ %s. %e\n", configPath, err) + os.Exit(1) + } + fmt.Printf("Init Config %s\n", configPath) +} + +func URL() string { + return configStruct.URL +} +func Username() string { + return configStruct.Username +} +func Password() string { + p, _ := base64.StdEncoding.DecodeString(configStruct.Password) + return strings.TrimSpace(string(p)) +} +func ScrobbleEnabled() bool { + return configStruct.EnableScrobble +} +func MaxRadioSongs() int { + return configStruct.MaxRadioSongs +} +func ExperimentalRadioAlgo() bool { + return configStruct.ExperimentalRadioAlgo +} + +func SetPassword(p string) { + configStruct.Password = base64.StdEncoding.EncodeToString([]byte(p)) +} + +func SetUsername(u string) { + configStruct.Username = u +} + +func SetURL(u string) { + configStruct.URL = u +} + +func loadConfig() (*_config, error) { + c := &_config{} + err := defaults.Set(c) + if err != nil { + panic(err) + } + file, err := os.ReadFile(configPath) + if err != nil { + return nil, err + } + if err = yaml.Unmarshal(file, c); err != nil { + return nil, err + } + return c, nil +} + +func SaveConfig() { + yml, err := yaml.Marshal(configStruct) + if err != nil { + fmt.Printf("[ERROR] Failed to convert config to yaml. %e\n", err) + os.Exit(1) + } + err = os.WriteFile(configPath, yml, 0600) + if err != nil { + fmt.Printf("[ERROR] Failed to save config file @ %s. %e\n", configPath, err) + os.Exit(1) + } +} diff --git a/internal/playback/controller.go b/internal/playback/controller.go new file mode 100644 index 0000000..69cb8b8 --- /dev/null +++ b/internal/playback/controller.go @@ -0,0 +1,223 @@ +package playback + +import ( + "io" + "time" + + "git.dayanhub.com/sagi/subsonic-tui/internal/client" + "github.com/delucks/go-subsonic" + "github.com/gopxl/beep" + "github.com/gopxl/beep/mp3" + "github.com/gopxl/beep/speaker" +) + +type PlaybackState int + +const ( + PlaybackStateStopped = iota + PlaybackStatePaused + PlaybackStatePlaying +) + +type Controller struct { + client *client.Client + stream beep.StreamSeekCloser + song *subsonic.Child + songElapsedFunc func(song *subsonic.Child, elapsed time.Duration) + initialFormat *beep.Format + currentFormat *beep.Format + position float64 + closeChan chan bool + songEndedChan chan bool + songEndedFunc func(song *subsonic.Child) + ctrl *beep.Ctrl + desktopPlayback DesktopPlayback + queue *queue + playbackState PlaybackState +} + +func NewController(client *client.Client) *Controller { + controller := &Controller{ + client: client, + closeChan: make(chan bool), + songEndedChan: make(chan bool), + playbackState: PlaybackStateStopped, + queue: newQueue(), + } + controller.desktopPlayback = desktopPlayer(controller) + controller.desktopPlayback.Start() + go controller.playbackTicker() + return controller +} + +func (c *Controller) State() PlaybackState { + return c.playbackState +} + +func (c *Controller) Play(song *subsonic.Child) { + if song == nil { + return + } + r, err := c.client.Stream(song.ID) + if err != nil { + //TODO: Log error + c.Stop() + return + } + c.Stream(r, song) +} +func (c *Controller) Next() { + song := c.queue.Next() + if song != nil { + c.Play(song) + } +} + +func (c *Controller) AddToQueue(songs []*subsonic.Child) { + shouldPlay := c.queue.Add(songs...) + if shouldPlay { + c.Play(c.queue.GetCurrentSong()) + } + c.desktopPlayback.OnPlaylistChanged() +} + +func (c *Controller) GetQueuePosition() int { + return c.queue.GetPosition() +} + +func (c *Controller) GetCurrentSong() *subsonic.Child { + return c.queue.GetCurrentSong() +} + +func (c *Controller) SetQueue(songs []*subsonic.Child) { + c.queue.Clear() + c.Stop() + c.queue.Set(songs) + c.Play(c.queue.GetCurrentSong()) + c.desktopPlayback.OnPlaylistChanged() +} + +func (c *Controller) SetQueuePosition(position int) { + s := c.queue.SetPosition(position) + c.Play(s) +} + +func (c *Controller) Prev() { + song := c.queue.Prev() + if song != nil { + c.Play(song) + } +} +func (c *Controller) GetQueue() []*subsonic.Child { + return c.queue.Get() +} + +func (c *Controller) ClearQueue() { + c.Stop() + c.queue.Clear() + c.desktopPlayback.OnPlayPause() + c.desktopPlayback.OnSongChanged() + c.desktopPlayback.OnPlaylistChanged() +} + +func (c *Controller) SetSongElapsedFunc(f func(sing *subsonic.Child, elapsed time.Duration)) { + c.songElapsedFunc = f +} + +func (c *Controller) SetSongEndedFunc(f func(song *subsonic.Child)) { + c.songEndedFunc = f +} + +func (c *Controller) Close() error { + c.Stop() + c.closeChan <- true + return nil +} + +func (c *Controller) TogglePlayPause() { + if c.playbackState != PlaybackStateStopped { + c.ctrl.Paused = !c.ctrl.Paused + if c.ctrl.Paused { + c.playbackState = PlaybackStatePaused + } else { + c.playbackState = PlaybackStatePlaying + } + } + c.desktopPlayback.OnPlayPause() +} + +func (c *Controller) Stop() { + if c.ctrl == nil { + return + } + speaker.Clear() + c.ctrl.Paused = true + c.playbackState = PlaybackStateStopped + c.ctrl = nil + c.stream = nil + c.songElapsedFunc(c.song, time.Duration(0)) + c.song = nil + c.position = 0 + c.desktopPlayback.OnPlayPause() + c.desktopPlayback.OnPlaylistChanged() +} + +func (c *Controller) playbackTicker() { + for { + select { + case <-c.closeChan: + return + case <-c.songEndedChan: + c.Stop() + c.Next() + default: + if c.playbackState == PlaybackStatePlaying && c.song != nil { + if c.stream != nil { + pos := c.stream.Position() + elapsed := c.currentFormat.SampleRate.D(pos).Round(time.Second) + c.position = elapsed.Seconds() + c.songElapsedFunc(c.song, elapsed) + c.desktopPlayback.OnPositionChanged(int(c.position)) + } + } + } + time.Sleep(time.Second) + } +} + +func (c *Controller) Stream(reader io.Reader, song *subsonic.Child) { + c.Stop() + // Ensure artwork cache... + _, _ = c.client.GetCoverArt(song.CoverArt) + + readerCloser := io.NopCloser(reader) + decodedMp3, format, err := mp3.Decode(readerCloser) + decodedMp3.Position() + if err != nil { + panic("mp3.NewDecoder failed: " + err.Error()) + } + + if c.initialFormat == nil { + c.initialFormat = &format + } + + c.currentFormat = &format + + var stream beep.Streamer = decodedMp3 + if err = speaker.Init(format.SampleRate, format.SampleRate.N(time.Second/10)); err != nil { + stream = beep.Resample(3, format.SampleRate, c.initialFormat.SampleRate, decodedMp3) + } + + c.stream = decodedMp3 + c.song = song + + ctrl := &beep.Ctrl{Streamer: stream} + c.ctrl = ctrl + c.playbackState = PlaybackStatePlaying + speaker.Play(beep.Seq(ctrl, beep.Callback(func() { + c.songEndedFunc(song) + c.songEndedChan <- true + }))) + c.desktopPlayback.OnSongChanged() + c.desktopPlayback.OnPlayPause() +} diff --git a/internal/playback/desktop.go b/internal/playback/desktop.go new file mode 100644 index 0000000..f5f7d6f --- /dev/null +++ b/internal/playback/desktop.go @@ -0,0 +1,10 @@ +package playback + +type DesktopPlayback interface { + Start() + Stop() error + OnPlayPause() + OnPlaylistChanged() + OnSongChanged() + OnPositionChanged(sec int) +} diff --git a/internal/playback/mpris.go b/internal/playback/mpris.go new file mode 100644 index 0000000..dd7e83c --- /dev/null +++ b/internal/playback/mpris.go @@ -0,0 +1,249 @@ +package playback + +import ( + "encoding/base32" + "fmt" + + "git.dayanhub.com/sagi/subsonic-tui/internal/client" + "github.com/delucks/go-subsonic" + "github.com/godbus/dbus/v5" + "github.com/quarckster/go-mpris-server/pkg/events" + "github.com/quarckster/go-mpris-server/pkg/server" + . "github.com/quarckster/go-mpris-server/pkg/types" +) + +const ( + mprisPlayerNmae = "MehSonic" + mprisNoTrack = "/org/mpris/MediaPlayer2/TrackList/NoTrack" +) + +type mprisRoot struct{} + +func (r mprisRoot) Raise() error { + return nil +} +func (r mprisRoot) Quit() error { + return nil +} +func (r mprisRoot) CanQuit() (bool, error) { + return true, nil +} +func (r mprisRoot) CanRaise() (bool, error) { + return false, nil +} +func (r mprisRoot) HasTrackList() (bool, error) { + return false, nil +} +func (r mprisRoot) Identity() (string, error) { + return mprisPlayerNmae, nil +} +func (r mprisRoot) SupportedUriSchemes() ([]string, error) { + return []string{}, nil +} +func (r mprisRoot) SupportedMimeTypes() ([]string, error) { + return []string{}, nil +} + +type mprisPlayer struct { + ctrl *Controller +} + +// Implement other methods of `pkg.types.OrgMprisMediaPlayer2PlayerAdapter` +func (p mprisPlayer) Next() error { + p.ctrl.Next() + return nil +} +func (p mprisPlayer) Previous() error { + p.ctrl.Prev() + return nil +} +func (p mprisPlayer) Pause() error { + if p.ctrl.State() == PlaybackStatePlaying { + p.ctrl.TogglePlayPause() + } + return nil +} +func (p mprisPlayer) PlayPause() error { + switch p.ctrl.State() { + case PlaybackStatePaused, PlaybackStatePlaying: + p.ctrl.TogglePlayPause() + case PlaybackStateStopped: + p.ctrl.Play(p.ctrl.GetCurrentSong()) + } + return nil +} +func (p mprisPlayer) Stop() error { + p.ctrl.Stop() + return nil +} +func (p mprisPlayer) Play() error { + switch p.ctrl.State() { + case PlaybackStatePaused: + p.ctrl.TogglePlayPause() + case PlaybackStateStopped: + p.ctrl.Play(p.ctrl.GetCurrentSong()) + } + return nil +} +func (p mprisPlayer) Seek(offset Microseconds) error { + return nil +} +func (p mprisPlayer) SetPosition(trackId string, position Microseconds) error { + return nil +} +func (p mprisPlayer) OpenUri(uri string) error { + return nil +} +func (p mprisPlayer) PlaybackStatus() (PlaybackStatus, error) { + switch p.ctrl.State() { + case PlaybackStatePlaying: + return PlaybackStatusPlaying, nil + case PlaybackStatePaused: + return PlaybackStatusPaused, nil + case PlaybackStateStopped: + return PlaybackStatusStopped, nil + } + // Should not get here + return PlaybackStatusStopped, nil + +} +func (p mprisPlayer) Rate() (float64, error) { + return 1, nil +} +func (p mprisPlayer) SetRate(float64) error { + return nil +} +func (p mprisPlayer) Metadata() (Metadata, error) { + s := p.ctrl.GetCurrentSong() + objPath := mprisNoTrack + if s != nil { + objPath = encodeTrackId(s.ID) + } else { + s = &subsonic.Child{} + } + md := Metadata{ + TrackId: dbus.ObjectPath(objPath), + Length: secondsToMicroseconds(s.Duration), + Title: s.Title, + Album: s.Album, + Artist: []string{s.Artist}, + DiscNumber: s.DiscNumber, + Genre: []string{s.Genre}, + TrackNumber: s.Track, + UserRating: float64(s.UserRating), + UseCount: int(s.PlayCount), + } + artw := client.ArtCache.GetPath(s.CoverArt) + if artw != nil { + md.ArtUrl = fmt.Sprintf("file://%s", *artw) + } + return md, nil +} +func (p mprisPlayer) Volume() (float64, error) { + return 1, nil +} +func (p mprisPlayer) SetVolume(float64) error { + return nil +} +func (p mprisPlayer) Position() (int64, error) { + return int64(secondsToMicroseconds(int(p.ctrl.position))), nil +} +func (p mprisPlayer) MinimumRate() (float64, error) { + return 1, nil +} +func (p mprisPlayer) MaximumRate() (float64, error) { + return 1, nil +} +func (p mprisPlayer) CanGoNext() (bool, error) { + return p.ctrl.queue.HasNext(), nil +} +func (p mprisPlayer) CanGoPrevious() (bool, error) { + return p.ctrl.queue.HasPrev(), nil +} +func (p mprisPlayer) CanPlay() (bool, error) { + return p.ctrl.GetCurrentSong() != nil, nil +} +func (p mprisPlayer) CanPause() (bool, error) { + return true, nil +} +func (p mprisPlayer) CanSeek() (bool, error) { + return false, nil +} +func (p mprisPlayer) CanControl() (bool, error) { + return true, nil +} + +var _ DesktopPlayback = &mprisPlayback{} + +type mprisPlayback struct { + root mprisRoot + player mprisPlayer + eventHandler *events.EventHandler + server *server.Server + err error +} + +func (p *mprisPlayback) Start() { + go func() { + p.err = p.server.Listen() + }() +} + +func (p *mprisPlayback) Stop() error { + return p.server.Stop() +} + +func (p *mprisPlayback) OnPlayPause() { + if p.err != nil { + return + } + p.err = p.eventHandler.Player.OnPlayPause() +} +func (p *mprisPlayback) OnPlaylistChanged() { + if p.err != nil { + return + } + p.err = p.eventHandler.Player.OnOptions() +} +func (p *mprisPlayback) OnSongChanged() { + if p.err != nil { + return + } + p.err = p.eventHandler.Player.OnTitle() +} + +func (p *mprisPlayback) OnPositionChanged(position int) { + if p.err != nil { + return + } + p.err = p.eventHandler.Player.OnSeek(secondsToMicroseconds(position)) + if p.err != nil { + return + } + p.err = p.eventHandler.Player.OnOptions() +} + +func desktopPlayer(c *Controller) DesktopPlayback { + r := mprisRoot{} + p := mprisPlayer{ + ctrl: c, + } + s := server.NewServer(mprisPlayerNmae, r, p) + ev := events.NewEventHandler(s) + + return &mprisPlayback{ + root: r, + player: p, + server: s, + eventHandler: ev, + } +} + +func secondsToMicroseconds(s int) Microseconds { + return Microseconds(s * 1_000_000) +} + +func encodeTrackId(id string) string { + data := []byte(id) + return fmt.Sprintf("/%s/Track/%s", mprisPlayerNmae, base32.StdEncoding.WithPadding('0').EncodeToString(data)) +} diff --git a/internal/playback/queue.go b/internal/playback/queue.go new file mode 100644 index 0000000..2800f28 --- /dev/null +++ b/internal/playback/queue.go @@ -0,0 +1,84 @@ +package playback + +import "github.com/delucks/go-subsonic" + +type queue struct { + currentSong int + songQueue []*subsonic.Child +} + +func newQueue() *queue { + return &queue{ + currentSong: 0, + songQueue: []*subsonic.Child{}, + } +} + +func (q *queue) Set(songs []*subsonic.Child) { + q.currentSong = 0 + q.songQueue = songs +} + +func (q *queue) Clear() { + q.currentSong = 0 + q.songQueue = []*subsonic.Child{} +} + +// returns true if queue was empty before addition +func (q *queue) Add(songs ...*subsonic.Child) bool { + shouldStartPlaying := len(q.songQueue) == 0 + q.songQueue = append(q.songQueue, songs...) + if shouldStartPlaying { + q.currentSong = 0 + return true + } + return false +} + +// returns a song if position has changed +func (q *queue) SetPosition(position int) *subsonic.Child { + if position == q.currentSong || position < 0 || len(q.songQueue) < position { + return nil + } + q.currentSong = position + return q.GetCurrentSong() +} + +func (q *queue) GetPosition() int { + return q.currentSong +} + +func (q *queue) GetCurrentSong() *subsonic.Child { + if len(q.songQueue) == 0 { + return nil + } + return q.songQueue[q.currentSong] +} + +func (q *queue) HasPrev() bool { + return 0 < q.currentSong +} + +func (q *queue) HasNext() bool { + return q.currentSong < len(q.songQueue)-1 +} + +func (q *queue) Next() *subsonic.Child { + if len(q.songQueue) > q.currentSong+1 { + q.currentSong = q.currentSong + 1 + return q.GetCurrentSong() + } + return nil +} + +func (q *queue) Prev() *subsonic.Child { + if q.currentSong > 0 { + q.currentSong = q.currentSong - 1 + return q.GetCurrentSong() + } + return nil +} + +func (q *queue) Get() []*subsonic.Child { + return q.songQueue +} diff --git a/internal/tui/tui.go b/internal/tui/tui.go new file mode 100644 index 0000000..9927162 --- /dev/null +++ b/internal/tui/tui.go @@ -0,0 +1,124 @@ +package tui + +import ( + "fmt" + "os" + + "git.dayanhub.com/sagi/subsonic-tui/internal/client" + "git.dayanhub.com/sagi/subsonic-tui/internal/config" + "git.dayanhub.com/sagi/subsonic-tui/internal/playback" + "git.dayanhub.com/sagi/subsonic-tui/internal/tui/views" + "github.com/gdamore/tcell/v2" + "github.com/rivo/tview" +) + +type TUI struct { + app *tview.Application + layout views.View + + client *client.Client + playbackCtl *playback.Controller +} + +func NewLogin() *TUI { + app := tview.NewApplication() + layout := views.NewLoginView(func(u, p, url string) { + c := client.NewClient(url) + err := c.Authenticate(u, p) + if err != nil { + app.Stop() + fmt.Printf("[Error] Failed to login. Aborting %e", err) + os.Exit(1) + } + config.SetURL(url) + config.SetUsername(u) + config.SetPassword(p) + config.SaveConfig() + app.Stop() + }, func() { + app.Stop() + os.Exit(0) + }) + app.EnableMouse(true). + SetRoot(layout.GetView(), true) + + app.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey { + if event.Key() == tcell.KeyEsc { + app.Stop() + os.Exit(0) + } + return event + }) + + return &TUI{ + app: app, + layout: layout, + } +} + +func NewPlayer(client *client.Client, playbackCtl *playback.Controller) *TUI { + app := tview.NewApplication() + + layout := views.NewLayout(client, playbackCtl, func() { + go app.Draw() + }) + help := views.NewHelp() + + pages := tview.NewPages() + pages.AddPage("app", layout.GetView(), true, true) + pages.AddPage("help", help.GetView(), true, false) + + help.SetKeyPressedFunc(func() { + pages.SwitchToPage("app") + }) + app.EnableMouse(true). + SetRoot(pages, true) + + app.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey { + if currentPage, _ := pages.GetFrontPage(); currentPage == "help" { + pages.SwitchToPage("app") + help.GetView().Blur() + layout.GetView().Focus(nil) + return nil + } + if layout.Mode() == views.StatusModeSearch { + return event + } + if event.Rune() == 'q' { + app.Stop() + fmt.Println("Exiting..") + return nil + } else if event.Rune() == 'h' { + return tcell.NewEventKey(tcell.KeyLeft, rune(tcell.KeyLeft), event.Modifiers()) + } else if event.Rune() == 'j' { + return tcell.NewEventKey(tcell.KeyDown, rune(tcell.KeyDown), event.Modifiers()) + } else if event.Rune() == 'k' { + return tcell.NewEventKey(tcell.KeyUp, rune(tcell.KeyUp), event.Modifiers()) + } else if event.Rune() == 'l' { + return tcell.NewEventKey(tcell.KeyRight, rune(tcell.KeyRight), event.Modifiers()) + } else if event.Rune() == '?' { + pages.SwitchToPage("help") + layout.GetView().Blur() + go app.Draw() + } + return event + }) + app.SetAfterDrawFunc(func(screen tcell.Screen) { + layout.Update() + }) + app.GetFocus().Blur() + + //app.SetFocus(layout.GetView()) + + return &TUI{ + app: app, + layout: layout, + client: client, + playbackCtl: playbackCtl, + } + +} + +func (t *TUI) Run() error { + return t.app.Run() +} diff --git a/internal/tui/views/albums.go b/internal/tui/views/albums.go new file mode 100644 index 0000000..3cb9a50 --- /dev/null +++ b/internal/tui/views/albums.go @@ -0,0 +1,73 @@ +package views + +import ( + "git.dayanhub.com/sagi/subsonic-tui/internal/client" + "git.dayanhub.com/sagi/subsonic-tui/internal/config" + "github.com/delucks/go-subsonic" + "github.com/rivo/tview" +) + +var _ View = &albums{} + +type albums struct { + view *tview.Table + client *client.Client + albums []*subsonic.AlbumID3 + callback func(albumID string) +} + +func NewAlbums(client *client.Client) *albums { + + list := tview.NewTable() + + list.SetBackgroundColor(config.ColorBackground) + list.SetTitle("Albums [2]") + list.SetBorder(true) + + resp, _ := client.GetAlbums() + + obj := &albums{ + view: list, + client: client, + albums: resp, + } + + list.SetSelectedFunc(func(row, column int) { + obj.callback(obj.albums[row].ID) + }) + + list.SetFocusFunc(func() { + list.SetBorderColor(config.ColorSelectedBoarder) + list.SetSelectable(true, false) + }) + list.SetBlurFunc(func() { + list.SetBorderColor(config.ColorBluredBoarder) + list.SetSelectable(false, false) + }) + + obj.Update() + return obj +} + +func (a *albums) SetAlbums(al []*subsonic.AlbumID3) { + a.albums = al + a.Update() +} + +func (a *albums) Update() { + a.view.Clear() + for i, pl := range a.albums { + title := tview.NewTableCell(pl.Name).SetExpansion(1).SetMaxWidth(15) + artist := tview.NewTableCell(pl.Artist).SetExpansion(1).SetAlign(tview.AlignRight) + a.view.SetCell(i, 0, title) + a.view.SetCell(i, 1, artist) + } +} + +func (a *albums) SetCallback(f func(albumID string)) { + a.callback = f +} + +func (a *albums) GetView() tview.Primitive { + return a.view +} diff --git a/internal/tui/views/artists.go b/internal/tui/views/artists.go new file mode 100644 index 0000000..94f3d5c --- /dev/null +++ b/internal/tui/views/artists.go @@ -0,0 +1,70 @@ +package views + +import ( + "git.dayanhub.com/sagi/subsonic-tui/internal/client" + "git.dayanhub.com/sagi/subsonic-tui/internal/config" + "github.com/delucks/go-subsonic" + "github.com/rivo/tview" +) + +var _ View = &artists{} + +type artists struct { + view *tview.Table + client *client.Client + artists []*subsonic.ArtistID3 + selectArtistFunc func(artistId string) + openArtistFunc func(artistId string) +} + +func NewArtists(client *client.Client) *artists { + + list := tview.NewTable() + + list.SetBackgroundColor(config.ColorBackground) + list.SetTitle("Artists [1]") + list.SetBorder(true) + list.SetFocusFunc(func() { + list.SetBorderColor(config.ColorSelectedBoarder) + list.SetSelectable(true, false) + }) + list.SetBlurFunc(func() { + list.SetBorderColor(config.ColorBluredBoarder) + list.SetSelectable(false, false) + }) + + arts, _ := client.GetArtists() + + for i, artist := range arts { + cell := tview.NewTableCell(artist.Name).SetExpansion(1) + list.SetCell(i, 0, cell) + // list.AddItem(artist.Name, fmt.Sprintf("%s", artist.Name), '0', nil) + } + + resp := &artists{ + view: list, + client: client, + artists: arts, + } + + list.SetSelectedFunc(func(row, column int) { + resp.openArtistFunc(resp.artists[row].ID) + }) + + return resp +} + +func (a *artists) SetSelectArtistFunc(f func(artistId string)) { + a.selectArtistFunc = f +} +func (a *artists) SetOpenArtistFunc(f func(artistId string)) { + a.openArtistFunc = f +} + +func (a *artists) Update() { + +} + +func (a *artists) GetView() tview.Primitive { + return a.view +} diff --git a/internal/tui/views/button.go b/internal/tui/views/button.go new file mode 100644 index 0000000..847438a --- /dev/null +++ b/internal/tui/views/button.go @@ -0,0 +1,21 @@ +package views + +import ( + "git.dayanhub.com/sagi/subsonic-tui/internal/config" + "github.com/gdamore/tcell/v2" + "github.com/rivo/tview" +) + +func NewButton(label string) *tview.Button { + style := tcell.Style{} + inactiveS := style.Background(config.ColorButtonBg). + Foreground(config.ColorButtonTxt).Bold(true) + activeS := style.Background(config.ColorButtonSelectedBg). + Foreground(config.ColorButtonSelectedTxt).Bold(true).Underline(true) + + b := tview.NewButton(label) + b.SetStyle(inactiveS) + b.SetActivatedStyle(activeS) + + return b +} diff --git a/internal/tui/views/help.go b/internal/tui/views/help.go new file mode 100644 index 0000000..0343076 --- /dev/null +++ b/internal/tui/views/help.go @@ -0,0 +1,113 @@ +package views + +import ( + "git.dayanhub.com/sagi/subsonic-tui/internal/config" + "github.com/rivo/tview" +) + +var _ View = &help{} + +type help struct { + view *tview.Flex + keyPressedFunc func() +} + +type keyMap struct { + key string + description string +} + +var keyMaps = []keyMap{ + { + "Arrows", "Navigation", + }, + { + "h, j, k, l", "Navigation. Use [shift] for moving panes", + }, + { + "g", "Jump to top", + }, + { + "G", "Jump to bottom", + }, + { + "p", "Toggle Play/Pause", + }, + { + "s", "Stop", + }, + { + "n", "Play next song", + }, + { + "N", "Play previous song", + }, + { + "c", "Stop and clear queue", + }, + { + "r", "Start song radio", + }, + { + "/", "Search", + }, + { + "q", "Quit", + }, +} + +func NewHelp() *help { + h := &help{} + view := tview.NewTable() + view.SetBackgroundColor(config.ColorBackground) + height := 16 + width := 100 + view.SetBorder(true) + view.SetTitle(" Keybindings ") + view.SetTitleAlign(tview.AlignCenter) + + for i, km := range keyMaps { + odd := i%2 != 0 + txtColor := config.ColorText + if odd { + txtColor = config.ColorTextAccent + } + keyCell := tview.NewTableCell(km.key). + SetExpansion(1). + SetAlign(tview.AlignCenter). + SetTextColor(txtColor) + descCell := tview.NewTableCell(km.description). + SetExpansion(1). + SetAlign(tview.AlignCenter). + SetTextColor(txtColor) + view.SetCell(i, 0, keyCell) + view.SetCell(i, 1, descCell) + } + + innerFlex := tview.NewFlex().SetDirection(tview.FlexRow). + AddItem(EmptyBox, 0, 1, false). + AddItem(view, height, 1, true). + AddItem(EmptyBox, 0, 1, false) + innerFlex.SetBackgroundColor(config.ColorBackground) + wrapper := tview.NewFlex(). + AddItem(EmptyBox, 0, 1, false). + AddItem(innerFlex, width, 1, true). + AddItem(EmptyBox, 0, 1, false) + wrapper.SetBackgroundColor((config.ColorBackground)) + + h.view = wrapper + + return h +} + +func (h *help) GetView() tview.Primitive { + return h.view +} + +func (h *help) Update() { + +} + +func (h *help) SetKeyPressedFunc(f func()) { + h.keyPressedFunc = f +} diff --git a/internal/tui/views/layout.go b/internal/tui/views/layout.go new file mode 100644 index 0000000..0b2bc6d --- /dev/null +++ b/internal/tui/views/layout.go @@ -0,0 +1,398 @@ +package views + +import ( + "time" + + "git.dayanhub.com/sagi/subsonic-tui/internal/client" + "git.dayanhub.com/sagi/subsonic-tui/internal/config" + "git.dayanhub.com/sagi/subsonic-tui/internal/playback" + "github.com/delucks/go-subsonic" + "github.com/gdamore/tcell/v2" + "github.com/rivo/tview" +) + +var _ View = &layout{} + +type layout struct { + view *tview.Pages + player View + currentFocusedView tview.Primitive + smallView *tview.Flex + largeView *tview.Grid + status *statusLine + mainView *main +} + +func NewLayout(client *client.Client, playbackCtl *playback.Controller, refreshUI func()) *layout { + layout := &layout{} + + largeView := tview.NewGrid().SetRows(0, 4, 1) + largeView.SetBackgroundColor(config.ColorBackground) + smallView := tview.NewFlex().SetDirection(tview.FlexRow) + smallView.SetBackgroundColor(config.ColorBackground) + layout.largeView = largeView + layout.smallView = smallView + pages := tview.NewPages() + pages.SetBackgroundColor(config.ColorBackground) + + // Status / command / search + statusLine := NewStatusLine() + layout.status = statusLine + + // Side Panel (Artist/Albums/Playlist) + albums := NewAlbums(client) + artists := NewArtists(client) + playlists := NewPlaylists(client) + + sidePanel := tview.NewGrid().SetRows(0, 0, 0) + sidePanel.AddItem(artists.GetView(), 0, 0, 1, 1, 0, 0, false) + sidePanel.AddItem(albums.GetView(), 1, 0, 1, 1, 0, 0, false) + sidePanel.AddItem(playlists.GetView(), 2, 0, 1, 1, 0, 0, false) + + // main pane + main := NewMainView(client, statusLine.Log) + layout.mainView = main + // Queue + queue := NewQueue() + + // Main view + mainView := tview.NewFlex() + mainView.SetBackgroundColor(config.ColorBackground) + mainView.AddItem(sidePanel, 0, 1, false) + mainView.AddItem(main.GetView(), 0, 2, false) + mainView.AddItem(queue.GetView(), 0, 1, false) + largeView.AddItem(mainView, 0, 0, 1, 3, 0, 0, false) + // Player + player := NewPlayer(client) + largeView.AddItem(player.GetView(), 1, 0, 1, 3, 0, 0, false) + + // Add status line + largeView.AddItem(statusLine.GetView(), 2, 0, 1, 3, 0, 0, false) + + // Callbacks + artists.SetSelectArtistFunc(func(artistId string) { + artists.view.Blur() + statusLine.Log("Fetching artist's albums...") + go func() { + a, _ := client.GetArtist(artistId) + albums.SetAlbums(a.Album) + albums.GetView().Focus(nil) + refreshUI() + }() + }) + artists.SetOpenArtistFunc(func(artistId string) { + artists.view.Blur() + statusLine.Log("Fetching artists...") + layout.currentFocusedView = main.GetView() + layout.rebuildSmallView() + go func() { + a, _ := client.GetArtist(artistId) + main.SetArtist(a) + main.GetView().Focus(nil) + refreshUI() + }() + }) + + albums.SetCallback(func(albumID string) { + albums.view.Blur() + statusLine.Log("Fetching album...") + layout.currentFocusedView = main.GetView() + layout.rebuildSmallView() + go func() { + a, _ := client.GetAlbum(albumID) + main.SetAlbum(a) + main.view.Focus(nil) + refreshUI() + }() + }) + + playlists.SetCallback(func(p *subsonic.Playlist) { + playlists.view.Blur() + statusLine.Log("Fetching playlist...") + layout.currentFocusedView = main.GetView() + layout.rebuildSmallView() + go func() { + playlist, _ := client.GetPlaylist(p.ID) + main.SetPlaylist(playlist) + main.view.Focus(nil) + refreshUI() + }() + }) + + main.SetPlayAllFunc(func(songs ...*subsonic.Child) { + statusLine.Log("Loaded #%d songs.", len(songs)) + playbackCtl.SetQueue(songs) + queue.Update(songs, playbackCtl.GetQueuePosition()) + }) + main.SetPlayAddSongFunc(func(song ...*subsonic.Child) { + statusLine.Log("Added #%d songs to queue.", len(song)) + playbackCtl.AddToQueue(song) + queue.Update(playbackCtl.GetQueue(), playbackCtl.GetQueuePosition()) + }) + + playbackCtl.SetSongElapsedFunc(func(song *subsonic.Child, elapsed time.Duration) { + player.SetSongInfo(song) + player.UpdateProgress(elapsed) + queue.Update(playbackCtl.GetQueue(), playbackCtl.GetQueuePosition()) + refreshUI() + }) + + playbackCtl.SetSongEndedFunc(func(song *subsonic.Child) { + statusLine.Log("") + queue.Update(playbackCtl.GetQueue(), playbackCtl.GetQueuePosition()) + if config.ScrobbleEnabled() { + // Scrobble + _ = client.Scrobble(song.ID) + } + }) + + queue.SetPlayFunc(func(position int) { + playbackCtl.SetQueuePosition(position) + queue.Update(playbackCtl.GetQueue(), playbackCtl.GetQueuePosition()) + }) + + statusLine.SetOnUpdateFunc(func() { + refreshUI() + }) + + statusLine.SetSearchFunc(func(quary string) { + if len(quary) == 0 { + layout.currentFocusedView.Focus(nil) + statusLine.Log("Search canceled") + return + } + // Search... + statusLine.Log("Searching for '%s'....", quary) + statusLine.view.Blur() + go func() { + result, _ := client.Search(quary) + layout.currentFocusedView.Blur() + main.SetSearch(result, quary) + layout.currentFocusedView = main.GetView() + layout.rebuildSmallView() + refreshUI() + }() + }) + + // Key Bindings + pages.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey { + if statusLine.Mode() == StatusModeSearch { + return event + } + if event.Rune() == '1' { + // Focus Artists + artists.view.Blur() + albums.view.Blur() + playlists.view.Blur() + main.view.Blur() + queue.view.Blur() + artists.view.Focus(nil) + layout.currentFocusedView = artists.GetView() + layout.rebuildSmallView() + return nil + } else if event.Rune() == '2' { + // Focus Albums + artists.view.Blur() + albums.view.Blur() + playlists.view.Blur() + main.view.Blur() + queue.view.Blur() + albums.view.Focus(nil) + layout.currentFocusedView = albums.GetView() + layout.rebuildSmallView() + return nil + } else if event.Rune() == '3' { + // Focus Playlists + artists.view.Blur() + albums.view.Blur() + playlists.view.Blur() + main.view.Blur() + queue.view.Blur() + playlists.view.Focus(nil) + layout.currentFocusedView = playlists.GetView() + layout.rebuildSmallView() + return nil + } else if event.Rune() == '`' { + // Focus Songs + artists.view.Blur() + albums.view.Blur() + playlists.view.Blur() + main.view.Blur() + queue.view.Blur() + main.view.Focus(nil) + layout.currentFocusedView = main.GetView() + layout.rebuildSmallView() + return nil + } else if event.Rune() == '4' { + // Focus Queue + artists.view.Blur() + albums.view.Blur() + playlists.view.Blur() + main.view.Blur() + queue.view.Blur() + queue.view.Focus(nil) + layout.currentFocusedView = queue.GetView() + layout.rebuildSmallView() + return nil + } else if event.Rune() == 'n' { + playbackCtl.Next() + queue.Update(playbackCtl.GetQueue(), playbackCtl.GetQueuePosition()) + return nil + + } else if event.Rune() == 'N' { + playbackCtl.Prev() + queue.Update(playbackCtl.GetQueue(), playbackCtl.GetQueuePosition()) + return nil + } else if event.Rune() == 's' { + playbackCtl.Stop() + queue.Update(playbackCtl.GetQueue(), playbackCtl.GetQueuePosition()) + return nil + } else if event.Rune() == 'p' { + if playbackCtl.State() == playback.PlaybackStateStopped { + song := playbackCtl.GetCurrentSong() + if song != nil { + playbackCtl.Play(song) + } + queue.Update(playbackCtl.GetQueue(), playbackCtl.GetQueuePosition()) + return nil + } + playbackCtl.TogglePlayPause() + return nil + } else if event.Rune() == 'c' { + playbackCtl.ClearQueue() + queue.Update(playbackCtl.GetQueue(), playbackCtl.GetQueuePosition()) + return nil + } else if event.Rune() == '/' { + layout.currentFocusedView.Blur() + statusLine.Search() + refreshUI() + return nil + } else if event.Rune() == 'L' { + if layout.currentFocusedView == albums.GetView() { + layout.currentFocusedView.Blur() + main.view.Focus(nil) + layout.currentFocusedView = main.GetView() + layout.rebuildSmallView() + } else if layout.currentFocusedView == artists.GetView() { + layout.currentFocusedView.Blur() + main.view.Focus(nil) + layout.currentFocusedView = main.GetView() + layout.rebuildSmallView() + } else if layout.currentFocusedView == playlists.GetView() { + layout.currentFocusedView.Blur() + main.view.Focus(nil) + layout.currentFocusedView = main.GetView() + layout.rebuildSmallView() + } else if layout.currentFocusedView == main.GetView() { + layout.currentFocusedView.Blur() + queue.view.Focus(nil) + layout.currentFocusedView = queue.GetView() + layout.rebuildSmallView() + } + } else if event.Rune() == 'H' { + if layout.currentFocusedView == queue.GetView() { + layout.currentFocusedView.Blur() + main.view.Focus(nil) + layout.currentFocusedView = main.GetView() + layout.rebuildSmallView() + } else if layout.currentFocusedView == main.GetView() { + layout.currentFocusedView.Blur() + artists.view.Focus(nil) + layout.currentFocusedView = artists.GetView() + layout.rebuildSmallView() + } + } else if event.Rune() == 'J' { + if layout.currentFocusedView == albums.GetView() { + layout.currentFocusedView.Blur() + playlists.view.Focus(nil) + layout.currentFocusedView = playlists.GetView() + layout.rebuildSmallView() + } else if layout.currentFocusedView == artists.GetView() { + layout.currentFocusedView.Blur() + albums.view.Focus(nil) + layout.currentFocusedView = albums.GetView() + layout.rebuildSmallView() + } else if layout.currentFocusedView == playlists.GetView() { + layout.currentFocusedView.Blur() + artists.view.Focus(nil) + layout.currentFocusedView = artists.GetView() + layout.rebuildSmallView() + } + } else if event.Rune() == 'K' { + if layout.currentFocusedView == albums.GetView() { + layout.currentFocusedView.Blur() + artists.view.Focus(nil) + layout.currentFocusedView = artists.GetView() + layout.rebuildSmallView() + } else if layout.currentFocusedView == artists.GetView() { + layout.currentFocusedView.Blur() + playlists.view.Focus(nil) + layout.currentFocusedView = playlists.GetView() + layout.rebuildSmallView() + } else if layout.currentFocusedView == playlists.GetView() { + layout.currentFocusedView.Blur() + albums.view.Focus(nil) + layout.currentFocusedView = albums.GetView() + layout.rebuildSmallView() + } + } + + return event + }) + + largeView.SetFocusFunc(func() { + largeView.Blur() + layout.currentFocusedView.Focus(nil) + }) + smallView.SetFocusFunc(func() { + smallView.Blur() + layout.currentFocusedView.Focus(nil) + }) + + statusLine.Log("Press '?' for help") + + pages.AddPage("small", smallView, true, false) + pages.AddPage("large", largeView, true, true) + + layout.view = pages + layout.player = player + //Auto focus on artists + artists.GetView().Focus(nil) + layout.currentFocusedView = artists.GetView() + layout.rebuildSmallView() + return layout +} +func (l *layout) rebuildSmallView() { + l.smallView.Clear() + l.smallView.AddItem(l.currentFocusedView, 0, 1, false) + l.smallView.AddItem(l.player.GetView(), 4, 0, false) + l.smallView.AddItem(l.status.GetView(), 1, 0, false) +} + +func (l *layout) Mode() Statusmode { + return l.status.Mode() +} + +func (l *layout) GetView() tview.Primitive { + return l.view +} + +func (l *layout) Update() { + _, _, w, h := l.view.GetRect() + page, _ := l.view.GetFrontPage() + smallView := w < 100 || h < 30 + if smallView { + if page != "small" { + l.mainView.SetMiniView(true) + go l.view.SwitchToPage("small") + return + } + } else { + if page != "large" { + l.mainView.SetMiniView(false) + go l.view.SwitchToPage("large") + return + } + } + l.player.Update() +} diff --git a/internal/tui/views/login.go b/internal/tui/views/login.go new file mode 100644 index 0000000..85d70a2 --- /dev/null +++ b/internal/tui/views/login.go @@ -0,0 +1,73 @@ +package views + +import ( + "github.com/rivo/tview" +) + +var _ View = &login{} + +const ( + ViewEventLoginClicked = "login-clicked" +) + +type login struct { + view *tview.Flex + form *tview.Form + username string + password string + url string + loginFunc func(u, p, url string) + exitFunc func() +} + +func (l *login) GetView() tview.Primitive { + return l.view +} + +func (l *login) onFormLogin() { + l.loginFunc(l.username, l.password, l.url) +} + +func NewLoginView(loginFunc func(u, p, url string), exitFunc func()) View { + l := &login{} + l.loginFunc = loginFunc + l.exitFunc = exitFunc + + form := tview.NewForm(). + AddInputField("Server URL", "https://", 20, nil, func(text string) { + l.url = text + }). + AddInputField("Username", "", 20, nil, func(text string) { + l.username = text + }). + AddPasswordField("Password", "", 20, '*', func(text string) { + l.password = text + }). + AddButton("Login", l.onFormLogin). + AddButton("Quit", func() { + l.exitFunc() + }) + form.SetBorder(true).SetTitle(" Login ").SetTitleAlign(tview.AlignCenter) + + width := 50 + height := 20 + + wrapper := tview.NewFlex(). + AddItem(nil, 0, 1, false). + AddItem(tview.NewFlex().SetDirection(tview.FlexRow). + AddItem(nil, 0, 1, false). + AddItem(form, height, 1, true). + AddItem(nil, 0, 1, false), width, 1, true). + AddItem(nil, 0, 1, false) + + l.view = wrapper + l.form = form + + l.GetView().Focus(func(p tview.Primitive) {}) + form.SetFocus(0) + return l +} + +func (l *login) Update() { + +} diff --git a/internal/tui/views/main.go b/internal/tui/views/main.go new file mode 100644 index 0000000..a6bb8a2 --- /dev/null +++ b/internal/tui/views/main.go @@ -0,0 +1,616 @@ +package views + +import ( + "fmt" + "strconv" + "time" + + "git.dayanhub.com/sagi/subsonic-tui/internal/client" + "git.dayanhub.com/sagi/subsonic-tui/internal/common" + "git.dayanhub.com/sagi/subsonic-tui/internal/config" + "github.com/delucks/go-subsonic" + "github.com/gdamore/tcell/v2" + "github.com/rivo/tview" +) + +var _ View = &main{} + +type mainviewmode int + +const ( + mainModeAlbum mainviewmode = iota + mainModePlaylist mainviewmode = iota + mainModeArtist mainviewmode = iota + mainModeSearch mainviewmode = iota +) + +type main struct { + view *tview.Flex + client *client.Client + mode mainviewmode + query string + miniView bool + album *subsonic.AlbumID3 + searchResult *subsonic.SearchResult3 + playlist *subsonic.Playlist + songList *tview.Table + artist *subsonic.ArtistID3 + artistInfo *subsonic.ArtistInfo2 + playAllFunc func(song ...*subsonic.Child) + addSongsFunc func(song ...*subsonic.Child) + log func(format string, a ...any) +} + +func NewMainView(client *client.Client, log func(format string, a ...any)) *main { + playlistAlbum := &main{ + client: client, + log: log, + } + + flex := tview.NewFlex().SetDirection(tview.FlexRow) + + flex.SetBackgroundColor(config.ColorBackground) + flex.SetTitle("Subsonic TUI [`]") + flex.SetBorder(true) + flex.SetFocusFunc(func() { + flex.SetBorderColor(config.ColorSelectedBoarder) + if playlistAlbum.songList != nil { + //playlistAlbum.view.Blur() + playlistAlbum.songList.Focus(nil) + } + }) + flex.SetBlurFunc(func() { + flex.SetBorderColor(config.ColorBluredBoarder) + if playlistAlbum.songList != nil { + playlistAlbum.songList.Blur() + } + }) + + playlistAlbum.view = flex + // Empty Box for starters... + playlistAlbum.view.AddItem(EmptyBox, 0, 1, false) + return playlistAlbum +} + +func (m *main) SetMiniView(mini bool) { + m.miniView = mini +} + +func (m *main) SetAlbum(album *subsonic.AlbumID3) { + m.mode = mainModeAlbum + m.album = album + m.Update() + m.log("") +} + +func (m *main) SetPlaylist(playlist *subsonic.Playlist) { + m.mode = mainModePlaylist + m.playlist = playlist + m.Update() + m.log("") +} + +func (m *main) SetArtist(artist *subsonic.ArtistID3) { + m.mode = mainModeArtist + m.artist = artist + info, _ := m.client.GetArtistInfo(artist.ID) + m.artistInfo = info + m.Update() + m.log("") +} + +func (m *main) SetSearch(result *subsonic.SearchResult3, query string) { + m.mode = mainModeSearch + m.searchResult = result + m.query = query + m.Update() + m.log("Found #%d artists, #%d albums and #%d songs", + len(result.Artist), + len(result.Album), + len(result.Song), + ) +} + +func (m *main) drawPlaylist() { + subtitle := fmt.Sprintf("%s\n\nCreated by: %s | %s", m.playlist.Comment, m.playlist.Owner, time.Duration(m.playlist.Duration*int(time.Second)).String()) + m.populateHeader(m.playlist.Name, subtitle, m.playlist.Duration, m.playlist.CoverArt) + playBtn := m.drawPlaylistAlbumButtons(m.playlist.Entry) + m.populateSongs(m.playlist.Entry, playBtn) +} + +func (m *main) drawAlbum() { + subtitle := fmt.Sprintf("%s\n\n%d | %s", m.album.Artist, m.album.Year, time.Duration(m.album.Duration*int(time.Second)).String()) + m.populateHeader(m.album.Name, subtitle, m.album.Duration, m.album.CoverArt) + playBtn := m.drawPlaylistAlbumButtons(m.album.Song) + m.populateSongs(m.album.Song, playBtn) + +} + +func (m *main) drawArtist() { + m.populateHeader(m.artist.Name, m.artistInfo.Biography, 0, m.artist.CoverArt) + btn := m.drawArtistButtons() + m.populateAlbums(btn) +} + +func (m *main) drawSearch() { + sub := fmt.Sprintf("Query: %s", m.query) + m.populateHeader("Search Results", sub, 0, "") + m.populateSearchResults() +} + +func (m *main) Update() { + m.view.Clear() + switch m.mode { + case mainModeAlbum: + m.drawAlbum() + case mainModePlaylist: + m.drawPlaylist() + case mainModeArtist: + m.drawArtist() + case mainModeSearch: + m.drawSearch() + } + m.songList.Focus(nil) +} + +func (m *main) drawArtistButtons() *tview.Button { + // Add buttons: Radio + songs, _ := m.client.GetTopSongs(m.artist.Name, 10) + f := tview.NewFlex() + f.SetBackgroundColor(config.ColorBackground) + f.SetBorderPadding(0, 0, 2, 2) + // Buttons + radio := NewButton("Radio") + top10 := NewButton("Top 10") + // Button callbacks + top10.SetSelectedFunc(func() { + top10.Blur() + m.log("Playing %s's top 10 songs", m.artist.Name) + m.playAllFunc(songs...) + m.songList.Focus(nil) + }) + radio.SetSelectedFunc(func() { + radio.Blur() + m.log("Generating %s's radio", m.artist.Name) + go func() { + radioSongs := []*subsonic.Child{} + if config.ExperimentalRadioAlgo() { + radioSongs, _ = m.client.GetExperimentalArtistRadio(m.artist, m.artistInfo, config.MaxRadioSongs()) + } + if len(radioSongs) == 0 { + radioSongs, _ = m.client.GetSimilarSongs(m.artist.ID, config.MaxRadioSongs()) + } + + common.ShuffleSlice(radioSongs) + m.playAllFunc(radioSongs...) + }() + m.songList.Focus(nil) + }) + radio.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey { + switch event.Key() { + case tcell.KeyDown: + radio.Blur() + m.songList.Focus(nil) + return nil + case tcell.KeyRight: + radio.Blur() + top10.Focus(nil) + return nil + } + return event + }) + top10.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey { + switch event.Key() { + case tcell.KeyDown: + top10.Blur() + m.songList.Focus(nil) + return nil + case tcell.KeyLeft: + top10.Blur() + radio.Focus(nil) + return nil + } + return event + }) + + f.AddItem(radio, 0, 1, false) + f.AddItem(EmptyBox, 0, 1, false) + if len(songs) > 0 { + f.AddItem(top10, 0, 1, false) + } + f.AddItem(EmptyBox, 0, 1, false) + + // Add the buttons to the view + m.view.AddItem(f, 1, 0, false) + // Margin bottom of 1 line + m.view.AddItem(EmptyBox, 1, 0, false) + + return radio +} + +func (m *main) populateAlbums(btn *tview.Button) { + table := tview.NewTable() + table.SetBackgroundColor(config.ColorBackground) + table.SetWrapSelection(true, false) + for i, album := range m.artist.Album { + year := tview.NewTableCell(fmt.Sprintf("%d", album.Year)).SetTextColor(config.ColorTextAccent) + name := tview.NewTableCell(album.Name).SetExpansion(2).SetAlign(tview.AlignCenter) + d := time.Second * time.Duration(album.Duration) + duration := tview.NewTableCell(d.String()).SetAlign(tview.AlignRight).SetExpansion(1) + + table.SetCell(i, 0, year) + table.SetCell(i, 1, name) + table.SetCell(i, 2, duration) + } + + table.SetFocusFunc(func() { + m.view.SetBorderColor(config.ColorSelectedBoarder) + table.SetSelectable(true, false) + }) + table.SetBlurFunc(func() { + m.view.SetBorderColor(config.ColorBluredBoarder) + table.SetSelectable(false, false) + }) + table.SetSelectedFunc(func(row, column int) { + alb, _ := m.client.GetAlbum(m.artist.Album[row].ID) + m.SetAlbum(alb) + m.view.Focus(nil) + }) + table.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey { + row, _ := m.songList.GetSelection() + if row == 0 && event.Key() == tcell.KeyUp { + table.Blur() + m.view.SetBorderColor(config.ColorSelectedBoarder) + btn.Focus(nil) + return nil + } + return event + }) + m.songList = table + + m.view.AddItem(table, 0, 1, false) + +} + +func (m *main) drawPlaylistAlbumButtons(songs []*subsonic.Child) *tview.Button { + // Add buttons: Play | Shuffle | Add to queue + f := tview.NewFlex() + f.SetBackgroundColor(config.ColorBackground) + f.SetBorderPadding(0, 0, 2, 2) + // Buttons + play := NewButton("Play") + shuffle := NewButton("Shuffle") + queue := NewButton("Queue") + artist := NewButton("Artist") + // Button callbacks + play.SetSelectedFunc(func() { + play.Blur() + m.playAllFunc(songs...) + m.songList.Focus(nil) + }) + play.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey { + switch event.Key() { + case tcell.KeyLeft: + play.Blur() + artist.Focus(nil) + return nil + case tcell.KeyRight: + play.Blur() + shuffle.Focus(nil) + return nil + case tcell.KeyDown: + play.Blur() + m.songList.Focus(nil) + return nil + } + return event + }) + shuffle.SetSelectedFunc(func() { + shuffle.Blur() + cpy := make([]*subsonic.Child, len(songs)) + copy(cpy, songs) + common.ShuffleSlice(cpy) + m.playAllFunc(cpy...) + m.songList.Focus(nil) + }) + shuffle.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey { + switch event.Key() { + case tcell.KeyLeft: + shuffle.Blur() + play.Focus(nil) + return nil + case tcell.KeyRight: + shuffle.Blur() + queue.Focus(nil) + return nil + case tcell.KeyDown: + shuffle.Blur() + m.songList.Focus(nil) + return nil + } + return event + }) + queue.SetSelectedFunc(func() { + queue.Blur() + m.addSongsFunc(songs...) + m.songList.Focus(nil) + }) + queue.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey { + switch event.Key() { + case tcell.KeyLeft: + queue.Blur() + shuffle.Focus(nil) + return nil + case tcell.KeyRight: + queue.Blur() + artist.Focus(nil) + return nil + case tcell.KeyDown: + queue.Blur() + m.songList.Focus(nil) + return nil + } + return event + }) + artist.SetSelectedFunc(func() { + artist.Blur() + ar, _ := m.client.GetArtist(m.album.ArtistID) + m.SetArtist(ar) + m.songList.Focus(nil) + }) + artist.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey { + switch event.Key() { + case tcell.KeyLeft: + artist.Blur() + queue.Focus(nil) + return nil + case tcell.KeyRight: + artist.Blur() + play.Focus(nil) + return nil + case tcell.KeyDown: + artist.Blur() + m.songList.Focus(nil) + return nil + } + return event + }) + + f.AddItem(play, 0, 1, true) + f.AddItem(EmptyBox, 0, 1, false) + f.AddItem(shuffle, 0, 1, false) + f.AddItem(EmptyBox, 0, 1, false) + f.AddItem(queue, 0, 1, false) + f.AddItem(EmptyBox, 0, 1, false) + f.AddItem(artist, 0, 1, false) + + // Add the buttons to the view + m.view.AddItem(f, 1, 0, false) + // Margin bottom of 1 line + m.view.AddItem(EmptyBox, 1, 0, false) + + return play +} + +func (m *main) populateSongs(songs []*subsonic.Child, play *tview.Button) { + table := tview.NewTable() + table.SetBackgroundColor(config.ColorBackground) + table.SetWrapSelection(true, false) + for i, song := range songs { + num := tview.NewTableCell(fmt.Sprintf("%d", i+1)).SetTextColor(config.ColorTextAccent) + title := tview.NewTableCell(song.Title).SetMaxWidth(15).SetExpansion(2) + artist := tview.NewTableCell(song.Artist).SetMaxWidth(15).SetExpansion(1) + d := time.Second * time.Duration(song.Duration) + duration := tview.NewTableCell(d.String()).SetAlign(tview.AlignRight).SetExpansion(1) + table.SetCell(i, 0, num) + table.SetCell(i, 1, title) + table.SetCell(i, 2, artist) + table.SetCell(i, 3, duration) + } + + m.songList = table + table.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey { + // on first line and pressing up -> play button + row, _ := table.GetSelection() + if row == 0 && event.Key() == tcell.KeyUp { + table.Blur() + m.view.SetBorderColor(config.ColorSelectedBoarder) + play.Focus(nil) + return nil + } else if event.Rune() == 'r' { + song := songs[row] + m.log("Generating song (%s) radio....", song.Title) + go func() { + radioSongs, _ := m.client.GetSimilarSongs(song.ID, config.MaxRadioSongs()) + m.playAllFunc(radioSongs...) + }() + } + return event + }) + table.SetFocusFunc(func() { + m.view.SetBorderColor(config.ColorSelectedBoarder) + table.SetSelectable(true, false) + }) + table.SetBlurFunc(func() { + m.view.SetBorderColor(config.ColorBluredBoarder) + table.SetSelectable(false, false) + }) + m.songList.SetSelectedFunc(func(row, column int) { + m.addSongsFunc(songs[row]) + }) + + m.view.AddItem(table, 0, 1, false) +} + +func (m *main) populateSearchResults() { + table := tview.NewTable() + table.SetBackgroundColor(config.ColorBackground) + table.SetWrapSelection(true, false) + row := 0 + lastArtist := 0 + lastAlbum := 0 + + // Artists + if len(m.searchResult.Artist) > 0 { + // Header + header := tview.NewTableCell("Artists").SetSelectable(false) + table.SetCell(row, 0, header) + row++ + //List + for i, artist := range m.searchResult.Artist { + index := tview.NewTableCell(fmt.Sprintf("%d", i+1)). + SetTextColor(config.ColorTextAccent) + a := tview.NewTableCell(artist.Name).SetExpansion(2).SetMaxWidth(15) + acount := tview.NewTableCell(fmt.Sprintf("%d Albums", artist.AlbumCount)). + SetExpansion(1).SetAlign(tview.AlignRight).SetMaxWidth(15) + table.SetCell(row, 0, index) + table.SetCell(row, 1, a) + table.SetCell(row, 2, acount) + row++ + } + lastArtist = row + } + + // Albums + + if len(m.searchResult.Album) > 0 { + // Header + header := tview.NewTableCell("Albums").SetSelectable(false) + table.SetCell(row, 0, header) + row++ + //List + for i, album := range m.searchResult.Album { + index := tview.NewTableCell(fmt.Sprintf("%d", i+1)). + SetTextColor(config.ColorTextAccent) + title := tview.NewTableCell(album.Name).SetExpansion(2).SetMaxWidth(15) + artist := tview.NewTableCell(album.Artist). + SetExpansion(1).SetAlign(tview.AlignRight).SetMaxWidth(15) + table.SetCell(row, 0, index) + table.SetCell(row, 1, title) + table.SetCell(row, 2, artist) + row++ + } + lastAlbum = row + } + // Songs + if len(m.searchResult.Song) > 0 { + // Header + header := tview.NewTableCell("Songs").SetSelectable(false) + table.SetCell(row, 0, header) + row++ + //List + for i, song := range m.searchResult.Song { + index := tview.NewTableCell(fmt.Sprintf("%d", i+1)). + SetTextColor(config.ColorTextAccent) + title := tview.NewTableCell(song.Title).SetExpansion(2).SetMaxWidth(15) + artist := tview.NewTableCell(song.Artist). + SetExpansion(1).SetAlign(tview.AlignRight).SetMaxWidth(15) + table.SetCell(row, 0, index) + table.SetCell(row, 1, title) + table.SetCell(row, 2, artist) + row++ + } + } + + m.songList = table + table.SetFocusFunc(func() { + m.view.SetBorderColor(config.ColorSelectedBoarder) + table.SetSelectable(true, false) + }) + table.SetBlurFunc(func() { + m.view.SetBorderColor(config.ColorBluredBoarder) + table.SetSelectable(false, false) + }) + table.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey { + row, _ := table.GetSelection() + if row <= lastAlbum { + return event + } + if event.Rune() != 'r' { + return event + } + cell := table.GetCell(row, 0) + index, err := strconv.Atoi(cell.Text) + if err != nil { + return nil + } + song := m.searchResult.Song[index-1] + m.log("Generating song (%s) radio....", song.Title) + go func() { + radioSongs, _ := m.client.GetSimilarSongs(song.ID, config.MaxRadioSongs()) + m.playAllFunc(radioSongs...) + }() + return nil + }) + m.songList.SetSelectedFunc(func(row, column int) { + cell := table.GetCell(row, 0) + index, err := strconv.Atoi(cell.Text) + if err != nil { + return + } + if row <= lastArtist { + artist, _ := m.client.GetArtist(m.searchResult.Artist[index-1].ID) + m.SetArtist(artist) + } else if lastArtist < row && row <= lastAlbum { + album, _ := m.client.GetAlbum(m.searchResult.Album[index-1].ID) + m.SetAlbum(album) + } else { + m.addSongsFunc(m.searchResult.Song[index-1]) + } + }) + + m.view.AddItem(table, 0, 1, false) +} + +func (m *main) populateHeader(title, subtitle string, + duration int, coverArtID string) { + + header := tview.NewFlex() + header.SetBackgroundColor(config.ColorBackground) + art := tview.NewImage() + art.SetBackgroundColor(config.ColorBackground) + + img, _ := m.client.GetCoverArt(coverArtID) + art.SetImage(img) + t := tview.NewTextView(). + SetTextColor(config.ColorTextAccent). + SetTextAlign(tview.AlignCenter). + SetText(title) + t.SetBackgroundColor(config.ColorBackground) + s := tview.NewTextView(). + SetTextColor(config.ColorText). + SetTextAlign(tview.AlignCenter). + SetText(subtitle).SetWordWrap(true) + s.SetBackgroundColor(config.ColorBackground) + + g := tview.NewFlex().SetDirection(tview.FlexRow) + g.SetBackgroundColor(config.ColorBackground) + g.AddItem(EmptyBox, 1, 1, false) + g.AddItem(t, 1, 1, false) + g.AddItem(s, 0, 1, false) + + header.AddItem(art, 0, 1, false) + header.AddItem(g, 0, 3, false) + size := 6 + if m.miniView { + size = 4 + } + m.view.AddItem(header, size, 1, false) + + // Margin bottom of 1 line + if !m.miniView { + m.view.AddItem(EmptyBox, 1, 0, false) + } +} + +func (m *main) SetPlayAllFunc(f func(song ...*subsonic.Child)) { + m.playAllFunc = f +} + +func (m *main) SetPlayAddSongFunc(f func(song ...*subsonic.Child)) { + m.addSongsFunc = f +} + +func (m *main) GetView() tview.Primitive { + return m.view +} diff --git a/internal/tui/views/player.go b/internal/tui/views/player.go new file mode 100644 index 0000000..45fb8d0 --- /dev/null +++ b/internal/tui/views/player.go @@ -0,0 +1,117 @@ +package views + +import ( + "fmt" + "time" + + "git.dayanhub.com/sagi/subsonic-tui/internal/client" + "git.dayanhub.com/sagi/subsonic-tui/internal/config" + "github.com/delucks/go-subsonic" + "github.com/rivo/tview" +) + +var _ View = &player{} + +type player struct { + client *client.Client + view tview.Primitive + grid *tview.Grid + artwork *tview.Image + progress *tview.Flex + songInfo *tview.TextView + song *subsonic.Child +} + +func NewPlayer(client *client.Client) *player { + grid := tview.NewGrid().SetColumns(9, 0) + grid.SetBackgroundColor(config.ColorBackground) + + //album art + art := tview.NewImage() + art.SetBackgroundColor(config.ColorBackground) + + grid.AddItem(art, 0, 0, 1, 1, 4, 4, false) + // Progress + progress := tview.NewFlex() + progress.SetBackgroundColor(config.ColorBackground) + + // Song songInfo + songInfo := tview.NewTextView() + songInfo.SetDynamicColors(true) + songInfo.SetBackgroundColor(config.ColorBackground) + + // Info + Progress + songProg := tview.NewFlex().SetDirection(tview.FlexRow) + songProg.AddItem(songInfo, 0, 4, false) + songProg.AddItem(progress, 0, 1, false) + grid.AddItem(songProg, 0, 1, 1, 1, 0, 0, false) + + player := &player{ + client: client, + view: grid, + artwork: art, + songInfo: songInfo, + grid: grid, + progress: progress, + } + + player.SetSongInfo(&subsonic.Child{ + Title: "Subsonic TUI", + Album: "MaVeZe", + Artist: "ZeGoomba", + CoverArt: "", + Duration: 0, + }) + player.UpdateProgress(time.Duration(0)) + + return player +} + +func (p *player) SetSongInfo(song *subsonic.Child) { + info := fmt.Sprintf("[yellow]Title:[white] %s\n[yellow]Album:[white] %s\n[yellow]Atrists:[white] %s", + song.Title, song.Album, song.Artist) + p.songInfo.SetText(info) + p.song = song + p.LoadAlbumArt(song.CoverArt) +} + +func (p *player) LoadAlbumArt(ID string) { + i, _ := p.client.GetCoverArt(ID) + p.artwork.SetImage(i) +} + +func (p *player) UpdateProgress(elapsed time.Duration) { + + if p.song.Duration == 0 { + // Startup... Show version number + versionInfo := tview.NewTextView().SetText("Version: 0.1") + versionInfo.SetBackgroundColor(config.ColorPlaybackProgressRemaining) + versionInfo.SetTextColor(config.ColorPlaybackProgressElapsed) + p.progress.AddItem(versionInfo, 0, 1, false) + return + } + + songDuration := time.Duration(p.song.Duration) * time.Second + overlappedBox := tview.NewTextView() + overlappedBox.SetBackgroundColor(config.ColorPlaybackProgressElapsed) + overlappedBox.SetTextColor(config.ColorPlaybackProgressRemaining) + overlappedBox.SetText(songDuration.String()) + remainingBox := tview.NewTextView() + remainingBox.SetBackgroundColor(config.ColorPlaybackProgressRemaining) + remainingBox.SetTextColor(config.ColorPlaybackProgressElapsed) + remainingBox.SetTextAlign(tview.AlignRight) + rm := time.Duration(songDuration.Seconds()-elapsed.Seconds()) * time.Second + remaining := fmt.Sprintf("-%s", rm.String()) + remainingBox.SetText(remaining) + p.progress.Clear() + p.progress.AddItem(overlappedBox, 0, int(elapsed.Seconds()), false) + p.progress.AddItem(remainingBox, 0, int(songDuration.Seconds())-int(elapsed.Seconds()), false) +} + +func (p *player) GetView() tview.Primitive { + return p.view +} + +func (p *player) Update() { + //p.UpdateProgress("00:00", 50) +} diff --git a/internal/tui/views/playlists.go b/internal/tui/views/playlists.go new file mode 100644 index 0000000..674720a --- /dev/null +++ b/internal/tui/views/playlists.go @@ -0,0 +1,63 @@ +package views + +import ( + "git.dayanhub.com/sagi/subsonic-tui/internal/client" + "git.dayanhub.com/sagi/subsonic-tui/internal/config" + "github.com/delucks/go-subsonic" + "github.com/rivo/tview" +) + +var _ View = &playlists{} + +type playlists struct { + view *tview.Table + client *client.Client + callback func(playlist *subsonic.Playlist) +} + +func NewPlaylists(client *client.Client) *playlists { + + obj := &playlists{ + client: client, + } + + list := tview.NewTable() + + list.SetBackgroundColor(config.ColorBackground) + list.SetTitle("Playlists [3]") + list.SetBorder(true) + list.SetFocusFunc(func() { + list.SetBorderColor(config.ColorSelectedBoarder) + list.SetSelectable(true, false) + }) + list.SetBlurFunc(func() { + list.SetBorderColor(config.ColorBluredBoarder) + list.SetSelectable(false, false) + }) + + pls, _ := client.GetPlaylists() + for i, pl := range pls { + cell := tview.NewTableCell(pl.Name).SetExpansion(1) + list.SetCell(i, 0, cell) + } + + list.SetSelectedFunc(func(row, column int) { + obj.callback(pls[row]) + }) + + obj.view = list + + return obj +} + +func (p *playlists) SetCallback(f func(playlist *subsonic.Playlist)) { + p.callback = f +} + +func (p *playlists) Update() { + +} + +func (p *playlists) GetView() tview.Primitive { + return p.view +} diff --git a/internal/tui/views/queue.go b/internal/tui/views/queue.go new file mode 100644 index 0000000..8ef7bb7 --- /dev/null +++ b/internal/tui/views/queue.go @@ -0,0 +1,81 @@ +package views + +import ( + "fmt" + "time" + + "git.dayanhub.com/sagi/subsonic-tui/internal/config" + "github.com/delucks/go-subsonic" + "github.com/rivo/tview" +) + +type queue struct { + view *tview.Table + playFunc func(index int) + currentSong int + songQueue []*subsonic.Child +} + +func NewQueue() *queue { + table := tview.NewTable() + table.SetBackgroundColor(config.ColorBackground) + table.SetTitle("Queue [4]") + table.SetBorder(true) + table.SetFocusFunc(func() { + table.SetBorderColor(config.ColorSelectedBoarder) + }) + table.SetBlurFunc(func() { + table.SetBorderColor(config.ColorBluredBoarder) + }) + + return &queue{ + view: table, + currentSong: 0, + } +} + +func (q *queue) SetPlayFunc(f func(index int)) { + q.playFunc = f +} + +func (q *queue) drawQueue() { + q.view.Clear() + list := q.view + list.SetWrapSelection(true, false) + list.SetSelectable(true, false) + for i, song := range q.songQueue { + isCurrentSong := q.currentSong == i + isPlayed := i < q.currentSong + bgColor := config.ColorBackground + if isCurrentSong { + bgColor = config.ColorQueuePlayingBg + } else if isPlayed { + bgColor = config.ColorQueuePlayedBg + } + num := tview.NewTableCell(fmt.Sprintf("%d", i+1)).SetTextColor(config.ColorTextAccent).SetBackgroundColor(bgColor) + title := tview.NewTableCell(song.Title).SetMaxWidth(15).SetExpansion(2).SetBackgroundColor(bgColor) + artist := tview.NewTableCell(song.Artist).SetMaxWidth(15).SetExpansion(1).SetBackgroundColor(bgColor) + d := time.Second * time.Duration(song.Duration) + duration := tview.NewTableCell(d.String()).SetAlign(tview.AlignRight).SetExpansion(1).SetBackgroundColor(bgColor) + list.SetCell(i, 0, num) + list.SetCell(i, 1, title) + list.SetCell(i, 2, artist) + list.SetCell(i, 3, duration) + } + + list.SetSelectedFunc(func(row, column int) { + q.currentSong = row + q.playFunc(row) + }) +} + +func (q *queue) Update(songs []*subsonic.Child, currentSong int) { + q.songQueue = songs + q.currentSong = currentSong + q.drawQueue() + +} + +func (q *queue) GetView() tview.Primitive { + return q.view +} diff --git a/internal/tui/views/status_line.go b/internal/tui/views/status_line.go new file mode 100644 index 0000000..4de74b6 --- /dev/null +++ b/internal/tui/views/status_line.go @@ -0,0 +1,98 @@ +package views + +import ( + "fmt" + + "git.dayanhub.com/sagi/subsonic-tui/internal/config" + "github.com/gdamore/tcell/v2" + "github.com/rivo/tview" +) + +var _ View = &statusLine{} + +type statusLine struct { + view *tview.Flex + mode Statusmode + onUpdateFunc func() + onSearchFunc func(quary string) +} + +type Statusmode int + +const ( + StatusModeLog Statusmode = iota + StatusModeSearch Statusmode = iota +) + +func NewStatusLine() *statusLine { + status := tview.NewFlex() + status.SetBackgroundColor(config.ColorBackground) + // Default empty box + status.AddItem(EmptyBox, 0, 1, false) + + return &statusLine{ + view: status, + mode: StatusModeLog, + } +} + +func (s *statusLine) SetSearchFunc(f func(quary string)) { + s.onSearchFunc = f +} + +func (s *statusLine) Mode() Statusmode { + return s.mode +} + +func (s *statusLine) Search() { + s.mode = StatusModeSearch + s.view.Clear() + label := "Search: " + _, _, w, _ := s.view.GetRect() + query := "" + inputField := tview.NewInputField() + inputField. + SetLabel(label). + SetFieldWidth(w - len(label)). + SetDoneFunc(func(key tcell.Key) { + if key == tcell.KeyEnter { + s.mode = StatusModeLog + s.onSearchFunc(query) + } else if key == tcell.KeyEsc { + s.mode = StatusModeLog + s.onSearchFunc("") + } + }). + SetChangedFunc(func(text string) { + query = text + }) + inputField.Focus(nil) + inputField.SetBackgroundColor(config.ColorBackground) + inputField.SetFieldBackgroundColor(config.ColorBackground) + s.view.AddItem(inputField, 0, 1, true) + s.Update() +} + +func (s *statusLine) SetOnUpdateFunc(f func()) { + s.onUpdateFunc = f +} + +func (s *statusLine) Log(format string, a ...any) { + if s.mode != StatusModeLog { + return + } + str := fmt.Sprintf(format, a...) + s.view.Clear() + txt := tview.NewTextView().SetDynamicColors(true) + txt.SetBackgroundColor(config.ColorBackground) + txt.SetText(str) + s.view.AddItem(txt, 0, 1, false) + s.Update() +} + +func (s *statusLine) GetView() tview.Primitive { + return s.view +} +func (s *statusLine) Update() { + s.onUpdateFunc() +} diff --git a/internal/tui/views/view.go b/internal/tui/views/view.go new file mode 100644 index 0000000..cc5cb52 --- /dev/null +++ b/internal/tui/views/view.go @@ -0,0 +1,15 @@ +package views + +import ( + "git.dayanhub.com/sagi/subsonic-tui/internal/config" + "github.com/rivo/tview" +) + +type ViewEvent string + +var EmptyBox tview.Primitive = tview.NewBox().SetBackgroundColor(config.ColorBackground) + +type View interface { + GetView() tview.Primitive + Update() +} diff --git a/main.go b/main.go new file mode 100644 index 0000000..3c8c8b6 --- /dev/null +++ b/main.go @@ -0,0 +1,42 @@ +package main + +import ( + "fmt" + + "git.dayanhub.com/sagi/subsonic-tui/internal/client" + "git.dayanhub.com/sagi/subsonic-tui/internal/config" + "git.dayanhub.com/sagi/subsonic-tui/internal/playback" + "git.dayanhub.com/sagi/subsonic-tui/internal/tui" +) + +func main() { + defer client.ArtCache.Destroy() + // Create Client + subsonicClient := client.NewClient(config.URL()) + err := subsonicClient.Authenticate(config.Username(), config.Password()) + if err != nil { + // We need to show Login... + login := tui.NewLogin() + err := login.Run() + if err != nil { + panic(err) + } + + } + fmt.Println("Trying to login...") + subsonicClient = client.NewClient(config.URL()) + err = subsonicClient.Authenticate(config.Username(), config.Password()) + if err != nil { + panic(err) + } + // Saving config - will result in adding new defaults to the file + config.SaveConfig() + + playbackCtl := playback.NewController(subsonicClient) + defer playbackCtl.Close() + + tui := tui.NewPlayer(subsonicClient, playbackCtl) + if err := tui.Run(); err != nil { + panic(err) + } +} diff --git a/renovate.json b/renovate.json new file mode 100644 index 0000000..c5f8d63 --- /dev/null +++ b/renovate.json @@ -0,0 +1,6 @@ +{ + "$schema": "https://docs.renovatebot.com/renovate-schema.json", + "reviewers": [ + "sagi" + ] +}