Showing preview only (2,646K chars total). Download the full file or copy to clipboard to get everything.
Repository: GNOME/gnome-music
Branch: master
Commit: 8a9e6c6e6947
Files: 250
Total size: 2.3 MB
Directory structure:
gitextract_kect3s27/
├── .gitlab/
│ └── issue_templates/
│ └── default.md
├── .gitlab-ci.yml
├── .gitmodules
├── CONTRIBUTING.md
├── LICENSE
├── NEWS
├── README.md
├── data/
│ ├── meson.build
│ ├── org.gnome.Music.desktop.in.in
│ ├── org.gnome.Music.gresource.xml
│ ├── org.gnome.Music.gschema.xml
│ ├── org.gnome.Music.metainfo.xml.in.in
│ ├── org.gnome.Music.service.in
│ ├── queries/
│ │ ├── album_disc.rq
│ │ ├── album_discs.rq
│ │ ├── albums.rq
│ │ ├── artist_albums.rq
│ │ ├── artists.rq
│ │ ├── playlist_add_song.rq
│ │ ├── playlist_create.rq
│ │ ├── playlist_delete.rq
│ │ ├── playlist_delete_song.rq
│ │ ├── playlist_query_all.rq
│ │ ├── playlist_query_delete_entry.rq
│ │ ├── playlist_query_playlist.rq
│ │ ├── playlist_query_songs.rq
│ │ ├── playlist_rename_title.rq
│ │ ├── playlist_reorder_songs.rq
│ │ ├── search_albums.rq
│ │ ├── search_artists.rq
│ │ ├── search_songs.rq
│ │ └── songs.rq
│ ├── style.css
│ └── ui/
│ ├── AlbumCover.ui
│ ├── AlbumNavigationPage.ui
│ ├── AlbumTile.ui
│ ├── AlbumWidget.ui
│ ├── AlbumsSearchNavigationPage.ui
│ ├── AlbumsView.ui
│ ├── ArtistAlbumsWidget.ui
│ ├── ArtistNavigationPage.ui
│ ├── ArtistSearchTile.ui
│ ├── ArtistTile.ui
│ ├── ArtistsSearchNavigationPage.ui
│ ├── ArtistsView.ui
│ ├── DiscBox.ui
│ ├── DiscListItem.ui
│ ├── HeaderBar.ui
│ ├── PlayerToolbar.ui
│ ├── PlaylistControls.ui
│ ├── PlaylistDialog.ui
│ ├── PlaylistDialogRow.ui
│ ├── PlaylistTile.ui
│ ├── PlaylistsView.ui
│ ├── PlaylistsWidget.ui
│ ├── PreferencesDialog.ui
│ ├── RepeatModeButton.ui
│ ├── SearchHeaderBar.ui
│ ├── SearchView.ui
│ ├── SongWidget.ui
│ ├── SongWidgetMenu.ui
│ ├── StatusNavigationPage.ui
│ ├── TwoLineTip.ui
│ ├── VolumeButton.ui
│ ├── Window.ui
│ └── shortcuts-dialog.ui
├── gnome-music.doap
├── gnome-music.in
├── gnomemusic/
│ ├── __init__.py
│ ├── about.py
│ ├── albumart.py
│ ├── application.py
│ ├── artistart.py
│ ├── asynciolimiter.py
│ ├── corealbum.py
│ ├── coreartist.py
│ ├── coredisc.py
│ ├── coregrilo.py
│ ├── coremodel.py
│ ├── coresong.py
│ ├── coverpaintable.py
│ ├── embeddedart.py
│ ├── grilowrappers/
│ │ ├── __init__.py
│ │ ├── localsearchplaylists.py
│ │ ├── localsearchwrapper.py
│ │ ├── playlist.py
│ │ └── smartplaylist.py
│ ├── gstplayer.py
│ ├── inhibitsuspend.py
│ ├── mediaartloader.py
│ ├── mpris.py
│ ├── musiclogger.py
│ ├── notificationmanager.py
│ ├── pauseonsuspend.py
│ ├── player.py
│ ├── playlisttoast.py
│ ├── queue.py
│ ├── search.py
│ ├── shufflelistmodel.py
│ ├── songart.py
│ ├── songtoast.py
│ ├── storeart.py
│ ├── texturecache.py
│ ├── trackerwrapper.py
│ ├── utils.py
│ ├── views/
│ │ ├── __init__.py
│ │ ├── albumsview.py
│ │ ├── artistsview.py
│ │ ├── playlistsview.py
│ │ └── searchview.py
│ ├── widgets/
│ │ ├── __init__.py
│ │ ├── albumcover.py
│ │ ├── albumnavigationpage.py
│ │ ├── albumssearchnavigationpage.py
│ │ ├── albumtile.py
│ │ ├── albumwidget.py
│ │ ├── artistalbumswidget.py
│ │ ├── artistnavigationpage.py
│ │ ├── artistsearchtile.py
│ │ ├── artistssearchnavigationpage.py
│ │ ├── artisttile.py
│ │ ├── discbox.py
│ │ ├── headerbar.py
│ │ ├── playertoolbar.py
│ │ ├── playlistcontrols.py
│ │ ├── playlistdialog.py
│ │ ├── playlistdialogrow.py
│ │ ├── playlistswidget.py
│ │ ├── playlisttile.py
│ │ ├── preferencesdialog.py
│ │ ├── repeatmodebutton.py
│ │ ├── searchheaderbar.py
│ │ ├── smoothscale.py
│ │ ├── songwidget.py
│ │ ├── songwidgetmenu.py
│ │ ├── startoggle.py
│ │ ├── statusnavigationpage.py
│ │ ├── twolinetip.py
│ │ └── volumebutton.py
│ ├── window.py
│ └── windowplacement.py
├── help/
│ ├── LINGUAS
│ ├── bg/
│ │ └── bg.po
│ ├── ca/
│ │ └── ca.po
│ ├── cs/
│ │ └── cs.po
│ ├── da/
│ │ └── da.po
│ ├── de/
│ │ └── de.po
│ ├── el/
│ │ └── el.po
│ ├── es/
│ │ └── es.po
│ ├── eu/
│ │ └── eu.po
│ ├── fr/
│ │ └── fr.po
│ ├── gl/
│ │ └── gl.po
│ ├── hr/
│ │ └── hr.po
│ ├── hu/
│ │ └── hu.po
│ ├── id/
│ │ └── id.po
│ ├── it/
│ │ └── it.po
│ ├── kk/
│ │ └── kk.po
│ ├── ko/
│ │ └── ko.po
│ ├── meson.build
│ ├── nl/
│ │ └── nl.po
│ ├── pl/
│ │ └── pl.po
│ ├── pt_BR/
│ │ └── pt_BR.po
│ ├── ro/
│ │ └── ro.po
│ ├── ru/
│ │ └── ru.po
│ ├── sr/
│ │ └── sr.po
│ ├── sv/
│ │ └── sv.po
│ ├── tr/
│ │ └── tr.po
│ ├── uk/
│ │ └── uk.po
│ └── zh_CN/
│ └── zh_CN.po
├── meson.build
├── meson_options.txt
├── org.gnome.Music.json
└── po/
├── LINGUAS
├── POTFILES.in
├── POTFILES.skip
├── ab.po
├── af.po
├── an.po
├── ar.po
├── as.po
├── be.po
├── bg.po
├── bs.po
├── ca.po
├── ca@valencia.po
├── cs.po
├── da.po
├── de.po
├── el.po
├── en_GB.po
├── eo.po
├── es.po
├── et.po
├── eu.po
├── fa.po
├── fi.po
├── fr.po
├── fur.po
├── fy.po
├── ga.po
├── gd.po
├── gl.po
├── he.po
├── hi.po
├── hr.po
├── hu.po
├── ia.po
├── id.po
├── is.po
├── it.po
├── ja.po
├── ka.po
├── kab.po
├── kk.po
├── kn.po
├── ko.po
├── kw.po
├── lt.po
├── lv.po
├── meson.build
├── mjw.po
├── ml.po
├── ms.po
├── nb.po
├── ne.po
├── nl.po
├── oc.po
├── pa.po
├── pl.po
├── pt.po
├── pt_BR.po
├── ro.po
├── ru.po
├── sk.po
├── sl.po
├── sr.po
├── sr@latin.po
├── sv.po
├── ta.po
├── te.po
├── tg.po
├── th.po
├── tr.po
├── ug.po
├── uk.po
├── uz.po
├── vi.po
├── zh_CN.po
├── zh_HK.po
└── zh_TW.po
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitlab/issue_templates/default.md
================================================
## Description
[Description of the bug or feature]
## Steps To Reproduce
- Step 1
- Step 2
- Step 3
## Expected Behaviour
[What you expected to happen]
## Actual Behaviour
[What actually happened]
## Specifications
Gnome Music Version:
Desktop Environment:
Wayland or Xorg:
Flatpak or Native:
Tracker Version:
Grilo Version:
## Additional Information
================================================
FILE: .gitlab-ci.yml
================================================
include:
- project: 'GNOME/citemplates'
file: 'flatpak/flatpak_ci_initiative.yml'
- component: gitlab.gnome.org/GNOME/citemplates/release-service@master
inputs:
dist-job-name: "flatpak"
tarball-artifact-path: "${TARBALL_ARTIFACT_PATH}"
stages:
- check
- build-flatpak
- deploy
variables:
APP_ID: "org.gnome.Music.Devel"
FLATPAK_MODULE: "gnome-music"
MANIFEST_PATH: "org.gnome.Music.json"
RUNTIME_REPO: "https://nightly.gnome.org/gnome-nightly.flatpakrepo"
BUNDLE: "gnome-music-dev.flatpak"
GIT_SUBMODULE_STRATEGY: normal
TARBALL_ARTIFACT_PATH: ".flatpak-builder/build/${FLATPAK_MODULE}/_flatpak_build/meson-dist/${CI_PROJECT_NAME}-${CI_COMMIT_TAG}.tar.xz"
flatpak:
extends: .flatpak@x86_64
stage: build-flatpak
flatpak-aarch64:
extends: .flatpak@aarch64
stage: build-flatpak
nightly:
extends: .publish_nightly
dependencies:
- flatpak
nightly-aarch64:
extends: .publish_nightly
needs:
- flatpak-aarch64
dependencies:
- flatpak-aarch64
flake8:
stage: check
image: registry.fedoraproject.org/fedora:latest
script:
- dnf install -y python3-flake8
- flake8 --ignore E402,W503 --show-source gnomemusic/
mypy:
stage: check
image: registry.fedoraproject.org/fedora:latest
script:
- dnf install -y python3-mypy
- mypy --ignore-missing-imports --disallow-incomplete-defs gnomemusic
================================================
FILE: .gitmodules
================================================
[submodule "subprojects/shared-modules"]
path = subprojects/shared-modules
url = https://github.com/flathub/shared-modules.git
================================================
FILE: CONTRIBUTING.md
================================================
# Contributing
[Our guide](https://welcome.gnome.org/app/Music/) has everything to get you started.
## Build instructions
Music uses the [meson](http://mesonbuild.com/) build system.
The recommended way to work on Music is using flatpak through [gnome builder](https://welcome.gnome.org/app/Music/#working-on-the-code).
## Debugging
GNOME Music uses [GLib logging facilities](https://developer.gnome.org/glib/stable/glib-running.html) to print debug messages. It can be activated by setting the `G_MESSAGES_DEBUG` environment variable:
```sh
G_MESSAGES_DEBUG=org.gnome.Music gnome-music
```
## Coding style
GNOME Music is written in Python and adheres to the coding style described in the python style guide [PEP-8](https://www.python.org/dev/peps/pep-0008/).
Docstrings adhere to [PEP-257](https://www.python.org/dev/peps/pep-0257/). The content of docstrings uses the [Sphinx markup style](http://www.sphinx-doc.org/). Docstrings should be added to all (new) public functions.
Take note of the following rules as a basic style guide, but when in doubt consult PEP-8.
### Line length
>>>
Limit all lines to a maximum of 79 characters.
For flowing long blocks of text with fewer structural restrictions (docstrings or comments), the line length should be limited to 72 characters.
>>>
### Indentation
Music uses hanging indents when the lines get too long.
>>>
When using a hanging indent the following should be considered; there should be no arguments on the first line and further indentation should be used to clearly distinguish itself as a continuation line.
>>>
```python
# More indentation included to distinguish this from the rest.
def long_function_name(
var_one, var_two, var_three,
var_four):
print(var_one)
# Hanging indents should add a level.
foo = long_function_name(
var_one, var_two,
var_three, var_four)
```
### Line break before a binary operator
```python
# Yes: easy to match operators with operands
income = (gross_wages
+ taxable_interest
+ (dividends - qualified_dividends)
- ira_deduction
- student_loan_interest)
# Add some extra indentation on the conditional continuation line.
if (this_is_one_thing
and that_is_another_thing):
do_something()
```
### Class internals
All non-public classwide variables or methods should be prepended with an underscore.
>>>
_single_leading_underscore: weak "internal use" indicator. E.g. from M import * does not import objects whose name starts with an underscore.
>>>
### Type checking
Post 3.38 Music is starting to use type checking for all new code. This means that all arguments, returns values and variables have defined types and these types are checked for errors during the CI phase. Music uses [mypy](http://www.mypy-lang.org/) for the type checking pass.
The specific syntax is best learned from the code already adapted ([coresong.py](gnomemusic/coresong.py), [grltrackerwrapper.py](gnomemusic/grilowrappers/grltrackerwrapper.py)) or online sources, note that Music uses the annotation style. A simple example follows.
###### Old
```python
x = []
x.append(1)
```
###### New
```python
from typing import List
x: List[int] = []
x.append(1)
```
#### Properties
Mypy does not currently support PyGObject properties. This means property setters need to be forceibly ignored.
```python
@GObject.Property(type=bool, default=False)
def selected(self) -> bool:
return self._selected
@selected.setter # type: ignore
def selected(self, value: bool) -> None:
self._selected = value
```
### PyGObject specifics
#### Properties
Most objects in Music are derived from GObject and have properties. Use [PyGObject properties](https://pygobject.readthedocs.io/en/latest/guide/api/properties.html) through decorator usage if you add properties to your code.
Short form for simple properties:
```python
selected = GObject.Property(type=bool, default=False)
```
With method definition if more control is needed:
```python
@GObject.Property(type=bool, default=False)
def selection_mode(self):
return self._selection_mode
@selection_mode.setter
def selection_mode(self, value):
self._selection_mode = value
```
Manipulate and refer to GObject properties with the *props* attribute to set them apart from regular python attributes:
```python
is_selected = object.props.selected
object.props.selection_mode = True
```
##### Multi-word properties
Note that GObject multi-word properties are separated by `-` as in `'selection-mode'`, however Python does not allow `-` in variable or method names. So these are translated to `_` instead. You might find both `'selection-mode'` and `selection_mode` in the code (depending on how they are used), but they refer to the same property.
#### Templates
Music uses ui templates extensively for building the user interface. The basic usage in Python is as follows, with the `widget.ui` file being a regular GTK template:
```python
@Gtk.Template(resource_path="/org/gnome/Music/widget.ui")
class Widget(Gtk.Widget):
__gtype_name__ = "Widget"
_button = Gtk.Template.Child()
@Gtk.Template.Callback()
def _on_button_clicked(self, klass):
pass
```
## Commit messages
Music is fairly strict on the format and contents of commit messages. New contributors often struggle with this.
The GNOME Handbook has a good [intro](https://handbook.gnome.org/development/commit-messages.html) on what a proper commit message is and this is a **must read** for first-time contributors.
It is always recommended to look at other Music commit messages as well to get an idea of what a good commit message is specific to Music.
It should look somewhat like:
>>>
tag: Short explanation
Problem in some detail.
Implemented fix.
Closes: #issuenr
>>>
## Merge requests
When opening a Merge Request, please enable the [_'Allow commits from members who can merge to the target branch'_](https://docs.gitlab.com/ee/user/project/merge_requests/allow_collaboration.html) checkbox. This allows the Music maintainers to help out on the Merge Request as needed.
================================================
FILE: LICENSE
================================================
# This GPL license have a exception clause added, see at the bottom of file
# for details.
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) 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
this service 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 make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. 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.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute 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 and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
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
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the 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 a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, 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.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE 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.
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
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
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 2 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, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision 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, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This 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.
The GNOME Music authors hereby grant permission for non-GPL compatible
GStreamer plugins to be used and distributed together with GStreamer and
GNOME Music. This permission is above and beyond the permissions granted
by the GPL license by which GNOME Music is covered. If you modify this
code, you may extend this exception to your version of the code, but you
are not obligated to do so. If you do not wish to do so, delete this
exception statement from your version.
================================================
FILE: NEWS
================================================
Overview of changes in 50.alpha
===============================
Overview of changes in 49 rc
============================
Bugs fixed:
Fix order of playlist queries on dnd
Handle empty fields for Grl.Media creation
Extend asyncio use in playlists
Overview of changes in 49 beta
==============================
• Translation updates
Bugs fixed:
Flatpak build fixes for Grilo changes (#648)
Fix non-responsive window (#628)
Fix covers not scaling with gtk 4.19
Improve handling of failures in the art pipeline (#650)
Add D-Bus service file (!1099)
Thanks to our contributors this release:
Balló György
Jean Felder
Marinus Schraal
Overview of changes in 48.0
===========================
• Translation updates
Bugs fixed:
• Detect GIRepository version to use based on glib version
• Remove GIRepository import
Overview of changes in 48.beta
==============================
• Use PyGObject asyncio
• Support HiDPI covers
• Fix styling issues
• Improve search reliability
Bugs fixed:
Show MRPIS art on delayed retrieval (#611)
Thanks to our contributors this release:
Alireza Shabani
Brage Fuglseth
Jean Felder
Marinus Schraal
Tau Gärtli
Walt Shabani
Overview of changes in 47.0
===========================
• Add track based ReplayGain setting
Bugs fixed:
Expose ReplayGain settings (#594)
Thanks to our contributors this release:
Alpesh Jamgade
Marinus Schraal
Overview of changes in 46.1
===========================
• Fix search dropping the first character
Bugs fixed:
Handle bad image formats graciously (#605)
Fix first char dropping on search (#553)
Fix PyGObject change fallout
Incorrect/missing URLs in app metadata (#599)
Thanks to our contributors this release:
Andre Klapper
Debanga Sarma
Marinus Schraal
Michael Catanzaro
Vaishnavi Nawghare
Overview of changes in 46.0
===========================
• Translation updates
Overview of changes in 46.beta
==============================
• Ported to Adwaita 1.4 and 1.6 widgets
• Songs view removed
• Preferences dialog added
• Dropped old-style selection mode
Bugs Fixed:
Port to new libadwaita widgets (#579)
Remove GOA use and LastFM support (#584)
Fix Tracker 3 queries (#578)
Fix jumping scrolling (#580)
Replace StarImage with StarToggle (#497)
Improve texture scaling (#513)
Add preferences dialog (#471)
Improve player duration query handling (#449)
Remove Songs view (#570)
Improve 'Recently Played' query (!1047)
Improve appdata (!1026)
Thanks to our contributors this release:
Carlos Garnacho
Jean Felder
Feliks Weber
Marinus Schraal
Mpho Jele
Radek Crlík
Sabri Ünal
Shema Angelo Verlain
Tobias Bernard
Vincent Cottineau
Overview of changes in 45.0
===========================
• Minor quality of life improvements
Thanks to our contributors this release:
Carlos Garnacho
Jean Felder
Harold Knowlden
Marinus Schraal
Updated or added translations:
Abkhazian
Romanian
Italian
Turkish
British English
French
Hungarian
German
Hebrew
Ukrainian
Greek
Slovenian
Belarusian
Russian
Portuguese
Chinese (China)
Polish
Finnish
Spanish
Indonesian
Galician
Basque
Occitan
Georgian
Kazakh
Swedish
Czech
Punjabi
Korean
Dutch
Lithuanian
Danish
Catalan
Latvian
Overview of changes in 44.0
===========================
• Update appdata for the 44.0 release
Overview of changes in 44.rc
============================
• Shortcuts menu cleanups
• Misc focus fixes in album widgets
• Decrease memory usage in SongsView
Bugs Fixed:
SongView popup is a memory hog (#495)
Shuffle on/off mixup (#543)
Default template for issues (#525)
Thanks to our contributors this release:
Andre Klapper
Automeris Naranja
Ezike Ebuka
Jean Felder
Marinus Schraal
Sabri Ünal
Overview of changes in 44.beta
==============================
• Make shuffle shuffle again
• Fix time display in RTL languages
• Port to soup 3
• Port about to AdwAboutWindow
• No longer mismatch art on scrolling
• Fix async queue block on fresh art retrieval
• Use new GNOME Settings app id in flatpak
• Fix welcome image rendering
Bugs fixed:
Rework ArtStack to handle cycling widgets better (#500)
Shuffle broken in Music 42 (#515)
Time is reversed in RTL (#509)
Thanks to our contributors this release:
Carlos Garnacho
Christopher Davis
Georges Basile Stavracas Neto
Jean Felder
Marinus Schraal
Yosef Or Boczko
Updated or added translations:
Abkhazian
Basque
Belarusian
Brazilian Portuguese
Bulgarian
Catalan
Chinese (China)
Chinese (Taiwan)
Croatian
Czech
Danish
Dutch
Finnish
French
Friulian
Galician
Georgian
German
Greek
Hebrew
Hungarian
Icelandic
Indonesian
Kazakh
Korean
Latvian
Lithuanian
Nepali
Occitan
Persian
Polish
Portuguese
Russian
Serbian
Slovak
Slovenian
Spanish
Swedish
Turkish
Ukrainian
Overview of changes in 42.0
===========================
• GTK-4 regression fixes
Bugs fixed:
App title untranslated (#510)
Thanks to our contributors this release:
Fabian Bornschein
Georges Basile Stavracas Neto
Jean Felder
Marinus Schraal
Sophie Herold
Updated translations:
Ukrainian
Portuguese
Brazilian Portuguese
Indonesian
Catalan
Russian
Chinese (China)
Lithuanian
Hebrew
Czech
Persian
French
Turkish
Finnish
Spanish
Galician
Slovak
Slovenian
Polish
Basque
Swedish
Korean
Croatian
Danish
Bulgarian
Hungarian
Kazakh
Japanese
Serbian
German
Occitan
Norwegian Bokmål
Italian
Overview of changes in 42.beta
==============================
• Port to GTK-4
• Dark mode switching
Bugs fixed:
Fix slow startup (!923)
Thanks to our contributors this release:
Christopher Davis
Jakub Steiner
Jean Felder
Koushik Sahu
Marinus Schraal
Michael Catanzaro
Sam Hewitt
Sophie Herold
Updated translations:
Danish
Icelandic
Swedish
Russian
Indonesian
Catalan
Friulian
Latvian
Frisian
Bulgarian
Serbian
Vietnamese
Overview of changes in 41.0
===========================
Updated translations:
Basque
Spanish
Croatian
German
Occitan
Danish
Polish
Hungarian
Hebrew
Dutch
Belarusian
Turkish
Overview of changes in 41.rc
============================
• Touch-ups for the new design
• Async improvements
Bugs fixed:
Fix duplicated playlist song removal (#469)
Fix flowbox selection state (#460)
Thanks to our contributors this release:
Marinus Schraal
Mpho Jele
Updated translations:
Indonesian
Ukrainian
Swedish
Czech
Spanish
Basque
Catalan
Brazilian Portuguese
Galician
Finnish
British English
Kazakh
Slovenian
Slovak
Frisian
French
Korean
Persian
Greek
Lithuanian
Romanian
Chinese (China)
Overview of changes in 41.beta
==============================
• Implemented much of the new design mockups
• Update initial state art
Thanks to our contributors this release:
Christopher Davis
Georges Basile Stavracas Neto
Jakub Steiner
Jean Felder
Lucy Coleclough
Marinus Schraal
Rafael Coelho
Sabri Ünal
Vineet Reddy
Updated translations:
Vietnamese
Hebrew
Dutch
Ukrainian
Swedish
Occitan
Spanish
Indonesian
Russian
Slovenian
Romanian
Brazilian Portuguese
German
Turkish
Catalan
Friulian
Chinese (China)
Portuguese
Added translation:
Frisian
Overview of changes in 40.0
===========================
• Update appdata for the 40.0 release
Overview of changes in 40.rc
============================
• Improve startup loading
• Misc playlist handling fixes
• Use publication date instead of creation date for songs
Bugs fixed:
Scrobbling crash (#412, !769)
Fix artist queries to retrieve art (!773)
Ignore redundant Tracker delete events (!781)
Fix album selection checkboxes style (#414)
Fix playlist deletion (!793, !813)
adding songs to favorite crashes the app (#441)
GNOME Music crashes during startup: discbox is None (#430)
Crash when creating a playlist containing a quotation mark (#447)
Thanks to our contributors this release:
James A. Baker
Jean Felder
Marinus Schraal
Yann Delaby
Updated translation:
British English
Catalan
Chinese (Taiwan)
Danish
Friulian
Galician
Hebrew
Norwegian Bokmål
Punjabi
Romanian
Slovak
Overview of changes in 3.38.0
=============================
Updated translations:
Danish
Greek
Hungarian
Italian
Latvian
Portuguese
Overview of changes in 3.37.92
==============================
* Port to Tracker 3
* Art retrieval complete rework
* Flatpak cleanups and updates
Bugs fixed:
gnome-music gets stuck when next button is pressed when current song is about to finish (#375)
Selection mode search doesn't work (#405)
Selecting an album in albums view in selection mode randomly deselects other albums (#406)
Selection mode only works for artists during search (#407)
Music crashed if gnome-online-accounts is unavailable (#410)
MPRIS playlist fixes (!741)
Gracefully handle locale.{bind,}textdomain not being available (!735)
Thanks to our contributors this release:
Adam Blanchet
Carlos Garnacho
Chinmay Gurjar
Jean Felder
Marinus Schraal
Piotr Drąg
Rasmus Thomsen
Sam Thursfield
Simon McVittie
Updated translation:
Basque
Brazilian Portuguese
Catalan
Chinese (China)
Croatian
Czech
Dutch
Finnish
French
Friulian
Galician
German
Indonesian
Japanese
Kazakh
Korean
Lithuanian
Persian
Polish
Serbian
Slovak
Slovenian
Spanish
Swedish
Turkish
Ukrainian
Overview of changes in 3.37.3
=============================
Bugs fixed:
pauseonsuspend: Fix calls to MusicLogger.warning() (!724)
Duplication of menu bar (#387)
High CPU usage (#360)
Bind more SongWidget properties (!663)
Thanks to our contributors this release:
Evan Nehring
Jean Felder
Marinus Schraal
Nils Reuße
Updated translation:
Kazakh
Overview of changes in 3.37.2
=============================
* Use Gtk.Template for all the Views and remove BaseView
* Prefer Albumartist field for artist search
* Change Artist view selection from artist to song
* Extend Gtk.Template usage for Window
* Deinitialize Grilo on shutdown
* Music now explicitly depends on Pango 1.44 or above
* Flatpak cleanups and updates
* Various widgets style and code cleanups
Bugs fixed:
Artist view should support music selection (#26)
In-app notifications need to be dismissable (#259)
Stop using show_all (#320)
Crash while searching due to bugs in searchview.py (#372)
Crash on start: object 'AttrFontFeatures' has no attribute 'new' (#374)
Wrong song count in favourite playlist (#376)
Please stop changing the module search path (#377)
Use libsoup for art retrieval (#378)
Music crashes on 'check_smart_playlist_change' call (#382)
Thanks to our contributors this release:
Ashwani Singh Tanwar
Atharva Veer
Chinmay Gurjar
Erik Inkinen
Evan Nehring
Jean Felder
Marinus Schraal
Weifang Lai
Added translations:
Ukrainian
Updated translations:
Catalan
Chinese (China)
Chinese (Taiwan)
Hebrew
Norwegian Bokmål
Romanian
Russian
Slovak
Slovenian
Ukrainian
Overview of changes in 3.36.0
=============================
Updated translations:
Italian
German
Dutch
Overview of changes in 3.35.92
==============================
• Restore smart playlists update
• Improve Tracker content tracking
• Flatpak cleanups and updates
Bugs fixed:
Properly load Grilo Tracker plugin (!650)
Stop a deleted playlist if it is playing (!661)
Misc playlists fixes (!654)
Flatpak: remove unused dleyna support (!644)
flatpak assorted fixes (!645)
Thanks to our contributors this release:
Georges Basile Stavracas Neto
Jackson Campolattaro
Marinus Schraal
Jean Felder
Updated translations:
Brazilian Portuguese
British English
Catalan
Chinese (Taiwan)
Croatian
Czech
Danish
Finnish
French
Galician
Hungarian
Korean
Indonesian
Lithuanian
Persian
Polish
Serbian
Spanish
Swedish
Turkish
Overview of changes in 3.35.91.1
================================
Bug fixed:
Possible crash on warning (!643)
Overview of changes in 3.35.91
==============================
• Use natural order for sorting
• Expose Last.fm scrobbler in the UI
• Add local runtime cache for scrobbling
• Add GLib style logging and remove old logging and debug switch
Bugs fixed:
Sort albums title containing digits numerically (#22)
PlaylistsView: select the next playlist on deletion (#359)
Expose scrobbling support (#218)
Switching to playlist gives an empty view (#348)
Use tabular numbers for song duration (!623)
Crash after select all items (#364)
Deleting an empty playlist crashes (#365)
Disable selection button in Playlist View while searching (#366)
Help overlay remove Ctrl+F1 shortcut (!643)
Thanks to our contributors this release:
Use Alexander Mikhaylenko
Chinmay Gurjar
Jean Felder
Marinus Schraal
Sabri Ünal
Translation added:
Malay
Updated translations:
Greek
Indonesian
Spanish
Slovak
Chinese (Taiwan)
Finnish
Friulian
Brazilian Portuguese
Italian
Swedish
Croatian
Persian
Lithuanian
Japanese
Basque
French
Turkish
Czech
British English
Serbian
Galician
Overview of changes in 3.35.3
=============================
* Improve Tracker content tracking
* Update appdate screenshots
Bugs fixed:
F1 key is not opening help page (#353)
Play on empty playlist crashes Music (#354,#355)
Crash when pressing Alt+Left in SearchView (#357)
Update the appdata screenshots (#327)
Thanks to our contributors this release:
Ishaan Shah
Jean Felder
Marinus Schraal
Added translations:
Basque
Indonesian
Updated translations:
Chinese (Taiwan)
Ukranian
Brazilian Portuguese
Galician
Overview of changes in 3.35.2
=============================
* Album Covers are now loaded on demand
* Use MusicBrainz identifiers to download album covers
* Restore support for "Album Artist" tag
* Disable online search by default
* Restore MPRIS playlist support and misc MPRIS cleanups
* Playlist fixes
* Bring back loading notifications
* Nightly application icon
Bugs fixed:
Fix a crash in Last.fm support (#328)
GNOME shell MPRIS controls are not visible (#332)
PlayerToolbar can become invisible (#335)
Issues when resizing window below apparent minimum width (#337)
GNOME music crashes after creating a huge amount of threads (#312)
GNOME Music crashes if xdg_music_dir is not set (#338)
group artists with a feat or an original artist under the same artist (#331)
Songs Not in ~/Music Show Up In Search (#317)
Fix visual glitches (#300)
Use pkglibdir for gfmlibdir (!509)
Limit smartplaylist content to XDG Music dir (#311)
Crash when removing GOA account (#145)
Model fixes (!557, !552, !533, !499)
Fix icon rendering issues (!543)
Selection fixes (!528)
Restore the development style (!563)
Thanks to our contributors this release:
Jean Felder
Sam Hewitt
Marinus Schraal
Jan Alexander Steffens
Jakub Steiner
Sumaid Syed
Sam Thursfield
Added translations:
Tamil
Translations updated:
Catalan
Danish
Dutch
Friulian
Persian
Spanish
Overview of changes in 3.34.0
=============================
This release marks the first stable release after a invasive rewrite of Music
internals and may still be rough around the edges. Regressions and known issues
are kept track of in #299, further issue reports are welcome.
* A flatpak issue with cover art retrieval was fixed
Thanks to our contributors this release:
Jean Felder
Tranlations updated:
Japanese
Italian
Overview of changes in 3.33.92
==============================
This release contains even more bug fixes and cleanups following the core
rewrite. Regressions and known issues are kept track of in #299, further testing
and issue reports are welcome.
Thanks to our contributors this release:
Hugo Posnic
Piotr Drąg
Jean Felder
Marinus Schraal
Translations updated:
Indonesian
Karb
Basque
Swedish
Finnish
Romanian
Lithuanian
Spanish
Catalan
Polish
Serbian
German
Latvian
Slovenian
Hungarian
Galician
Korean
British English
Turkish
French
Greek
Catalan
Brazilian Portuguese
Czech
Croatian
Overview of changes in 3.33.90
==============================
This release contains a lot of bug fixes following the rewrite of the core of
Music. This work is not yet complete, but the overall state should be
improved. Regressions and known issues are kept track of in #299. Further
reports are welcome.
Some other things were worked on as well:
* Search view rewrite and style update
* Display an empty view if Tracker version is outdated
Thanks to our contributors this release:
Piotr Drąg
Jean Felder
Marinus Schraal
Added translations:
Karbi
Translations updated:
Portuguese
Basque
Spanish
Romanian
Swedish
Overview of changes in 3.33.4
=============================
This release contains a rewrite of the core of Music. This work is not yet
complete, but should be in a usable state. Regressions and known issues are
kept track of in #299. Further reports are welcome.
Some other things were worked on as well:
* Support gapless playback
* MPRIS support rewrite
* Playlists rewrite
Thanks to our contributors this release:
Georgers Basile Stavracas Neto
Jean Felder
Jesus Bermudez Velazquez
Marinus Schraal
Translations updated:
Hungarian
Greek
Dutch
Croatian
Swedish
Slovenian
Icelandic
Overview of changes in 3.33.2
=============================
* Improve Smooth progressbar support
* Improve display of information for songs with no tags
* Select a random song at launch when playing a playlist in shuffle mode
* AppData tags update (initiative #8)
* MPRIS misc cleanups
* Lots of general cleanups
Bugs fixed:
gnome-music crashes on startup (#105)
Stop using GtkBox:padding, GtkBox:fill and GtkBox:expand (#215)
Do not rely on Tracker generated metadata (#223)
MPRIS2 reports wrong .desktop file name (#263)
Crash with mouse 'back' button (#265)
Repeat song not working on Gnome Music 3.32.0 (#266)
Order of search and select buttons incorrect (#270)
flatpak nightly: Clicking on MPRIS player launches wrong version (#273)
Incorrect timeline (progress bar) position for m4a file (#274)
HeaderBar in selection mode has the search/cancel button order wrong (#275)
Repeat All Does Not Repeat Single Songs From Search (#278)
Resuming Playback Actually Restarts Song (#280)
Thanks to our contributors this release:
Christopher Davis
Reuben Dsouza
Bilal Elmoussaoui
Jean Felder
Andre Klapper
Kalev Lember
Marinus Schraal
Veerasamy Sevagen
Georges Basile Stavracas Neto
Sumaid Syed
Translation updated:
Chinese (China)
Chinese (Taiwan)
Croatian
Esperanto
Friulian
Hungarian
Indonesian
Italian
Polish
Portuguese (Brazil)
Romanian
Spanish
Swedish
Overview of changes in 3.32.0
=============================
Translations updated:
Finnish
Catalan
French
Overview of changes in 3.31.92
==============================
Bugs fixed:
Fix initial state graphics in dark mode (#258)
Thanks to our contributors this release:
Tjipke van der Heide
Veerasamy Sevagen
Translations updated:
Turkish
Finnish
Icelandic
Dutch
Lithuanian
Basque
Brazilian Portuguese
Korean
Italian
Russian
Serbian
Friulian
German
Vietnamese
Latvian
Overview of changes in 3.31.91
==============================
* Show an empty view when Tracker is unavailable
Bugs fixed:
Play correct song while paused (#256)
Show a warning when Tracker is not available (#165)
Cannot cancel 'All' sources in search via button (#92)
Crashes when trying to play any song (#244)
Crash while tracks are being loaded (#252)
Thanks to our contributors this release:
Jean Felder
Marinus Schraal
Sagar Lakhani
Translations updated:
Czech
Polish
Spanish
Romanian
Hungarian
Swedish
Indonesian
Slovenian
Galician
Kazakh
Danish
Chinese (Taiwan)
Overview of changes in 3.31.90
==============================
* Add pause on suspend
* Rework and cleanup MPRIS a lot
* Use new Adwaita devel styling
* Partial port to Gtk.EventController
* Set error style on searchbar entry if applicable
Bugs fixed:
Limit composer length (#222)
Fix keyboard shortcuts (#238)
Correct MPRIS positioning (#227)
Fix playlist renaming (#248)
Fix Tracker criticals (#251)
Fix popover positioning (#214)
Pause when suspending (#68)
Add error state for searchbar entry (#228)
Thanks to our contributors this release:
Christophe van den Abbeele
Christopher Davis
Harry Xie
Jean Felder
Jordan Petridis
Marinus Schraal
Mohanna Datta Yelugoti
Nikolay Yanchuk
Translations updated:
Czech
Slovenian
Esperanto
Spanish
French
Greek
Friulian
Swedish
Hungarian
Galician
Romanian
Indonesian
Italian
Finnish
Turkish
Polish
Catalan
Hungarian
Overview of changes in 3.31.1
=============================
* Replace app menu with Primary menu (initiative #4)
* Add TheAudioDB for coverart lookup
* Dark mode fixes
* Fix crash on opening help
* New app icon (initiative #2)
* Flatpak fixes
Bugs fixed:
Fix checkbox selection (!245)
Set application id correctly (!241)
Add The AudioDB support (!247)
Fix search dissapearing on return from child (!253)
Clean up data dir (#193)
mpris: Prevent crash from play call with no playlist (!255)
application: Fix crash on opening help (#22)
Darkmode fixes (!269,!271)
repeat-mode fixes (!274)
Restart remote cover lookup on source availability (!284)
ui: Change arrow menu button icons (#233)
Thanks to our contributors this release:
Christopher Davis
Islam Bahnasy
Jakub Steiner
Jean Felder
Marinus Schraal
Shivansh Handa
Tapasweni Pathak
Translations updated:
Serbian
Overview of changes in 3.30.0
=============================
Translations updated:
Galician
Hungarian
Vietnamese
Latvian
Croatian
Danish
Overview of changes in 3.29.92
==============================
* Make static playlists more reliable
* Populate views on demand (improves startup)
* Fix player toolbar song/artist order
* Switch view navigation from <Ctrl> to <Alt>
* Add tooltips in more places
* Style treeview stars
* Lots of cleanups and reliability fixes
Bugs fixed:
Fix Flatpak delayed loading (!239)
Style treeview stars with CSS (!238)
Use alt instead of ctrl for navigating tabs (#198)
Do not allow view switching in all modes (!237)
Introduce loading state (!233)
grilo: Fix crash when Tracker is not (yet) loaded (!230)
Populate views when opened (!232)
views: Fix now-playing icon display (#203)
On last play done, first song gets notified (#60)
Shuffle shouldn't replay songs (#154)
playlistview: improvements and bugfixes (!227,!229)
meson: Do not add version suffix on default build (!228)
Thanks to our contributors this release:
Jean Felder
Marinus Schraal
Translations updated:
Swedish
Friulian
Brazilian Portuguese
Finnish
Icelandic
Romanian
Kazakh
Korean
Indonesian
Italian
Overview of changes in 3.29.91
==============================
* Finished moving the existing ui to use Gtk.Template
* Added some minor transitions going to selection-mode
* Add OARS tag
* Reword application description
Bugs fixed:
Wait for last album to load (#174)
appdata: Add OARS tag & reword description (!177)
disable sidebar stack transition (!206)
playlistview: Add translator context to Play menu (!211)
add GOA dependency (#212)
use Gtk.Template for AlbumCover (#183)
tarball fails to build (#211)
use Gtk.Template for About dialog (#183)
App-bundles selection-mode headerbar color incorrect (#208)
Use Gdk.Event accessors (#213)
Add SidebarRow widget (!221)
use Gtk.Template for Searchbar and move to widgets (!226)
Thanks to our contributors this release:
Alexander Mikhaylenko
Jean Felder
Jordan Petridis
Marinus Schraal
Nick Richards
Piotr Drąg
Tyler Garcia
Translations updated:
Spanish
Slovenian
German
Polish
Turkish
Czech
Lithuanian
Chinese (Taiwan)
Greek
Overview of changes in 3.29.90
==============================
* Lots of widgets ported to use Gtk.Template
* Added development app bundles to CI
* Codebase wide cleanups and refactoring
* Port sidebars away from libgd views
Bugs fixed:
Using keyboard reveals the playerbar in in selection mode (#197)
High contrast theme not folled for sidebars (#37)
Right click to select Albums is inconsistent (#89)
Flatpak + CI devops (#185)
Music goes into an endless loop (#200)
artistalbumswidget: missing attribute artist (#199)
searchmode: Leaving selection mode with Escape dismisses search results (#195)
Hard transition when entering selection mode (#27)
Thanks to our contributors this release:
Apostol Bakalov
Jean Felder
Jordan Petridis
Marinus Schraal
Piotr Drąg
Translations updated:
Czech
Chinese (China)
Spanish
Chinese (Taiwan)
Romanian
Friulian
Catalan
Slovenian
German
French
Greek
Overview of changes in 3.29.2.1
===============================
* Add release commit to dist tarball
Overview of changes in 3.29.2
=============================
* Update appdata
* Fix issue with untranslated UI elements
* CI use flake8 instead of pep8 & pyflakes
* CI generate flatpak bundles for every commit and MR
* Use libsoup for http requests
* Use CSS styling instead of widget attributes
* Merge emptystate views
* Add optional suspend inhibition gsetting
* Cleanup and split of Player and Toolbar classes
* Numerous miscellaneous cleanups
Bugs fixed:
Partly untranslated user interface (#169)
albumartcache: Do not close non-existing stream on error (!95)
albumartcache: Fix possible lookup loop (!95)
albumartcache: Do not send two signals on error (!95)
Minor optimizations (!138)
flatpak: Enable MPRIS and GNOME media keys (!129)
notificationspopup: Fix source not found warning (!131)
Ellipsized songs in Artists View are improperly aligned (#173)
Fix notification calls on startup (!147)
grilo: Fix audio check (!159)
AlbumsView: Fix runtime updates still triggering
[playlist dialog] implement empty state dialog (#74)
Default search does not search in composer field (#140)
SearchView does not use the same model as other views (#160)
Use CSS style instead of html markup to color text (#163)
Fix Running Length label translation in AlbumViewWidget (#177)
local searchtag not removed when doing non-local searches (#130)
Replace requests usage with libsoup (#144)
Use DzlBoldingLabel for TrackWidget (#178)
player: Add optional inhibition of system suspend (#182)
Pressing escape when renaming a playlist does not cancel rename (#188)
Thanks to our contributors this release:
Ashwin Mohan
Apostol Bakalov
Jean Felder
Marinus Schraal
Adrian Solom
Juan José González
Bruce Cowan
Alexander Mikhaylenko
Subhadip Jana
Georges Basile Stavracas
Piotr Drąg
Translations updated:
Danish
Croatian
Greek
British English
Turkish
Russian
Slovenian
Romanian
Friulian
Czech
Indonesian
Spanish
Overview of changes in 3.27.92
==============================
* Port to Meson
* Lots of fixes to the flatpak json
* Fixes to playlists behaviour
* Fix some shortcut logic
* Fix issue with bluetooth headset input
* Delayed loading of covers in albumsview to decrease startup time
* Lots of general cleanups
* Update to latest libgd
Bugs fixed:
Music won't build from flatpak (#138)
Disable last.fm scrobbling if Music is disabled in GOA (#139)
playlistview: Remove obsolete column renderer (!61)
albumsview: Use correct checkbox style (!68)
playlistview: Only show icons for playing playlists (#149)
query: Filter out on-disk playlist formats (#72, #151)
Replace logger.warn with logger.warning (#153)
Switch to meson build system (#1)
window: Handle Gdk Audio keys (#93)
window: Restore selection popup functionality (#152)
meson: Add fallback in case XDG_DATA_DIRS is not set (!85)
Deleting a playlist does not stop the player (#156)
Follow up searches do not trigger an actual search (#148)
Changing playlist resets player model (#136)
Thanks to our contributors this release:
Benoît Legat
Bilal Elmoussaoui
Georges Basile Stavracas Neto
Janne Körkkö
Jean Felder
Marinus Schraal
Translations updated:
Swedish
Spanish
Friulian
Polish
Indonesian
Catalan
Chinese (Taiwan)
Brazilian Portuguese
Galician
Croatian
Finnish
Dutch
German
Hungarian
Slovak
Serbian
Korean
Croatian
Italian
Czech
French
Vietnamese
Scottish Gaelic
Lithuanian
Kazakh
Latvian
Overview of changes in 3.27.90
==============================
* Lots of cleanup/refactoring
* Moved to Gitlab
* Add album scrobbling
* Dropped some more libgd use
* Add context menu to interact with playlist items
* Drag and drop reorder in playlists
* Add album scrobbling
* Rework notifications
* Rework art cache
* CI fixes
* Last bits of HiDPI support
Bugs fixed:
Clicking on cancel button from selection bar crashses music (#142)
Crashed when trying to play music over UPnP (#46)
Playlists are not displayed (#127)
Fix deprecated accelerator call (#2)
Crash during startup in albumart lookup (#121)
Use stack for covers in player (#55)
Finish HiDPI support (#65)
Scale art more efficiently (#81)
Playlist not deleted after close (#106)
Allow undo on playlist track removal (#50)
Fix artist/album search return all songs (#4)
Replace deprecated override_color call (#3)
Allow access to host cache from flatpak (!15)
Reset song to clean on new playlist (#135)
Use context menu on playlist tracks (#48)
Replace deprecated add_accelerator call (#2)
Console spam on startup related to Spotify (#132)
Thanks to our contributors this release:
Alberto Fanjul
Felipe Borges
Gyanesh Malhotra
Jean Felder
Marinus Schraal
Subhadip Jana
Translations updated:
German
Polish
Friulian
Indonesian
Finnish
Swedish
Catalan
Hungarian
Esperanto
Overview of changes in 3.27.4
=============================
Bugs fixed:
Migrate from intltool to gettext (#787272)
Add appstream metadata to non-deprecated location (#790869)
Playlist ordering in views (#772090)
Fix style of GdTaggedEntry (#791077)
PEP-8 fixes & cleanups (#791481,!7,!9,!10,!17,!18)
Update libgd (!8)
Fixes to navigating back (#777238)
Enable mouse button for navigating back (#771934)
Fix constructor deprecation warning (#790127)
Fix PyGObject deprecation warning (#788701)
Fix order in method call (!21)
Fix log decorator order (!22)
Use python3 style super() calls (!16)
DiscListBoxWidget update favourites (!23)
Add the ability to rename playlists (!11)
Update README.md (!12)
Thanks to our contributors this release:
Abhinav Singh
Florian Darfeuille
Jean Felder
Jeremy Bicha
Kainaat Singh
Marinus Schraal
Niels De Graef
Phil Dawson
Piotr Drąg
Sambhav Kothari
Translations updated:
Dutch
Romanian
Icelandic
Persian
Catalan (Valencian)
German
Czech
Friulian
Norwegian bokmål
Croatian
Indonesian
Serbian
Swedish
Overview of changes in 3.26.0
=============================
Translations updated:
Catalan
French
Romanian
Danish
Overview of changes in 3.25.92
==============================
Bugs fixed:
786454 Wrong player.set_playlist call in albumwidget.py
780548 Problem scrolling albums on wayland
709073 Different icon in System Settings Sound pane
Thanks to our contributors this release:
Jan-Michael Brummer
Jean Felder
Marinus Schraal
Robert Greener
Translations updated:
Croatian
Italian
Danish
Vietnamese
Overview of changes in 3.25.91
==============================
Bugs fixed:
786541 Add missing logger imports
786315 Make the playlist button a circle
Thanks to our contributors this release:
Jean Felder
Jordan Petridis
Translations updated:
Polish
French
Overview of changes in 3.25.90
==============================
* Limit concurrent loading of coverart
* Fixes to appdata
* Use tracker:title-order for sorting
Bugs fixed:
783466 query: Use tracker:title-order() SPARQL function for title sorting
785697 Remove comments from org.gnome.Music.json
Thanks to our contributors this release:
Carlos Garnacho
Felipe Borges
Georges Basile Stavracas Neto
Kalev Lember
Marinus Schraal
Piotr Drąg
Translations updated:
Turkish
Croatian
Czech
Malayalam
Overview of changes in 3.25.4
=============================
* Build: depend on libtracker-sparql-2.0
* Add Flatpak manifest
* Mark forgotten string for translation
Bugs fixed:
776668 fix minor seek stutter
774500 refactor gnome-music.in to be more readable
781684 playlistview artist field incorrect
777346 allow seek using arrow keys
781754 fix media-player-keys bus name
Thanks to our contributors this release:
Abhinav Singh
Carlos Garnacho
Carlos Soriano
Felipe Borges
Marinus Schraal
Pablo Palácios
Piotr Drąg
Translations updated:
Belarusian
Slovenian
Polish
Indonesian
Overview of changes in 3.24.1.1
===============================
* Revert desktop file rename
* In turn revert Flatpak manifest addition
Overview of changes in 3.24.1
=============================
* Add Flatpak manifest
* Fix crashers
* Up Grilo requirements
Bugs fixed:
780523 playlist dialog shows the playlist that is going to be deleted
779905 build: Add a first version of Flatpak manifest
Thanks to our contributors this release:
Abhinav Singh
Carlos Soriano
Marinus Schraal
Translations updated:
Portuguese
Norwegian bokmål
Greek
Croatian
Overview of changes in 3.24.0
=============================
Translations updated:
Russian
Latvian
Brazilian Portuguese
Overview of changes in 3.23.92
==============================
* Code cleanups
* Local art retrieval added
* AppData screenshots updated
Bugs fixed:
779013 only one (older) screenshot in appdata file
779585 Window is wider than 1024px
777041 Unexpected behaviour of playlist notification actions, sometimes
deletes, sometimes not
776668 double click on seek bar pauses the songs
779052 MPRIS TrackList GoTo Method Crashes gnome-music
779584 Handle coverart extraction in gnome-music
Thanks to our contributors this release:
Abhinav Singh
Andreas Nilsson
Carlos Garnacho
Marinus Schraal
Translations updated:
Hungarian
Slovak
Serbian
Galician
Lithuanian
Italian
Czech
Polish
Danish
Scottish Gaelic
Occitan
French
Korean
Indonesian
Basque
Icelandic
Swedish
Chinese (Taiwan)
Finnish
Overview of changes in 3.23.91
==============================
* Code cleanups
Bugs fixed:
774470 Use song instead of track in the source codebase
774449 Cleanup baseview.py
Thanks to our contributors this release:
Marinus Schraal
Rashi Sah
Suyash Garg
Translations updated:
Finnish
Kazakh
Danish
Norwegian bokmål
Slovak
Polish
Basque
Indonesian
Italian
Hungarian
Catalan
Friulian
Ukrainian
German
Brazilian Portuguese
Serbian
Spanish
Overview of changes in 3.23.90
==============================
* Empty-state added for playlist dialog
* Cleanups
Bugs fixed:
772089 [playlist dialog] implement empty state dialog
776680 'Select All' doesn't have an action in Artists tab
777541 Crashes as soon as trying to play a song
777219 PEP 8 fix : application.py
Thanks to our contributors this release:
Abhinav Singh
Alberto Fanjul
Marinus Schraal
Yash Singh
Translations updated:
Czech
Indonesian
German
Turkish
Catalan
Polish
Slovak
Friulian
Overview of changes in 3.23.4
=============================
* Revamp notifications and drop GdNotification
* More cleanups
Bugs fixed:
776157 Improve notifications' interaction
776849 Gnome-music crashes on clicking "select all" in album
777127 Pressing back after no search results from single album view leads to
force close
777235 Pressing back button when searching through a subview, should turn
search off and go back
777216 PEP 8 fix : __init__.py
776673 Recompile resources when builddir is not same as srcdir
772975 In a playlist repeatSong/shuffle/repeatSong take effect from the next
song
Thanks to our contributors this release:
Abhinav Singh
Alberto Fanjul
Georges Basile Stavracas Neto
Marinus Schraal
Sambhav Kothari
Translations updated:
Finnish
Kazakh
Spanish
Overview of changes in 3.23.3
=============================
* Start to use Grilo for storing metadata
* Rework starring widget
* DistListBox improvements
* Stop walking directories for no reason
* Finish move to tracker async calls
Bugs fixed:
774754 Use correct Grilo property for favourite tracking
772689 Use tracker async queries
775759 create_playlists cursor_callback method has a TypeError
775930 Correct error variable names
Thanks to our contributors:
Carlos Garnacho
Georges Basile Stavracas Neto
Marinus Schraal
Sambhav Kothari
Yash Singh
Translations updated:
German
Hungarian
Russian
Overview of changes in 3.23.2
=============================
* Rely on Cairo for cover scaling
* Smooth progressbar
* Make more tracker calls async
* General cleanups
* Tackle long-standing issues with album separation
Bugs fixed:
773478 artistviews: pep cleanup
772263 Use unicode in translatable strings
772698 async work
774260 handle optional album-artist in queries
774481 Add missing license header to gnome-music.in
773769 songsview: pep cleanup
772628 player: make progress scale move smoothly
Thanks to our contributors:
Carlos Garnacho
Clayton G. Hobbs
Marinus Schraal
Pablo Palácios
Piotr Drąg
Suyash Garg
Yash Singh
Translation updated:
Czech
Friulian
Hungarian
Norwegian bokmål
Slovenian
Overview of changes in 3.23.1
=============================
* Rework art lookup
* Add HiDPI support (90% done)
* Add mnemonics
* Rework about dialog
* Split up views & widgets
* Rework the album widgets
* Show multi-disc albums as such
* Make playlist retrieval non-blocking
* Add composer label & search
Bugs fixed:
761185 Help should use tag when referring to application names
771348 Use | as I18N separator
772403 Album art: also consider height when scaling
765476 Crashes upon opening with a GLib error
719452 Provide proper output if gobject-introspection-devel is missing
773192 Fix playlists loading time
705094 Display more details on Album view
750827 Album views - if an album has multiple disks, group tracks by disk
761891 Weird interaction selection mode + favourites
Thanks to our contributors:
Carlos Garnacho
Georges Basile Stavracas Neto
Konstantin PospelovSebastian Rasmussen
Marinus Schraal
Sebastian Rasmussen
Translation updated:
Basque
Chinese (simplified)
Chinese (Taiwan)
Czech
Danish
Friulian
German
Italian
Swedish
Overview of changes in 3.22.0
=============================
* Update mainters in doap
Translations updated:
Ukrainian
Catalan
Scottish Gaelic
Persian
Overview of changes in 3.21.92
==============================
* Fix keyboard play/pause handling
* Remove top separator in song lists
* Do not remove static playlists on Delete keypress
Bugs fixes:
771249 Static playlists should not be removed using the Delete key
770178 Remove the first Songs row separator
754096 Space doesn't always toggle pause/play
Thanks to our contributors:
Konstantin Pospelov
Marinus Schraal
Yash Singh
Translations updated:
Danish
Greek
Latvian
Galician
Swedish
Hebrew
Vietnamese
British English
Lithuanian
Kazakh
Korean
Friulian
Serbian
Overview of changes in 3.21.90
==============================
* New keyboard shortcuts and a shortcuts window to go with it
* Move to cleanup the codebase style (PEP-8) & use docstrings, see README
* Better sorting in albums and artists view
* Playlist dialog enhanced with a 'new playlist' entry
* Move to GtkFlowBox for albums view, a significant performance improvement
Bugs fixed:
761502 Include playlists from Music dir only & order static playlists on top
766115 Return songs only once
746447 Require tracker 1.8 for titled playlists
765609 Fix mpris repeatmode
761625 Cleanup artist/author ambiguity
747953 Don't leak information over http through Grilo & unregister sources
754700 Require Grilo 0.3.1 and use the album-artist key if available
742531 Ignore punctuation when sorting albums and artists, requires tracker 1.9
758637 Implement new keyboard shortcuts
757833 Add GtkShortcut window
769774 Fix sidelist shadow
769772 Use GtkSearchBar for the searchbar + misc fixes
744834 Add new playlist entry to playlist dialog + misc fixes
760164 Use GtkFlowBox for albums view
Thanks to our contributors:
Billy Barrow
Carlos Garnacho
Divyanshu Vishwakarma
Elias Entrup
Evandro Giovanini
Felipe Borges
Gaurav Narula
Georges Basile Stavracas Neto
Kevin Haller
Marinus Schraal
Translations updated:
Occitan
Catalan
Spanish
French
Friulian
Slovak
Czech
Indonesian
Brazilian Portuguese
German
Hungarian
Finnish
Polish
Portuguese
Overview of changes in 3.20.2
=============================
Bugs fixed:
705069 Port to Gio GDBUS API
763618 Clarify jhbuild instructions in README
755089 Emit playback-status-changed after playlist ends
744820 Accept response on row-activated in Playlist Dialog
765598 Bump Gtk+ minimum version to 3.19.3
761961 Stop the player when destroying window
Translations updated:
Swedish
Friulian
Esperanto
Brazilian Portuguese
Occitan
Overview of changes in 3.20.0
=============================
Translations updated:
Danish
Hungarian
Overview of changes in 3.19.92
==============================
Bugs fixed:
762821 Update Grilo plugin ranks to 0.3 format
761941 Fix Pango critical warnings on searchbar
761890 Check if visible child is ArtistsAlbumsWidget on search toggle
763304 Don't assume that nmm:MusicPieces will have a nie:url in playlists
744821 Properly de/activate select button on PlaylistDialog when navigating w/ arrow keys
744831 Fix crash while deleting multiple playlists
a173f2 Update libgd
Translations updated:
Occitan
Korean
Slovenian
French
Special thanks to the new contributors:
Gaurav Narula
Marinus Schraal
Prashant Tyagi
Saiful B. Khan
Overview of changes in 3.19.91
==============================
Bugs fixed:
744829 No more duplicate playlists on the sidebar
762406 More Grilo 0.3 transition fixes
762265 No more notifications on track changes
Translations updated:
Slovak
Occitan
Ukrainian
Overview of changes in 3.19.90
==============================
Bugs fixed:
761173 Update tracker queries to sparql 1.1 syntax
760170 Fix check button appearance on AlbumWidget
760170 Fix check buttons appearance in Songs and Playlist view
736463 Reposition the scrollbar in the search window
760171 Resized songs list for better viewing in large window
Translations updated:
Latvian
Bulgarian
Overview of changes in 3.19.4
=============================
Bugs fixed:
Let GtkApplication automatically load the app-menu
Refactor the way we connect menu actions
758942 Use grilo 0.3 for GNOME 3.20
758942 Fix deprecation warnings in GTK+
Update libgd from master
Scale the playlist name to match the mockups
759024 Use the path of the filter model in search results
739924 Make search find strings with accents
759882 Fix warnings when switching between stack pages
Add symbolic icon
760033 Make albumart fetching truly asynchronous
760033 Defer serialization of default icon
760033 Set model on the view after all insertions happened
760033 Remove check for dup jobs
760033 Don't add items on idle
760033 Depend on Tracker >= 1.7.1
759587 Rework songs, artists, playlists, and albums queries
Pass width/height during pixbuf loading
751163 Restrict music catalog to the Music folder
760381 Use GIO async APIs to download cover art
734958 Increase the maximum width of the artist and track name
Translations updated:
Spanish
Slovenian
Overview of changes in 3.18.2
=============================
Bugs fixed:
755601 Fix styling for entry tags (libgd)
756256 Fix XML tag in help
746446 Reset app title to Music after leaving album view
756330 Fix crashes when coming back from search view
757227 Fix missing toolbar when coming back from search resultg
Translations updated:
Serbian
German
Greek
Czech
Basque
Lithuanian
Hungarian
Overview of changes in 3.18.0
=============================
Translations updated:
Danish
Swedish
Overview of changes in 3.17.92
=============================
Bugs fixed:
744827 Empty stars in 'Search' view
754654 Fixes for staticmethod definitions
754702 Search drop-down doesn't show the right default source
754836 Toggling search of when on a albumWidget doesn't make search view disappear
754977 gnomemusic/widgets.py using depreciated PARAM_READWRITE
Translations updated:
Added Icelandic
Finnish update
Fix FSF address in Polish
French
Kazakh
Korean
Lithuanian
Turkish
Persian
Overview of changes in 3.17.91
=============================
Bugs fixed:
738516 Tags in search textbox are broken
Translations updated:
Chinese (Taiwan)
French
Galician s
German
Greek
Indonesian
Italian
Polish
Update Catalan transation
Overview of changes in 3.17.90
=============================
Bugs fixed:
744658 Playlists sidebar - border is cut off
753488 Clicking on artist on search results does nothing
Translations updated:
Brazilian Portuguese
Czech
Fix Portuguese desktop keywords
Friulian
Norwegian bokmål
Turkish
Overview of changes in 3.17.4
=============================
Bugs fixed:
705070 Last.fm/libre.fm integration
747233 Remove "All Artists"
752591 Convert margin_right to margin_end
752592 Trivial code formatting cleanups
Several deprecations were removed
More performance improvements
Translations updated
Overview of changes in 3.17.3
=============================
Bugs fixed:
743362 Give a nicer welcome
744464 No results screen for Search
747749 Cant't play favourite song in Album view
748375 #!/bin/bash in autogen.sh
749981 Tracks outside Music and Downloads are displayed in playlists
Translations updated:
Added Occitan
Dutch 316
Esperanto
Fix to Catalan
Greek
Norwegian bokmål
Slovak
Spanish
Tajik
Turkish
l10n: Update Japanese
update zh_CN
Overview of changes in 3.16.0
=============================
Translations updated:
Basque language
Finnish update
Fix a syntax error in desktop file keywords Bosnian
Indonesian
Tajik
Update Aragonese
Update Catalan
Overview of changes in 3.15.92
=============================
* Bug fix release
Bugs fixed:
744657 Loading in-app notification gets stuck
745646 Improve sorting of "songs" view
745647 shuffleHistory fixes
745648 Song view elements jump around
745650 Not Enough Space Given For Track Titles in Album View
Translations updated:
Added Bosnian
Danish
German
Korean
Polish
Serbian
Slovenian
Swedish
Turkish
l10n: Update Japanese
Overview of changes in 3.15.91
=============================
* Bug fix release
Bugs fixed:
705852 Now playing indicator is lost on switching views / artists / artist albums
729377 Convert menu of gear button in the Playlists view into a popover
729525 Show a loading animation when Add to Playlist is clicked in Albums and Artists view
743310 Updates to Smart Playlist functionality in 3.15.4
743883 Refresh Playlists/Songs view when star toggled
743884 Protect smart playlists
743901 Favorite Playlist and Starring implementation
744005 stars in Album/Artist/Search views
744655 Loading in-app notification is malformed
744807 Last song on album view keeps repeating in "mix/no repeat" mode
744832 Undo playlist delete --> reinsert at previous position
Translations updated:
Basque language
Brazilian Portuguese
Chinese (Taiwan)
Czech
Fix German desktop file keyword
French
Galician s
Greek
Hebrew
Hungarian
Italian
Kazakh
Lithuanian
Norwegian bokmål from Åka Sikrom
Russian
Slovak
Spanish
Swedish
Ukrainian
Update Aragonese
Overview of changes in 3.15.90
=============================
* New smart playlist - Favourite tracks, all views updated to allow
making a track favourite
* All Artists is not selected by default - improves performance
* All smart playlists now retyurn max 50 items
* Playlists menu now uses popover
* Notification appears on loading operations
* Favourite songs are now displayed on search view
* GStreamer discoverer performance fixes from garnacho
* Minor UI fixes
* Bugs fixed:
744005 stars in Album/Artist/Search views
729525 Show a loading animation when Add to Playlist is clicked in Albums and Artists view
729377 Convert menu of gear button in the Playlists view into a popover
743310 Updates to Smart Playlist functionality in 3.15.4
* Updated translations and help files
Overview of changes in 3.15.4
=============================
* Smart playlists - Most Played, Never Played, Recently Played
The list is not yet final, stay tuned. Note that we use Last.fm's way
to count song as 'played' - more than 40% of song content should be played.
* Chunked loading was removed - scrolling should be faster
* Content is now hidden before fully loaded - notification on the progress will
land in master in next version.
* Playlists are remvoed after time out, removal can be undone
* Dependency cnahge: libmediaart-2.0.pc is now required
* Replaygain tags are now supported
* Overall performance fixes
* Bugs fixed:
729376 New Playlist in application menu doesn't do anything
704257 Visible content loading
742603 Regression: empty covers are oversized in playbar, still 'in-progress' on artists view
742451 Support Undo when removing playlists
733686 Gnome music will not launch
726459 Crash on playlist tabs when new media has been scanned
702519 Smart playlists
742800 Playlist broken due to typo
742123 Hitting 'cancel' while creating new playlist crashes program
731613 gnome-music-3.12.2 fails to start if xdg default directories are not created
742011 Query: add a/an to articles
730269 ReplayGain support?
* Updated translations and help files
Overview of changes in 3.15.2
=============================
* Better thread handling while fetching album art
* Some UI/UX goodies
* Notification can now be disabled
* 'The' (and translation) is not disregarded during sorting
* MPRIS improvements
* Bugs fixed:
736925 Remove deprecation warnings from AlbumWidget.ui
737142 Remove remaining gtk deprecation warnings
737571 No covers loaded on libmediaart 0.6.0
736241 Prefer embedded album art over downloaded
732151 High CPU and sluggish performance
733473 Use "Alt + left arrow" to navigate back
738465 Have a dconf switch to disable notifications
731392 Nicer empty state
729378 Disregard "The" in titles
734513 play/pause is activated twice when pressing spacebar and play/pause button is active/selected
729309 Add support for MPRIS Playlists
740211 Add support for MPRIS TrackList
740212 Bump MPRIS support to 2.2
740330 Album view - music icons are badly rendered
740524 Missing license headers in playlists.py and searchbar.py
731639 The pictures have different proportions, influencing the effect of alignment
729459 under Artists, tracks in the same album are very far apart from each other
740490 Music "forgets" search string, but search results remain
* Updated translations and help files
Overview of changes in 3.14.0
=============================
* Updated translations and help files
Overview of changes in 3.13.92
=============================
* Bugs fixed:
735890 Fix the icons in RTL with new GTK+
* Updated translations and help files
Overview of changes in 3.13.90
=============================
* Ported to GtkActionbBar - now requires GTK+ 3.12
* Correct icoin is displayed for playlist menu (https://wiki.gnome.org/Initiatives/GnomeGoals/GearIcons)
* Better search UI
* HighContrast icons
* Improved Back navigation
* Notifications now behave correctly when paused and less flicker
* Bugs fixed:
734786 center the search results
734404 Missing high contrast icon
734122 unable to switch to all albums view after return from search view
734117 Pause button does not change to play button in the notification
732150 Remove custom player bar styling
732951 Don't use emblem-system-symbolic
* Updated translations and help files
Overview of changes in 3.13.4
=============================
* Bump python3 requirement to 3.3 (due to str.casefold)
* Bugs fixed:
733095 Seeking in track above 36 minutes leads to crash
* Updated translations and help files
Overview of changes in 3.13.3
=============================
* Playlists are now stored in Tracker
* Back button now returns back to Search if available
* Bugs fixed:
707461 add man page
729311 Use Tracker to save Playlists
728254 Incorrect item is removed in playlists if it has duplicates
728255 Don't show playlists in Songs
728330 Crash when the name of the new playlist contains special characters
* Updated translations and help files
Overview of changes in 3.13.2
=============================
* Improved search with source and match type selection
* Remote sources support: Jamendo, Magnatune, UPnP/DLNA
* Player bar now looks better when window is small
* Bugs fixed:
729100 Media art in notifications is blank instead of symbolic when media art is not found
729102 Notification doesn't show up when media art doesn't exist
728255 Don't show playlists in Songs
725949 gnome-music buttons have no tooltips
728407 Enabling selection mode via right-click doesn't work inside albums in Albums view
729521 Albums list in Artists view shouldn't be sensitive when in selection mode
706948 Only show music from my ~/Music folder
699807 PlayerToolbar - artist and track name can shrink to nothing
730205 AttributeError: 'Stack' object has no attribute 'get_child_by_name'
726713 Update of songs interferes with selection mode
* Updated translations and help files
Overview of changes in 3.13.1
=============================
* Thumbnail fetching was reworked. now should be much faster
* New dependency: libmediaart
* Updated playlist UI
* Now requires GTK 3.10
* Shuffle menu is now a popover
* Load More button was removed
* Bugs fixed:
724627 Playlists UX review
726721 Some tracks are identified as 'MediaVideo' and crash in various places
727444 gnome-music crashed with OSError in_on_source_added(): [Errno 5] I/O error
727522 Accelerator for Select All doesn't work
728323 Set the icon name of the window as "gnome-music"
724112 Crashes when cannot connect to tracker
702565 Load cover art on scroll in Albums and Artists view
699832 Replace Load More with autoloading on pressure
729096 Media art is not shown in MPRIS clients
* Updated translations and help files
Overview of changes in 3.11.92
=============================
* Improved and tranlated help
* Space now plays/pauses the current song
* Minor UI updates to playlists
* Bugs fixed:
707454 Space switches to next item
724627 Make select button insensitive while creating New Playlist
725904 Tracks don't appear in artists view for albums that have many tracks
* Updated translations
Overview of changes in 3.11.91
=============================
* Initial help infrastructure
* More info is printed if the track cannot be played
* Last 10 played tracks are stored in shuffle history
* Other minor improvements and bug fixes
* Bugs fixed:
707744 Song is being replayed when paused
724228 Remove 'now playing' from the app menu
707457 Restart current track when Previous button was clicked and position is more than 3 seconds
725355 Do not crash if we happen to come across a filename we can't decode
723942 Search on keypress function opens search bar even when pressing any key
724954 Selecting all albums is not visible at first
707376 Set the position of the view scrollbar to current song when a song is changed
* Updated translations:
Spanish
Norwegian bokmål
Tajik
Czech
Brazilian Portuguese
Hebrew
Chinese
Lithuanian
Italian
Hungarian
Finnish
Overview of changes in 3.11.90
=============================
* Initial playlists support
* Filter-as-you-type
* Misc fixes and improvements
* Bugs fixed:
700022 app no longer fits half maximized
721297 Shuffle is not random enough
723765 Static spinner superimposed over album artwork
708154 Crash when Search button is toggled on No Music view
724027 theme: actionbar has a doubleborder
724025 searchbar isn't styled properly
724016 don't segment artist list sidebar
721595 Typing should trigger a search
723750 The stack switcher is gone when run gnome-music with GTK+ 3.11
709234 Music cannot be run via ssh forwarding
* Added translations:
Aragonese
Esperanto
* Updated translations:
Hebrew
Lithuanian
Traditional Chinese
Norwegian bokmål
Turkish
Finnish
Czech
Greek
Brazilian Portuguese
Galician
Chinese simplified
Slovenian
German
Italian
Spanish
Tajik
Overview of changes in 3.11.2
=============================
* Exit selection mode on pressing Esc
* Pep8 compatibility
* Broken AppData file was removed from sources
* Bugs fixed:
707590 Fix app menu accelerator conflict
708279 Make the cancel button as center vertically
709033 Album Cover art not displayed in the notifications
707399 Add translator comment to not translate GSettings values
705853 Enter selection mode on right-click
707633 Save window position, size and maximization state
709465 Update position while switching songs
* Added translations:
Afrikaans
Catalan (Valencian)
Malayalam
Telugu
* Updated translations:
Norwegian bokmål
Turkish
Persian
Simplified Chinese
Slovenian
Tajik
Spanish
Galician
Greek
Dutch
Overview of changes in 3.10.0
=============================
* Added translations:
Estonian
Belarusian
* Updated translations:
Assamese
Portuguese
Latvian
Slovak
Ukrainian
Traditional Chinese
Catalan
Kannada
Indonesian
Hebrew
Overview of changes in 3.9.92
=============================
* Added AppData description
* Icons are now RTL-compatible
* Notifications appear during the playback
* All views can be filtered via search button or Ctrl+F shortcut
* URLs with no FileDataObject (*.cue) are now filtered
* Fixed MPRIS commands: close, play, thumbnail display
* Songs view now displays 'Unknown Album' for tracks with no album set
* Gnome Music notifies about startup
* Bugs fixed:
702377 Add support for notifications
703303 Music doesn't properly tell MPRIS clients that the song is replayed when in repeat song mode
706576 Repeat/Shuffle icons should have RTL variants
707388 Add AppData description
707632 MPRIS Close command is broken
707824 No notification when Music starts
707937 freeze-break branch | Crash when try to start song
707938 gnome-music crashes with TypeError: Argument 0 does not allow None as a value
708102 Thumbnail no longer shows up in MPRIS clients
708103 Playing default playlist is broken
708116 Crash in notification when the current track gets hidden while searching
708117 Use RTL variants of buttons in notifications on RTL languages
708159 Empty album column when an album title is unknown
* Added translations:
Basque
British English
Catalan
Danish
Dutch
French
Indonesian
Korean
Latvian
Traditional Chinese
* Updated translations:
Brazilian Portuguese
Czech
Finnish
Galician
German
Hungarian
Italian
Lithuanian
Norwegian bokmål
Polish
Russian
Serbian
Slovak
Slovenian
Spanish
Tajik
Overview of changes in 3.9.91
=============================
* All songs will now be loaded in Songs view after switching to it
for the first time
* First song in Songs view will play if Play is executed in MPRIS and
there is no current playlist
* The URIs are now discovered asynchronously, to make loading songs
faster
* An error icon will now show up when the file is deleted
* The message when no music files are found is now more verbose
* Bugs fixed:
700776 Licensing problems
705855 Crash when attempting to get properties over DBus
706019 Don't use the discoverer if we don't care of the results
706294 Duration in Albums view increases every time an album is se...
706353 About box changes size when license button is toggled on, l...
706457 Invalid copyright headers
706533 More explanation when Music says "No Music Found"
706800 Cancel button in toolbar shouldn't be emphasized
706947 Can't shuffle my entire library without clicking "load more...
* Added translations:
Irish
Tajik
* Updated translations:
Brazilian Portuguese
Czech
Galician
Italian
Lithuanian
Norwegian bokmål
Polish
Slovak
Slovenian
Spanish
Overview of changes in 3.9.90
=============================
* Initial release
================================================
FILE: README.md
================================================
# Music
Play and organize your music collection with Music, a GNOME app.

You can join the developers on [Matrix](https://handbook.gnome.org/get-in-touch/matrix.html): [#gnome-music:gnome.org](https://matrix.to/#/#gnome-music:gnome.org).
## Contributing
### Code
Please follow our [contributing guidelines](CONTRIBUTING.md).
### Translations
Music is translated by the GNOME translation team on [Damned lies](https://l10n.gnome.org/).
Find your language in the list on [the Music module page on Damned lies](https://l10n.gnome.org/module/gnome-music/).
================================================
FILE: data/meson.build
================================================
# Compiling the resources
# about_dialog is defined in data/ui/meson.build to generate the output file in that directory
gnome.compile_resources(
PROJECT_RDNN_NAME,
PROJECT_RDNN_NAME + '.gresource.xml',
gresource_bundle: true,
source_dir: meson.current_build_dir(),
install_dir: PKGDATA_DIR,
install: true
)
schema_src = PROJECT_RDNN_NAME + '.gschema.xml'
gnome.compile_schemas(build_by_default: true, depend_files: files(schema_src))
# Installing the schema file
install_data(
schema_src,
install_dir: join_paths(get_option('datadir'), 'glib-2.0/schemas')
)
# Merging the translations with the desktop file
desktop_conf = configuration_data()
desktop_conf.set('icon', APPLICATION_ID)
i18n.merge_file(
type: 'desktop',
input: configure_file(
output: PROJECT_RDNN_NAME + '.desktop.in',
input: PROJECT_RDNN_NAME + '.desktop.in.in',
configuration: desktop_conf),
output: APPLICATION_ID + '.desktop',
po_dir: join_paths(meson.project_source_root(), 'po'),
install: true,
install_dir: join_paths(get_option('prefix'), get_option('datadir'), 'applications')
)
# Validating the desktop file
desktop_file_validate = find_program('desktop-file-validate', required:false)
if desktop_file_validate.found()
test (
'Validate desktop file',
desktop_file_validate,
args: join_paths(meson.current_build_dir (), APPLICATION_ID + '.desktop')
)
endif
# Merging the translations with the appdata file
appdata_conf = configuration_data()
appdata_conf.set('appid', APPLICATION_ID)
appdata_conf.set('package_url', PACKAGE_URL)
appdata_conf.set('package_url_bug', PACKAGE_URL_BUG)
appdata_file = i18n.merge_file(
input: configure_file(
output: PROJECT_RDNN_NAME + '.metainfo.xml.in',
input: PROJECT_RDNN_NAME + '.metainfo.xml.in.in',
configuration: appdata_conf
),
output: APPLICATION_ID + '.metainfo.xml',
po_dir: join_paths(meson.project_source_root(), 'po'),
install: true,
install_dir: join_paths(get_option('prefix'), get_option('datadir'), 'metainfo')
)
# Validating the appdata file
appstreamcli = find_program('appstreamcli', required: false)
if (appstreamcli.found())
test('Validate appdata file',
appstreamcli,
args: ['validate', '--no-net', '--explain', appdata_file],
workdir: meson.current_build_dir()
)
endif
# Installing the default icon
install_data(
join_paths('icons/hicolor/scalable/apps', APPLICATION_ID + '.svg'),
install_dir: join_paths(get_option('prefix'), get_option('datadir'), 'icons/hicolor/scalable/apps')
)
# Installing the symbolic icon
install_data(
join_paths('icons/hicolor/symbolic/apps', PROJECT_RDNN_NAME + '-symbolic.svg'),
install_dir: join_paths(get_option('prefix'), get_option('datadir'), 'icons/hicolor/symbolic/apps'),
rename: '@0@-symbolic.svg'.format(APPLICATION_ID)
)
# Installing the D-Bus service file
service_conf = configuration_data()
service_conf.set('appid', APPLICATION_ID)
service_conf.set('bindir', join_paths(get_option('prefix'), get_option('bindir')))
configure_file(
input: PROJECT_RDNN_NAME + '.service.in',
output: APPLICATION_ID + '.service',
configuration: service_conf,
install: true,
install_dir: join_paths(get_option('prefix'), get_option('datadir'), 'dbus-1', 'services')
)
================================================
FILE: data/org.gnome.Music.desktop.in.in
================================================
[Desktop Entry]
Name=Music
GenericName=Music Player
Comment=Play and organize your music collection
# Translators: Do NOT translate or transliterate this text (this is an icon file name)!
Icon=@icon@
Exec=gnome-music
Terminal=false
Type=Application
Categories=GNOME;GTK;AudioVideo;Player;Audio;
# Translators: Search terms to find this application. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon!
Keywords=Music;Player;
StartupNotify=true
DBusActivatable=true
================================================
FILE: data/org.gnome.Music.gresource.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<gresources>
<gresource prefix="/org/gnome/Music">
<file alias="shortcuts-dialog.ui" preprocess="xml-stripblanks">ui/shortcuts-dialog.ui</file>
<file>style.css</file>
<file>icons/welcome-music.svg</file>
<file preprocess="xml-stripblanks">ui/AlbumCover.ui</file>
<file preprocess="xml-stripblanks">ui/AlbumNavigationPage.ui</file>
<file preprocess="xml-stripblanks">ui/AlbumTile.ui</file>
<file preprocess="xml-stripblanks">ui/AlbumWidget.ui</file>
<file preprocess="xml-stripblanks">ui/AlbumsSearchNavigationPage.ui</file>
<file preprocess="xml-stripblanks">ui/AlbumsView.ui</file>
<file preprocess="xml-stripblanks">ui/ArtistAlbumsWidget.ui</file>
<file preprocess="xml-stripblanks">ui/ArtistNavigationPage.ui</file>
<file preprocess="xml-stripblanks">ui/ArtistSearchTile.ui</file>
<file preprocess="xml-stripblanks">ui/ArtistsSearchNavigationPage.ui</file>
<file preprocess="xml-stripblanks">ui/ArtistsView.ui</file>
<file preprocess="xml-stripblanks">ui/ArtistTile.ui</file>
<file preprocess="xml-stripblanks">ui/DiscBox.ui</file>
<file preprocess="xml-stripblanks">ui/HeaderBar.ui</file>
<file preprocess="xml-stripblanks">ui/PlayerToolbar.ui</file>
<file preprocess="xml-stripblanks">ui/PlaylistControls.ui</file>
<file preprocess="xml-stripblanks">ui/PlaylistDialog.ui</file>
<file preprocess="xml-stripblanks">ui/PlaylistDialogRow.ui</file>
<file preprocess="xml-stripblanks">ui/PlaylistsView.ui</file>
<file preprocess="xml-stripblanks">ui/PlaylistsWidget.ui</file>
<file preprocess="xml-stripblanks">ui/PlaylistTile.ui</file>
<file preprocess="xml-stripblanks">ui/PreferencesDialog.ui</file>
<file preprocess="xml-stripblanks">ui/RepeatModeButton.ui</file>
<file preprocess="xml-stripblanks">ui/SearchHeaderBar.ui</file>
<file preprocess="xml-stripblanks">ui/SearchView.ui</file>
<file preprocess="xml-stripblanks">ui/SongWidget.ui</file>
<file preprocess="xml-stripblanks">ui/SongWidgetMenu.ui</file>
<file preprocess="xml-stripblanks">ui/StatusNavigationPage.ui</file>
<file preprocess="xml-stripblanks">ui/TwoLineTip.ui</file>
<file preprocess="xml-stripblanks">ui/VolumeButton.ui</file>
<file preprocess="xml-stripblanks">ui/Window.ui</file>
</gresource>
<gresource prefix="/org/gnome/Music/icons/scalable/actions">
<file alias="deaf-symbolic.svg" preprocess="xml-stripblanks">icons/deaf-symbolic.svg</file>
<file alias="music-playlist-symbolic.svg">icons/music-playlist-symbolic.svg</file>
<file alias="music-artist-symbolic.svg">icons/music-artist-symbolic.svg</file>
<file alias="question-round-symbolic.svg" preprocess="xml-stripblanks">icons/question-round-symbolic.svg</file>
</gresource>
<gresource prefix="/org/gnome/Music">
<file>queries/albums.rq</file>
<file>queries/album_disc.rq</file>
<file>queries/album_discs.rq</file>
<file>queries/artists.rq</file>
<file>queries/artist_albums.rq</file>
<file>queries/search_albums.rq</file>
<file>queries/search_artists.rq</file>
<file>queries/search_songs.rq</file>
<file>queries/songs.rq</file>
<file>queries/playlist_add_song.rq</file>
<file>queries/playlist_create.rq</file>
<file>queries/playlist_delete.rq</file>
<file>queries/playlist_delete_song.rq</file>
<file>queries/playlist_rename_title.rq</file>
<file>queries/playlist_reorder_songs.rq</file>
<file>queries/playlist_query_all.rq</file>
<file>queries/playlist_query_delete_entry.rq</file>
<file>queries/playlist_query_playlist.rq</file>
<file>queries/playlist_query_songs.rq</file>
</gresource>
</gresources>
================================================
FILE: data/org.gnome.Music.gschema.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<schemalist>
<enum id="org.gnome.Music.RepeatMode">
<value nick="none" value="0"/>
<value nick="song" value="1"/>
<value nick="all" value="2"/>
<value nick="shuffle" value="3"/>
</enum>
<enum id="org.gnome.Music.ReplayGain">
<value nick="disabled" value="0"/>
<value nick="album" value="1"/>
<value nick="track" value="2"/>
</enum>
<schema path="/org/gnome/Music/" id="org.gnome.Music" gettext-domain="org.gnome.Music">
<key type="ai" name="window-size">
<default>[768, 600]</default>
<summary>Window size</summary>
<description>Window size (width and height).</description>
</key>
<key type="b" name="window-maximized">
<default>true</default>
<summary>Window maximized</summary>
<description>Window maximized state.</description>
</key>
<key enum="org.gnome.Music.RepeatMode" name="repeat">
<default>'none'</default>
<summary>Playback repeat mode</summary>
<!-- Translators: Don't translate allowed values, just the description in the brackets -->
<description>Value identifies whether to repeat or randomize playback through the collection. Allowed values are: “none” (repeat and shuffle are off), “song” (repeat current song), “all” (repeat playlist, no shuffle), “shuffle” (shuffle playlist, presumes repeat all).</description>
</key>
<key enum="org.gnome.Music.ReplayGain" name="replaygain">
<default>'disabled'</default>
<summary>Enable ReplayGain</summary>
<!-- Translators: Don't translate allowed values, just the description in the brackets -->
<description>Enables or disables ReplayGain for albums or track. Allowed values are: “disabled” (disables replaygain), “album” (replaygain per album), “track” (replaygain per track).</description>
</key>
<key type="b" name="inhibit-suspend">
<default>false</default>
<summary>Inhibit system suspend</summary>
<description>Enables or disables inhibiting system suspend while playing music</description>
</key>
</schema>
</schemalist>
================================================
FILE: data/org.gnome.Music.metainfo.xml.in.in
================================================
<?xml version="1.0" encoding="UTF-8"?>
<component type="desktop-application">
<id>@appid@</id>
<metadata_license>CC0-1.0</metadata_license>
<project_license>GPL-2.0+ and LGPL-2.0+ and CC-BY-SA-4.0</project_license>
<developer id="org.gnome">
<name>The GNOME Project</name>
</developer>
<name>Music</name>
<summary>Play and organize your music collection</summary>
<description>
<p>
An easy and pleasant way to play your music.
</p>
<p>
Find tracks in your local collection, use automatically generated playlists or curate a fresh one.
</p>
</description>
<screenshots>
<screenshot type="default">
<image type="source">https://gitlab.gnome.org/GNOME/gnome-music/raw/HEAD/data/screenshots/gnome-music-1.png</image>
</screenshot>
<screenshot>
<image type="source">https://gitlab.gnome.org/GNOME/gnome-music/raw/HEAD/data/screenshots/gnome-music-2.png</image>
</screenshot>
<screenshot>
<image type="source">https://gitlab.gnome.org/GNOME/gnome-music/raw/HEAD/data/screenshots/gnome-music-3.png</image>
</screenshot>
<screenshot>
<image type="source">https://gitlab.gnome.org/GNOME/gnome-music/raw/HEAD/data/screenshots/gnome-music-4.png</image>
</screenshot>
</screenshots>
<branding>
<color type="primary" scheme_preference="light">#f6d32d</color>
<color type="primary" scheme_preference="dark">#e5870a</color>
</branding>
<url type="homepage">@package_url@</url>
<url type="bugtracker">@package_url_bug@</url>
<url type="donation">https://www.gnome.org/donate</url>
<url type="help">https://help.gnome.org/users/gnome-music/stable/</url>
<url type="translate">https://l10n.gnome.org/module/gnome-music/</url>
<url type="vcs-browser">https://gitlab.gnome.org/GNOME/gnome-music</url>
<url type="contribute">https://welcome.gnome.org/app/Music/</url>
<url type="contact">https://matrix.to/#/#gnome-music:gnome.org</url>
<content_rating type="oars-1.1" />
<requires>
<display_length compare="ge">404</display_length>
</requires>
<recommends>
<internet>first-run</internet>
<display_length compare="ge">800</display_length>
</recommends>
<supports>
<control>keyboard</control>
<control>pointing</control>
<control>touch</control>
</supports>
<project_group>GNOME</project_group>
<launchable type="desktop-id">@appid@.desktop</launchable>
<translation type="gettext">@appid@</translation>
<update_contact>mschraal@gnome.org</update_contact>
<releases>
<release version="48.0" date="2025-03-13">
<description>
<p>Support HiDPI covers</p>
<p>Improve search reliability</p>
<p>Styling fixes</p>
</description>
</release>
<release version="47.0" date="2024-09-16">
<description>
<p>Add track based ReplayGain</p>
</description>
</release>
<release version="46.1" date="2024-07-16">
<description>
<p>
Fix search dropping the first character and other minor improvements.
</p>
</description>
</release>
<release version="46.0" date="2024-03-17">
<description>
<p>
This release introduces a preferences dialog exposing options
previously hidden, like suspend inhibition and ReplayGain settings.
It also updates to the freshest styling for navigation and dialogs.
</p>
<p>
Other notable changes include:
</p>
<ul>
<li>Fix jumpiness in scrolling larger collections</li>
<li>
Add an automated item in playlists view for song files that do not
contain the necessary tags to be shown in the albums and artists
views.
</li>
<li>
Drop LastFM support due to removal of the provider from GNOME
Online Accounts
</li>
<li>Removal of the songs view</li>
<li>Drop global selection mode</li>
</ul>
</description>
</release>
<release version="45.0" date="2023-09-16">
<description>
<p>Minor quality of life improvements</p>
</description>
</release>
<release version="44.0" date="2023-03-22">
<description>
<p>
First stable release for GNOME 44. This version mostly consists
of stability improvements. There are also some notable
improvements:
</p>
<ul>
<li>Port to soup 3</li>
<li>Fix shuffle</li>
<li>Decrease memory usage in SongsView</li>
</ul>
<p>This release also updates translations.</p>
</description>
</release>
<release version="42.1" date="2022-04-25">
<description>
<ul>
<li>Make shuffle shuffle again</li>
<li>Fix time display in RTL languages</li>
<li>No longer mismatch art on scrolling</li>
<li>Fix async queue block on fresh art retrieval</li>
</ul>
</description>
</release>
<release version="42.0" date="2022-03-20">
<description>
<p>
Music has been ported to GTK-4. This brings some performance
improvements for larger collections.
</p>
</description>
</release>
<release version="41.0" date="2021-09-18">
<description>
<p>
This version brings an updated design with even more focus on the
content. Under the hood there have been improvements to the
responsiveness, especially during application start.
</p>
</description>
</release>
<release version="40.0" date="2021-03-21">
<description>
<p>
First stable release for GNOME 40. This version mostly consists
of stability improvements. There are also some notable
improvements:
</p>
<ul>
<li>Improve startup loading</li>
<li>Use publication date instead of creation date for songs</li>
</ul>
<p>This release also updates translations.</p>
</description>
</release>
<release version="3.38.0" date="2020-09-14">
<description>
<p>
First stable release for GNOME 3.38. This version does not rely on
Tracker running on the host. There are also some notable
improvements:
</p>
<ul>
<li>Port to Tracker version 3</li>
<li>Prefer Albumartist field for artist search</li>
<li>Change Artist view selection from artist to song</li>
<li>Lots of general cleanups and bugfixes</li>
</ul>
<p>This release also updates translations.</p>
</description>
</release>
<release version="3.36.0" date="2020-03-07">
<description>
<p>
First stable release for GNOME 3.36. Besides a general focus on
stability there are some notable improvements:
</p>
<ul>
<li>Restore smart playlists update</li>
<li>Expose Last.fm scrobbler in the UI</li>
</ul>
<p>This release also updates translations.</p>
</description>
</release>
<release version="3.35.92" date="2020-03-02" type="development">
<description>
<p>
This is an unstable release in the 3.35 development series,
with the following improvements:
</p>
<ul>
<li>Restore smart playlists update</li>
<li>Improve Tracker content tracking</li>
<li>Flatpak cleanups and updates</li>
<li>Lots of general cleanups and bugfixes</li>
</ul>
<p>This release also updates translations.</p>
</description>
</release>
<release version="3.35.91" date="2020-02-15" type="development">
<description>
<p>
This is an unstable release in the 3.33 development series,
with the following improvements:
</p>
<ul>
<li>Use natural order for sorting</li>
<li>Expose Last.fm scrobbler in the UI</li>
<li>Add a local runtime cache for scrobbling</li>
<li>Lots of general cleanups and bugfixes</li>
</ul>
<p>This release also updates and adds translations.</p>
</description>
</release>
<release version="3.35.3" date="2020-01-05" type="development">
<description>
<p>
This is an unstable release in the 3.33 development series,
with the following improvements:
</p>
<ul>
<li>Improve Tracker content tracking</li>
<li>Update screenshots</li>
<li>Fix a few crashers</li>
<li>Lots of general cleanups</li>
</ul>
<p>This release also updates translations.</p>
</description>
</release>
<release version="3.33.2" date="2019-05-20" type="development">
<description>
<p>
This is an unstable release in the 3.33 development series,
with the following improvements:
</p>
<ul>
<li>Improve Smooth progressbar support</li>
<li>Improve display of information for songs with no tags</li>
<li>Select a random song at launch when playing a playlist in shuffle mode</li>
<li>AppData tags update</li>
<li>Fix crash with mouse 'back' button</li>
<li>MPRIS misc cleanups</li>
<li>Lots of general cleanups</li>
</ul>
<p>This release also updates translations.</p>
</description>
</release>
<release version="3.32.0" date="2019-03-13" />
</releases>
</component>
================================================
FILE: data/org.gnome.Music.service.in
================================================
[D-BUS Service]
Name=@appid@
Exec=@bindir@/gnome-music --gapplication-service
================================================
FILE: data/queries/album_disc.rq
================================================
# Inputs: album_id, disc_nr
SELECT
?id
?url
?title
?artist
?album
?duration
?trackNumber
?albumDiscNumber
?publicationDate
nie:usageCounter(?id) AS ?playCount
?tag AS ?favorite
WHERE {
SERVICE <dbus:{bus_name}> {
GRAPH tracker:Audio {
SELECT DISTINCT
?song AS ?id
nie:isStoredAs(?song) AS ?url
nie:title(?song) AS ?title
nmm:artistName(nmm:artist(?song)) AS ?artist
nie:title(nmm:musicAlbum(?song)) AS ?album
nfo:duration(?song) AS ?duration
nmm:trackNumber(?song) AS ?trackNumber
nmm:setNumber(nmm:musicAlbumDisc(?song)) AS ?albumDiscNumber
YEAR(?date) AS ?publicationDate
WHERE {
?song a nmm:MusicPiece ;
nmm:musicAlbum ~album_id .
OPTIONAL { ?song nie:contentCreated ?date . }
FILTER (
nmm:setNumber(nmm:musicAlbumDisc(?song)) = ~disc_nr
)
{location_filter}
}
ORDER BY ?trackNumber
}
}
OPTIONAL {
?id nao:hasTag ?tag .
FILTER (?tag = nao:predefined-tag-favorite)
}
}
================================================
FILE: data/queries/album_discs.rq
================================================
# Inputs: album_id
SELECT
?albumDiscNumber
WHERE {
SERVICE <dbus:{bus_name}> {
GRAPH tracker:Audio {
SELECT DISTINCT
nmm:setNumber(nmm:musicAlbumDisc(?song)) AS ?albumDiscNumber
WHERE {
?song a nmm:MusicPiece;
nmm:musicAlbum ~album_id .
{location_filter}
}
ORDER BY ?albumDiscNumber
}
}
}
================================================
FILE: data/queries/albums.rq
================================================
SELECT
?type
?id
?title
?composer
?albumArtist
?artist
?url
?publicationDate
WHERE {
SERVICE <dbus:{bus_name}> {
GRAPH tracker:Audio {
SELECT
?album AS ?id
nie:title(?album) AS ?title
?composer
?albumArtist
nmm:artistName(?artist) AS ?artist
nie:isStoredAs(?song) AS ?url
YEAR(MAX(nie:contentCreated(?song))) AS ?publicationDate
WHERE {
?album a nmm:MusicAlbum .
?song a nmm:MusicPiece ;
nmm:musicAlbum ?album ;
nmm:artist ?artist .
OPTIONAL {
?song nmm:composer/nmm:artistName ?composer . }
OPTIONAL {
?album nmm:albumArtist/nmm:artistName ?albumArtist . }
{location_filter}
}
GROUP BY ?album
ORDER BY ?title ?albumArtist ?artist ?publicationDate
}
}
}
================================================
FILE: data/queries/artist_albums.rq
================================================
# Inputs: ~artist
SELECT
?id
?title
?publicationDate
WHERE {
SERVICE <dbus:{bus_name}> {
GRAPH tracker:Audio {
SELECT DISTINCT
?album AS ?id
nie:title(?album) AS ?title
YEAR(nie:contentCreated(?song)) AS ?publicationDate
WHERE {
{
?song a nmm:MusicPiece;
nmm:musicAlbum ?album;
nmm:artist ~artist .
} UNION {
?song a nmm:MusicPiece;
nmm:musicAlbum ?album .
?album a nmm:MusicAlbum;
nmm:albumArtist ~artist .
}
{location_filter}
}
GROUP BY ?album
ORDER BY ?publicationDate ?album
}
}
}
================================================
FILE: data/queries/artists.rq
================================================
SELECT
?id
?artist
WHERE {
SERVICE <dbus:{bus_name}> {
GRAPH tracker:Audio {
SELECT
(COALESCE(?album_artist, ?artist) AS ?id)
?artist_bind AS ?artist
WHERE {
?song a nmm:MusicPiece;
nmm:musicAlbum ?album;
nmm:artist ?artist .
OPTIONAL {
?album a nmm:MusicAlbum;
nmm:albumArtist ?album_artist .
}
BIND(COALESCE(
nmm:artistName(?album_artist),
nmm:artistName(?artist)) AS ?artist_bind)
{location_filter}
}
GROUP BY ?artist_bind
ORDER BY ?artist_bind
}
}
}
================================================
FILE: data/queries/playlist_add_song.rq
================================================
# Inputs: playlist, uri
DELETE {
~playlist nfo:entryCounter ?counter .
}
INSERT {
_:entry a nfo:MediaFileListEntry ;
nfo:entryUrl ~uri ;
nfo:listPosition ?position .
~playlist nfo:entryCounter ?position ;
nfo:hasMediaFileListEntry _:entry .
}
WHERE {
SELECT
?counter
(?counter + 1) AS ?position
WHERE {
~playlist a nmm:Playlist ;
a nfo:MediaList ;
nfo:entryCounter ?counter .
}
}
================================================
FILE: data/queries/playlist_create.rq
================================================
INSERT {
~playlist a nmm:Playlist ;
a nfo:MediaList ;
nie:title ~title ;
nfo:entryCounter 0 .
}
================================================
FILE: data/queries/playlist_delete.rq
================================================
DELETE WHERE {
~playlist a rdfs:Resource ;
a nmm:Playlist ;
a nfo:MediaList .
}
================================================
FILE: data/queries/playlist_delete_song.rq
================================================
# Inputs: ~entry, ~playlist
DELETE {
?entry nfo:listPosition ?old_position .
}
INSERT {
?entry nfo:listPosition ?new_position .
}
WHERE {
SELECT
?entry
?old_position
(?old_position - 1) AS ?new_position
WHERE {
?entry a nfo:MediaFileListEntry ;
nfo:listPosition ?old_position .
~playlist nfo:hasMediaFileListEntry ?entry .
FILTER (?old_position > ?removed_position)
{
SELECT
?removed_position
WHERE {
~playlist a nmm:Playlist ;
a nfo:MediaList ;
nfo:hasMediaFileListEntry ~entry .
~entry nfo:listPosition ?removed_position .
}
}
}
};
DELETE {
~playlist nfo:entryCounter ?old_counter .
}
INSERT {
~playlist nfo:entryCounter ?new_counter .
}
WHERE {
SELECT
?old_counter
(?old_counter - 1) AS ?new_counter
WHERE {
~playlist a nmm:Playlist ;
a nfo:MediaList ;
nfo:entryCounter ?old_counter .
}
};
DELETE {
~playlist nfo:hasMediaFileListEntry ~entry .
~entry a rdfs:Resource .
}
WHERE {
~playlist a nmm:Playlist ;
a nfo:MediaList ;
nfo:hasMediaFileListEntry ~entry .
}
================================================
FILE: data/queries/playlist_query_all.rq
================================================
SELECT DISTINCT
?playlist AS ?id
?title
?creationDate
?childCount
WHERE
{
?playlist a nmm:Playlist ;
nie:title ?title ;
nrl:added ?creationDate;
nfo:entryCounter ?childCount .
}
================================================
FILE: data/queries/playlist_query_delete_entry.rq
================================================
# Inputs: playlist, position
SELECT
?entry AS ?id
WHERE {
~playlist_id a nmm:Playlist ;
a nfo:MediaList ;
nfo:hasMediaFileListEntry ?entry .
?entry a nfo:MediaFileListEntry ;
nfo:listPosition ~position .
}
================================================
FILE: data/queries/playlist_query_playlist.rq
================================================
# Inputs: playlist
SELECT DISTINCT
~playlist AS ?id
?title
?creationDate
?childCount
WHERE
{
~playlist a nmm:Playlist ;
nie:title ?title ;
nrl:added ?creationDate;
nfo:entryCounter ?childCount .
}
================================================
FILE: data/queries/playlist_query_songs.rq
================================================
# Inputs: playlist, miner_fs_busname, location_filter
SELECT
?song AS ?id
?url
?title
?artist
?album
?duration
?tag
nie:contentAccessed(?song) AS ?lastPlayed
nie:usageCounter(?song) AS ?playCount
WHERE {
~playlist a nmm:Playlist ;
a nfo:MediaList ;
nfo:hasMediaFileListEntry ?entry .
?entry a nfo:MediaFileListEntry ;
nfo:entryUrl ?url .
SERVICE <dbus:{bus_name}> {
GRAPH tracker:Audio {
SELECT
?song
nie:title(?song) AS ?title
nmm:artistName(nmm:artist(?song)) AS ?artist
nie:title(nmm:musicAlbum(?song)) AS ?album
nfo:duration(?song) AS ?duration
?url
WHERE {
?song a nmm:MusicPiece ;
nie:isStoredAs ?url .
{location_filter}
}
}
}
OPTIONAL {
?song nao:hasTag ?tag .
FILTER( ?tag = nao:predefined-tag-favorite )
}
} ORDER BY nfo:listPosition(?entry)
================================================
FILE: data/queries/playlist_rename_title.rq
================================================
DELETE {
~playlist nie:title ?title .
}
INSERT {
~playlist nie:title ~title .
}
WHERE {
~playlist a nmm:Playlist ;
nie:title ?title ;
a nfo:MediaList .
}
================================================
FILE: data/queries/playlist_reorder_songs.rq
================================================
# Inputs: id, old_position, new_position
DELETE {
?entry nfo:listPosition ~old_position .
}
INSERT {
?entry nfo:listPosition ~new_position .
}
WHERE {
?entry nfo:listPosition ~old_position .
~id a nmm:Playlist ;
a nfo:MediaList ;
nfo:hasMediaFileListEntry ?entry .
}
================================================
FILE: data/queries/search_albums.rq
================================================
# Inputs: name
SELECT
?id
WHERE {
SERVICE <dbus:{bus_name}> {
GRAPH tracker:Audio {
SELECT DISTINCT
nmm:musicAlbum(?song) AS ?id
WHERE {
?song a nmm:MusicPiece .
BIND(tracker:normalize(nie:title(nmm:musicAlbum(?song)), 'nfkd') AS ?match1) .
BIND(tracker:normalize(nmm:artistName(nmm:artist(?song)), 'nfkd') AS ?match2) .
BIND(tracker:normalize(nie:title(?song), 'nfkd') AS ?match3) .
BIND(tracker:normalize(nmm:composer(?song), 'nfkd') AS ?match4) .
FILTER (
CONTAINS(tracker:case-fold(tracker:unaccent(?match1)), ~name)
|| CONTAINS(tracker:case-fold(?match1), ~name)
|| CONTAINS(tracker:case-fold(tracker:unaccent(?match2)), ~name)
|| CONTAINS(tracker:case-fold(?match2), ~name)
|| CONTAINS(tracker:case-fold(tracker:unaccent(?match3)), ~name)
|| CONTAINS(tracker:case-fold(?match3), ~name)
|| CONTAINS(tracker:case-fold(tracker:unaccent(?match4)), ~name)
|| CONTAINS(tracker:case-fold(?match4), ~name)
)
{location_filter}
} LIMIT 50
}
}
}
================================================
FILE: data/queries/search_artists.rq
================================================
# Inputs: name
SELECT
?id
WHERE {
SERVICE <dbus:{bus_name}> {
GRAPH tracker:Audio {
SELECT DISTINCT
COALESCE(?album_artist, ?artist) AS ?id
WHERE {
?song a nmm:MusicPiece ;
nmm:musicAlbum ?album ;
nmm:artist ?artist .
OPTIONAL {
?album a nmm:MusicAlbum ;
nmm:albumArtist ?album_artist .
}
BIND(COALESCE(nmm:artistName(?album_artist), nmm:artistName(?artist)) AS ?artist_bind)
BIND(tracker:normalize(nmm:artistName(nmm:albumArtist(?artist_bind)), 'nfkd') AS ?match1) .
BIND(tracker:normalize(nmm:artistName(nmm:artist(?song)), 'nfkd') AS ?match2) .
BIND(tracker:normalize(nie:title(?song), 'nfkd') AS ?match3) .
BIND(tracker:normalize(nmm:composer(?song), 'nfkd') AS ?match4) .
FILTER (
CONTAINS(tracker:case-fold(tracker:unaccent(?match1)), ~name)
|| CONTAINS(tracker:case-fold(?match1), ~name)
|| CONTAINS(tracker:case-fold(tracker:unaccent(?match2)), ~name)
|| CONTAINS(tracker:case-fold(?match2), ~name)
|| CONTAINS(tracker:case-fold(tracker:unaccent(?match3)), ~name)
|| CONTAINS(tracker:case-fold(?match3), ~name)
|| CONTAINS(tracker:case-fold(tracker:unaccent(?match4)), ~name)
|| CONTAINS(tracker:case-fold(?match4), ~name)
)
{location_filter}
} LIMIT 50
}
}
}
================================================
FILE: data/queries/search_songs.rq
================================================
# Inputs: name
SELECT
?id
WHERE {
SERVICE <dbus:{bus_name}> {
GRAPH tracker:Audio {
SELECT DISTINCT
?song AS ?id
WHERE {
?song a nmm:MusicPiece .
BIND(tracker:normalize(nie:title(nmm:musicAlbum(?song)), 'nfkd') AS ?match1) .
BIND(tracker:normalize(nmm:artistName(nmm:artist(?song)), 'nfkd') AS ?match2) .
BIND(tracker:normalize(nie:title(?song), 'nfkd') AS ?match3) .
BIND(tracker:normalize(nmm:composer(?song), 'nfkd') AS ?match4) .
FILTER (
CONTAINS(tracker:case-fold(tracker:unaccent(?match1)), ~name)
|| CONTAINS(tracker:case-fold(?match1), ~name)
|| CONTAINS(tracker:case-fold(tracker:unaccent(?match2)), ~name)
|| CONTAINS(tracker:case-fold(?match2), ~name)
|| CONTAINS(tracker:case-fold(tracker:unaccent(?match3)), ~name)
|| CONTAINS(tracker:case-fold(?match3), ~name)
|| CONTAINS(tracker:case-fold(tracker:unaccent(?match4)), ~name)
|| CONTAINS(tracker:case-fold(?match4), ~name)
)
{location_filter}
} LIMIT 50
}
}
}
================================================
FILE: data/queries/songs.rq
================================================
SELECT
?urn
?title
?id
?url
?artist
?album
?duration
?trackNumber
?albumDiscNumber
nie:contentAccessed(?urn) AS ?lastPlayed
nie:usageCounter(?urn) AS ?playCount
?tag AS ?favorite
?album_urn
WHERE {
SERVICE <dbus:{bus_name}> {
GRAPH tracker:Audio {
SELECT DISTINCT
?song AS ?urn
nie:title(?song) AS ?title
?song AS ?id
nie:isStoredAs(?song) AS ?url
nmm:artistName(nmm:artist(?song)) AS ?artist
nie:title(nmm:musicAlbum(?song)) AS ?album
nfo:duration(?song) AS ?duration
nmm:trackNumber(?song) AS ?trackNumber
nmm:setNumber(nmm:musicAlbumDisc(?song)) AS ?albumDiscNumber
nmm:musicAlbum(?song) AS ?album_urn
WHERE {
{song_bind}
?song a nmm:MusicPiece .
{location_filter}
}
}
}
OPTIONAL {
?urn nao:hasTag ?tag .
FILTER (?tag = nao:predefined-tag-favorite)
}
} ORDER BY ?title ?artist
================================================
FILE: data/style.css
================================================
/* AlbumCover/AlbumTile */
.artist-label {
font-size: smaller;
}
/* AlbumsView */
#albums gridview {
padding: 18px;
}
#albums gridview > child {
margin: 9px;
padding: 6px;
}
#albums gridview > child:hover,child:selected {
background-color: var(--border-color);
}
/* SearchView FlowBox tiles */
.tile:hover {
background-color: var(--border-color);
}
/* Cover images in large tiles in AlbumsView and SearchView */
.tile-image {
margin: 6px;
}
.playlist-icon {
padding: 10px;
border-radius: 50%;
background-color: var(--border-color);
}
.disc-label {
padding: 12px 0;
}
/* PlayerToolbar */
.smooth-scale {
padding-top: 0px;
padding-bottom: 0px;
}
.grey-image {
color: color-mix(in srgb, currentColor 30%, transparent);
}
/* Used in TwoLineTip, AlbumWidget and ArtistAlbumsWidget */
.bold-label {
font-weight: bold;
}
.playlistdialog-row:selected {
color: var(--window-fg-color);
background-color: var(--border-color);
}
.playlistdialog-row:selected label {
color: var(--view-fg-color);
}
/* SearchView */
.search-header {
font-weight: bold;
}
/* dnd icon for SongWidget */
.drag-handle {
color: color-mix(in srgb, currentColor 40%, transparent);
}
.drag-handle:backdrop {
color: color-mix(in srgb, currentColor 40%, transparent);
}
/* SongWidget rows */
.songwidget {
padding: 12px;
}
/* Starring */
button.star:hover {
opacity: 1;
}
@keyframes rotate_star {
from { -gtk-icon-transform: rotate(-72deg); }
to {}
}
@keyframes rotate_unstar {
from { -gtk-icon-transform: rotate(72deg); }
to {}
}
button.star.interacted.starred image {
animation: rotate_star 0.4s ease;
}
button.star.interacted:not(.starred) image {
animation: rotate_unstar 0.4s ease;
}
================================================
FILE: data/ui/AlbumCover.ui
================================================
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="AlbumCover" parent="GtkFlowBoxChild">
<style>
<class name="tile"/>
</style>
</template>
</interface>
================================================
FILE: data/ui/AlbumNavigationPage.ui
================================================
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<requires lib="gtk" version="4.0"/>
<template class="AlbumNavigationPage" parent="AdwNavigationPage">
<property name="title">Albums</property>
<child>
<object class="AdwToolbarView">
<child type="top">
<object class="AdwHeaderBar">
<property name="title-widget">
<object class="AdwWindowTitle" id="_page_title"/>
</property>
</object>
</child>
<property name="content">
<object class="GtkScrolledWindow" id="_album_scrolled_window">
<property name="focusable">False</property>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<property name="hscrollbar_policy">never</property>
</object>
</property>
</object>
</child>
</template>
</interface>
================================================
FILE: data/ui/AlbumTile.ui
================================================
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<requires lib="gtk" version="4.0"/>
<template class="AlbumTile" parent="GtkBox">
<property name="has_tooltip">True</property>
<property name="valign">start</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkImage" id="_cover_image">
<property name="vexpand">True</property>
<property name="valign">center</property>
<property name="halign">center</property>
<style>
<class name="tile-image"/>
</style>
</object>
</child>
<child>
<object class="GtkLabel" id="_album_label">
<property name="justify">center</property>
<property name="wrap">True</property>
<property name="ellipsize">middle</property>
<property name="max_width_chars">20</property>
<property name="lines">1</property>
</object>
</child>
<child>
<object class="GtkLabel" id="_artist_label">
<property name="ellipsize">middle</property>
<property name="max_width_chars">20</property>
<style>
<class name="artist-label"/>
<class name="dim-label"/>
</style>
</object>
</child>
</template>
</interface>
================================================
FILE: data/ui/AlbumWidget.ui
================================================
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="AlbumWidget" parent="AdwBin">
<child>
<object class="AdwClamp">
<property name="margin-bottom">48</property>
<property name="margin-top">48</property>
<property name="maximum-size">1000</property>
<child>
<object class="GtkBox">
<property name="halign">fill</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkBox" id="albumInfo">
<property name="halign">fill</property>
<property name="hexpand">True</property>
<property name="spacing">32</property>
<child>
<object class="GtkImage" id="_cover_image">
<property name="halign">center</property>
<property name="valign">center</property>
</object>
</child>
<child>
<object class="GtkBox" id="albumDetails">
<property name="halign">center</property>
<property name="valign">start</property>
<property name="orientation">vertical</property>
<property name="margin-top">18</property>
<child>
<object class="GtkLabel" id="_title_label">
<property name="focusable">False</property>
<property name="halign">start</property>
<property name="ellipsize">middle</property>
<property name="margin-bottom">18</property>
<style>
<class name="title-1"/>
</style>
</object>
</child>
<child>
<object class="GtkLabel" id="_artist_label">
<property name="focusable">False</property>
<property name="halign">start</property>
<property name="ellipsize">middle</property>
<property name="margin-bottom">12</property>
<style>
<class name="title-3"/>
</style>
</object>
</child>
<child>
<object class="GtkLabel" id="_released_label">
<property name="focusable">False</property>
<property name="halign">start</property>
<property name="use_markup">True</property>
<property name="margin-bottom">12</property>
<style>
<class name="dim-label"/>
</style>
</object>
</child>
<child>
<object class="GtkLabel" id="_composer_label">
<property name="focusable">False</property>
<property name="halign">start</property>
<property name="ellipsize">end</property>
<property name="margin-bottom">12</property>
<style>
<class name="dim-label"/>
</style>
</object>
</child>
<child>
<object class="GtkBox">
<property name="orientation">horizontal</property>
<property name="spacing">12</property>
<property name="margin-top">6</property>
<child>
<object class="GtkButton" id="_play_button">
<property name="width-request">44</property>
<property name="height-request">44</property>
<property name="icon-name">media-playback-start-symbolic</property>
<property name="tooltip-text" translatable="yes">Play</property>
<property name="valign">center</property>
<signal name="clicked" handler="_on_play_button_clicked"/>
<style>
<class name="circular"/>
</style>
</object>
</child>
<child>
<object class="GtkMenuButton" id="_menu_button">
<property name="width-request">44</property>
<property name="height-request">44</property>
<property name="halign">start</property>
<property name="valign">center</property>
<property name="focus_on_click">False</property>
<property name="menu-model">album_menu</property>
<property name="direction">none</property>
<property name="icon_name">view-more-symbolic</property>
<style>
<class name="circular"/>
</style>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="GtkListBox" id="_disc_list_box">
<property name="focusable">False</property>
<property name="margin-top">48</property>
<property name="selection_mode">0</property>
<style>
<class name="background"/>
</style>
</object>
</child>
</object>
</child>
</object>
</child>
</template>
<menu id="album_menu">
<item>
<attribute name="label" translatable="yes">_Play</attribute>
<attribute name="action">album.play</attribute>
</item>
<item>
<attribute name="label" translatable="yes">Add to _Favorite Songs</attribute>
<attribute name="action">album.add_favorites</attribute>
</item>
<item>
<attribute name="label" translatable="yes">_Add to Playlist…</attribute>
<attribute name="action">album.add_playlist</attribute>
</item>
</menu>
</interface>
================================================
FILE: data/ui/AlbumsSearchNavigationPage.ui
================================================
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<requires lib="gtk" version="4.0"/>
<template class="AlbumsSearchNavigationPage" parent="AdwNavigationPage">
<property name="title" translatable="yes">Albums</property>
<child>
<object class="AdwToolbarView">
<child type="top">
<object class="AdwHeaderBar"/>
</child>
<property name="content">
<object class="GtkScrolledWindow">
<property name="focusable">False</property>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<property name="hscrollbar_policy">never</property>
<child>
<object class="AdwClamp">
<property name="maximum-size">1600</property>
<child>
<object class="GtkBox">
<property name="halign">fill</property>
<property name="hexpand">True</property>
<property name="margin-bottom">20</property>
<property name="margin-end">120</property>
<property name="margin-start">120</property>
<property name="margin-top">20</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkFlowBox" id="_all_albums_flowbox">
<property name="halign">fill</property>
<property name="hexpand">True</property>
<property name="valign">start</property>
<property name="homogeneous">True</property>
<property name="min_children_per_line">1</property>
<property name="max_children_per_line">6</property>
<property name="margin-bottom">18</property>
<property name="margin-top">18</property>
<property name="row_spacing">12</property>
<property name="column_spacing">6</property>
<property name="selection_mode">none</property>
<signal name="child-activated" handler="_on_album_activated"/>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</property>
</object>
</child>
</template>
</interface>
================================================
FILE: data/ui/AlbumsView.ui
================================================
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<requires lib="gtk" version="4.0"/>
<template class="AlbumsView" parent="AdwBin">
<child>
<object class="GtkScrolledWindow" id="_scrolled_window">
<child>
<object class="GtkGridView" id="_gridview">
<property name="max-columns">10</property>
<property name="single-click-activate">True</property>
</object>
</child>
</object>
</child>
</template>
</interface>
================================================
FILE: data/ui/ArtistAlbumsWidget.ui
================================================
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<requires lib="gtk" version="4.0"/>
<template class="ArtistAlbumsWidget" parent="GtkBox">
<property name="orientation">vertical</property>
<child>
<object class="AdwClamp">
<property name="maximum-size">1000</property>
<property name="orientation">horizontal</property>
<child>
<object class="GtkListBox" id="_listbox">
<style>
<class name="background"/>
</style>
</object>
</child>
</object>
</child>
</template>
</interface>
================================================
FILE: data/ui/ArtistNavigationPage.ui
================================================
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<requires lib="gtk" version="4.0"/>
<template class="ArtistNavigationPage" parent="AdwNavigationPage">
<property name="title">Artist</property>
<child>
<object class="AdwToolbarView">
<child type="top">
<object class="AdwHeaderBar" id="_headerbar"/>
</child>
<property name="content">
<object class="GtkScrolledWindow" id="_artist_scrolled_window">
<property name="focusable">False</property>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<property name="hscrollbar_policy">never</property>
</object>
</property>
</object>
</child>
</template>
</interface>
================================================
FILE: data/ui/ArtistSearchTile.ui
================================================
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="ArtistSearchTile" parent="GtkFlowBoxChild">
<child>
<object class="GtkBox">
<property name="has_tooltip">True</property>
<property name="valign">start</property>
<property name="orientation">vertical</property>
<signal name="query-tooltip" handler="_on_tooltip_query"/>
<child>
<object class="GtkImage" id="_cover_image">
<property name="hexpand">True</property>
<style>
<class name="tile-image"/>
</style>
</object>
</child>
<child>
<object class="GtkLabel" id="_artist_label">
<property name="justify">center</property>
<property name="wrap">True</property>
<property name="ellipsize">middle</property>
<property name="max_width_chars">20</property>
<property name="lines">1</property>
</object>
</child>
</object>
</child>
<style>
<class name="tile"/>
</style>
</template>
</interface>
================================================
FILE: data/ui/ArtistTile.ui
================================================
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="ArtistTile" parent="GtkBox">
<property name="focusable">False</property>
<child>
<object class="GtkBox">
<property name="orientation">horizontal</property>
<child>
<object class="GtkImage" id="_cover_image">
<property name="halign">center</property>
<property name="valign">center</property>
</object>
</child>
<child>
<object class="GtkLabel" id="_label">
<property name="focusable">False</property>
<property name="ellipsize">end</property>
<property name="halign">start</property>
<property name="hexpand">False</property>
<property name="margin-bottom">16</property>
<property name="margin-end">10</property>
<property name="margin-start">10</property>
<property name="margin-top">16</property>
</object>
</child>
</object>
</child>
</template>
</interface>
================================================
FILE: data/ui/ArtistsSearchNavigationPage.ui
================================================
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<requires lib="gtk" version="4.0"/>
<template class="ArtistsSearchNavigationPage" parent="AdwNavigationPage">
<property name="title" translatable="yes">Artists</property>
<child>
<object class="AdwToolbarView">
<child type="top">
<object class="AdwHeaderBar"/>
</child>
<property name="content">
<object class="GtkScrolledWindow">
<property name="focusable">False</property>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<property name="hscrollbar_policy">never</property>
<child>
<object class="AdwClamp">
<property name="maximum-size">1600</property>
<child>
<object class="GtkBox">
<property name="halign">fill</property>
<property name="hexpand">True</property>
<property name="margin-bottom">20</property>
<property name="margin-end">120</property>
<property name="margin-start">120</property>
<property name="margin-top">20</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkFlowBox" id="_all_artists_flowbox">
<property name="column_spacing">6</property>
<property name="halign">fill</property>
<property name="hexpand">True</property>
<property name="homogeneous">True</property>
<property name="margin-bottom">18</property>
<property name="margin-top">18</property>
<property name="max-children-per-line">6</property>
<property name="min-children-per-line">1</property>
<property name="row_spacing">12</property>
<property name="selection-mode">none</property>
<property name="valign">start</property>
<signal name="child-activated" handler="_on_artist_activated"/>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</property>
</object>
</child>
</template>
</interface>
================================================
FILE: data/ui/ArtistsView.ui
================================================
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<requires lib="gtk" version="4.0"/>
<template class="ArtistsView" parent="AdwBin">
<child>
<object class="AdwOverlaySplitView" id="_split_view">
<property name="sidebar">
<object class="GtkScrolledWindow">
<child>
<object class="GtkListView" id="_sidebar">
<signal name="activate" handler="_on_artist_activated"/>
<style>
<class name="navigation-sidebar"/>
</style>
</object>
</child>
</object>
</property>
<property name="content">
<object class="GtkScrolledWindow" id="_artist_view">
<property name="hexpand">true</property>
<property name="vexpand">true</property>
</object>
</property>
</object>
</child>
</template>
</interface>
================================================
FILE: data/ui/DiscBox.ui
================================================
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<requires lib="gtk" version="4.0"/>
<template parent="GtkListBoxRow" class="DiscBox">
<property name="focusable">False</property>
<property name="activatable">False</property>
<property name="selectable">False</property>
<child>
<object class="GtkListBox" id="_list_box">
<property name="focusable">False</property>
<property name="valign">start</property>
<property name="selection_mode">none</property>
<signal name="row-activated" handler="_song_activated"/>
<style>
<class name="boxed-list"/>
</style>
</object>
</child>
</template>
</interface>
================================================
FILE: data/ui/DiscListItem.ui
================================================
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<requires lib="gtk+" version="4.0"/>
<template class="DiscListItem" parent="GtkListItem">
<property name="child">
<object class="GtkBox">
<property name="orientation">vertical</property>
<child>
<object class="GtkLabel">
<binding name="label">
<lookup name="disc_nr" type="CoreDisc">
<lookup name="item">GtkListItem</lookup>
</lookup>
</binding>
</object>
</child>
<child>
<object class="DiscBox" id="_disc_box">
<binding name="model">
<lookup name="model" type="CoreDisc">
<lookup name="item">GtkListItem</lookup>
</lookup>
</binding>
</object>
</child>
</object>
</property>
</template>
</interface>
================================================
FILE: data/ui/HeaderBar.ui
================================================
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="HeaderBar" parent="AdwBin">
<child>
<object class="AdwHeaderBar" id="_headerbar">
<property name="vexpand">False</property>
<child type="end">
<object class="GtkMenuButton" id="_menu_button">
<property name="valign">center</property>
<property name="sensitive">True</property>
<property name="icon-name">open-menu-symbolic</property>
<property name="menu-model">_primary_menu</property>
<property name="primary">True</property>
<property name="tooltip_text" translatable="yes">Menu</property>
</object>
</child>
<child type="start">
<object class="GtkToggleButton" id="_search_button">
<property name="valign">center</property>
<property name="sensitive">True</property>
<property name="icon-name">edit-find-symbolic</property>
<property name="tooltip_text" translatable="yes">Search</property>
</object>
</child>
</object>
</child>
</template>
<menu id="_primary_menu">
<section>
<item>
<attribute name="label" translatable="true">Preferences</attribute>
<attribute name="action">app.preferences</attribute>
</item>
<item>
<attribute name="label" translatable="true">Keyboard Shortcuts</attribute>
<attribute name="action">app.shortcuts</attribute>
</item>
<item>
<attribute name="label" translatable="true">Help</attribute>
<attribute name="action">app.help</attribute>
</item>
<item>
<attribute name="label" translatable="true">About Music</attribute>
<attribute name="action">app.about</attribute>
</item>
</section>
</menu>
</interface>
================================================
FILE: data/ui/PlayerToolbar.ui
================================================
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<requires lib="gtk" version="4.0"/>
<template class="PlayerToolbar" parent="GtkActionBar">
<property name="focusable">False</property>
<property name="revealed">False</property>
<child>
<object class="GtkBox" id="_song_info_box">
<property name="focusable">False</property>
<property name="halign">center</property>
<property name="has_tooltip">True</property>
<property name="valign">center</property>
<property name="spacing">8</property>
<property name="margin-bottom">6</property>
<property name="margin-end">6</property>
<property name="margin-start">6</property>
<property name="margin-top">6</property>
<signal name="query-tooltip" handler="_on_tooltip_query"/>
<child>
<object class="GtkImage" id="_cover_image">
</object>
</child>
<child>
<object class="GtkBox" id="nowplaying_labels">
<property name="focusable">False</property>
<property name="halign">center</property>
<property name="valign">center</property>
<property name="orientation">vertical</property>
<property name="homogeneous">True</property>
<property name="spacing">3</property>
<child>
<object class="GtkLabel" id="_title_label">
<property name="focusable">False</property>
<property name="halign">start</property>
<property name="ellipsize">middle</property>
<property name="max_width_chars">28</property>
<style>
<class name="bold-label"/>
</style>
</object>
</child>
<child>
<object class="GtkLabel" id="_artist_label">
<property name="focusable">False</property>
<property name="halign">start</property>
<property name="ellipsize">middle</property>
<property name="max_width_chars">28</property>
</object>
</child>
</object>
</child>
</object>
</child>
<child type="center">
<object class="GtkBox" id="_buttons_and_scale">
<property name="hexpand">True</property>
<property name="orientation">vertical</property>
<property name="focusable">False</property>
<property name="margin-bottom">6</property>
<property name="margin-end">6</property>
<property name="margin-start">6</property>
<property name="margin-top">6</property>
<child>
<object class="GtkBox" id="buttons">
<property name="focusable">False</property>
<property name="halign">center</property>
<property name="spacing">12</property>
<child>
<object class="GtkButton" id="_prev_button">
<property name="sensitive">False</property>
<property name="focusable">True</property>
<property name="receives_default">True</property>
<property name="icon_name">media-skip-backward-symbolic</property>
<property name="tooltip_text" translatable="yes">Previous</property>
<property name="valign">center</property>
<signal name="clicked" handler="_on_prev_button_clicked"/>
<style>
<class name="circular"/>
</style>
</object>
</child>
<child>
<object class="GtkButton" id="_play_button">
<property name="sensitive">False</property>
<property name="focusable">True</property>
<property name="receives_default">True</property>
<property name="tooltip_text" translatable="yes">Play</property>
<signal name="clicked" handler="_on_play_button_clicked"/>
<style>
<class name="pill"/>
</style>
<child>
<object class="GtkImage" id="_play_pause_image">
<property name="icon_name">media-playback-start-symbolic</property>
<property name="icon_size">2</property>
</object>
</child>
</object>
</child>
<child>
<object class="GtkButton" id="_next_button">
<property name="sensitive">False</property>
<property name="focusable">True</property>
<property name="receives_default">True</property>
<property name="icon_name">media-skip-forward-symbolic</property>
<property name="tooltip_text" translatable="yes">Next</property>
<property name="valign">center</property>
<signal name="clicked" handler="_on_next_button_clicked"/>
<style>
<class name="circular"/>
</style>
</object>
</child>
</object>
</child>
<child>
<object class="AdwClamp">
<property name="maximum-size">1000</property>
<child>
<object class="GtkBox" id="scale_and_timer">
<property name="orientation">horizontal</property>
<property name="focusable">False</property>
<property name="margin_top">12</property>
<child>
<object class="GtkLabel" id="_progress_time_label">
<property name="focusable">False</property>
<property name="halign">start</property>
<property name="valign">center</property>
<property name="label">0∶00</property>
<style>
<class name="numeric"/>
</style>
</object>
</child>
<child>
<object class="SmoothScale" id="_progress_scale">
<property name="focusable">True</property>
<property name="valign">center</property>
<property name="hexpand">True</property>
<property name="draw_value">False</property>
<signal name="value-changed" handler="_on_progress_value_changed"/>
<style>
<class name="smooth-scale"/>
</style>
</object>
</child>
<child>
<object class="GtkLabel" id="_duration_label">
<property name="focusable">False</property>
<property name="halign">start</property>
<property name="valign">center</property>
<property name="label">0∶00</property>
<style>
<class name="numeric"/>
</style>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</child>
<child type="end">
<object class="GtkBox" id="menuBox">
<property name="height_request">34</property>
<property name="focusable">False</property>
<property name="halign">end</property>
<property name="valign">center</property>
<property name="margin-bottom">6</property>
<property name="margin-end">6</property>
<property name="margin-start">6</property>
<property name="margin-top">6</property>
<child>
<object class="RepeatModeButton" id="_repeat_mode_button"/>
</child>
<child>
<object class="VolumeButton" id="_volume_button"/>
</child>
</object>
</child>
</template>
</interface>
================================================
FILE: data/ui/PlaylistControls.ui
================================================
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<menu id="playlistMenu">
<item>
<attribute name="label" translatable="yes">_Play</attribute>
<attribute name="action">win.playlist_play</attribute>
</item>
<item>
<attribute name="label" translatable="yes">_Delete</attribute>
<attribute name="action">win.playlist_delete</attribute>
</item>
<item>
<attribute name="label" translatable="yes">_Rename…</attribute>
<attribute name="action">win.playlist_rename</attribute>
</item>
</menu>
<template class="PlaylistControls" parent="GtkBox">
<property name="orientation">vertical</property>
<property name="focusable">False</property>
<property name="margin-top">30</property>
<child>
<object class="GtkStack" id="_name_stack">
<child>
<object class="GtkLabel" id="_name_label">
<property name="focusable">False</property>
<property name="hexpand">True</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">Playlist Name</property>
<property name="ellipsize">middle</property>
<property name="margin-bottom">10</property>
<style>
<class name="title-1"/>
</style>
</object>
</child>
<child>
<object class="GtkStackPage">
<property name="name">renaming_dialog</property>
<property name="child">
<object class="GtkBox">
<property name="orientation">horizontal</property>
<style>
<class name="linked"/>
</style>
<child>
<object class="GtkEntry" id="_rename_entry">
<child>
<object class="GtkEventControllerKey" id="_rename_controller">
<signal name="key-pressed" handler="_on_rename_entry_key_pressed"/>
</object>
</child>
<property name="focusable">True</property>
<property name="receives_default">True</property>
<signal name="activate" handler="_on_playlist_renamed"/>
<signal name="changed" handler="_on_rename_entry_changed"/>
</object>
</child>
<child>
<object class="GtkButton" id="_rename_done_button">
<property name="focusable">True</property>
<property name="receives_default">True</property>
<property name="label" translatable="yes">_Done</property>
<property name="use_underline">True</property>
<property name="sensitive">True</property>
<signal name="clicked" handler="_on_playlist_renamed"/>
<style>
<class name="suggested-action"/>
</style>
</object>
</child>
</object>
</property>
</object>
</child>
</object>
</child>
<child>
<object class="GtkLabel" id="_songs_count_label">
<property name="focusable">False</property>
<property name="halign">start</property>
<property name="label"></property>
<property name="margin-bottom">4</property>
<style>
<class name="body"/>
</style>
</object>
</child>
<child>
<object class="GtkBox">
<property name="orientation">horizontal</property>
<property name="spacing">12</property>
<property name="margin-top">18</property>
<property name="margin-bottom">8</property>
<child>
<object class="GtkButton" id="_play_button">
<property name="height-request">44</property>
<property name="width-request">44</property>
<property name="focusable">True</property>
<property name="receives-default">True</property>
<property name="icon_name">media-playback-start-symbolic</property>
<property name="tooltip-text" translatable="yes">Play</property>
<property name="valign">center</property>
<signal name="clicked" handler="_on_play_button_clicked"/>
<style>
<class name="circular"/>
</style>
</object>
</child>
<child>
<object class="GtkMenuButton" id="_menubutton">
<property name="height-request">44</property>
<property name="width-request">44</property>
<property name="focusable">True</property>
<property name="receives_default">True</property>
<property name="halign">start</property>
<property name="valign">center</property>
<property name="focus_on_click">False</property>
<property name="menu-model">playlistMenu</property>
<property name="direction">none</property>
<property name="icon_name">view-more-symbolic</property>
<style>
<class name="circular"/>
</style>
</object>
</child>
</object>
</child>
</template>
</interface>
================================================
FILE: data/ui/PlaylistDialog.ui
================================================
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<requires lib="gtk" version="4.0"/>
<template class="PlaylistDialog" parent="AdwDialog">
<property name="width_request">400</property>
<property name="height_request">500</property>
<property name="focusable">False</property>
<property name="child">
<object class="AdwToolbarView" id="_toolbar_view">
<child type="top">
<object class="AdwHeaderBar" id="_title_bar">
<property name="focusable">False</property>
<property name="show_end_title_buttons">False</property>
<property name="title-widget">
<object class="GtkLabel">
<property name="label" translatable="yes">Add to Playlist</property>
<property name="single-line-mode">True</property>
<property name="ellipsize">end</property>
<property name="width-chars">5</property>
<style>
<class name="title"/>
</style>
</object>
</property>
<child>
<object class="GtkButton" id="_cancel_button">
<property name="label" translatable="yes">_Cancel</property>
<property name="use_underline">True</property>
<property name="focusable">False</property>
<property name="receives_default">False</property>
<signal name="clicked" handler="_on_cancel_button_clicked"/>
</object>
</child>
<child type="end">
<object class="GtkButton" id="_select_button">
<property name="label" translatable="yes">_Add</property>
<property name="sensitive">False</property>
<property name="use_underline">True</property>
<property name="focusable">False</property>
<property name="receives_default">False</property>
<signal name="clicked" handler="_on_selection"/>
<style>
<class name="suggested-action"/>
</style>
</object>
</child>
</object>
</child>
<property name="content">
<object class="GtkBox" id="dialog-vbox">
<property name="focusable">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkStack" id="_add_playlist_stack">
<property name="focusable">False</property>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<property name="transition_duration">250</property>
<child>
<object class="GtkBox" id="_empty_box">
<property name="visible">False</property>
<property name="focusable">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkBox">
<property name="focusable">False</property>
<property name="orientation">vertical</property>
<property name="valign">fill</property>
<property name="vexpand">True</property>
<property name="margin-bottom">18</property>
<property name="margin-end">18</property>
<property name="margin-start">18</property>
<property name="margin-top">18</property>
<child>
<object class="GtkImage" id="image">
<property name="focusable">False</property>
<property name="valign">center</property>
<property name="pixel_size">100</property>
<property name="icon_name">emblem-music-symbolic</property>
<property name="icon_size">0</property>
<property name="margin-bottom">16</property>
<property name="vexpand">True</property>
<style>
<class name="grey-image"/>
</style>
</object>
</child>
<child>
<object class="GtkLabel" id="label">
<property name="focusable">False</property>
<property name="label" translatable="yes">Enter a name for your first playlist</property>
<property name="valign">end</property>
</object>
</child>
<child>
<object class="GtkEntry" id="_first_playlist_entry">
<property name="width_request">300</property>
<property name="height_request">10</property>
<property name="focusable">True</property>
<property name="halign">center</property>
<property name="margin-bottom">16</property>
<property name="margin-end">18</property>
<property name="margin-start">18</property>
<property name="margin-top">18</property>
<signal name="activate" handler="_on_editing_done"/>
<signal name="changed" handler="_on_add_playlist_entry_changed"/>
<child>
<object class="GtkEventControllerFocus">
<signal name="enter" handler="_on_add_playlist_entry_focused"/>
</object>
</child>
</object>
</child>
<child>
<object class="GtkButton" id="_first_playlist_button">
<property name="label" translatable="yes">C_reate</property>
<property name="use_underline">True</property>
<property name="width_request">120</property>
<property name="height_request">25</property>
<property name="sensitive">False</property>
<property name="focusable">True</property>
<property name="receives_default">True</property>
<property name="halign">center</property>
<property name="valign">center</property>
<property name="margin-bottom">20</property>
<property name="margin-end">18</property>
<property name="margin-start">18</property>
<property name="margin-top">10</property>
<signal name="clicked" handler="_on_editing_done"/>
</object>
</child>
</object>
</child>
<child>
<object class="GtkBox">
<property name="focusable">False</property>
</object>
</child>
</object>
</child>
<child>
<object class="GtkBox" id="_normal_box">
<property name="visible">False</property>
<property name="focusable">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkScrolledWindow" id="scrolledwindow">
<property name="focusable">True</property>
<property name="vexpand">True</property>
<child>
<object class="GtkListBox" id="_listbox">
<property name="focusable">True</property>
<property name="selection_mode">single</property>
<property name="valign">start</property>
<signal name="selected-rows-changed" handler="_on_selected_rows_changed"/>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</property>
<child type="bottom">
<object class="GtkBox" id="_bottom_bar">
<property name="focusable">False</property>
<property name="margin-bottom">6</property>
<property name="margin-end">6</property>
<property name="margin-start">6</property>
<property name="margin-top">6</property>
<child>
<object class="GtkEntry" id="_new_playlist_entry">
<property name="focusable">True</property>
<property name="hexpand">True</property>
<property name="placeholder_text" translatable="yes">New Playlist…</property>
<signal name="activate" handler="_on_editing_done"/>
<signal name="changed" handler="_on_add_playlist_entry_changed"/>
<child>
<object class="GtkEventControllerFocus">
<signal name="enter" handler="_on_add_playlist_entry_focused"/>
</object>
</child>
</object>
</child>
<child>
<object class="GtkButton" id="_new_playlist_button">
<property name="label" translatable="yes">Add</property>
<property name="sensitive">False</property>
<property name="focusable">True</property>
<property name="receives_default">False</property>
<signal name="clicked" handler="_on_editing_done"/>
<style>
<class name="suggested-action"/>
</style>
</object>
</child>
<style>
<class name="linked"/>
</style>
</object>
</child>
</object>
</property>
<style>
<class name="view"/>
</style>
</template>
</interface>
================================================
FILE: data/ui/PlaylistDialogRow.ui
================================================
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="PlaylistDialogRow" parent="GtkListBoxRow">
<style>
<class name="playlistdialog-row"/>
</style>
<child>
<object class="GtkBox" id="hbox">
<child>
<object class="GtkLabel" id="_label">
<property name="ellipsize">end</property>
<property name="margin-bottom">8</property>
<property name="margin-end">8</property>
<property name="margin-start">8</property>
<property name="margin-top">8</property>
<property name="xalign">0.0</property>
</object>
</child>
<child>
<object class="GtkImage" id="_selection_icon">
<property name="icon-name">selection-mode-symbolic</property>
<property name="icon-size">1</property>
</object>
</child>
</object>
</child>
</template>
</interface>
================================================
FILE: data/ui/PlaylistTile.ui
================================================
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="PlaylistTile" parent="GtkListBoxRow">
<child>
<object class="GtkBox">
<property name="orientation">horizontal</property>
<child>
<object class="GtkImage" id="_icon">
<property name="focusable">False</property>
<property name="icon-size">normal</property>
<property name="valign">center</property>
<style>
<class name="playlist-icon"/>
</style>
</object>
</child>
<child>
<object class="GtkLabel" id="_label">
<property name="focusable">False</property>
<property name="ellipsize">end</property>
<property name="halign">start</property>
<property name="hexpand">False</property>
<property name="margin-bottom">16</property>
<property name="margin-end">10</property>
<property name="margin-start">10</property>
<property name="margin-top">16</property>
</object>
</child>
</object>
</child>
</template>
</interface>
================================================
FILE: data/ui/PlaylistsView.ui
================================================
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<requires lib="gtk" version="4.0"/>
<template class="PlaylistsView" parent="AdwBin">
<child>
<object class="AdwOverlaySplitView" id="_split_view">
<property name="sidebar">
<object class="GtkScrolledWindow">
<property name="width-request">220</property>
<child>
<object class="GtkListBox" id="_sidebar">
<property name="selection-mode">1</property>
<signal name="row-activated" handler="_on_playlist_activated"/>
<style>
<class name="navigation-sidebar"/>
</style>
</object>
</child>
</object>
</property>
<property name="content">
<object class="AdwBin" id="_playlist_page">
</object>
</property>
</object>
</child>
</template>
</interface>
================================================
FILE: data/ui/PlaylistsWidget.ui
================================================
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="PlaylistsWidget" parent="GtkBox">
<property name="orientation">vertical</property>
<child>
<object class="AdwClamp">
<property name="maximum-size">1000</property>
<child>
<object class="PlaylistControls" id="_pl_ctrls">
</object>
</child>
</object>
</child>
<child>
<object class="GtkScrolledWindow" id="playlist-container">
<property name="vexpand">True</property>
<child>
<object class="AdwClamp">
<property name="maximum-size">1000</property>
<property name="valign">start</property>
<child>
<object class="GtkListBox" id="_songs_list">
<property name="margin-bottom">20</property>
<property name="margin-top">20</property>
<signal name="row-activated" handler="_on_song_activated"/>
<style>
<class name="boxed-list"/>
</style>
</object>
</child>
</object>
</child>
</object>
</child>
</template>
</interface>
================================================
FILE: data/ui/PreferencesDialog.ui
================================================
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="PreferencesDialog" parent="AdwPreferencesDialog">
<property name="title" translatable="true">Preferences</property>
<child>
<object class="AdwPreferencesPage">
<child>
<object class="AdwPreferencesGroup">
<property name="title" translatable="true">Player Settings</property>
<child>
<object class="AdwComboRow" id="_repeatmode_row">
<property name="title" translatable="true">Repeat Mode</property>
<property name="model">
<object class="GtkStringList">
<items>
<item translatable="true">None</item>
<item translatable="true">Song</item>
<item translatable="true">All</item>
<item translatable="true">Shuffle</item>
</items>
</object>
</property>
</object>
</child>
<child>
<object class="AdwComboRow" id="_replay_gain_row">
<property name="title" translatable="true">ReplayGain</property>
<property name="subtitle" translatable="true">Balance loudness between songs if ReplayGain metadata is found</property>
<property name="model">
<object class="GtkStringList">
<items>
<item translatable="true">Disabled</item>
<item translatable="true">Album</item>
<item translatable="true">Track</item>
</items>
</object>
</property>
</object>
</child>
</object>
</child>
<child>
<object class="AdwPreferencesGroup">
<property name="title" translatable="true">Power Settings</property>
<child>
<object class="AdwSwitchRow" id="_inhibit_suspend_row">
<property name="title" translatable="true">Inhibit Suspend</property>
<property name="subtitle" translatable="true">Only while playing</property>
</object>
</child>
</object>
</child>
</object>
</child>
</template>
</interface>
================================================
FILE: data/ui/RepeatModeButton.ui
================================================
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="RepeatModeButton" parent="GtkBox">
<child>
<object class="GtkMenuButton" id="_menu_button">
<property name="direction">up</property>
<property name="focusable">True</property>
<property name="receives_default">True</property>
<property name="icon_name">media-playlist-consecutive-symbolic</property>
<style>
<class name="circular"/>
</style>
<accessibility>
<property name="label" translatable="yes">Set Repeat Mode</property>
</accessibility>
</object>
</child>
</template>
</interface>
================================================
FILE: data/ui/SearchHeaderBar.ui
================================================
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="SearchHeaderBar" parent="AdwBin">
<child>
<object class="AdwHeaderBar" id="_search_header_bar">
<property name="vexpand">False</property>
<child type="start">
<object class="GtkToggleButton" id="_search_button">
<property name="valign">center</property>
<property name="sensitive">True</property>
<property name="icon-name">edit-find-symbolic</property>
<property name="tooltip_text" translatable="yes">Search</property>
</object>
</child>
</object>
</child>
</template>
</interface>
================================================
FILE: data/ui/SearchView.ui
================================================
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="SearchView" parent="AdwNavigationPage">
<property name="title">Search view</property>
<property name="tag">searchview</property>
<property name="child">
<object class="AdwToolbarView" id="_search_toolbar_view">
<property name="top-bar-style">raised</property>
<property name="content">
<object class="GtkStack" id="_stack">
<child>
<object class="GtkStackPage">
<property name="name">main</property>
<property name="child">
<object class="GtkScrolledWindow" id="_search_results">
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<child>
<object class="AdwClamp">
<property name="maximum-size">1600</property>
<child>
<object class="GtkBox" id="container">
<property name="halign">fill</property>
<property name="hexpand">True</property>
<property name="margin-bottom">20</property>
<property name="margin-end">120</property>
<property name="margin-start">120</property>
<property name="margin-top">20</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkBox" id="_artist_header">
<property name="halign">fill</property>
<property name="hexpand">True</property>
<property name="homogeneous">True</property>
<property name="orientation">horizontal</property>
<property name="visible">False</property>
<child>
<object class="GtkLabel">
<property name="focusable">False</property>
<property name="halign">start</property>
<property name="label" translatable="yes">Artists</property>
<style>
<class name="search-header"/>
</style>
</object>
</child>
<child>
<object class="GtkButton" id="_view_all_artists">
<property name="halign">end</property>
<child>
<object class="GtkBox">
<property name="spacing">6</property>
<child>
<object class="GtkLabel">
<property name="label" translatable="yes">View All</property>
</object>
</child>
<child>
<object class="GtkImage">
<property name="icon-name">go-next-symbolic</property>
</object>
</child>
</object>
</child>
<signal name="clicked" handler="_on_all_artists_clicked"/>
</object>
</child>
</object>
</child>
<child>
<object class="GtkFlowBox" id="_artist_flowbox">
<property name="column_spacing">6</property>
<property name="halign">fill</property>
<property name="hexpand">True</property>
<property name="homogeneous">True</property>
<property name="margin-bottom">18</property>
<property name="margin-top">18</property>
<property name="max-children-per-line">6</property>
<property name="min-children-per-line">1</property>
<property name="row_spacing">12</property>
<property name="selection-mode">none</property>
<property name="valign">start</property>
<property name="visible">False</property>
<signal name="child-activated" handler="_on_artist_activated"/>
</object>
</child>
<child>
<object class="GtkBox" id="_album_header">
<property name="halign">fill</property>
<property name="hexpand">True</property>
<property name="homogeneous">True</property>
<property name="orientation">horizontal</property>
<property name="visible">False</property>
<child>
<object class="GtkLabel">
<property name="focusable">False</property>
<property name="halign">start</property>
<property name="label" translatable="yes">Albums</property>
<style>
<class name="search-header"/>
</style>
</object>
</child>
<child>
<object class="GtkButton" id="_view_all_albums">
<property name="halign">end</property>
<child>
<object class="GtkBox">
<property name="spacing">6</property>
<child>
<object class="GtkLabel">
<property name="label" translatable="yes">View All</property>
</object>
</child>
<child>
<object class="GtkImage">
<property name="icon-name">go-next-symbolic</property>
</object>
</child>
</object>
</child>
<signal name="clicked" handler="_on_all_albums_clicked"/>
</object>
</child>
</object>
</child>
<child>
<object class="GtkFlowBox" id="_album_flowbox">
<property name="halign">fill</property>
<property name="hexpand">True</property>
<property name="valign">start</property>
<property name="visible">False</property>
<property name="homogeneous">True</property>
<property name="min_children_per_line">1</property>
<property name="max_children_per_line">6</property>
<property name="margin-bottom">18</property>
<property name="margin-top">18</property>
<property name="row_spacing">12</property>
<property name="column_spacing">6</property>
<property name="selection_mode">none</property>
<signal name="child-activated" handler="_on_album_activated"/>
</object>
</child>
<child>
<object class="GtkBox" id="_songs_header">
<property name="halign">fill</property>
<property name="hexpand">True</property>
<property name="homogeneous">True</property>
<property name="orientation">horizontal</property>
<child>
<object class="GtkLabel">
<property name="focusable">False</property>
<property name="halign">start</property>
<property name="label" translatable="yes">Songs</property>
<style>
<class name="search-header"/>
</style>
</object>
</child>
</object>
</child>
<child>
<object class="GtkListBox" id="_songs_listbox">
<property name="margin-top">20</property>
<signal name="row-activated" handler="_song_activated"/>
<style>
<class name="boxed-list"/>
</style>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</property>
</object>
</child>
<child>
<object class="GtkStackPage">
<property name="name">status</property>
<property name="child">
<object class="AdwStatusPage" id="_status_page"/>
</property>
</object>
</child>
</object>
</property>
</object>
</property>
<style>
<class name="view"/>
</style>
</template>
</interface>
================================================
FILE: data/ui/SongWidget.ui
================================================
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<requires lib="gtk" version="4.0"/>
<template class="SongWidget" parent="GtkListBoxRow">
<property name="selectable">False</property>
<child>
<object class="GtkBox" id="box1">
<property name="focusable">False</property>
<property name="spacing">6</property>
<child>
<object class="GtkImage" id="_dnd_icon">
<property name="visible">False</property>
<property name="icon-name">list-drag-handle-symbolic</property>
<style>
<class name="drag-handle"/>
</style>
</object>
</child>
<child>
<object class="GtkBox" id="box3">
<property name="width_request">48</property>
<property name="focusable">False</property>
<property name="homogeneous">True</property>
<child>
<object class="GtkImage" id="_play_icon">
<property name="focusable">False</property>
<property name="icon_size">1</property>
</object>
</child>
<child>
<object class="GtkLabel" id="_number_label">
<property name="focusable">False</property>
<property name="halign">end</property>
<property name="justify">right</property>
<style>
<class name="dim-label"/>
</style>
</object>
</child>
</object>
</child>
<child>
<object class="GtkBox" id="title_box">
<property name="focusable">False</property>
<property name="hexpand">True</property>
<child>
<object class="GtkLabel" id="_title_label">
<property name="focusable">False</property>
<property name="xalign">0</property>
<property name="halign">start</property>
<property name="hexpand">True</property>
<property name="ellipsize">end</property>
<property name="max_width_chars">90</property>
<property name="justify">fill</property>
<property name="margin-start">9</property>
</object>
</child>
</object>
</child>
<child>
<object class="GtkBox" id="_artist_box">
<property name="visible">False</property>
<property name="focusable">False</property>
<property name="hexpand">True</property>
<child>
<object class="GtkLabel" id="_artist_label">
<property name="focusable">False</property>
<property name="xalign">0</property>
<property name="halign">start</property>
<property name="hexpand">True</property>
<property name="ellipsize">end</property>
<property name="max_width_chars">90</property>
<property name="justify">fill</property>
<property name="margin-start">9</property>
</object>
</child>
</object>
</child>
<child>
<object class="GtkBox" id="_album_duration_box">
<property name="focusable">False</property>
<property name="hexpand">True</property>
<property name="spacing">6</property>
<child>
<object class="GtkLabel" id="_album_label">
<property name="visible">False</property>
<property name="focusable">False</property>
<property name="xalign">0</property>
<property name="halign">start</property>
<property name="hexpand">True</property>
<property name="ellipsize">end</property>
<property name="max_width_chars">90</property>
<property name="justify">fill</property>
</object>
</child>
<child>
<object class="GtkLabel" id="_duration_label">
<property name="focusable">False</property>
<property name="halign">end</property>
<property name="hexpand">True</property>
<property name="single_line_mode">True</property>
<style>
<class name="bold-label"/>
</style>
</object>
</child>
</object>
</child>
<child>
<object class="StarToggle" id="_star_toggle">
<property name="valign">center</property>
<property name="margin-end">12</property>
<property name="margin-start">12</property>
</object>
</child>
<child>
<object class="GtkMenuButton" id="_menu_button">
<property name="visible">False</property>
<property name="focusable">True</property>
<property name="icon-name">view-more-symbolic</property>
<style>
<class name="flat"/>
</style>
</object>
</child>
</object>
</child>
<child>
<object class="GtkDragSource" id="_drag_source">
<property name="actions">move</property>
<property name="propagation-phase">none</property>
<signal name="prepare" handler="_on_drag_prepare"/>
<signal name="drag-begin" handler="_on_drag_begin"/>
</object>
</child>
<child>
<object class="GtkDropTarget">
<property name="actions">move</property>
<property name="formats">SongWidget</property>
<property name="preload">True</property>
gitextract_kect3s27/
├── .gitlab/
│ └── issue_templates/
│ └── default.md
├── .gitlab-ci.yml
├── .gitmodules
├── CONTRIBUTING.md
├── LICENSE
├── NEWS
├── README.md
├── data/
│ ├── meson.build
│ ├── org.gnome.Music.desktop.in.in
│ ├── org.gnome.Music.gresource.xml
│ ├── org.gnome.Music.gschema.xml
│ ├── org.gnome.Music.metainfo.xml.in.in
│ ├── org.gnome.Music.service.in
│ ├── queries/
│ │ ├── album_disc.rq
│ │ ├── album_discs.rq
│ │ ├── albums.rq
│ │ ├── artist_albums.rq
│ │ ├── artists.rq
│ │ ├── playlist_add_song.rq
│ │ ├── playlist_create.rq
│ │ ├── playlist_delete.rq
│ │ ├── playlist_delete_song.rq
│ │ ├── playlist_query_all.rq
│ │ ├── playlist_query_delete_entry.rq
│ │ ├── playlist_query_playlist.rq
│ │ ├── playlist_query_songs.rq
│ │ ├── playlist_rename_title.rq
│ │ ├── playlist_reorder_songs.rq
│ │ ├── search_albums.rq
│ │ ├── search_artists.rq
│ │ ├── search_songs.rq
│ │ └── songs.rq
│ ├── style.css
│ └── ui/
│ ├── AlbumCover.ui
│ ├── AlbumNavigationPage.ui
│ ├── AlbumTile.ui
│ ├── AlbumWidget.ui
│ ├── AlbumsSearchNavigationPage.ui
│ ├── AlbumsView.ui
│ ├── ArtistAlbumsWidget.ui
│ ├── ArtistNavigationPage.ui
│ ├── ArtistSearchTile.ui
│ ├── ArtistTile.ui
│ ├── ArtistsSearchNavigationPage.ui
│ ├── ArtistsView.ui
│ ├── DiscBox.ui
│ ├── DiscListItem.ui
│ ├── HeaderBar.ui
│ ├── PlayerToolbar.ui
│ ├── PlaylistControls.ui
│ ├── PlaylistDialog.ui
│ ├── PlaylistDialogRow.ui
│ ├── PlaylistTile.ui
│ ├── PlaylistsView.ui
│ ├── PlaylistsWidget.ui
│ ├── PreferencesDialog.ui
│ ├── RepeatModeButton.ui
│ ├── SearchHeaderBar.ui
│ ├── SearchView.ui
│ ├── SongWidget.ui
│ ├── SongWidgetMenu.ui
│ ├── StatusNavigationPage.ui
│ ├── TwoLineTip.ui
│ ├── VolumeButton.ui
│ ├── Window.ui
│ └── shortcuts-dialog.ui
├── gnome-music.doap
├── gnome-music.in
├── gnomemusic/
│ ├── __init__.py
│ ├── about.py
│ ├── albumart.py
│ ├── application.py
│ ├── artistart.py
│ ├── asynciolimiter.py
│ ├── corealbum.py
│ ├── coreartist.py
│ ├── coredisc.py
│ ├── coregrilo.py
│ ├── coremodel.py
│ ├── coresong.py
│ ├── coverpaintable.py
│ ├── embeddedart.py
│ ├── grilowrappers/
│ │ ├── __init__.py
│ │ ├── localsearchplaylists.py
│ │ ├── localsearchwrapper.py
│ │ ├── playlist.py
│ │ └── smartplaylist.py
│ ├── gstplayer.py
│ ├── inhibitsuspend.py
│ ├── mediaartloader.py
│ ├── mpris.py
│ ├── musiclogger.py
│ ├── notificationmanager.py
│ ├── pauseonsuspend.py
│ ├── player.py
│ ├── playlisttoast.py
│ ├── queue.py
│ ├── search.py
│ ├── shufflelistmodel.py
│ ├── songart.py
│ ├── songtoast.py
│ ├── storeart.py
│ ├── texturecache.py
│ ├── trackerwrapper.py
│ ├── utils.py
│ ├── views/
│ │ ├── __init__.py
│ │ ├── albumsview.py
│ │ ├── artistsview.py
│ │ ├── playlistsview.py
│ │ └── searchview.py
│ ├── widgets/
│ │ ├── __init__.py
│ │ ├── albumcover.py
│ │ ├── albumnavigationpage.py
│ │ ├── albumssearchnavigationpage.py
│ │ ├── albumtile.py
│ │ ├── albumwidget.py
│ │ ├── artistalbumswidget.py
│ │ ├── artistnavigationpage.py
│ │ ├── artistsearchtile.py
│ │ ├── artistssearchnavigationpage.py
│ │ ├── artisttile.py
│ │ ├── discbox.py
│ │ ├── headerbar.py
│ │ ├── playertoolbar.py
│ │ ├── playlistcontrols.py
│ │ ├── playlistdialog.py
│ │ ├── playlistdialogrow.py
│ │ ├── playlistswidget.py
│ │ ├── playlisttile.py
│ │ ├── preferencesdialog.py
│ │ ├── repeatmodebutton.py
│ │ ├── searchheaderbar.py
│ │ ├── smoothscale.py
│ │ ├── songwidget.py
│ │ ├── songwidgetmenu.py
│ │ ├── startoggle.py
│ │ ├── statusnavigationpage.py
│ │ ├── twolinetip.py
│ │ └── volumebutton.py
│ ├── window.py
│ └── windowplacement.py
├── help/
│ ├── LINGUAS
│ ├── bg/
│ │ └── bg.po
│ ├── ca/
│ │ └── ca.po
│ ├── cs/
│ │ └── cs.po
│ ├── da/
│ │ └── da.po
│ ├── de/
│ │ └── de.po
│ ├── el/
│ │ └── el.po
│ ├── es/
│ │ └── es.po
│ ├── eu/
│ │ └── eu.po
│ ├── fr/
│ │ └── fr.po
│ ├── gl/
│ │ └── gl.po
│ ├── hr/
│ │ └── hr.po
│ ├── hu/
│ │ └── hu.po
│ ├── id/
│ │ └── id.po
│ ├── it/
│ │ └── it.po
│ ├── kk/
│ │ └── kk.po
│ ├── ko/
│ │ └── ko.po
│ ├── meson.build
│ ├── nl/
│ │ └── nl.po
│ ├── pl/
│ │ └── pl.po
│ ├── pt_BR/
│ │ └── pt_BR.po
│ ├── ro/
│ │ └── ro.po
│ ├── ru/
│ │ └── ru.po
│ ├── sr/
│ │ └── sr.po
│ ├── sv/
│ │ └── sv.po
│ ├── tr/
│ │ └── tr.po
│ ├── uk/
│ │ └── uk.po
│ └── zh_CN/
│ └── zh_CN.po
├── meson.build
├── meson_options.txt
├── org.gnome.Music.json
└── po/
├── LINGUAS
├── POTFILES.in
├── POTFILES.skip
├── ab.po
├── af.po
├── an.po
├── ar.po
├── as.po
├── be.po
├── bg.po
├── bs.po
├── ca.po
├── ca@valencia.po
├── cs.po
├── da.po
├── de.po
├── el.po
├── en_GB.po
├── eo.po
├── es.po
├── et.po
├── eu.po
├── fa.po
├── fi.po
├── fr.po
├── fur.po
├── fy.po
├── ga.po
├── gd.po
├── gl.po
├── he.po
├── hi.po
├── hr.po
├── hu.po
├── ia.po
├── id.po
├── is.po
├── it.po
├── ja.po
├── ka.po
├── kab.po
├── kk.po
├── kn.po
├── ko.po
├── kw.po
├── lt.po
├── lv.po
├── meson.build
├── mjw.po
├── ml.po
├── ms.po
├── nb.po
├── ne.po
├── nl.po
├── oc.po
├── pa.po
├── pl.po
├── pt.po
├── pt_BR.po
├── ro.po
├── ru.po
├── sk.po
├── sl.po
├── sr.po
├── sr@latin.po
├── sv.po
├── ta.po
├── te.po
├── tg.po
├── th.po
├── tr.po
├── ug.po
├── uk.po
├── uz.po
├── vi.po
├── zh_CN.po
├── zh_HK.po
└── zh_TW.po
SYMBOL INDEX (739 symbols across 69 files)
FILE: gnomemusic/about.py
function show_about (line 25) | def show_about(app_id, version, parent):
FILE: gnomemusic/albumart.py
class AlbumArt (line 35) | class AlbumArt(GObject.GObject):
method __init__ (line 41) | def __init__(self, application, corealbum):
method _on_embedded_art_found (line 56) | def _on_embedded_art_found(self, embeddedart, found):
method _in_cache (line 62) | async def _in_cache(self) -> None:
FILE: gnomemusic/application.py
class Application (line 34) | class Application(Adw.Application):
method __init__ (line 36) | def __init__(self, application_id, version):
method coregrilo (line 64) | def coregrilo(self):
method log (line 74) | def log(self):
method player (line 84) | def player(self):
method settings (line 94) | def settings(self):
method coremodel (line 104) | def coremodel(self):
method window (line 113) | def window(self):
method search (line 123) | def search(self):
method notificationmanager (line 133) | def notificationmanager(self):
method _set_actions (line 141) | def _set_actions(self) -> None:
method _about (line 176) | def _about(
method _help (line 181) | def _help(
method _mute (line 195) | def _mute(
method _play_pause (line 200) | def _play_pause(
method _preferences_dialog (line 205) | def _preferences_dialog(
method _quit (line 214) | def _quit(
method _repeat_toggle (line 219) | def _repeat_toggle(
method _shuffle_toggle (line 229) | def _shuffle_toggle(
method _song_next (line 237) | def _song_next(
method _song_previous (line 242) | def _song_previous(
method _song_stop (line 247) | def _song_stop(
method _volume_decrease (line 252) | def _volume_decrease(
method _volume_increase (line 266) | def _volume_increase(
method do_startup (line 284) | def do_startup(self):
method do_activate (line 290) | def do_activate(self):
FILE: gnomemusic/artistart.py
class ArtistArt (line 34) | class ArtistArt(GObject.GObject):
method __init__ (line 40) | def __init__(self, application, coreartist):
method _in_cache (line 54) | async def _in_cache(self) -> None:
FILE: gnomemusic/asynciolimiter.py
function _pop_pending (line 52) | def _pop_pending(
class _BaseLimiter (line 71) | class _BaseLimiter(_ABC):
method wait (line 74) | async def wait(self) -> None: # pragma: no cover # ABC
method cancel (line 83) | def cancel(self) -> None: # pragma: no cover # ABC
method breach (line 92) | def breach(self) -> None: # pragma: no cover # ABC
method reset (line 101) | def reset(self) -> None: # pragma: no cover # ABC
method wrap (line 111) | def wrap(self, coro: _Awaitable[_T]) -> _Awaitable[_T]:
class _CommonLimiterMixin (line 150) | class _CommonLimiterMixin(_BaseLimiter):
method __init__ (line 160) | def __init__(self, *args, **kwargs) -> None: # type: ignore
method wait (line 171) | async def wait(self) -> None:
method cancel (line 182) | def cancel(self) -> None:
method breach (line 186) | def breach(self) -> None:
method _cancel_wakeup (line 195) | def _cancel_wakeup(self) -> None:
method reset (line 200) | def reset(self) -> None:
method _maybe_lock (line 208) | def _maybe_lock(self) -> None: # pragma: no cover # ABC
method __del__ (line 216) | def __del__(self):
method close (line 238) | def close(self) -> None:
class Limiter (line 247) | class Limiter(_CommonLimiterMixin):
method __init__ (line 276) | def __init__(self, rate: float, *, max_burst: int = 5) -> None:
method __repr__ (line 289) | def __repr__(self):
method rate (line 294) | def rate(self) -> float:
method rate (line 299) | def rate(self, value: float) -> None:
method _maybe_lock (line 308) | def _maybe_lock(self):
method _schedule_wakeup (line 313) | def _schedule_wakeup(self, at: _Optional[float] = None, # type: ignore
method _wakeup (line 331) | def _wakeup(self) -> None:
class LeakyBucketLimiter (line 392) | class LeakyBucketLimiter(_CommonLimiterMixin):
method __init__ (line 431) | def __init__(self, rate: float, *, capacity: int = 10) -> None:
method __repr__ (line 446) | def __repr__(self):
method rate (line 452) | def rate(self) -> float:
method rate (line 459) | def rate(self, value: float) -> None:
method _maybe_lock (line 468) | def _maybe_lock(self):
method _schedule_wakeup (line 480) | def _schedule_wakeup(self, at: _Optional[float] = None, # type: ignore
method reset (line 496) | def reset(self) -> None:
method _wakeup (line 507) | def _wakeup(self) -> None:
class StrictLimiter (line 555) | class StrictLimiter(_CommonLimiterMixin):
method __init__ (line 569) | def __init__(self, rate: float) -> None:
method __repr__ (line 579) | def __repr__(self):
method _maybe_lock (line 583) | def _maybe_lock(self):
method _schedule_wakeup (line 588) | def _schedule_wakeup(self):
method _wakeup (line 594) | def _wakeup(self):
FILE: gnomemusic/corealbum.py
class CoreAlbum (line 18) | class CoreAlbum(GObject.GObject):
method __init__ (line 34) | def __init__(
method update (line 51) | def update(self, cursor_dict):
method remove_song_from_album (line 63) | def remove_song_from_album(self, disc_nr: int, song_id: str) -> None:
method _get_album_model (line 74) | def _get_album_model(self):
method model (line 87) | def model(self):
method _on_list_items_changed (line 95) | def _on_list_items_changed(self, model, position, removed, added):
method _on_duration_changed (line 103) | def _on_duration_changed(self, coredisc, duration):
method thumbnail (line 112) | def thumbnail(self):
method thumbnail (line 125) | def thumbnail(self, value):
method corealbum (line 133) | def corealbum(self) -> CoreAlbum:
FILE: gnomemusic/coreartist.py
class CoreArtist (line 18) | class CoreArtist(GObject.GObject):
method __init__ (line 27) | def __init__(
method update (line 45) | def update(self, cursor_dict: Dict[str, Any]) -> None:
method _get_artist_album_model (line 49) | def _get_artist_album_model(self):
method model (line 64) | def model(self):
method thumbnail (line 71) | def thumbnail(self):
method thumbnail (line 84) | def thumbnail(self, value):
FILE: gnomemusic/coredisc.py
class CoreDisc (line 16) | class CoreDisc(GObject.GObject):
method __init__ (line 24) | def __init__(
method update (line 43) | def update(self, corealbum: CoreAlbum) -> None:
method model (line 47) | def model(self) -> Gtk.SortListModel:
method _on_disc_changed (line 64) | def _on_disc_changed(self, model, position, removed, added):
method remove_song_from_disc (line 72) | def remove_song_from_disc(self, song_urn: str) -> None:
FILE: gnomemusic/coregrilo.py
class CoreGrilo (line 45) | class CoreGrilo(GObject.GObject):
method __init__ (line 70) | def __init__(self, application):
method _on_tracker_available_changed (line 129) | def _on_tracker_available_changed(
method _on_source_added (line 138) | def _on_source_added(self, registry, source):
method _on_source_removed (line 164) | def _on_source_removed(self, registry, source):
method get_artist_albums (line 168) | def get_artist_albums(
method get_album_discs (line 179) | def get_album_discs(
method get_album_disc (line 189) | def get_album_disc(
method writeback_tracker (line 199) | def writeback_tracker(self, coresong: CoreSong, tag: str) -> None:
method search (line 210) | def search(self, text: str) -> None:
method get_song_art (line 221) | def get_song_art(self, coresong: CoreSong) -> None:
method get_album_art (line 248) | def get_album_art(self, corealbum: CoreAlbum) -> None:
method get_artist_art (line 276) | def get_artist_art(self, coreartist: CoreArtist) -> None:
method stage_playlist_deletion (line 301) | def stage_playlist_deletion(self, playlist):
method finish_playlist_deletion (line 310) | def finish_playlist_deletion(self, playlist, deleted):
method create_playlist (line 320) | def create_playlist(self, playlist_title, callback):
FILE: gnomemusic/coremodel.py
class CoreModel (line 44) | class CoreModel(GObject.GObject):
method __init__ (line 78) | def __init__(self, application: Application) -> None:
method _on_songs_items_changed (line 173) | def _on_songs_items_changed(self, model, position, removed, added):
method _songs_sort (line 185) | def _songs_sort(
method _playlists_sort (line 203) | def _playlists_sort(self, playlist_a, playlist_b, data=None):
method _set_player_model (line 222) | def _set_player_model(self, queue_type, model):
method active_core_object (line 336) | def active_core_object(self):
method active_core_object (line 346) | def active_core_object(self, value):
method songs (line 376) | def songs(self):
method songs_proxy (line 382) | def songs_proxy(self):
method albums (line 387) | def albums(self):
method albums_proxy (line 393) | def albums_proxy(self):
method artists (line 398) | def artists(self):
method artists_proxy (line 404) | def artists_proxy(self):
method albums_sort (line 410) | def albums_sort(self):
method artists_sort (line 416) | def artists_sort(self):
method queue (line 422) | def queue(self):
method recent_queue (line 428) | def recent_queue(self):
method recent_queue_size (line 434) | def recent_queue_size(self):
method songs_search (line 440) | def songs_search(self):
method songs_search_proxy (line 446) | def songs_search_proxy(self):
method albums_search (line 452) | def albums_search(self) -> Gtk.FlattenListModel:
method albums_search_filter (line 458) | def albums_search_filter(self):
method albums_search_proxy (line 463) | def albums_search_proxy(self) -> Gio.ListStore:
method artists_search (line 469) | def artists_search(self) -> Gtk.FlattenListModel:
method artists_search_filter (line 475) | def artists_search_filter(self):
method artists_search_proxy (line 480) | def artists_search_proxy(self) -> Gio.ListStore:
method playlists (line 485) | def playlists(self):
method playlists_sort (line 491) | def playlists_sort(self):
method playlists_filter (line 497) | def playlists_filter(self):
method user_playlists_sort (line 503) | def user_playlists_sort(self):
method user_playlists_filter (line 509) | def user_playlists_filter(self):
FILE: gnomemusic/coresong.py
class CoreSong (line 18) | class CoreSong(GObject.GObject):
class Validation (line 26) | class Validation(GObject.GEnum):
method __init__ (line 47) | def __init__(
method __eq__ (line 66) | def __eq__(self, other: object) -> bool:
method favorite (line 71) | def favorite(self) -> bool:
method favorite (line 75) | def favorite(self, favorite: bool) -> None:
method last_played (line 83) | def last_played(self) -> Optional[GLib.DateTime]:
method last_played (line 92) | def last_played(self, value: Optional[GLib.DateTime]) -> None:
method thumbnail (line 104) | def thumbnail(self) -> str:
method thumbnail (line 117) | def thumbnail(self, value: str) -> None:
method update (line 124) | def update(self, cursor_dict: Dict[str, Any]) -> None:
method bump_play_count (line 147) | def bump_play_count(self) -> None:
FILE: gnomemusic/coverpaintable.py
class CoverPaintable (line 44) | class CoverPaintable(GObject.GObject, Gdk.Paintable):
method __init__ (line 53) | def __init__(
method do_snapshot (line 77) | def do_snapshot(self, snapshot: Gtk.Snapshot, w: float, h: float) -> N...
method _snapshot_texture (line 83) | def _snapshot_texture(
method _snapshot_fallback_icon (line 112) | def _snapshot_fallback_icon(
method _radius (line 139) | def _radius(self) -> float:
method _on_dark_changed (line 147) | def _on_dark_changed(
method coreobject (line 156) | def coreobject(self) -> Optional[CoreObject]:
method coreobject (line 165) | def coreobject(self, coreobject: CoreObject) -> None:
method _on_thumbnail_changed (line 191) | def _on_thumbnail_changed(
method _on_texture_cache (line 204) | def _on_texture_cache(
method icon_type (line 213) | def icon_type(self) -> DefaultIconType:
method icon_type (line 222) | def icon_type(self, value: DefaultIconType) -> None:
method do_get_flags (line 232) | def do_get_flags(self) -> Gdk.PaintableFlags:
method do_get_intrinsic_height (line 235) | def do_get_intrinsic_height(self) -> int:
method do_get_intrinsic_width (line 238) | def do_get_intrinsic_width(self) -> int:
FILE: gnomemusic/embeddedart.py
class EmbeddedArt (line 35) | class EmbeddedArt(GObject.GObject):
method __init__ (line 48) | def __init__(self):
method query (line 68) | def query(self, coreobject, title):
method _discovered (line 114) | def _discovered(self, discoverer, info, error):
method _save_pixbuf (line 156) | async def _save_pixbuf(self, data: bytes) -> None:
method _lookup_cover_in_directory (line 200) | async def _lookup_cover_in_directory(self) -> None:
FILE: gnomemusic/grilowrappers/localsearchplaylists.py
class LocalSearchPlaylists (line 23) | class LocalSearchPlaylists(GObject.GObject):
method __init__ (line 27) | def __init__(
method _initial_playlists_fill (line 67) | async def _initial_playlists_fill(self):
method _add_user_playlist (line 115) | def _add_user_playlist(
method _playlists_filter (line 127) | def _playlists_filter(self, playlist):
method _user_playlists_filter (line 130) | def _user_playlists_filter(self, playlist):
method stage_playlist_deletion (line 134) | def stage_playlist_deletion(self, playlist):
method finish_playlist_deletion (line 144) | def finish_playlist_deletion(
method _finish_playlist_deletion (line 154) | async def _finish_playlist_deletion(
method create_playlist (line 183) | def create_playlist(self, playlist_title: str, callback: Callable) -> ...
method _create_playlist (line 191) | async def _create_playlist(
method check_smart_playlist_change (line 236) | def check_smart_playlist_change(self):
FILE: gnomemusic/grilowrappers/localsearchwrapper.py
class LocalSearchWrapper (line 28) | class LocalSearchWrapper(GObject.Object):
method __init__ (line 36) | def __init__(
method _prepare_statement (line 129) | def _prepare_statement(self, resource_path: str) -> str:
method _init_albums_model (line 141) | async def _init_albums_model(self) -> None:
method _init_artists_model (line 169) | async def _init_artists_model(self) -> None:
method _init_songs_model (line 197) | async def _init_songs_model(self) -> None:
method _find_equal_coreobject_urn (line 238) | def _find_equal_coreobject_urn(
method _fileid_event (line 243) | async def _fileid_event(self, event: Tsparql.NotifierEvent) -> None:
method _on_notifier_event (line 268) | def _on_notifier_event(
method _update_album (line 276) | async def _update_album(self, coresong: CoreSong) -> None:
method _add_song (line 285) | async def _add_song(self, urn: str) -> None:
method _get_album_discs (line 321) | async def _get_album_discs(
method get_album_discs (line 354) | def get_album_discs(
method _get_album_disc (line 363) | async def _get_album_disc(
method get_album_disc (line 400) | def get_album_disc(
method _get_artist_albums (line 409) | async def _get_artist_albums(
method get_artist_albums (line 445) | def get_artist_albums(
method search (line 454) | def search(self, text: str) -> None:
method _search_generic (line 480) | async def _search_generic(
method stage_playlist_deletion (line 535) | def stage_playlist_deletion(self, playlist: Optional[Playlist]) -> None:
method finish_playlist_deletion (line 545) | def finish_playlist_deletion(
method create_playlist (line 557) | def create_playlist(
FILE: gnomemusic/grilowrappers/playlist.py
class Playlist (line 19) | class Playlist(GObject.GObject):
method __init__ (line 32) | def __init__(
method _prepare_statement (line 82) | def _prepare_statement(self, resource_path: str) -> str:
method model (line 95) | def model(self):
method model (line 103) | def model(self, value):
method _populate_model (line 106) | async def _populate_model(self):
method _bind_to_main_song (line 143) | def _bind_to_main_song(self, coresong):
method title (line 170) | def title(self):
method title (line 179) | def title(self, new_name: str) -> None:
method _set_title (line 186) | async def _set_title(self, new_name: str) -> None:
method stage_song_deletion (line 200) | def stage_song_deletion(self, coresong, index):
method undo_pending_song_deletion (line 210) | def undo_pending_song_deletion(self, coresong, position):
method finish_song_deletion (line 220) | def finish_song_deletion(self, coresong: CoreSong, position: int) -> N...
method _finish_song_deletion (line 229) | async def _finish_song_deletion(
method add_songs (line 273) | def add_songs(self, coresongs: List[CoreSong]) -> None:
method _add_songs (line 280) | async def _add_songs(self, coresongs: List[CoreSong]) -> None:
method reorder (line 300) | def reorder(self, previous_position: int, new_position: int) -> None:
method _reorder (line 308) | async def _reorder(
FILE: gnomemusic/grilowrappers/smartplaylist.py
class SmartPlaylist (line 19) | class SmartPlaylist(Playlist):
method __init__ (line 24) | def __init__(self, **kwargs):
method model (line 31) | def model(self):
method _populate_model (line 38) | async def _populate_model(self) -> None:
method update (line 77) | def update(self):
class MostPlayed (line 88) | class MostPlayed(SmartPlaylist):
method __init__ (line 91) | def __init__(self, **kwargs):
class NeverPlayed (line 140) | class NeverPlayed(SmartPlaylist):
method __init__ (line 143) | def __init__(self, **kwargs):
class RecentlyPlayed (line 191) | class RecentlyPlayed(SmartPlaylist):
method __init__ (line 194) | def __init__(self, **kwargs):
class RecentlyAdded (line 268) | class RecentlyAdded(SmartPlaylist):
method __init__ (line 271) | def __init__(self, **kwargs):
class Favorites (line 329) | class Favorites(SmartPlaylist):
method __init__ (line 332) | def __init__(self, **kwargs):
class InsufficientTagged (line 379) | class InsufficientTagged(SmartPlaylist):
method __init__ (line 382) | def __init__(self, **kwargs):
class AllSongs (line 442) | class AllSongs(SmartPlaylist):
method __init__ (line 445) | def __init__(self, **kwargs):
FILE: gnomemusic/gstplayer.py
class Playback (line 40) | class Playback(IntEnum):
class GstPlayer (line 48) | class GstPlayer(GObject.GObject):
method __init__ (line 65) | def __init__(self, application: Application) -> None:
method _setup_replaygain (line 127) | def _setup_replaygain(self):
method _on_replaygain_setting_changed (line 151) | def _on_replaygain_setting_changed(
method _on_about_to_finish (line 165) | def _on_about_to_finish(self, klass):
method _on_async_done (line 168) | def _on_async_done(self, bus, message):
method _on_duration_changed (line 176) | def _on_duration_changed(self, bus: Gst.Bus, message: Gst.Message) -> ...
method _query_duration (line 179) | def _query_duration(self) -> None:
method _create_clock_tick (line 189) | def _create_clock_tick(self):
method _destroy_clock_tick (line 197) | def _destroy_clock_tick(self) -> None:
method _on_new_clock (line 203) | def _on_new_clock(self, bus, message):
method _on_clock_tick (line 208) | def _on_clock_tick(self, clock, time, id, data):
method _on_bus_element (line 212) | def _on_bus_element(self, bus, message):
method _on_bus_buffering (line 216) | def _on_bus_buffering(self, bus: Gst.Bus, message: Gst.Message) -> None:
method _on_bus_stream_start (line 227) | def _on_bus_stream_start(self, bus, message):
method _on_state_changed (line 232) | def _on_state_changed(self, bus, message):
method _on_bus_error (line 253) | def _on_bus_error(self, bus, message):
method _on_bus_eos (line 272) | def _on_bus_eos(self, bus, message):
method state (line 278) | def state(self):
method state (line 287) | def state(self, state):
method url (line 307) | def url(self):
method url (line 316) | def url(self, url_):
method position (line 324) | def position(self):
method duration (line 338) | def duration(self):
method duration (line 353) | def duration(self, duration):
method seek (line 362) | def seek(self, seconds):
method _start_plugin_installation (line 371) | def _start_plugin_installation(
method _show_codec_confirmation_dialog (line 395) | def _show_codec_confirmation_dialog(
method _handle_missing_plugins (line 416) | def _handle_missing_plugins(self):
method _is_missing_plugin_message (line 440) | def _is_missing_plugin_message(self, message):
class MissingCodecsDialog (line 449) | class MissingCodecsDialog(Gtk.MessageDialog):
method __init__ (line 451) | def __init__(self, parent_window, install_helper_name):
method set_codec_names (line 467) | def set_codec_names(self, codec_names):
FILE: gnomemusic/inhibitsuspend.py
class InhibitSuspend (line 36) | class InhibitSuspend(GObject.GObject):
method __init__ (line 43) | def __init__(self, application):
method _inhibit_suspend (line 62) | def _inhibit_suspend(self):
method _uninhibit_suspend (line 74) | def _uninhibit_suspend(self):
method _on_inhibit_suspend_changed (line 79) | def _on_inhibit_suspend_changed(
method _on_player_state_changed (line 84) | def _on_player_state_changed(self, klass, arguments):
FILE: gnomemusic/mediaartloader.py
class MediaArtLoader (line 34) | class MediaArtLoader(GObject.GObject):
method __init__ (line 50) | def __init__(self) -> None:
method _start (line 58) | async def _start(self, uri: str) -> None:
method start (line 128) | def start(self, uri: str) -> None:
method cancel (line 135) | def cancel(self) -> None:
FILE: gnomemusic/mpris.py
class DBusInterface (line 45) | class DBusInterface:
method __init__ (line 47) | def __init__(self, name, path, application):
method _get_bus (line 61) | async def _get_bus(self, name: str) -> None:
method _on_method_call (line 95) | def _on_method_call(
method _dbus_emit_signal (line 135) | def _dbus_emit_signal(self, signal_name, values):
method camelcase_to_snake_case (line 150) | def camelcase_to_snake_case(name):
class MPRIS (line 155) | class MPRIS(DBusInterface):
method __init__ (line 289) | def __init__(self, app):
method _get_playback_status (line 335) | def _get_playback_status(self):
method _get_loop_status (line 344) | def _get_loop_status(self):
method _get_metadata (line 352) | def _get_metadata(self, coresong=None, index=None):
method _on_thumbnail_changed (line 397) | def _on_thumbnail_changed(
method _get_song_dbus_path (line 414) | def _get_song_dbus_path(self, coresong=None, index=None):
method _on_recent_queue_changed (line 440) | def _on_recent_queue_changed(
method _get_playlist_dbus_path (line 457) | def _get_playlist_dbus_path(self, playlist):
method _get_mpris_playlist_from_playlist (line 472) | def _get_mpris_playlist_from_playlist(self, playlist):
method _get_active_playlist (line 477) | def _get_active_playlist(self):
method _on_current_song_changed (line 497) | def _on_current_song_changed(self, player: Player) -> None:
method _on_queue_model_changed (line 518) | def _on_queue_model_changed(
method _on_player_state_changed (line 547) | def _on_player_state_changed(self, klass, args):
method _on_repeat_mode_changed (line 557) | def _on_repeat_mode_changed(self, player, param):
method _on_seek_finished (line 575) | def _on_seek_finished(self, player):
method _on_queue_changed (line 579) | def _on_queue_changed(
method _on_playlists_items_changed (line 593) | def _on_playlists_items_changed(self, model, position, removed, added):
method _on_playlist_renamed (line 606) | def _on_playlist_renamed(self, playlist, param):
method _raise (line 610) | def _raise(self):
method _quit (line 614) | def _quit(self):
method _next (line 618) | def _next(self):
method _previous (line 622) | def _previous(self):
method _pause (line 629) | def _pause(self):
method _play_pause (line 633) | def _play_pause(self):
method _stop (line 637) | def _stop(self):
method _play (line 641) | def _play(self):
method _seek (line 648) | def _seek(self, offset_msecond):
method _set_position (line 666) | def _set_position(self, track_id, position_msecond):
method _open_uri (line 678) | def _open_uri(self, uri):
method _seeked (line 687) | def _seeked(self, position_msecond):
method _get_tracks_metadata (line 694) | def _get_tracks_metadata(self, track_paths):
method _add_track (line 709) | def _add_track(self, uri, after_track, set_as_current):
method _remove_track (line 716) | def _remove_track(self, path):
method _go_to (line 723) | def _go_to(self, path):
method _track_list_replaced (line 739) | def _track_list_replaced(self, track_paths, current_song_path):
method _load_queue (line 752) | def _load_queue(self, playlist):
method _activate_playlist (line 762) | def _activate_playlist(self, playlist_path):
method _get_playlists (line 786) | def _get_playlists(self, index, max_count, order, reverse):
method _get (line 810) | def _get(self, interface_name, property_name):
method _get_all (line 822) | def _get_all(self, interface_name):
method _set (line 886) | def _set(self, interface_name, property_name, new_value):
method _properties_changed (line 909) | def _properties_changed(self, interface_name, changed_properties,
method _introspect (line 918) | def _introspect(self):
FILE: gnomemusic/musiclogger.py
class MusicLogger (line 31) | class MusicLogger(GObject.GObject):
method _log (line 44) | def _log(self, message, level):
method message (line 71) | def message(self, message):
method warning (line 80) | def warning(self, message):
method info (line 89) | def info(self, message):
method debug (line 98) | def debug(self, message):
FILE: gnomemusic/notificationmanager.py
class NotificationManager (line 32) | class NotificationManager(GObject.Object):
method __init__ (line 39) | def __init__(self, application):
method _on_window_changed (line 53) | def _on_window_changed(self, klass, value):
method _push_loading (line 58) | def _push_loading(self):
method _pop_loading (line 67) | def _pop_loading(self):
method __aenter__ (line 77) | async def __aenter__(self) -> None:
method __aexit__ (line 80) | async def __aexit__(
FILE: gnomemusic/pauseonsuspend.py
class PauseOnSuspend (line 20) | class PauseOnSuspend(GObject.GObject):
method __init__ (line 27) | def __init__(self, player: Player) -> None:
method _init_pause_on_suspend (line 46) | async def _init_pause_on_suspend(self) -> None:
method _on_player_state_changed (line 59) | def _on_player_state_changed(self, player: Player, state: int) -> None:
method _take_lock (line 77) | async def _take_lock(self) -> None:
method _release_lock (line 101) | def _release_lock(self) -> None:
method _pause_playing (line 110) | def _pause_playing(
FILE: gnomemusic/player.py
class Player (line 42) | class Player(GObject.GObject):
method __init__ (line 58) | def __init__(self, application):
method has_next (line 112) | def has_next(self):
method has_previous (line 122) | def has_previous(self):
method playing (line 132) | def playing(self):
method _on_queue_model_items_changed (line 140) | def _on_queue_model_items_changed(
method _on_repeat_mode_changed (line 147) | def _on_repeat_mode_changed(
method _on_about_to_finish (line 152) | def _on_about_to_finish(self, klass):
method _on_eos (line 160) | def _on_eos(self, klass):
method _on_error (line 175) | def _on_error(self, klass=None):
method _on_stream_start (line 185) | def _on_stream_start(self, klass):
method _load (line 194) | def _load(self, coresong):
method play (line 200) | def play(self, coresong=None):
method pause (line 226) | def pause(self):
method stop (line 230) | def stop(self):
method next (line 236) | def next(self):
method previous (line 246) | def previous(self):
method play_pause (line 271) | def play_pause(self):
method _on_clock_tick (line 278) | def _on_clock_tick(self, klass, tick):
method _update_stats (line 296) | def _update_stats(self) -> None:
method repeat_mode (line 302) | def repeat_mode(self) -> RepeatMode:
method repeat_mode (line 311) | def repeat_mode(self, mode):
method position (line 319) | def position(self):
method current_song (line 329) | def current_song(self):
method get_position (line 337) | def get_position(self):
method set_position (line 347) | def set_position(self, position_second):
method _on_seek_finished (line 361) | def _on_seek_finished(self, klass):
FILE: gnomemusic/playlisttoast.py
class PlaylistToast (line 36) | class PlaylistToast(GObject.Object):
method __init__ (line 42) | def __init__(self, application: Application, playlist: Playlist) -> None:
method _toast_undo_cb (line 67) | def _toast_undo_cb(
method _on_dismissed (line 73) | def _on_dismissed(self, widget: Gtk.Widget) -> None:
FILE: gnomemusic/queue.py
class Queue (line 24) | class Queue(GObject.GObject):
class Type (line 31) | class Type(IntEnum):
method __init__ (line 41) | def __init__(self, application: Application) -> None:
method has_next (line 65) | def has_next(self) -> bool:
method has_previous (line 78) | def has_previous(self) -> bool:
method get_next (line 92) | def get_next(self) -> Optional[CoreSong]:
method next (line 111) | def next(self) -> bool:
method previous (line 140) | def previous(self) -> bool:
method position (line 170) | def position(self) -> int:
method current_song (line 180) | def current_song(self) -> Optional[CoreSong]:
method set_song (line 201) | def set_song(self, song: Optional[CoreSong]) -> Optional[CoreSong]:
method end (line 244) | def end(self) -> None:
method _update_model_recent (line 249) | def _update_model_recent(self) -> None:
method _on_repeat_mode_changed (line 254) | def _on_repeat_mode_changed(
method _on_queue_loaded (line 261) | def _on_queue_loaded(
method _reset_queue_state (line 265) | def _reset_queue_state(self) -> None:
method _validate_song (line 269) | def _validate_song(self, coresong: CoreSong) -> None:
method _validate_next_song (line 289) | def _validate_next_song(self) -> None:
method _validate_previous_song (line 302) | def _validate_previous_song(self) -> None:
method _on_discovered (line 315) | def _on_discovered(
FILE: gnomemusic/search.py
class Search (line 30) | class Search(GObject.GObject):
class State (line 32) | class State(IntEnum):
method __init__ (line 46) | def __init__(self):
FILE: gnomemusic/shufflelistmodel.py
class ShuffleListModel (line 17) | class ShuffleListModel(GObject.GObject, Gio.ListModel):
method __init__ (line 33) | def __init__(self, model: Gio.ListModel) -> None:
method _on_items_changed (line 47) | def _on_items_changed(
method do_get_item (line 54) | def do_get_item(self, position: int) -> CoreSong:
method do_get_n_items (line 57) | def do_get_n_items(self):
method do_get_item_type (line 60) | def do_get_item_type(self):
method shuffle (line 63) | def shuffle(
method deshuffle (line 86) | def deshuffle(self, position: int | None = None) -> None:
FILE: gnomemusic/songart.py
class SongArt (line 34) | class SongArt(GObject.GObject):
method __init__ (line 38) | def __init__(self, application, coresong):
method _on_embedded_art_found (line 53) | def _on_embedded_art_found(self, embeddedart, found):
method _in_cache (line 59) | async def _in_cache(self) -> None:
FILE: gnomemusic/songtoast.py
class SongToast (line 37) | class SongToast(GObject.Object):
method __init__ (line 43) | def __init__(
method _toast_undo_cb (line 76) | def _toast_undo_cb(
method _on_dismissed (line 83) | def _on_dismissed(self, widget: Gtk.Widget) -> None:
FILE: gnomemusic/storeart.py
class StoreArt (line 45) | class StoreArt(GObject.Object):
method __init__ (line 55) | def __init__(self):
method _start (line 69) | async def _start(
method start (line 169) | def start(
FILE: gnomemusic/texturecache.py
class TextureCache (line 44) | class TextureCache(GObject.GObject):
class LoadingState (line 48) | class LoadingState(IntEnum):
method __init__ (line 79) | def __init__(self) -> None:
method clear_pending_lookup_callback (line 93) | def clear_pending_lookup_callback(self) -> None:
method lookup (line 101) | def lookup(self, uri: str) -> None:
method _low_memory_warning (line 123) | def _low_memory_warning(
method _cache_cleanup (line 134) | def _cache_cleanup(cls) -> None:
method _on_art_loading_finished (line 161) | def _on_art_loading_finished(
FILE: gnomemusic/trackerwrapper.py
class TrackerState (line 40) | class TrackerState(IntEnum):
class TrackerWrapper (line 48) | class TrackerWrapper(GObject.GObject):
method __init__ (line 57) | def __init__(self, application: Application) -> None:
method _in_flatpak (line 78) | def _in_flatpak() -> bool:
method _setup_host_miner_fs (line 86) | async def _setup_host_miner_fs(self) -> None:
method _setup_local_miner_fs (line 109) | def _setup_local_miner_fs(self) -> None:
method _setup_local_bus_connection_cb (line 120) | def _setup_local_bus_connection_cb(self, klass, result):
method _setup_local_miner_fs_ping_cb (line 133) | def _setup_local_miner_fs_ping_cb(
method _setup_local_db (line 149) | async def _setup_local_db(self) -> None:
method cache_directory (line 169) | def cache_directory(self) -> str:
method miner_fs (line 181) | def miner_fs(self) -> Tracker.SparqlConnection:
method miner_fs_busname (line 185) | def miner_fs_busname(self) -> str:
method local_db (line 189) | def local_db(self) -> Tracker.SparqlConnection:
method tracker_available (line 195) | def tracker_available(self) -> TrackerState:
method location_filter (line 210) | def location_filter(self) -> Optional[str]:
method _update_favorite (line 228) | async def _update_favorite(self, coresong: CoreSong) -> None:
method _update_play_count (line 253) | async def _update_play_count(self, coresong: CoreSong) -> None:
method _update_last_played (line 274) | async def _update_last_played(self, coresong: CoreSong) -> None:
method update_tag (line 296) | def update_tag(self, coresong: CoreSong, tag: str) -> None:
FILE: gnomemusic/utils.py
class ArtSize (line 40) | class ArtSize(Enum):
method __init__ (line 47) | def __init__(self, width, height):
class CoreObjectType (line 53) | class CoreObjectType(Enum):
class DefaultIconType (line 60) | class DefaultIconType(Enum):
class RepeatMode (line 65) | class RepeatMode(Enum):
method __new__ (line 80) | def __new__(
class SongStateIcon (line 89) | class SongStateIcon(Enum):
class View (line 95) | class View(IntEnum):
function get_artist_from_cursor_dict (line 102) | def get_artist_from_cursor_dict(cursor_dict: Dict[str, Any]) -> str:
function get_title_from_cursor_dict (line 121) | def get_title_from_cursor_dict(cursor_dict):
function seconds_to_string (line 156) | def seconds_to_string(duration):
function normalize_caseless (line 170) | def normalize_caseless(text):
function natural_sort_names (line 180) | def natural_sort_names(name_a: str, name_b: str) -> int:
function dict_from_cursor (line 208) | def dict_from_cursor(cursor: Tsparql.SparqlCursor) -> Dict[str, Any]:
function get_int_from_cursor_dict (line 236) | def get_int_from_cursor_dict(cursor_dict: Dict[str, Any], field: str) ->...
FILE: gnomemusic/views/albumsview.py
class AlbumsView (line 18) | class AlbumsView(Adw.Bin):
method __init__ (line 34) | def __init__(self, application: Application) -> None:
method _on_album_activated (line 59) | def _on_album_activated(
method _setup_list_item (line 66) | def _setup_list_item(
method _bind_list_item (line 71) | def _bind_list_item(
FILE: gnomemusic/views/artistsview.py
class ArtistsView (line 38) | class ArtistsView(Adw.Bin):
method __init__ (line 56) | def __init__(self, application: Application) -> None:
method _on_list_view_setup (line 87) | def _on_list_view_setup(
method _on_list_view_bind (line 97) | def _on_list_view_bind(
method _on_model_items_changed (line 104) | def _on_model_items_changed(
method _on_artist_activated (line 115) | def _on_artist_activated(
FILE: gnomemusic/views/playlistsview.py
class PlaylistsView (line 36) | class PlaylistsView(Adw.Bin):
method __init__ (line 50) | def __init__(self, application):
method _sidebar_header_func (line 78) | def _sidebar_header_func(
method _add_playlist_to_sidebar (line 92) | def _add_playlist_to_sidebar(self, playlist: Playlist) -> PlaylistTile:
method _on_playlists_model_changed (line 100) | def _on_playlists_model_changed(self, model, position, removed, added):
method current_playlist (line 121) | def current_playlist(self):
method _on_playlist_activated (line 129) | def _on_playlist_activated(self, sidebar, row, untouched=False):
method _on_active_core_object_changed (line 136) | def _on_active_core_object_changed(self, klass, val):
method rename_active (line 160) | def rename_active(self):
FILE: gnomemusic/views/searchview.py
class SearchView (line 53) | class SearchView(Adw.NavigationPage):
class State (line 61) | class State(IntEnum):
method __init__ (line 87) | def __init__(self, application: Application) -> None:
method _create_song_widget (line 153) | def _create_song_widget(self, coresong: CoreSong) -> Gtk.ListBoxRow:
method _create_album_cover (line 161) | def _create_album_cover(self, corealbum: CoreAlbum) -> AlbumCover:
method _create_artist_widget (line 166) | def _create_artist_widget(self, coreartist):
method _on_album_model_items_changed (line 171) | def _on_album_model_items_changed(self, model, position, removed, added):
method _on_artist_model_items_changed (line 180) | def _on_artist_model_items_changed(self, model, position, removed, add...
method _on_model_items_changed (line 190) | def _on_model_items_changed(self, model, position, removed, added):
method _on_navigation_view_replaced (line 196) | def _on_navigation_view_replaced(self, view: Adw.NavigationView) -> None:
method _on_search_state_changed (line 200) | def _on_search_state_changed(
method _set_empty_status_page (line 213) | def _set_empty_status_page(self) -> None:
method _set_no_result_status_page (line 219) | def _set_no_result_status_page(self) -> None:
method _check_visibility (line 224) | def _check_visibility(self):
method _song_activated (line 238) | def _song_activated(
method _on_window_width_change (line 247) | def _on_window_width_change(self, widget, value):
method _on_album_activated (line 257) | def _on_album_activated(self, widget, child, user_data=None):
method _on_artist_activated (line 263) | def _on_artist_activated(self, widget, child, user_data=None):
method _on_all_artists_clicked (line 269) | def _on_all_artists_clicked(self, widget, user_data=None):
method _on_all_albums_clicked (line 275) | def _on_all_albums_clicked(self, widget, user_data=None):
FILE: gnomemusic/widgets/albumcover.py
class AlbumCover (line 12) | class AlbumCover(Gtk.FlowBoxChild):
method __init__ (line 20) | def __init__(self, corealbum: CoreAlbum) -> None:
method corealbum (line 34) | def corealbum(self):
FILE: gnomemusic/widgets/albumnavigationpage.py
class AlbumNavigationPage (line 17) | class AlbumNavigationPage(Adw.NavigationPage):
method __init__ (line 28) | def __init__(self, application: Application, corealbum: CoreAlbum) -> ...
FILE: gnomemusic/widgets/albumssearchnavigationpage.py
class AlbumsSearchNavigationPage (line 20) | class AlbumsSearchNavigationPage(Adw.NavigationPage):
method __init__ (line 28) | def __init__(
method _create_album_cover (line 45) | def _create_album_cover(self, corealbum: CoreAlbum) -> AlbumCover:
method _on_album_activated (line 51) | def _on_album_activated(
FILE: gnomemusic/widgets/albumtile.py
class AlbumTile (line 16) | class AlbumTile(Gtk.Box):
method __init__ (line 24) | def __init__(self) -> None:
method corealbum (line 38) | def corealbum(self) -> CoreAlbum:
method corealbum (line 47) | def corealbum(self, corealbum: CoreAlbum) -> None:
FILE: gnomemusic/widgets/albumwidget.py
class AlbumWidget (line 48) | class AlbumWidget(Adw.Bin):
method __init__ (line 68) | def __init__(self, application: Application) -> None:
method corealbum (line 112) | def corealbum(self) -> Optional[CoreAlbum]:
method corealbum (line 124) | def corealbum(self, corealbum: CoreAlbum) -> None:
method active_coreobject (line 168) | def active_coreobject(self) -> Optional[Union[CoreAlbum, CoreArtist]]:
method active_coreobject (line 186) | def active_coreobject(
method _set_disc_header (line 194) | def _set_disc_header(
method _create_widget (line 204) | def _create_widget(self, disc: CoreDisc) -> DiscBox:
method _on_model_items_changed (line 210) | def _on_model_items_changed(
method _set_composer_label (line 226) | def _set_composer_label(self) -> None:
method _on_release_info_changed (line 237) | def _on_release_info_changed(
method _play (line 254) | def _play(
method _song_activated (line 267) | def _song_activated(
method _on_add_favorites_action (line 271) | def _on_add_favorites_action(
method _on_add_playlist_action (line 280) | def _on_add_playlist_action(
method _on_play_action (line 296) | def _on_play_action(
method _on_play_button_clicked (line 302) | def _on_play_button_clicked(self, button: Gtk.Button) -> None:
FILE: gnomemusic/widgets/artistalbumswidget.py
class ArtistAlbumsWidget (line 38) | class ArtistAlbumsWidget(Gtk.Box):
method __init__ (line 50) | def __init__(self, application: Application) -> None:
method _update_model (line 60) | def _update_model(self) -> None:
method _add_album (line 65) | def _add_album(self, corealbum):
method coreartist (line 82) | def coreartist(self) -> CoreArtist:
method coreartist (line 91) | def coreartist(self, coreartist: CoreArtist) -> None:
FILE: gnomemusic/widgets/artistnavigationpage.py
class ArtistNavigationPage (line 17) | class ArtistNavigationPage(Adw.NavigationPage):
method __init__ (line 27) | def __init__(
FILE: gnomemusic/widgets/artistsearchtile.py
class ArtistSearchTile (line 34) | class ArtistSearchTile(Gtk.FlowBoxChild):
method __init__ (line 48) | def __init__(self, coreartist):
method _on_tooltip_query (line 73) | def _on_tooltip_query(self, widget, x, y, kb, tooltip, data=None):
FILE: gnomemusic/widgets/artistssearchnavigationpage.py
class ArtistsSearchNavigationPage (line 20) | class ArtistsSearchNavigationPage(Adw.NavigationPage):
method __init__ (line 28) | def __init__(
method _create_artist_widget (line 45) | def _create_artist_widget(
method _on_artist_activated (line 52) | def _on_artist_activated(
FILE: gnomemusic/widgets/artisttile.py
class ArtistTile (line 36) | class ArtistTile(Gtk.Box):
method __init__ (line 53) | def __init__(self) -> None:
method _on_button_pressed (line 72) | def _on_button_pressed(
method coreartist (line 79) | def coreartist(self) -> CoreArtist:
method coreartist (line 88) | def coreartist(self, coreartist: CoreArtist) -> None:
FILE: gnomemusic/widgets/discbox.py
class DiscBox (line 39) | class DiscBox(Gtk.ListBoxRow):
method __init__ (line 55) | def __init__(
method _create_widget (line 77) | def _create_widget(self, coresong):
method _song_activated (line 85) | def _song_activated(
FILE: gnomemusic/widgets/headerbar.py
class HeaderBar (line 31) | class HeaderBar(Adw.Bin):
class State (line 34) | class State(IntEnum):
method __init__ (line 50) | def __init__(self, application):
method state (line 71) | def state(self):
method state (line 80) | def state(self, value):
method _update (line 100) | def _update(self):
FILE: gnomemusic/widgets/playertoolbar.py
class PlayerToolbar (line 20) | class PlayerToolbar(Gtk.ActionBar):
method __init__ (line 42) | def __init__(self):
method player (line 58) | def player(self):
method player (line 67) | def player(self, player):
method _on_progress_value_changed (line 97) | def _on_progress_value_changed(self, progress_scale):
method _on_prev_button_clicked (line 102) | def _on_prev_button_clicked(self, button):
method _on_play_button_clicked (line 106) | def _on_play_button_clicked(self, button):
method _on_next_button_clicked (line 110) | def _on_next_button_clicked(self, button):
method _sync_playing (line 113) | def _sync_playing(self, player, state):
method _sync_prev_next (line 134) | def _sync_prev_next(self):
method _update_view (line 138) | def _update_view(self, player):
method _on_tooltip_query (line 163) | def _on_tooltip_query(self, widget, x, y, kb, tooltip, data=None):
method _on_repeat_mode_changed (line 168) | def _on_repeat_mode_changed(
FILE: gnomemusic/widgets/playlistcontrols.py
class PlaylistControls (line 34) | class PlaylistControls(Gtk.Box):
method __init__ (line 47) | def __init__(self):
method application (line 67) | def application(self):
method application (line 76) | def application(self, application):
method _on_delete_action (line 95) | def _on_delete_action(self, menutime, data=None):
method _on_play_button_clicked (line 105) | def _on_play_button_clicked(self, button: Gtk.Button) -> None:
method _on_rename_entry_changed (line 109) | def _on_rename_entry_changed(self, selection):
method _on_rename_entry_key_pressed (line 114) | def _on_rename_entry_key_pressed(self, controller, keyval, keycode, st...
method _on_playlist_renamed (line 119) | def _on_playlist_renamed(self, widget):
method _on_songs_count_changed (line 128) | def _on_songs_count_changed(self, klass, data=None):
method _enable_rename_playlist (line 137) | def _enable_rename_playlist(self, menuitem, data=None):
method _disable_rename_playlist (line 142) | def _disable_rename_playlist(self):
method rename_active (line 147) | def rename_active(self):
method playlist (line 157) | def playlist(self):
method playlist (line 166) | def playlist(self, new_playlist):
FILE: gnomemusic/widgets/playlistdialog.py
class PlaylistDialog (line 40) | class PlaylistDialog(Adw.Dialog):
method __init__ (line 58) | def __init__(
method _set_view (line 84) | def _set_view(self):
method _create_playlist_row (line 98) | def _create_playlist_row(self, playlist):
method _on_selection (line 108) | def _on_selection(self, select_button):
method _on_cancel_button_clicked (line 113) | def _on_cancel_button_clicked(self, cancel_button):
method _on_selected_rows_changed (line 117) | def _on_selected_rows_changed(self, klass):
method _on_editing_done (line 129) | def _on_editing_done(self, sender, data=None):
method _on_add_playlist_entry_changed (line 144) | def _on_add_playlist_entry_changed(self, editable, data=None):
method _on_add_playlist_entry_focused (line 151) | def _on_add_playlist_entry_focused(
FILE: gnomemusic/widgets/playlistdialogrow.py
class PlaylistDialogRow (line 31) | class PlaylistDialogRow(Gtk.ListBoxRow):
method __init__ (line 41) | def __init__(self, playlist):
FILE: gnomemusic/widgets/playlistswidget.py
class PlaylistsWidget (line 43) | class PlaylistsWidget(Gtk.Box):
method __init__ (line 51) | def __init__(
method _on_current_playlist_changed (line 78) | def _on_current_playlist_changed(self, playlists_view, value):
method _create_song_widget (line 89) | def _create_song_widget(
method _on_song_activated (line 103) | def _on_song_activated(
method _play (line 109) | def _play(self, coresong=None):
method _on_song_widget_moved (line 122) | def _on_song_widget_moved(self, target, source_position):
method _on_smart_playlist_change (line 127) | def _on_smart_playlist_change(self, coremodel):
method _on_play_playlist (line 133) | def _on_play_playlist(self, menuitem, data=None):
method rename_active (line 138) | def rename_active(self):
FILE: gnomemusic/widgets/playlisttile.py
class PlaylistTile (line 31) | class PlaylistTile(Gtk.ListBoxRow):
method __init__ (line 45) | def __init__(self, playlist):
FILE: gnomemusic/widgets/preferencesdialog.py
class PreferencesDialog (line 15) | class PreferencesDialog(Adw.PreferencesDialog):
method __init__ (line 25) | def __init__(self, application: Application) -> None:
method _update_repeate_mode (line 47) | def _update_repeate_mode(
method _update_replaygain (line 51) | def _update_replaygain(
FILE: gnomemusic/widgets/repeatmodebutton.py
class RepeatModeButton (line 14) | class RepeatModeButton(Gtk.Box):
method __init__ (line 21) | def __init__(self) -> None:
method player (line 46) | def player(self) -> Optional[Player]:
method player (line 55) | def player(self, player: Player) -> None:
method _on_repeat_menu_changed (line 80) | def _on_repeat_menu_changed(
FILE: gnomemusic/widgets/searchheaderbar.py
class SearchHeaderBar (line 15) | class SearchHeaderBar(Adw.Bin):
method __init__ (line 27) | def __init__(self, application):
method _search_entry_changed (line 62) | def _search_entry_changed(self, widget: Gtk.SearchEntry) -> bool:
method _on_search_mode_changed (line 72) | def _on_search_mode_changed(self, klass, data):
method _search_state_changed (line 76) | def _search_state_changed(self, klass, data):
method _set_error_style (line 87) | def _set_error_style(self, error):
method _on_search_text_changed (line 98) | def _on_search_text_changed(
FILE: gnomemusic/widgets/smoothscale.py
class SmoothScale (line 30) | class SmoothScale(Gtk.Scale):
method __init__ (line 38) | def __init__(self):
method player (line 59) | def player(self):
method player (line 68) | def player(self, player):
method _on_state_change (line 83) | def _on_state_change(self, klass, arguments):
method _on_duration_changed (line 102) | def _on_duration_changed(self, klass, arguments):
method _on_smooth_scale_seek_finish (line 110) | def _on_smooth_scale_seek_finish(self, value):
method _on_smooth_scale_seek (line 120) | def _on_smooth_scale_seek(self, scale, scroll_type, value):
method _on_button_released (line 140) | def _on_button_released(self, gesture, n_press, x, y):
method _on_button_pressed (line 150) | def _on_button_pressed(self, gesture, n_press, x, y):
method _update_timeout (line 156) | def _update_timeout(self):
method _remove_timeout (line 177) | def _remove_timeout(self):
method _on_smooth_scale_change_value (line 182) | def _on_smooth_scale_change_value(self, scroll):
method _update_position_callback (line 188) | def _update_position_callback(self):
FILE: gnomemusic/widgets/songwidget.py
class SongWidget (line 39) | class SongWidget(Gtk.ListBoxRow):
class State (line 73) | class State(IntEnum):
method __init__ (line 80) | def __init__(self, coresong, can_dnd=False, show_artist_and_album=False):
method _on_drag_prepare (line 143) | def _on_drag_prepare(
method _on_drag_begin (line 151) | def _on_drag_begin(
method _on_drop (line 167) | def _on_drop(
method state (line 183) | def state(self):
method state (line 192) | def state(self, value):
method _on_validation_changed (line 220) | def _on_validation_changed(self, coresong, sate):
method song_number (line 229) | def song_number(self):
method song_number (line 238) | def song_number(self, new_nr):
method menu (line 249) | def menu(self) -> Optional[Gtk.Popover]:
method menu (line 260) | def menu(self, menu: Optional[Gtk.PopoverMenu]) -> None:
FILE: gnomemusic/widgets/songwidgetmenu.py
class SongWidgetMenu (line 46) | class SongWidgetMenu(Gtk.PopoverMenu):
method __init__ (line 50) | def __init__(
method _open_location (line 98) | def _open_location(self, action: Gio.SimpleAction, param: Any) -> None:
method _play_song (line 101) | def _play_song(self, action: Gio.Simple, param: Any) -> None:
method _add_to_playlist (line 114) | def _add_to_playlist(self, action: Gio.Simple, param: Any) -> None:
method _remove_from_playlist (line 120) | def _remove_from_playlist(self, action: Gio.Simple, param: Any) -> None:
method coreobject (line 128) | def coreobject(self) -> CoreObject:
method coreobject (line 132) | def coreobject(self, coreobject: CoreObject) -> None:
FILE: gnomemusic/widgets/startoggle.py
class StarToggle (line 9) | class StarToggle(Gtk.ToggleButton):
method __init__ (line 17) | def __init__(self) -> None:
method _update (line 29) | def _update(self, _widget: Gtk.ToggleButton) -> None:
method _on_clicked (line 44) | def _on_clicked(self, _widget: Gtk.ToggleButton) -> None:
FILE: gnomemusic/widgets/statusnavigationpage.py
class StatusNavigationPage (line 18) | class StatusNavigationPage(Adw.NavigationPage):
class State (line 28) | class State(IntEnum):
method __init__ (line 42) | def __init__(self, application: Application) -> None:
method state (line 77) | def state(self) -> int:
method state (line 86) | def state(self, value: int) -> None:
method _set_empty_state (line 107) | def _set_empty_state(self) -> None:
method _set_search_state (line 113) | def _set_search_state(self) -> None:
method _set_no_tracker_state (line 117) | def _set_no_tracker_state(self) -> None:
method _set_tracker_outdated_state (line 125) | def _set_tracker_outdated_state(self) -> None:
FILE: gnomemusic/widgets/twolinetip.py
class TwoLineTip (line 29) | class TwoLineTip(Gtk.Box):
method __init__ (line 44) | def __init__(self):
FILE: gnomemusic/widgets/volumebutton.py
class VolumeButton (line 11) | class VolumeButton(Gtk.Box):
method __init__ (line 23) | def __init__(self) -> None:
method _on_adjustment_changed (line 40) | def _on_adjustment_changed(self, adjustment: Gtk.Adjustment) -> None:
method _on_mute_changed (line 51) | def _on_mute_changed(
method _on_volume_changed (line 61) | def _on_volume_changed(
method _cubic_to_linear (line 70) | def _cubic_to_linear(self, value: float) -> float:
method _linear_to_cubic (line 77) | def _linear_to_cubic(self, value: float) -> float:
method _set_adjustment (line 84) | def _set_adjustment(self) -> bool:
method _update_icon (line 97) | def _update_icon(self) -> None:
FILE: gnomemusic/window.py
class Window (line 22) | class Window(Adw.ApplicationWindow):
method __init__ (line 37) | def __init__(self, app):
method _setup_view (line 63) | def _setup_view(self):
method _switch_to_empty_view (line 100) | def _switch_to_empty_view(self) -> None:
method _on_search_mode_changed (line 110) | def _on_search_mode_changed(self, search, value):
method _on_songs_available (line 116) | def _on_songs_available(self, klass, value):
method _on_stack_visible_child_changed (line 128) | def _on_stack_visible_child_changed(self, klass, value):
method _on_tracker_available (line 131) | def _on_tracker_available(self, klass, value):
method _switch_to_player_view (line 139) | def _switch_to_player_view(self):
method headerbar (line 171) | def headerbar(self) -> HeaderBar:
method navigation_view (line 182) | def navigation_view(self) -> Adw.NavigationView:
method _on_key_press (line 191) | def _on_key_press(
method _set_actions (line 218) | def _set_actions(self) -> None:
method _navigate_back (line 238) | def _navigate_back(
method _search_bar_close (line 244) | def _search_bar_close(
method _search_bar_open (line 250) | def _search_bar_open(
method _view_albums (line 260) | def _view_albums(
method _view_artists (line 265) | def _view_artists(
method _view_playlists (line 270) | def _view_playlists(
method _switch_to_view (line 275) | def _switch_to_view(self, view_name: str) -> None:
method _is_main_view_active (line 280) | def _is_main_view_active(self) -> bool:
method set_player_visible (line 287) | def set_player_visible(self, visible):
method loading_pulse (line 294) | def loading_pulse(self) -> bool:
method loading_visible (line 304) | def loading_visible(self, show: bool) -> None:
FILE: gnomemusic/windowplacement.py
class WindowPlacement (line 34) | class WindowPlacement(GObject.GObject):
method __init__ (line 43) | def __init__(self, window):
method _restore_window_state (line 61) | def _restore_window_state(self):
method _on_size_change (line 71) | def _on_size_change(
method _store_size (line 77) | def _store_size(self, window: Window) -> bool:
method _on_maximized (line 88) | def _on_maximized(self, klass, value, data=None):
Condensed preview — 250 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (2,788K chars).
[
{
"path": ".gitlab/issue_templates/default.md",
"chars": 376,
"preview": "## Description\n\n[Description of the bug or feature]\n\n\n## Steps To Reproduce\n\n- Step 1\n- Step 2\n- Step 3\n\n\n## Expected Be"
},
{
"path": ".gitlab-ci.yml",
"chars": 1412,
"preview": "include:\n - project: 'GNOME/citemplates'\n file: 'flatpak/flatpak_ci_initiative.yml'\n - component: gitlab.gnome.org/"
},
{
"path": ".gitmodules",
"chars": 129,
"preview": "[submodule \"subprojects/shared-modules\"]\n\tpath = subprojects/shared-modules\n\turl = https://github.com/flathub/shared-mod"
},
{
"path": "CONTRIBUTING.md",
"chars": 6103,
"preview": "# Contributing\n\n[Our guide](https://welcome.gnome.org/app/Music/) has everything to get you started.\n\n## Build instructi"
},
{
"path": "LICENSE",
"chars": 18658,
"preview": "# This GPL license have a exception clause added, see at the bottom of file\n# for details.\n\n GNU GENE"
},
{
"path": "NEWS",
"chars": 60034,
"preview": "Overview of changes in 50.alpha\n===============================\n\n\nOverview of changes in 49 rc\n========================="
},
{
"path": "README.md",
"chars": 667,
"preview": "# Music\n\nPlay and organize your music collection with Music, a GNOME app.\n\n 2013 Arnel A. Borja <kyoushuu@yahoo.com>\n# Copyright (c) 2013 Vadim Rutkovsky <vrutkovs@redhat.com>\n# Co"
},
{
"path": "gnomemusic/artistart.py",
"chars": 2773,
"preview": "# Copyright 2019 The GNOME Music developers\n#\n# GNOME Music is free software; you can redistribute it and/or modify\n# it"
},
{
"path": "gnomemusic/asynciolimiter.py",
"chars": 20774,
"preview": "# SPDX-License-Identifier: MIT\n# Copyright (c) 2022 Bar Harel\n# Licensed under the MIT license as detailed in LICENSE.tx"
},
{
"path": "gnomemusic/corealbum.py",
"chars": 4330,
"preview": "# Copyright 2025 The GNOME Music developers\n#\n# SPDX-License-Identifier: GPL-2.0-or-later WITH GStreamer-exception-2008\n"
},
{
"path": "gnomemusic/coreartist.py",
"chars": 2683,
"preview": "# Copyright 2025 The GNOME Music developers\n#\n# SPDX-License-Identifier: GPL-2.0-or-later WITH GStreamer-exception-2008\n"
},
{
"path": "gnomemusic/coredisc.py",
"chars": 2606,
"preview": "# Copyright 2025 The GNOME Music developers\n#\n# SPDX-License-Identifier: GPL-2.0-or-later WITH GStreamer-exception-2008\n"
},
{
"path": "gnomemusic/coregrilo.py",
"chars": 12287,
"preview": "# Copyright 2019 The GNOME Music developers\n#\n# GNOME Music is free software; you can redistribute it and/or modify\n# it"
},
{
"path": "gnomemusic/coremodel.py",
"chars": 19570,
"preview": "# Copyright 2019 The GNOME Music developers\n#\n# GNOME Music is free software; you can redistribute it and/or modify\n# it"
},
{
"path": "gnomemusic/coresong.py",
"chars": 4992,
"preview": "# Copyright 2025 The GNOME Music developers\n#\n# SPDX-License-Identifier: GPL-2.0-or-later WITH GStreamer-exception-2008\n"
},
{
"path": "gnomemusic/coverpaintable.py",
"chars": 8232,
"preview": "# Copyright 2022 The GNOME Music developers\n#\n# GNOME Music is free software; you can redistribute it and/or modify\n# it"
},
{
"path": "gnomemusic/embeddedart.py",
"chars": 7834,
"preview": "# Copyright 2020 The GNOME Music developers\n#\n# GNOME Music is free software; you can redistribute it and/or modify\n# it"
},
{
"path": "gnomemusic/grilowrappers/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "gnomemusic/grilowrappers/localsearchplaylists.py",
"chars": 9603,
"preview": "# Copyright 2025 The GNOME Music developers\n#\n# SPDX-License-Identifier: GPL-2.0-or-later WITH GStreamer-exception-2008\n"
},
{
"path": "gnomemusic/grilowrappers/localsearchwrapper.py",
"chars": 22681,
"preview": "# Copyright 2025 The GNOME Music developers\n#\n# SPDX-License-Identifier: GPL-2.0-or-later WITH GStreamer-exception-2008\n"
},
{
"path": "gnomemusic/grilowrappers/playlist.py",
"chars": 13807,
"preview": "# Copyright 2024 The GNOME Music developers\n#\n# SPDX-License-Identifier: GPL-2.0-or-later WITH GStreamer-exception-2008\n"
},
{
"path": "gnomemusic/grilowrappers/smartplaylist.py",
"chars": 17727,
"preview": "# Copyright 2024 The GNOME Music developers\n#\n# SPDX-License-Identifier: GPL-2.0-or-later WITH GStreamer-exception-2008\n"
},
{
"path": "gnomemusic/gstplayer.py",
"chars": 17042,
"preview": "# Copyright © 2018 The GNOME Music developers\n#\n# GNOME Music is free software; you can redistribute it and/or modify\n# "
},
{
"path": "gnomemusic/inhibitsuspend.py",
"chars": 3544,
"preview": "# Copyright © 2018 The GNOME Music developers\n# GNOME Music is free software; you can redistribute it and/or modify\n# it"
},
{
"path": "gnomemusic/mediaartloader.py",
"chars": 5360,
"preview": "# Copyright 2022 The GNOME Music developers\n#\n# GNOME Music is free software; you can redistribute it and/or modify\n# it"
},
{
"path": "gnomemusic/mpris.py",
"chars": 36650,
"preview": "# Copyright 2019 The GNOME Music developers\n#\n# GNOME Music is free software; you can redistribute it and/or modify\n# it"
},
{
"path": "gnomemusic/musiclogger.py",
"chars": 3433,
"preview": "# Copyright 2020 The GNOME Music developers\n#\n# GNOME Music is free software; you can redistribute it and/or modify\n# it"
},
{
"path": "gnomemusic/notificationmanager.py",
"chars": 3008,
"preview": "# Copyright 2020 The GNOME Music Developers\n#\n# GNOME Music is free software; you can redistribute it and/or modify\n# it"
},
{
"path": "gnomemusic/pauseonsuspend.py",
"chars": 3738,
"preview": "# Copyright 2024 The GNOME Music developers\n#\n# SPDX-License-Identifier: GPL-2.0-or-later WITH GStreamer-exception-2008\n"
},
{
"path": "gnomemusic/player.py",
"chars": 12377,
"preview": "# Copyright © 2018 The GNOME Music developers\n#\n# GNOME Music is free software; you can redistribute it and/or modify\n# "
},
{
"path": "gnomemusic/playlisttoast.py",
"chars": 2960,
"preview": "# Copyright 2022 The GNOME Music Developers\n#\n# GNOME Music is free software; you can redistribute it and/or modify\n# it"
},
{
"path": "gnomemusic/queue.py",
"chars": 10884,
"preview": "# Copyright 2025 The GNOME Music developers\n#\n# SPDX-License-Identifier: GPL-2.0-or-later WITH GStreamer-exception-2008\n"
},
{
"path": "gnomemusic/search.py",
"chars": 1756,
"preview": "# Copyright 2018 The GNOME Music developers\n#\n# GNOME Music is free software; you can redistribute it and/or modify\n# it"
},
{
"path": "gnomemusic/shufflelistmodel.py",
"chars": 3388,
"preview": "# Copyright 2025 The GNOME Music developers\n#\n# SPDX-License-Identifier: GPL-2.0-or-later WITH GStreamer-exception-2008\n"
},
{
"path": "gnomemusic/songart.py",
"chars": 2958,
"preview": "# Copyright 2020 The GNOME Music developers\n#\n# GNOME Music is free software; you can redistribute it and/or modify\n# it"
},
{
"path": "gnomemusic/songtoast.py",
"chars": 3371,
"preview": "# Copyright 2022 The GNOME Music Developers\n#\n# GNOME Music is free software; you can redistribute it and/or modify\n# it"
},
{
"path": "gnomemusic/storeart.py",
"chars": 6756,
"preview": "# Copyright 2020 The GNOME Music developers\n#\n# GNOME Music is free software; you can redistribute it and/or modify\n# it"
},
{
"path": "gnomemusic/texturecache.py",
"chars": 6289,
"preview": "# Copyright 2022 The GNOME Music developers\n#\n# GNOME Music is free software; you can redistribute it and/or modify\n# it"
},
{
"path": "gnomemusic/trackerwrapper.py",
"chars": 11395,
"preview": "# Copyright 2019 The GNOME Music developers\n# GNOME Music is free software; you can redistribute it and/or modify\n# it u"
},
{
"path": "gnomemusic/utils.py",
"chars": 7848,
"preview": "# Copyright (c) 2016 Marinus Schraal <mschraal@src.gnome.org>\n#\n# GNOME Music is free software; you can redistribute it "
},
{
"path": "gnomemusic/views/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "gnomemusic/views/albumsview.py",
"chars": 2500,
"preview": "# Copyright 2024 The GNOME Music developers\n#\n# SPDX-License-Identifier: GPL-2.0-or-later WITH GStreamer-exception-2008\n"
},
{
"path": "gnomemusic/views/artistsview.py",
"chars": 4704,
"preview": "# Copyright (c) 2016 The GNOME Music Developers\n#\n# GNOME Music is free software; you can redistribute it and/or modify\n"
},
{
"path": "gnomemusic/views/playlistsview.py",
"chars": 6065,
"preview": "# Copyright 2020 The GNOME Music Developers\n#\n# GNOME Music is free software; you can redistribute it and/or modify\n# it"
},
{
"path": "gnomemusic/views/searchview.py",
"chars": 11106,
"preview": "# Copyright (c) 2016 The GNOME Music Developers\n#\n# GNOME Music is free software; you can redistribute it and/or modify\n"
},
{
"path": "gnomemusic/widgets/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "gnomemusic/widgets/albumcover.py",
"chars": 1091,
"preview": "# Copyright 2024 The GNOME Music developers\n#\n# SPDX-License-Identifier: GPL-2.0-or-later WITH GStreamer-exception-2008\n"
},
{
"path": "gnomemusic/widgets/albumnavigationpage.py",
"chars": 1431,
"preview": "# Copyright 2024 The GNOME Music developers\n#\n# SPDX-License-Identifier: GPL-2.0-or-later WITH GStreamer-exception-2008\n"
},
{
"path": "gnomemusic/widgets/albumssearchnavigationpage.py",
"chars": 1807,
"preview": "# Copyright 2024 The GNOME Music developers\n#\n# SPDX-License-Identifier: GPL-2.0-or-later WITH GStreamer-exception-2008\n"
},
{
"path": "gnomemusic/widgets/albumtile.py",
"chars": 1917,
"preview": "# Copyright 2024 The GNOME Music developers\n#\n# SPDX-License-Identifier: GPL-2.0-or-later WITH GStreamer-exception-2008\n"
},
{
"path": "gnomemusic/widgets/albumwidget.py",
"chars": 11454,
"preview": "# Copyright 2020 The GNOME Music developers\n#\n# GNOME Music is free software; you can redistribute it and/or modify\n# it"
},
{
"path": "gnomemusic/widgets/artistalbumswidget.py",
"chars": 3485,
"preview": "# Copyright (c) 2016 The GNOME Music Developers\n#\n# GNOME Music is free software; you can redistribute it and/or modify\n"
},
{
"path": "gnomemusic/widgets/artistnavigationpage.py",
"chars": 1380,
"preview": "# Copyright 2024 The GNOME Music developers\n#\n# SPDX-License-Identifier: GPL-2.0-or-later WITH GStreamer-exception-2008\n"
},
{
"path": "gnomemusic/widgets/artistsearchtile.py",
"chars": 2880,
"preview": "# Copyright 2019 The GNOME Music developers\n#\n# GNOME Music is free software; you can redistribute it and/or modify\n# it"
},
{
"path": "gnomemusic/widgets/artistssearchnavigationpage.py",
"chars": 1865,
"preview": "# Copyright 2024 The GNOME Music developers\n#\n# SPDX-License-Identifier: GPL-2.0-or-later WITH GStreamer-exception-2008\n"
},
{
"path": "gnomemusic/widgets/artisttile.py",
"chars": 3412,
"preview": "# Copyright 2019 The GNOME Music developers\n#\n# GNOME Music is free software; you can redistribute it and/or modify\n# it"
},
{
"path": "gnomemusic/widgets/discbox.py",
"chars": 3260,
"preview": "# Copyright (c) 2021 The GNOME Music Developers\n#\n# GNOME Music is free software; you can redistribute it and/or modify\n"
},
{
"path": "gnomemusic/widgets/headerbar.py",
"chars": 3719,
"preview": "# Copyright 2018 The GNOME Music developers\n#\n# GNOME Music is free software; you can redistribute it and/or modify\n# it"
},
{
"path": "gnomemusic/widgets/playertoolbar.py",
"chars": 5789,
"preview": "# Copyright © 2025 The GNOME Music Developers\n#\n# SPDX-License-Identifier: GPL-2.0-or-later WITH GStreamer-exception-200"
},
{
"path": "gnomemusic/widgets/playlistcontrols.py",
"chars": 6890,
"preview": "# Copyright 2018 The GNOME Music Developers\n#\n# GNOME Music is free software; you can redistribute it and/or modify\n# it"
},
{
"path": "gnomemusic/widgets/playlistdialog.py",
"chars": 5879,
"preview": "# Copyright 2019 The GNOME Music Developers\n#\n# GNOME Music is free software; you can redistribute it and/or modify\n# it"
},
{
"path": "gnomemusic/widgets/playlistdialogrow.py",
"chars": 2092,
"preview": "# Copyright 2019 The GNOME Music Developers\n#\n# GNOME Music is free software; you can redistribute it and/or modify\n# it"
},
{
"path": "gnomemusic/widgets/playlistswidget.py",
"chars": 5538,
"preview": "# Copyright 2020 The GNOME Music developers\n#\n# GNOME Music is free software; you can redistribute it and/or modify\n# it"
},
{
"path": "gnomemusic/widgets/playlisttile.py",
"chars": 2158,
"preview": "# Copyright 2019 The GNOME Music developers\n#\n# GNOME Music is free software; you can redistribute it and/or modify\n# it"
},
{
"path": "gnomemusic/widgets/preferencesdialog.py",
"chars": 1759,
"preview": "# Copyright 2024 The GNOME Music developers\n#\n# SPDX-License-Identifier: GPL-2.0-or-later WITH GStreamer-exception-2008\n"
},
{
"path": "gnomemusic/widgets/repeatmodebutton.py",
"chars": 2822,
"preview": "# Copyright 2025 The GNOME Music developers\n#\n# SPDX-License-Identifier: GPL-2.0-or-later WITH GStreamer-exception-2008\n"
},
{
"path": "gnomemusic/widgets/searchheaderbar.py",
"chars": 3548,
"preview": "# Copyright 2025 The GNOME Music developers\n#\n# SPDX-License-Identifier: GPL-2.0-or-later WITH GStreamer-exception-2008\n"
},
{
"path": "gnomemusic/widgets/smoothscale.py",
"chars": 6441,
"preview": "# Copyright © 2018 The GNOME Music developers\n#\n# GNOME Music is free software; you can redistribute it and/or modify\n# "
},
{
"path": "gnomemusic/widgets/songwidget.py",
"chars": 9341,
"preview": "# Copyright © 2018 The GNOME Music developers\n#\n# GNOME Music is free software; you can redistribute it and/or modify\n# "
},
{
"path": "gnomemusic/widgets/songwidgetmenu.py",
"chars": 5436,
"preview": "# Copyright 2021 The GNOME Music developers\n#\n# GNOME Music is free software; you can redistribute it and/or modify\n# it"
},
{
"path": "gnomemusic/widgets/startoggle.py",
"chars": 1365,
"preview": "# Copyright 2024 The GNOME Music developers\n#\n# SPDX-License-Identifier: GPL-2.0-or-later WITH GStreamer-exception-2008\n"
},
{
"path": "gnomemusic/widgets/statusnavigationpage.py",
"chars": 4738,
"preview": "# Copyright 2024 The GNOME Music developers\n#\n# SPDX-License-Identifier: GPL-2.0-or-later WITH GStreamer-exception-2008\n"
},
{
"path": "gnomemusic/widgets/twolinetip.py",
"chars": 1992,
"preview": "# Copyright 2018 The GNOME Music developers\n#\n# GNOME Music is free software; you can redistribute it and/or modify\n# it"
},
{
"path": "gnomemusic/widgets/volumebutton.py",
"chars": 3675,
"preview": "# Copyright 2025 The GNOME Music developers\n#\n# SPDX-License-Identifier: GPL-2.0-or-later WITH GStreamer-exception-2008\n"
},
{
"path": "gnomemusic/window.py",
"chars": 11456,
"preview": "# Copyright 2025 The GNOME Music developers\n#\n# SPDX-License-Identifier: GPL-2.0-or-later WITH GStreamer-exception-2008\n"
},
{
"path": "gnomemusic/windowplacement.py",
"chars": 3423,
"preview": "# Copyright 2018 The GNOME Music developers\n#\n# GNOME Music is free software; you can redistribute it and/or modify\n# it"
},
{
"path": "help/LINGUAS",
"chars": 84,
"preview": "bg\nca\ncs\nda\nde\nel\nes\neu\nfr\ngl\nhr\nhu\nid\nit\nkk\nko\nnl\npl\npt_BR\nro\nru\nsr\nsv\ntr\nuk\nzh_CN\n"
},
{
"path": "help/bg/bg.po",
"chars": 14556,
"preview": "# Bulgarian translation for gnome-music.\n# Copyright (C) 2024 gnome-music's COPYRIGHT HOLDER\n# This file is distributed "
},
{
"path": "help/ca/ca.po",
"chars": 14943,
"preview": "#\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: gnome-music master\\n\"\n\"POT-Creation-Date: 2022-07-25 15:45+0000\\n\"\n\"PO-Revisio"
},
{
"path": "help/cs/cs.po",
"chars": 14758,
"preview": "# Czech translation for gnome-music.\n# Copyright (C) 2014 gnome-music's COPYRIGHT HOLDER\n# This file is distributed unde"
},
{
"path": "help/da/da.po",
"chars": 14463,
"preview": "# Danish translation for gnome-music.\n# Copyright (C) 2015 gnome-music's COPYRIGHT HOLDER\n# This file is distributed und"
},
{
"path": "help/de/de.po",
"chars": 15241,
"preview": "# German translation for gnome-music.\n# Copyright (C) 2014 gnome-music's COPYRIGHT HOLDER\n# This file is distributed und"
},
{
"path": "help/el/el.po",
"chars": 15479,
"preview": "# Greek translation for gnome-music.\n# Copyright (C) 2014 gnome-music's COPYRIGHT HOLDER\n# This file is distributed unde"
},
{
"path": "help/es/es.po",
"chars": 15304,
"preview": "# Spanish translation for gnome-music.\n# Copyright (C) 2014 gnome-music's COPYRIGHT HOLDER\n# This file is distributed un"
},
{
"path": "help/eu/eu.po",
"chars": 14765,
"preview": "# Basque translation for gnome-music.\n# Copyright (C) 2019 gnome-music's COPYRIGHT HOLDER\n# This file is distributed und"
},
{
"path": "help/fr/fr.po",
"chars": 15415,
"preview": "# French translation for gnome-music.\n# Copyright (C) 2014 gnome-music's COPYRIGHT HOLDER\n# This file is distributed und"
},
{
"path": "help/gl/gl.po",
"chars": 15122,
"preview": "# Galician translation for gnome-music.\n# Copyright (C) 2014 gnome-music's COPYRIGHT HOLDER\n# This file is distributed u"
},
{
"path": "help/hr/hr.po",
"chars": 14651,
"preview": "# Croatian translation for gnome-music.\n# Copyright (C) 2017 gnome-music's COPYRIGHT HOLDER\n# This file is distributed u"
},
{
"path": "help/hu/hu.po",
"chars": 15049,
"preview": "# Hungarian translation for gnome-music.\n# Copyright (C) 2014, 2015, 2017, 2019, 2021 Free Software Foundation, Inc.\n# T"
},
{
"path": "help/id/id.po",
"chars": 14521,
"preview": "# Indonesian translation for gnome-music.\n# Copyright (C) 2019 gnome-music's COPYRIGHT HOLDER\n# This file is distributed"
},
{
"path": "help/it/it.po",
"chars": 14572,
"preview": "# Italian translation for gnome-music.\n# Copyright (C) 2019 gnome-music's COPYRIGHT HOLDER\n# This file is distributed un"
},
{
"path": "help/kk/kk.po",
"chars": 15100,
"preview": "# Kazakh translation for gnome-music.\r\n# Copyright (C) 2026 gnome-music's COPYRIGHT HOLDER\r\n# This file is distributed u"
},
{
"path": "help/ko/ko.po",
"chars": 12841,
"preview": "# Korean translation for gnome-music.\n# Copyright (C) 2014 gnome-music's COPYRIGHT HOLDER\n# This file is distributed und"
},
{
"path": "help/meson.build",
"chars": 417,
"preview": "gnome.yelp(meson.project_name(),\n sources: [\n 'introduction.page',\n 'index.page',\n 'play-music.page',\n 'pla"
},
{
"path": "help/nl/nl.po",
"chars": 14827,
"preview": "# Dutch translation for gnome-music.\n# Copyright (C) 2016 gnome-music's COPYRIGHT HOLDER\n# This file is distributed unde"
},
{
"path": "help/pl/pl.po",
"chars": 14700,
"preview": "# Polish translation for gnome-music help.\n# Copyright © 2017 the gnome-music authors.\n# This file is distributed under "
},
{
"path": "help/pt_BR/pt_BR.po",
"chars": 15136,
"preview": "# Brazilian Portuguese translation for gnome-music.\n# Copyright (C) 2021 gnome-music's COPYRIGHT HOLDER\n# This file is d"
},
{
"path": "help/ro/ro.po",
"chars": 14923,
"preview": "# Romanian translation for gnome-music.\n# Copyright (C) 2014 gnome-music's COPYRIGHT HOLDER\n# This file is distributed u"
},
{
"path": "help/ru/ru.po",
"chars": 14911,
"preview": "# Russian translation for gnome-music.\n# Copyright (C) 2022 gnome-music's COPYRIGHT HOLDER\n# This file is distributed un"
},
{
"path": "help/sr/sr.po",
"chars": 14368,
"preview": "# Serbian translation for gnome-music.\n# Copyright (C) 2026 gnome-music's COPYRIGHT HOLDER\n# This file is distributed un"
},
{
"path": "help/sv/sv.po",
"chars": 14505,
"preview": "# Swedish translation for gnome-music.\n# Copyright © 2016-2022 gnome-music's COPYRIGHT HOLDER\n# This file is distributed"
},
{
"path": "help/tr/tr.po",
"chars": 14793,
"preview": "# Turkish translation for gnome-music.\n# Copyright (C) 2021 gnome-music's COPYRIGHT HOLDER\n# This file is distributed un"
},
{
"path": "help/uk/uk.po",
"chars": 15190,
"preview": "# Ukrainian translation for gnome-music.\n# Copyright (C) 2020 gnome-music's COPYRIGHT HOLDER\n# This file is distributed "
},
{
"path": "help/zh_CN/zh_CN.po",
"chars": 11037,
"preview": "# Chinese (China) translation for gnome-music.\n# Copyright (C) 2022 gnome-music's COPYRIGHT HOLDER\n# This file is distri"
},
{
"path": "meson.build",
"chars": 3742,
"preview": "project('gnome-music',\n version: '50.alpha',\n meson_version: '>= 0.59.0'\n)\n\n# Importing modules\ngnome = import('gn"
},
{
"path": "meson_options.txt",
"chars": 110,
"preview": "option(\n 'profile',\n type: 'combo',\n choices: [\n 'default',\n 'development'\n ],\n value: 'default'\n)\n"
},
{
"path": "org.gnome.Music.json",
"chars": 5192,
"preview": "{\n \"app-id\": \"org.gnome.Music.Devel\",\n \"runtime\": \"org.gnome.Platform\",\n \"runtime-version\": \"master\",\n \"sdk\""
},
{
"path": "po/LINGUAS",
"chars": 255,
"preview": "ab\naf\nan\nar\nas\nbe\nbg\nbs\nca\nca@valencia\ncs\nda\nde\nel\nen_GB\neo\nes\net\neu\nfa\nfi\nfr\nfur\nfy\nga\ngd\ngl\nhe\nhi\nhr\nhu\nia\nid\nis\nit\nja"
},
{
"path": "po/POTFILES.in",
"chars": 1373,
"preview": "# List of source files containing translatable strings.\n# Please keep this file sorted alphabetically.\ndata/org.gnome.Mu"
},
{
"path": "po/POTFILES.skip",
"chars": 160,
"preview": "# List of source files that should *not* be translated.\n# Please keep this file sorted alphabetically.\ndata/ui/AboutDial"
},
{
"path": "po/ab.po",
"chars": 16982,
"preview": "msgid \"\"\nmsgstr \"\"\n\"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-music/issues\\n\"\n\"POT-Creation-Date: 2023-"
},
{
"path": "po/af.po",
"chars": 7505,
"preview": "# Afrikaans translation for gnome-music.\n# This file is distributed under the same license as the gnome-music package.\n#"
},
{
"path": "po/an.po",
"chars": 14378,
"preview": "# Aragonese translation for gnome-music.\n# Copyright (C) 2014 gnome-music's COPYRIGHT HOLDER\n# This file is distributed "
},
{
"path": "po/ar.po",
"chars": 20196,
"preview": "# Arabic translation for gnome-music\n# Copyright (C) 2014, 2025 gnome-music's COPYRIGHT HOLDER\n# This file is distribute"
},
{
"path": "po/as.po",
"chars": 11515,
"preview": "# Assamese translation for gnome-music.\n# Copyright (C) 2013 gnome-music's COPYRIGHT HOLDER\n# This file is distributed u"
},
{
"path": "po/be.po",
"chars": 22714,
"preview": "# Belarusian translation for gnome-music.\n# Copyright (C) 2013 gnome-music's COPYRIGHT HOLDER\n# This file is distributed"
},
{
"path": "po/bg.po",
"chars": 17218,
"preview": "# Bulgarian translation for gnome-music po-file.\n# Copyright (C) 2016 Free Software Foundation, Inc.\n# Copyright (C) 202"
},
{
"path": "po/bs.po",
"chars": 13355,
"preview": "# Bosnian translation for bosnianuniversetranslation\n# Copyright (c) 2013 Rosetta Contributors and Canonical Ltd 2013\n# "
},
{
"path": "po/ca.po",
"chars": 19514,
"preview": "# Catalan translation for gnome-calendar.\n# Copyright (C) 2012 gnome-music's COPYRIGHT HOLDER\n# This file is distributed"
},
{
"path": "po/ca@valencia.po",
"chars": 17804,
"preview": "# Catalan translation for gnome-calendar.\n# Copyright (C) 2012 gnome-music's COPYRIGHT HOLDER\n# This file is distributed"
},
{
"path": "po/cs.po",
"chars": 19206,
"preview": "# Czech translation for gnome-music.\n# Copyright (C) 2013 gnome-music's COPYRIGHT HOLDER\n# This file is distributed unde"
},
{
"path": "po/da.po",
"chars": 23317,
"preview": "# Danish translation for gnome-music.\n# Copyright (C) 2013-2018 gnome-music's COPYRIGHT HOLDER\n# This file is distribute"
},
{
"path": "po/de.po",
"chars": 25370,
"preview": "# German translation for gnome-music.\n# Copyright (C) 2013 gnome-music's COPYRIGHT HOLDER\n# This file is distributed und"
},
{
"path": "po/el.po",
"chars": 26901,
"preview": "# Greek translation for gnome-music.\n# Copyright (C) 2013 gnome-music's COPYRIGHT HOLDER\n# This file is distributed unde"
},
{
"path": "po/en_GB.po",
"chars": 15708,
"preview": "# British English translation for gnome-music.\n# Copyright (C) 2012 gnome-music's COPYRIGHT HOLDER\n# This file is distri"
},
{
"path": "po/eo.po",
"chars": 25403,
"preview": "# Esperanto translation for gnome-music.\n# Copyright (C) 2013 Free Software Foundation, Inc.\n# This file is distributed "
},
{
"path": "po/es.po",
"chars": 26656,
"preview": "# Spanish translation for gnome-music.\n# Copyright (C) 2012 gnome-music's COPYRIGHT HOLDER\n# This file is distributed un"
},
{
"path": "po/et.po",
"chars": 6344,
"preview": "# Estonian translation for gnome-music.\n# Copyright (C) 2013 gnome-music's COPYRIGHT HOLDER\n# This file is distributed u"
},
{
"path": "po/eu.po",
"chars": 23928,
"preview": "# Basque translation for gnome-music.\n# Copyright (C) 2013 gnome-music's COPYRIGHT HOLDER\n# This file is distributed und"
},
{
"path": "po/fa.po",
"chars": 24593,
"preview": "# Persian translation for gnome-music.\n# Copyright (C) 2013 gnome-music's COPYRIGHT HOLDER\n# This file is distributed un"
},
{
"path": "po/fi.po",
"chars": 23017,
"preview": "# Finnish translation for gnome-music.\n# Copyright (C) 2013 gnome-music's COPYRIGHT HOLDER\n# This file is distributed un"
},
{
"path": "po/fr.po",
"chars": 20908,
"preview": "# French translation for gnome-music.\n# Copyright (C) 2013-2022 gnome-music's COPYRIGHT HOLDER\n# This file is distribute"
},
{
"path": "po/fur.po",
"chars": 24743,
"preview": "# Friulian translation for gnome-music.\n# Copyright (C) 2015 gnome-music's COPYRIGHT HOLDER\n# This file is distributed u"
},
{
"path": "po/fy.po",
"chars": 17834,
"preview": "msgid \"\"\r\nmsgstr \"\"\r\n\"Project-Id-Version: gnome-music master\\n\"\r\n\"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/g"
},
{
"path": "po/ga.po",
"chars": 6281,
"preview": "# Irish translations for gnome-music package.\n# Copyright (C) 2013 Free Software Foundation, Inc.\n# This file is distrib"
}
]
// ... and 50 more files (download for full content)
About this extraction
This page contains the full source code of the GNOME/gnome-music GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 250 files (2.3 MB), approximately 625.7k tokens, and a symbol index with 739 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.