Full Code of GNOME/gnome-music for AI

master 8a9e6c6e6947 cached
250 files
2.3 MB
625.7k tokens
739 symbols
1 requests
Download .txt
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 resultg

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.

![screenshot](https://gitlab.gnome.org/GNOME/gnome-music/-/raw/master/data/screenshots/gnome-music-1.png)

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>
Download .txt
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
Download .txt
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![screenshot](https://gitlab.gnome.org/GNOME/"
  },
  {
    "path": "data/meson.build",
    "chars": 3255,
    "preview": "# Compiling the resources\n# about_dialog is defined in data/ui/meson.build to generate the output file in that directory"
  },
  {
    "path": "data/org.gnome.Music.desktop.in.in",
    "chars": 498,
    "preview": "[Desktop Entry]\nName=Music\nGenericName=Music Player\nComment=Play and organize your music collection\n# Translators: Do NO"
  },
  {
    "path": "data/org.gnome.Music.gresource.xml",
    "chars": 3717,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<gresources>\n  <gresource prefix=\"/org/gnome/Music\">\n    <file alias=\"shortcuts-d"
  },
  {
    "path": "data/org.gnome.Music.gschema.xml",
    "chars": 2292,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<schemalist>\n    <enum id=\"org.gnome.Music.RepeatMode\">\n        <value nick=\"none"
  },
  {
    "path": "data/org.gnome.Music.metainfo.xml.in.in",
    "chars": 9621,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<component type=\"desktop-application\">\n  <id>@appid@</id>\n  <metadata_license>CC0"
  },
  {
    "path": "data/org.gnome.Music.service.in",
    "chars": 78,
    "preview": "[D-BUS Service]\nName=@appid@\nExec=@bindir@/gnome-music --gapplication-service\n"
  },
  {
    "path": "data/queries/album_disc.rq",
    "chars": 1077,
    "preview": "# Inputs: album_id, disc_nr\nSELECT\n  ?id\n  ?url\n  ?title\n  ?artist\n  ?album\n  ?duration\n  ?trackNumber\n  ?albumDiscNumbe"
  },
  {
    "path": "data/queries/album_discs.rq",
    "chars": 366,
    "preview": "# Inputs: album_id\nSELECT\n  ?albumDiscNumber\nWHERE {\n  SERVICE <dbus:{bus_name}> {\n    GRAPH tracker:Audio {\n      SELEC"
  },
  {
    "path": "data/queries/albums.rq",
    "chars": 859,
    "preview": "SELECT\n  ?type\n  ?id\n  ?title\n  ?composer\n  ?albumArtist\n  ?artist\n  ?url\n  ?publicationDate\nWHERE {\n  SERVICE <dbus:{bu"
  },
  {
    "path": "data/queries/artist_albums.rq",
    "chars": 691,
    "preview": "# Inputs: ~artist\nSELECT\n  ?id\n  ?title\n  ?publicationDate\nWHERE {\n  SERVICE <dbus:{bus_name}> {\n    GRAPH tracker:Audio"
  },
  {
    "path": "data/queries/artists.rq",
    "chars": 634,
    "preview": "SELECT\n  ?id\n  ?artist\nWHERE {\n  SERVICE <dbus:{bus_name}> {\n    GRAPH tracker:Audio {\n      SELECT\n       (COALESCE(?al"
  },
  {
    "path": "data/queries/playlist_add_song.rq",
    "chars": 469,
    "preview": "# Inputs: playlist, uri\nDELETE {\n  ~playlist nfo:entryCounter ?counter .\n}\nINSERT {\n  _:entry a nfo:MediaFileListEntry ;"
  },
  {
    "path": "data/queries/playlist_create.rq",
    "chars": 137,
    "preview": "INSERT {\n  ~playlist a nmm:Playlist ;\n            a nfo:MediaList ;\n              nie:title ~title ;\n              nfo:e"
  },
  {
    "path": "data/queries/playlist_delete.rq",
    "chars": 105,
    "preview": "DELETE WHERE {\n  ~playlist a rdfs:Resource ;\n            a nmm:Playlist ;\n            a nfo:MediaList .\n}"
  },
  {
    "path": "data/queries/playlist_delete_song.rq",
    "chars": 1178,
    "preview": "# Inputs: ~entry, ~playlist\nDELETE {\n  ?entry nfo:listPosition ?old_position .\n}\nINSERT {\n  ?entry nfo:listPosition ?new"
  },
  {
    "path": "data/queries/playlist_query_all.rq",
    "chars": 245,
    "preview": "SELECT DISTINCT\n    ?playlist AS ?id\n    ?title\n    ?creationDate\n    ?childCount\nWHERE\n{\n    ?playlist a nmm:Playlist ;"
  },
  {
    "path": "data/queries/playlist_query_delete_entry.rq",
    "chars": 256,
    "preview": "# Inputs: playlist, position\nSELECT\n  ?entry AS ?id\n  WHERE {\n  ~playlist_id a nmm:Playlist ;\n               a nfo:Media"
  },
  {
    "path": "data/queries/playlist_query_playlist.rq",
    "chars": 264,
    "preview": "# Inputs: playlist\nSELECT DISTINCT\n    ~playlist AS ?id\n    ?title\n    ?creationDate\n    ?childCount\nWHERE\n{\n    ~playli"
  },
  {
    "path": "data/queries/playlist_query_songs.rq",
    "chars": 935,
    "preview": "# Inputs: playlist, miner_fs_busname, location_filter\nSELECT\n  ?song AS ?id\n  ?url\n  ?title\n  ?artist\n  ?album\n  ?durati"
  },
  {
    "path": "data/queries/playlist_rename_title.rq",
    "chars": 185,
    "preview": "DELETE {\n  ~playlist nie:title ?title .\n}\nINSERT {\n  ~playlist nie:title ~title .\n}\nWHERE {\n  ~playlist a nmm:Playlist ;"
  },
  {
    "path": "data/queries/playlist_reorder_songs.rq",
    "chars": 288,
    "preview": "# Inputs: id, old_position, new_position\nDELETE {\n  ?entry nfo:listPosition ~old_position .\n}\nINSERT {\n  ?entry nfo:list"
  },
  {
    "path": "data/queries/search_albums.rq",
    "chars": 1138,
    "preview": "# Inputs: name\nSELECT\n  ?id\nWHERE {\n  SERVICE <dbus:{bus_name}> {\n    GRAPH tracker:Audio {\n      SELECT DISTINCT\n      "
  },
  {
    "path": "data/queries/search_artists.rq",
    "chars": 1410,
    "preview": "# Inputs: name\nSELECT\n  ?id\nWHERE {\n  SERVICE <dbus:{bus_name}> {\n    GRAPH tracker:Audio {\n      SELECT DISTINCT\n      "
  },
  {
    "path": "data/queries/search_songs.rq",
    "chars": 1122,
    "preview": "# Inputs: name\nSELECT\n  ?id\nWHERE {\n  SERVICE <dbus:{bus_name}> {\n    GRAPH tracker:Audio {\n      SELECT DISTINCT\n      "
  },
  {
    "path": "data/queries/songs.rq",
    "chars": 951,
    "preview": "SELECT\n  ?urn\n  ?title\n  ?id\n  ?url\n  ?artist\n  ?album\n  ?duration\n  ?trackNumber\n  ?albumDiscNumber\n  nie:contentAccess"
  },
  {
    "path": "data/style.css",
    "chars": 1761,
    "preview": "/* AlbumCover/AlbumTile */\n.artist-label {\n    font-size: smaller;\n}\n\n/* AlbumsView */\n\n#albums gridview {\n    padding: "
  },
  {
    "path": "data/ui/AlbumCover.ui",
    "chars": 187,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<interface>\n  <template class=\"AlbumCover\" parent=\"GtkFlowBoxChild\">\n    <style>\n"
  },
  {
    "path": "data/ui/AlbumNavigationPage.ui",
    "chars": 916,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<interface>\n  <requires lib=\"gtk\" version=\"4.0\"/>\n  <template class=\"AlbumNavigat"
  },
  {
    "path": "data/ui/AlbumTile.ui",
    "chars": 1268,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<interface>\n  <requires lib=\"gtk\" version=\"4.0\"/>\n  <template class=\"AlbumTile\" p"
  },
  {
    "path": "data/ui/AlbumWidget.ui",
    "chars": 6613,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<interface>\n  <template class=\"AlbumWidget\" parent=\"AdwBin\">\n    <child>\n      <o"
  },
  {
    "path": "data/ui/AlbumsSearchNavigationPage.ui",
    "chars": 2504,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<interface>\n  <requires lib=\"gtk\" version=\"4.0\"/>\n  <template class=\"AlbumsSearch"
  },
  {
    "path": "data/ui/AlbumsView.ui",
    "chars": 497,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<interface>\n  <requires lib=\"gtk\" version=\"4.0\"/>\n  <template class=\"AlbumsView\" "
  },
  {
    "path": "data/ui/ArtistAlbumsWidget.ui",
    "chars": 598,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<interface>\n  <requires lib=\"gtk\" version=\"4.0\"/>\n  <template class=\"ArtistAlbums"
  },
  {
    "path": "data/ui/ArtistNavigationPage.ui",
    "chars": 784,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<interface>\n  <requires lib=\"gtk\" version=\"4.0\"/>\n  <template class=\"ArtistNaviga"
  },
  {
    "path": "data/ui/ArtistSearchTile.ui",
    "chars": 1109,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<interface>\n  <template class=\"ArtistSearchTile\" parent=\"GtkFlowBoxChild\">\n    <c"
  },
  {
    "path": "data/ui/ArtistTile.ui",
    "chars": 1058,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<interface>\n  <template class=\"ArtistTile\" parent=\"GtkBox\">\n    <property name=\"f"
  },
  {
    "path": "data/ui/ArtistsSearchNavigationPage.ui",
    "chars": 2508,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<interface>\n  <requires lib=\"gtk\" version=\"4.0\"/>\n  <template class=\"ArtistsSearc"
  },
  {
    "path": "data/ui/ArtistsView.ui",
    "chars": 925,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<interface>\n  <requires lib=\"gtk\" version=\"4.0\"/>\n  <template class=\"ArtistsView\""
  },
  {
    "path": "data/ui/DiscBox.ui",
    "chars": 697,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<interface>\n  <requires lib=\"gtk\" version=\"4.0\"/>\n  <template parent=\"GtkListBoxR"
  },
  {
    "path": "data/ui/DiscListItem.ui",
    "chars": 895,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<interface>\n  <requires lib=\"gtk+\" version=\"4.0\"/>\n  <template class=\"DiscListIte"
  },
  {
    "path": "data/ui/HeaderBar.ui",
    "chars": 1858,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<interface>\n  <template class=\"HeaderBar\" parent=\"AdwBin\">\n    <child>\n      <obj"
  },
  {
    "path": "data/ui/PlayerToolbar.ui",
    "chars": 7954,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<interface>\n  <requires lib=\"gtk\" version=\"4.0\"/>\n  <template class=\"PlayerToolba"
  },
  {
    "path": "data/ui/PlaylistControls.ui",
    "chars": 5320,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<interface>\n  <menu id=\"playlistMenu\">\n    <item>\n      <attribute name=\"label\" t"
  },
  {
    "path": "data/ui/PlaylistDialog.ui",
    "chars": 10651,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<interface>\n  <requires lib=\"gtk\" version=\"4.0\"/>\n  <template class=\"PlaylistDial"
  },
  {
    "path": "data/ui/PlaylistDialogRow.ui",
    "chars": 939,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<interface>\n  <template class=\"PlaylistDialogRow\" parent=\"GtkListBoxRow\">\n    <st"
  },
  {
    "path": "data/ui/PlaylistTile.ui",
    "chars": 1156,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<interface>\n  <template class=\"PlaylistTile\" parent=\"GtkListBoxRow\">\n    <child>\n"
  },
  {
    "path": "data/ui/PlaylistsView.ui",
    "chars": 937,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<interface>\n  <requires lib=\"gtk\" version=\"4.0\"/>\n  <template class=\"PlaylistsVie"
  },
  {
    "path": "data/ui/PlaylistsWidget.ui",
    "chars": 1191,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<interface>\n  <template class=\"PlaylistsWidget\" parent=\"GtkBox\">\n    <property na"
  },
  {
    "path": "data/ui/PreferencesDialog.ui",
    "chars": 2366,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<interface>\n  <template class=\"PreferencesDialog\" parent=\"AdwPreferencesDialog\">\n"
  },
  {
    "path": "data/ui/RepeatModeButton.ui",
    "chars": 664,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<interface>\n  <template class=\"RepeatModeButton\" parent=\"GtkBox\">\n    <child>\n   "
  },
  {
    "path": "data/ui/SearchHeaderBar.ui",
    "chars": 668,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<interface>\n  <template class=\"SearchHeaderBar\" parent=\"AdwBin\">\n    <child>\n    "
  },
  {
    "path": "data/ui/SearchView.ui",
    "chars": 11124,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<interface>\n  <template class=\"SearchView\" parent=\"AdwNavigationPage\">\n    <prope"
  },
  {
    "path": "data/ui/SongWidget.ui",
    "chars": 6129,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<interface>\n  <requires lib=\"gtk\" version=\"4.0\"/>\n  <template class=\"SongWidget\" "
  },
  {
    "path": "data/ui/SongWidgetMenu.ui",
    "chars": 859,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<interface>\n  <template class=\"SongWidgetMenu\" parent=\"GtkPopoverMenu\">\n    <prop"
  },
  {
    "path": "data/ui/StatusNavigationPage.ui",
    "chars": 2006,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<interface>\n  <template class=\"StatusNavigationPage\" parent=\"AdwNavigationPage\">\n"
  },
  {
    "path": "data/ui/TwoLineTip.ui",
    "chars": 730,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<interface>\n  <template class=\"TwoLineTip\" parent=\"GtkBox\">\n    <property name=\"f"
  },
  {
    "path": "data/ui/VolumeButton.ui",
    "chars": 2023,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<interface>\n  <template class=\"VolumeButton\" parent=\"GtkBox\">\n    <child>\n      <"
  },
  {
    "path": "data/ui/Window.ui",
    "chars": 2754,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<interface>\n  <requires lib=\"gtk\" version=\"4.0\"/>\n  <template class=\"Window\" pare"
  },
  {
    "path": "data/ui/shortcuts-dialog.ui",
    "chars": 5225,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<interface>\n  <object class=\"AdwShortcutsDialog\" id=\"shortcuts_dialog\">\n    <chil"
  },
  {
    "path": "gnome-music.doap",
    "chars": 1280,
    "preview": "<Project xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"\n         xmlns:rdfs=\"http://www.w3.org/2000/01/rdf-sche"
  },
  {
    "path": "gnome-music.in",
    "chars": 3567,
    "preview": "#!/usr/bin/env python3\n# Copyright © 2018 The GNOME Music Developers\n#\n# GNOME Music is free software; you can redistrib"
  },
  {
    "path": "gnomemusic/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "gnomemusic/about.py",
    "chars": 4517,
    "preview": "# aboutwindow.py\n#\n# Copyright 2022 Christopher Davis <christopherdavis@gnome.org>\n#\n# This program is free software: yo"
  },
  {
    "path": "gnomemusic/albumart.py",
    "chars": 3101,
    "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/application.py",
    "chars": 10631,
    "preview": "# Copyright (c) 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.

Copied to clipboard!