...
 
Commits (155)
Overview of changes in 3.30.2
=============================
Overview of changes in 3.31.90
==============================
* Delayed loading of remote cover art
* Fix keyboard shortcuts
* Flatpak fixes
* 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:
flatpak: Grilo lua plugin support is disabled (#226)
Almost none of the keyboard shortcuts work (#238)
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:
Serbian
Czech
Slovenian
Esperanto
Spanish
French
Greek
Friulian
Swedish
Hungarian
Galician
Romanian
Indonesian
Italian
Finnish
Turkish
Polish
Catalan
Hungarian
Overview of changes in 3.30.1
Overview of changes in 3.31.1
=============================
* Replace app menu with Primary menu (initiative #4)
* Add TheAudioDB for coverart lookup
* Dark mode fixes
* Add TheAudioDB support for coverart
* Fix issues with repeatmode handling
* Fix crash on opening help
* New app icon (initiative #2)
* Flatpak fixes
Bugs fixed:
albumwidget: Fix checkbox selection (!245)
Set the appliation id correctly (!241)
Add TheAudioDB support (!247)
Do not switch view in selection mode (!246)
Dark mode fixes (!269,!271)
player: Synchronize Player and PlayerPlaylist repeat-mode (!274)
Music crashes when accessing help with Yelp not installed (#220)
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:
Russian
Spanish
Serbian
Overview of changes in 3.30.0
=============================
......
......@@ -176,4 +176,8 @@ Problem in some detail.
Implemented fix.
Closes: #issuenr
>>>
\ No newline at end of file
>>>
## 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.
\ No newline at end of file
<interface>
<menu id="app-menu">
<section>
<item>
<attribute name="label" translatable="yes">_Keyboard Shortcuts</attribute>
<attribute name="action">win.show-help-overlay</attribute>
</item>
<item>
<attribute name="label" translatable="yes">_Help</attribute>
<attribute name="action">app.help</attribute>
<attribute name="accel">F1</attribute>
</item>
<item>
<attribute name="action">app.about</attribute>
<attribute name="label" translatable="yes">_About</attribute>
</item>
<item>
<attribute name="action">app.quit</attribute>
<attribute name="label" translatable="yes">_Quit</attribute>
<attribute name="accel">&lt;Primary&gt;q</attribute>
</item>
</section>
</menu>
</interface>
This diff is collapsed.
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 0 128 128"
style="display:inline;enable-background:new"
version="1.0"
id="svg11300"
height="128"
width="128">
<title
id="title4162">Adwaita Icon Template</title>
<defs
id="defs3">
<linearGradient
id="linearGradient1093">
<stop
id="stop1089"
offset="0"
style="stop-color:#f6d32d;stop-opacity:1" />
<stop
id="stop1091"
offset="1"
style="stop-color:#f9f06b;stop-opacity:1" />
</linearGradient>
<linearGradient
id="linearGradient2619">
<stop
style="stop-color:#c4a000;stop-opacity:1"
offset="0"
id="stop2615" />
<stop
style="stop-color:#edd400;stop-opacity:0"
offset="1"
id="stop2617" />
</linearGradient>
<linearGradient
id="linearGradient1171">
<stop
id="stop1165"
offset="0"
style="stop-color:#40494c;stop-opacity:1" />
<stop
style="stop-color:#232829;stop-opacity:1"
offset="0.57201189"
id="stop1167" />
<stop
id="stop1169"
offset="1"
style="stop-color:#000000;stop-opacity:1" />
</linearGradient>
<radialGradient
r="160"
fy="16.275131"
fx="280"
cy="16.275131"
cx="280"
gradientTransform="matrix(1,0,0,1.1758925,0,-118.6378)"
gradientUnits="userSpaceOnUse"
id="radialGradient1073"
xlink:href="#linearGradient2619" />
<radialGradient
r="56"
fy="65.435539"
fx="265.28162"
cy="65.435539"
cx="265.28162"
gradientTransform="matrix(1.3372396,0.35831226,-0.35833822,1.3373363,-60.03431,-112.79804)"
gradientUnits="userSpaceOnUse"
id="radialGradient1075"
xlink:href="#linearGradient1171" />
<linearGradient
gradientTransform="translate(-246.01698,-371.37682)"
gradientUnits="userSpaceOnUse"
y2="91.300674"
x2="431.13885"
y1="91.300674"
x1="99.845581"
id="linearGradient1095"
xlink:href="#linearGradient1093" />
</defs>
<metadata
id="metadata4">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:creator>
<cc:Agent>
<dc:title>GNOME Design Team</dc:title>
</cc:Agent>
</dc:creator>
<dc:source />
<cc:license
rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/" />
<dc:title>Adwaita Icon Template</dc:title>
<dc:subject>
<rdf:Bag />
</dc:subject>
<dc:date />
<dc:rights>
<cc:Agent>
<dc:title />
</cc:Agent>
</dc:rights>
<dc:publisher>
<cc:Agent>
<dc:title />
</cc:Agent>
</dc:publisher>
<dc:identifier />
<dc:relation />
<dc:language />
<dc:coverage />
<dc:description />
<dc:contributor>
<cc:Agent>
<dc:title />
</cc:Agent>
</dc:contributor>
</cc:Work>
<cc:License
rdf:about="http://creativecommons.org/licenses/by-sa/4.0/">
<cc:permits
rdf:resource="http://creativecommons.org/ns#Reproduction" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#Distribution" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#Notice" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#Attribution" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#ShareAlike" />
</cc:License>
</rdf:RDF>
</metadata>
<g
transform="translate(0,-172)"
style="display:inline"
id="layer1">
<g
style="display:inline"
id="layer9">
<rect
ry="8"
rx="8"
y="184"
x="12.000001"
height="104"
width="104"
id="rect15122"
style="display:inline;opacity:1;vector-effect:none;fill:#5e5c64;fill-opacity:1;stroke:none;stroke-width:0.01200435px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal;enable-background:new" />
<circle
r="60"
cy="236"
cx="64"
id="path15129"
style="display:inline;opacity:1;vector-effect:none;fill:#5e5c64;fill-opacity:1;stroke:none;stroke-width:0.01200435px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal;enable-background:new" />
<g
id="g1061"
transform="matrix(0.26562505,0,0,0.26562505,-10.395244,230.82553)"
style="display:inline;enable-background:new">
<g
transform="rotate(-30,413.50258,270.491)"
id="g1045" />
<ellipse
ry="195.77086"
rx="195.76466"
cy="19.474165"
cx="280.07614"
id="ellipse1049"
style="display:inline;opacity:1;vector-effect:none;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.04607898px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal;enable-background:new" />
<ellipse
style="display:inline;opacity:1;vector-effect:none;fill:#2a2a3b;fill-opacity:1;stroke:none;stroke-width:0.04591639px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal;enable-background:new"
id="ellipse1051"
cx="280.07614"
cy="19.47464"
rx="180.70584"
ry="180.71156" />
<ellipse
transform="rotate(90)"
ry="165.65254"
rx="165.64664"
cy="-280.07614"
cx="19.475237"
id="ellipse1053"
style="display:inline;opacity:1;vector-effect:none;fill:url(#linearGradient1095);fill-opacity:1;stroke:none;stroke-width:0.04678777px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal;enable-background:new" />
<circle
cy="20.005707"
cx="280"
id="circle1055"
style="display:inline;opacity:1;vector-effect:none;fill:url(#radialGradient1073);fill-opacity:1;stroke:none;stroke-width:0.04519285px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal;enable-background:new"
r="0" />
<ellipse
ry="75.299042"
rx="75.294106"
cy="19.475416"
cx="280.07617"
id="ellipse1057"
style="display:inline;opacity:1;vector-effect:none;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.04726049px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal;enable-background:new" />
<ellipse
transform="rotate(-15)"
ry="60.239342"
rx="60.234993"
cy="91.305618"
cx="265.49091"
id="ellipse1059"
style="display:inline;opacity:1;vector-effect:none;fill:url(#radialGradient1075);fill-opacity:1;stroke:none;stroke-width:0.04861055px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal;enable-background:new" />
</g>
<path
d="m 24.000056,278 a 1.9999996,2.0364742 0 0 1 -2,2.03648 1.9999996,2.0364742 0 0 1 -2,-2.03648 1.9999996,2.0364742 0 0 1 2,-2.03647 1.9999996,2.0364742 0 0 1 2,2.03647 z m 84.000004,0 a 1.9999996,2.0364742 0 0 1 -2,2.03648 1.9999996,2.0364742 0 0 1 -2,-2.03648 1.9999996,2.0364742 0 0 1 2,-2.03647 1.9999996,2.0364742 0 0 1 2,2.03647 z m 0,-84.00001 a 1.9999996,2.0364742 0 0 1 -2,2.03648 1.9999996,2.0364742 0 0 1 -2,-2.03648 1.9999996,2.0364742 0 0 1 2,-2.03647 1.9999996,2.0364742 0 0 1 2,2.03647 z m -84.000004,0 a 1.9999996,2.0364742 0 0 1 -2,2.03648 1.9999996,2.0364742 0 0 1 -2,-2.03648 1.9999996,2.0364742 0 0 1 2,-2.03647 1.9999996,2.0364742 0 0 1 2,2.03647 z"
style="display:inline;opacity:1;vector-effect:none;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.00896273px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal;enable-background:new"
id="path1116-3" />
</g>
</g>
</svg>
# Compiling the resources
VCS_TAG = ''
if get_option('profile') != 'default'
git = find_program('git', required : false)
if git.found()
VCS_TAG = run_command('git', 'rev-parse', '--short', 'HEAD').stdout().strip()
endif
if VCS_TAG == ''
VCS_TAG = '-devel'
else
VCS_TAG = '-@0@'.format(VCS_TAG)
endif
endif
about_dialog_conf = configuration_data()
about_dialog_conf.set('PACKAGE_VERSION', '@0@@1@'.format(meson.project_version(), VCS_TAG))
about_dialog_conf.set('PACKAGE_URL', PACKAGE_URL)
about_dialog_conf.set('PROGRAM_NAME', 'Music' + NAME_SUFFIX)
about_dialog_conf.set('APPID', APPLICATION_ID)
# 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: '.',
source_dir: meson.current_build_dir(),
install_dir: PKGDATA_DIR,
install: true,
dependencies: configure_file(
input: 'AboutDialog.ui.in',
output: 'AboutDialog.ui',
configuration: about_dialog_conf
)
dependencies: about_dialog
)
# Installing the schema file
......@@ -65,6 +44,8 @@ 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)
i18n.merge_file(
'appdata',
input: configure_file(
......@@ -89,13 +70,13 @@ if appstreamcli.found()
endif
# Installing the icons
icon_sizes = ['16', '22', '32', '48', '256']
icon_sizes = ['scalable']
foreach i : icon_sizes
install_data(
join_paths('icons/hicolor', i + 'x' + i, 'apps', PROJECT_RDNN_NAME + '.png'),
install_dir: join_paths(get_option('prefix'), get_option('datadir'), 'icons', 'hicolor', i + 'x' + i, 'apps'),
rename: '@0@.png'.format(APPLICATION_ID)
join_paths('icons/hicolor', i , 'apps', PROJECT_RDNN_NAME + '.svg'),
install_dir: join_paths(get_option('prefix'), get_option('datadir'), 'icons', 'hicolor', i , 'apps'),
rename: '@0@.svg'.format(APPLICATION_ID)
)
endforeach
......
......@@ -28,8 +28,8 @@
</screenshot>
</screenshots>
<project_group>GNOME</project_group>
<url type="homepage">https://wiki.gnome.org/Apps/Music</url>
<url type="bugtracker">https://gitlab.gnome.org/GNOME/gnome-music/issues</url>
<url type="homepage">@package_url@</url>
<url type="bugtracker">@package_url_bug@</url>
<url type="donation">https://www.gnome.org/friends/</url>
<url type="help">https://help.gnome.org/users/gnome-music/stable/</url>
<kudos>
......
@binding-set unbind-ctrl-space {
unbind "<ctrl>space";
}
/* Use widget for libgd classes, since they aren't updated
to gtk+-3.20 css naming yet. */
flowbox, treeview, widget {
-gtk-key-bindings: unbind-ctrl-space;
}
.discsongsflowbox > flowboxchild {
padding: 0px;
}
......@@ -56,10 +46,6 @@ box#ArtistAlbumsWidget .artist-label {
}
/* ArtistAlbumWidget */
.album-cover {
padding-left:24px;
}
.album-title {
padding-left:24px;
font-weight: bold;
......@@ -104,36 +90,6 @@ box#ArtistAlbumsWidget .artist-label {
font-weight: bold;
}
/* visual hint for development */
.devel headerbar {
background: transparent -gtk-icontheme("system-run-symbolic") 80% 0/128px 128px no-repeat,
linear-gradient(to left,
mix(@theme_fg_color, @theme_bg_color, 0.5) 0%,
@theme_bg_color 25%);
color: alpha(@theme_fg_color, 0.2);
}
.devel headerbar label {
color: @theme_fg_color;
}
.devel headerbar.selection-mode {
background: transparent -gtk-icontheme("system-run-symbolic") 80% 0/128px 128px no-repeat,
linear-gradient(to left,
@theme_selected_bg_color 0%,
@theme_selected_bg_color 25%);
color: alpha(@theme_fg_color, 0.2);
}
.devel headerbar.selection-mode label {
color: @theme_selected_fg_color;
}
/* headerbar - smooth selection-mode transition */
headerbar {
transition: 250ms ease-in-out;
}
/* TwoLineTip */
.tooltip-title {
font-weight: bold;
......
<?xml version="1.0" encoding="UTF-8"?>
<gresources>
<gresource prefix="/org/gnome/Music">
<file preprocess="xml-stripblanks">AboutDialog.ui</file>
<file alias="gtk/menus.ui" preprocess="xml-stripblanks">app-menu.ui</file>
<file alias="gtk/help-overlay.ui" preprocess="xml-stripblanks">help-overlay.ui</file>
<file>application.css</file>
<file>initial-state.png</file>
<file preprocess="xml-stripblanks">AlbumCover.ui</file>
<file preprocess="xml-stripblanks">AlbumWidget.ui</file>
<file preprocess="xml-stripblanks">ArtistAlbumWidget.ui</file>
<file preprocess="xml-stripblanks">ArtistAlbumsWidget.ui</file>
<file preprocess="xml-stripblanks">DiscBox.ui</file>
<file preprocess="xml-stripblanks">DropDown.ui</file>
<file preprocess="xml-stripblanks">EmptyView.ui</file>
<file preprocess="xml-stripblanks">FilterView.ui</file>
<file preprocess="xml-stripblanks">PlayerToolbar.ui</file>
<file preprocess="xml-stripblanks">Searchbar.ui</file>
<file preprocess="xml-stripblanks">SelectionBarMenuButton.ui</file>
<file preprocess="xml-stripblanks">SelectionToolbar.ui</file>
<file preprocess="xml-stripblanks">SidebarRow.ui</file>
<file preprocess="xml-stripblanks">SongWidget.ui</file>
<file preprocess="xml-stripblanks">HeaderBar.ui</file>
<file preprocess="xml-stripblanks">PlaylistContextMenu.ui</file>
<file preprocess="xml-stripblanks">PlaylistControls.ui</file>
<file preprocess="xml-stripblanks">PlaylistDialog.ui</file>
<file preprocess="xml-stripblanks">TwoLineTip.ui</file>
<file alias="gtk/help-overlay.ui" preprocess="xml-stripblanks">ui/help-overlay.ui</file>
<file>org.gnome.Music.css</file>
<file>icons/initial-state.png</file>
<file preprocess="xml-stripblanks">ui/AboutDialog.ui</file>
<file preprocess="xml-stripblanks">ui/AlbumCover.ui</file>
<file preprocess="xml-stripblanks">ui/AlbumWidget.ui</file>
<file preprocess="xml-stripblanks">ui/AppMenu.ui</file>
<file preprocess="xml-stripblanks">ui/ArtistAlbumWidget.ui</file>
<file preprocess="xml-stripblanks">ui/ArtistAlbumsWidget.ui</file>
<file preprocess="xml-stripblanks">ui/DiscBox.ui</file>
<file preprocess="xml-stripblanks">ui/DropDown.ui</file>
<file preprocess="xml-stripblanks">ui/EmptyView.ui</file>
<file preprocess="xml-stripblanks">ui/FilterView.ui</file>
<file preprocess="xml-stripblanks">ui/HeaderBar.ui</file>
<file preprocess="xml-stripblanks">ui/PlayerToolbar.ui</file>
<file preprocess="xml-stripblanks">ui/PlaylistContextMenu.ui</file>
<file preprocess="xml-stripblanks">ui/PlaylistControls.ui</file>
<file preprocess="xml-stripblanks">ui/PlaylistDialog.ui</file>
<file preprocess="xml-stripblanks">ui/Searchbar.ui</file>
<file preprocess="xml-stripblanks">ui/SelectionBarMenuButton.ui</file>
<file preprocess="xml-stripblanks">ui/SelectionToolbar.ui</file>
<file preprocess="xml-stripblanks">ui/SidebarRow.ui</file>
<file preprocess="xml-stripblanks">ui/SongWidget.ui</file>
<file preprocess="xml-stripblanks">ui/TwoLineTip.ui</file>
</gresource>
</gresources>
......@@ -34,6 +34,7 @@ Bruce Cowan
Carlos Garnacho
Carlos Soriano
Christophe van den Abbeele
Christopher Davis
Clayton G. Hobbs
Divyanshu Vishwakarma
Eslam Mostafa
......@@ -46,6 +47,9 @@ Gaurav Narula
Georges Basile Stavracas Neto
Guillaume Quintard
Gyanesh Malhotra
Harry Xie
Islam Bahnasy
Jakub Steiner
Janne Körkkö
Jan-Michael Brummer
Jean Felder
......@@ -58,8 +62,10 @@ Kalev Lember
Kevin Haller
Konstantin Pospelov
Marinus Schraal
Mohanna Datta Yelugoti
Nick Richards
Niels De Graef
Nikolay Yanchuk
Pablo Palácios
Phil Dawson
Piotr Drąg
......@@ -73,6 +79,7 @@ Shivani Poddar
Shivansh Handa
Subhadip Jana
Suyash Garg
Tapasweni Pathak
Taylor Garcia
Vadim Rutkovsky
Yash Singh
......@@ -94,6 +101,7 @@ Balázs Meskó
Balázs Úr
Baurzhan Muftakhidinov
Bruce Cowan
Carmen Bianca Bakker
Cédric Valmary
Chao-Hsiung Liao
Charles Monzat
......@@ -136,6 +144,7 @@ Osman Karagöz
Piotr Drąg
Rafael Fontenelle
Rūdolfs Mazurs
Sabri Ünal
Sebastian Rasmussen
Seong-ho Cho
Stas Solovey
......
......@@ -3,6 +3,7 @@
<interface>
<requires lib="gtk+" version="3.12"/>
<template class="AlbumWidget" parent="GtkEventBox">
<property name="visible">True</property>
<style>
<class name="view"/>
<class name="content-view"/>
......@@ -30,7 +31,7 @@
<property name="orientation">vertical</property>
<property name="spacing">18</property>
<child>
<object class="GtkImage" id="_cover">
<object class="CoverStack" id="_cover_stack">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">center</property>
......
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.22.1 -->
<interface>
<requires lib="gtk+" version="3.20"/>
<template class="AppMenu" parent="GtkPopoverMenu">
<property name="can_focus">False</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin">6</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkModelButton" id="_keyboard_shortcuts_model_button">
<property name="halign">fill</property>
<property name="hexpand">False</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="action_name">win.show-help-overlay</property>
<property name="text" translatable="yes">_Keyboard Shortcuts</property>
</object>
<packing>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkModelButton" id="_help_model_button">
<property name="halign">fill</property>
<property name="hexpand">False</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="action_name">app.help</property>
<property name="text" translatable="yes">_Help</property>
</object>
<packing>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkModelButton" id="_about_model_button">
<property name="halign">fill</property>
<property name="hexpand">False</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="action_name">app.about</property>
<property name="text" translatable="yes">_About Music</property>
</object>
<packing>
<property name="position">2</property>
</packing>
</child>
</object>
<packing>
<property name="submenu">main</property>
<property name="position">1</property>
</packing>
</child>
</template>
</interface>
......@@ -4,6 +4,29 @@
<template class="HeaderBar" parent="GtkHeaderBar">
<property name="visible">True</property>
<property name="vexpand">False</property>
<child>
<object class="GtkMenuButton" id="_menu_button">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="valign">center</property>
<property name="sensitive">True</property>
<property name="tooltip_text" translatable="yes">Menu</property>
<style>
<class name="image-button"/>
</style>
<child>
<object class="GtkImage" id="_menu_button_image">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="icon-name">open-menu-symbolic</property>
<property name="icon-size">1</property>
</object>
</child>
</object>
<packing>
<property name="pack_type">end</property>
</packing>
</child>
<child>
<object class="GtkToggleButton" id="_search_button">
<property name="visible">True</property>
......
......@@ -201,7 +201,6 @@
<property name="valign">center</property>
<property name="hexpand">True</property>
<property name="draw_value">False</property>
<signal name = "seek-finished" handler="_on_seek_finished" swapped="no"/>
<signal name = "value-changed" handler="_on_progress_value_changed" swapped="no"/>
</object>
</child>
......@@ -292,7 +291,7 @@
<object class="GtkImage" id="downArrow">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="icon_name">go-down-symbolic</property>
<property name="icon_name">pan-down-symbolic</property>
<property name="icon_size">1</property>
</object>
<packing>
......
......@@ -39,7 +39,7 @@
<object class="GtkImage">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="icon-name">go-down-symbolic</property>
<property name="icon-name">pan-down-symbolic</property>
</object>
<packing>
<property name="pack-type">start</property>
......
# AboutDialog.ui configuration
VCS_TAG = ''
if get_option('profile') != 'default'
git = find_program('git', required : false)
if git.found()
VCS_TAG = run_command('git', 'rev-parse', '--short', 'HEAD').stdout().strip()
endif
if VCS_TAG == ''
VCS_TAG = '-devel'
else
VCS_TAG = '-@0@'.format(VCS_TAG)
endif
endif
about_dialog_conf = configuration_data()
about_dialog_conf.set('PACKAGE_VERSION', '@0@@1@'.format(meson.project_version(), VCS_TAG))
about_dialog_conf.set('PACKAGE_URL', PACKAGE_URL)
about_dialog_conf.set('PROGRAM_NAME', 'Music' + NAME_SUFFIX)
about_dialog_conf.set('APPID', APPLICATION_ID)
about_dialog = configure_file(
input: 'AboutDialog.ui.in',
output: 'AboutDialog.ui',
configuration: about_dialog_conf
)
\ No newline at end of file
gnome-music (3.31.90-1) experimental; urgency=medium
* New upstream development release
* Bump minimum libgtk-3-dev to 3.23.1
* Build-Depend on debhelper-compat 12 and drop debian/compat
* Bump Standards-Version to 4.3.0
-- Jeremy Bicha <jbicha@debian.org> Fri, 08 Feb 2019 11:41:34 -0500
gnome-music (3.30.2-1) unstable; urgency=medium
* New upstream release
......
......@@ -7,7 +7,7 @@ Section: gnome
Priority: optional
Maintainer: Debian GNOME Maintainers <pkg-gnome-maintainers@lists.alioth.debian.org>
Uploaders: Jeremy Bicha <jbicha@debian.org>, Tim Lunn <tim@feathertop.org>
Build-Depends: debhelper (>= 11),
Build-Depends: debhelper-compat (= 12),
dh-python,
gnome-pkg-tools (>= 0.11),
gobject-introspection (>= 1.35.9),
......@@ -18,7 +18,7 @@ Build-Depends: debhelper (>= 11),
libglib2.0-dev (>= 2.35.9),
libgoa-1.0-dev,
libgrilo-0.3-dev (>= 0.3.4),
libgtk-3-dev (>= 3.19.3),
libgtk-3-dev (>= 3.23.1),
libmediaart-2.0-dev (>= 1.9.1),
libsoup2.4-dev,
libtracker-sparql-2.0-dev (>= 1.99.1),
......@@ -28,7 +28,7 @@ Build-Depends: debhelper (>= 11),
python3,
python3-cairo-dev (>= 1.14.0)
Rules-Requires-Root: no
Standards-Version: 4.2.1
Standards-Version: 4.3.0
Vcs-Browser: https://salsa.debian.org/gnome-team/gnome-music
Vcs-Git: https://salsa.debian.org/gnome-team/gnome-music.git
Homepage: https://wiki.gnome.org/Apps/Music
......@@ -41,7 +41,7 @@ Depends: gir1.2-dazzle-1.0 (>= 3.28.0),
gir1.2-grilo-0.3 (>= 0.3.4),
gir1.2-gst-plugins-base-1.0,
gir1.2-gstreamer-1.0,
gir1.2-gtk-3.0 (>= 3.19.3),
gir1.2-gtk-3.0 (>= 3.23.1),
gir1.2-mediaart-2.0 (>= 1.9.1),
gir1.2-soup-2.4,
gir1.2-totemplparser-1.0,
......
......@@ -3,7 +3,7 @@ Section: gnome
Priority: optional
Maintainer: Debian GNOME Maintainers <pkg-gnome-maintainers@lists.alioth.debian.org>
Uploaders: @GNOME_TEAM@
Build-Depends: debhelper (>= 11),
Build-Depends: debhelper-compat (= 12),
dh-python,
gnome-pkg-tools (>= 0.11),
gobject-introspection (>= 1.35.9),
......@@ -14,7 +14,7 @@ Build-Depends: debhelper (>= 11),
libglib2.0-dev (>= 2.35.9),
libgoa-1.0-dev,
libgrilo-0.3-dev (>= 0.3.4),
libgtk-3-dev (>= 3.19.3),
libgtk-3-dev (>= 3.23.1),
libmediaart-2.0-dev (>= 1.9.1),
libsoup2.4-dev,
libtracker-sparql-2.0-dev (>= 1.99.1),
......@@ -24,7 +24,7 @@ Build-Depends: debhelper (>= 11),
python3,
python3-cairo-dev (>= 1.14.0)
Rules-Requires-Root: no
Standards-Version: 4.2.1
Standards-Version: 4.3.0
Vcs-Browser: https://salsa.debian.org/gnome-team/gnome-music
Vcs-Git: https://salsa.debian.org/gnome-team/gnome-music.git
Homepage: https://wiki.gnome.org/Apps/Music
......@@ -37,7 +37,7 @@ Depends: gir1.2-dazzle-1.0 (>= 3.28.0),
gir1.2-grilo-0.3 (>= 0.3.4),
gir1.2-gst-plugins-base-1.0,
gir1.2-gstreamer-1.0,
gir1.2-gtk-3.0 (>= 3.19.3),
gir1.2-gtk-3.0 (>= 3.23.1),
gir1.2-mediaart-2.0 (>= 1.9.1),
gir1.2-soup-2.4,
gir1.2-totemplparser-1.0,
......
version=4
https://download.gnome.org/sources/@PACKAGE@/([\d\.]+[02468])/ \
https://download.gnome.org/sources/@PACKAGE@/([\d\.]+)/ \
@PACKAGE@@ANY_VERSION@\.tar\.xz
......@@ -84,8 +84,9 @@ class TrackerWrapper:
self.tracker = Tracker.SparqlConnection.get(None)
except Exception as e:
from sys import exit
logger.error("Cannot connect to tracker, error '%s'\Exiting",
str(e))
logger.error(
"Cannot connect to tracker, error {}\nExiting".format(
str(e)))
exit(1)
def __str__(self):
......
......@@ -43,12 +43,14 @@ logger = logging.getLogger(__name__)
@log
def _make_icon_frame(pixbuf, art_size=None, scale=1):
def _make_icon_frame(icon_surface, art_size=None, scale=1, default_icon=False):
border = 3
degrees = pi / 180
radius = 3
ratio = pixbuf.get_height() / pixbuf.get_width()
icon_w = icon_surface.get_width()
icon_h = icon_surface.get_height()
ratio = icon_h / icon_w
# Scale down the image according to the biggest axis
if ratio > 1:
......@@ -70,7 +72,7 @@ def _make_icon_frame(pixbuf, art_size=None, scale=1):
ctx.arc(radius, radius, radius - 0.5, 180 * degrees, 270 * degrees)
ctx.close_path()
ctx.set_line_width(0.6)
ctx.set_source_rgb(0.2, 0.2, 0.2)
ctx.set_source_rgba(0, 0, 0, 0.7)
ctx.stroke_preserve()
# fill the center
......@@ -78,12 +80,17 @@ def _make_icon_frame(pixbuf, art_size=None, scale=1):
ctx.fill()
matrix = cairo.Matrix()
matrix.scale(pixbuf.get_width() / (w - border * 2),
pixbuf.get_height() / (h - border * 2))
matrix.translate(-border, -border)
# paste the scaled pixbuf in the center
Gdk.cairo_set_source_pixbuf(ctx, pixbuf, 0, 0)
if default_icon:
matrix.translate(-w * (1 / 3), -h * (1 / 3))
ctx.set_operator(cairo.Operator.DIFFERENCE)
else:
matrix.scale(
icon_w / ((w - border * 2) * scale),
icon_h / ((h - border * 2) * scale))
matrix.translate(-border, -border)
ctx.set_source_surface(icon_surface, 0, 0)
pattern = ctx.get_source()
pattern.set_matrix(matrix)
ctx.rectangle(border, border, w - border * 2, h - border * 2)
......@@ -100,6 +107,7 @@ class DefaultIcon(GObject.GObject):
MUSIC = 'folder-music-symbolic'
_cache = {}
_default_theme = Gtk.IconTheme.get_default()
def __repr__(self):
return '<DefaultIcon>'
......@@ -110,32 +118,11 @@ class DefaultIcon(GObject.GObject):
@log
def _make_default_icon(self, icon_type, art_size, scale):
width = art_size.width * scale
height = art_size.height * scale
# TODO: Load icon async.
default_theme = Gtk.IconTheme.get_default()
icon_info = default_theme.lookup_icon_for_scale(
icon_type.value, max(art_size.width, art_size.height), scale, 0)
icon = icon_info.load_icon()
result = GdkPixbuf.Pixbuf.new(
icon.get_colorspace(), True, icon.get_bits_per_sample(), width,
height)
result.fill(0xffffffff)
icon_scale = 0.33
icon_info = self._default_theme.lookup_icon_for_scale(
icon_type.value, art_size.width / 3, scale, 0)
icon = icon_info.load_surface()
def icon_offset(x):
return int((x / 2) - (x * icon_scale * 0.5))
icon.composite(
result, icon_offset(width), icon_offset(height),
width * icon_scale, height * icon_scale, icon_offset(width),
icon_offset(height), icon_scale, icon_scale,
GdkPixbuf.InterpType.HYPER, 0x77)
icon_surface = _make_icon_frame(result, art_size, scale)
icon_surface = _make_icon_frame(icon, art_size, scale, True)
return icon_surface
......@@ -222,7 +209,9 @@ class Art(GObject.GObject):
@log
def _cache_hit(self, klass, pixbuf):
surface = _make_icon_frame(pixbuf, self._size, self._scale)
surface = Gdk.cairo_surface_create_from_pixbuf(
pixbuf, self._scale, None)
surface = _make_icon_frame(surface, self._size, self._scale)
self._surface = surface
self._set_grilo_thumbnail_path()
......@@ -316,64 +305,6 @@ class Art(GObject.GObject):
return self._surface
class ArtImage(Art):
"""Extends Art class to support Gtk.Image specifically"""
def __repr__(self):
return '<ArtImage>'
@log
def __init__(self, size, media):
super().__init__(size, media)
self._image = None
@log
def _cache_hit(self, klass, pixbuf):
super()._cache_hit(klass, pixbuf)
self._image.set_from_surface(self._surface)
@log
def _no_art_available(self):
super()._no_art_available()
self._image.set_from_surface(self._surface)
@GObject.Property
def image(self):
"""Returns the image object of the ArtImage class
:returns: The current image available in the class
:rtype: Gtk.Image
"""
return self._image.set_from_surface(self._surface)
@image.setter
def image(self, image):
"""Set the image of the Art class instance""
And starts the lookup process, automatically updating the image
when found.
:param Gtk.Image image: An Gtk.Image object
"""
self._image = image
self._image.set_property("width-request", self._size.width)
self._image.set_property("height-request", self._size.height)
self._scale = self._image.get_scale_factor()
self._surface = DefaultIcon().get(
DefaultIcon.Type.LOADING, self._size, self._scale)
self._image.set_from_surface(self._surface)
self.lookup()
class Cache(GObject.GObject):
"""Handles retrieval of MediaArt cache art
......@@ -720,8 +651,8 @@ class RemoteArt(GObject.GObject):
# FIXME: Passing the iostream here, otherwise it gets
# closed. PyGI specific issue?
ostream.splice_async(
istream, Gio.OutputStreamSpliceFlags.CLOSE_SOURCE |
Gio.OutputStreamSpliceFlags.CLOSE_TARGET, GLib.PRIORITY_LOW,
istream, Gio.OutputStreamSpliceFlags.CLOSE_SOURCE
| Gio.OutputStreamSpliceFlags.CLOSE_TARGET, GLib.PRIORITY_LOW,
None, self._splice_callback, [tmp_file, iostream])
@log
......@@ -733,7 +664,8 @@ class RemoteArt(GObject.GObject):
thumb_uri = item.get_thumbnail()
if thumb_uri is None:
if (thumb_uri is None
or thumb_uri == ""):
self.emit('unavailable')
return
......
......@@ -55,16 +55,14 @@ class Application(Gtk.Application):
GLib.set_application_name(_("Music"))
GLib.set_prgname(application_id)
GLib.setenv("PULSE_PROP_media.role", "music", True)
self._settings = Gio.Settings.new('org.gnome.Music')
self._init_style()
self._window = None
self._application_id = application_id
def _init_style(self):
css_provider_file = Gio.File.new_for_uri(
'resource:///org/gnome/Music/application.css')
css_provider = Gtk.CssProvider()
css_provider.load_from_file(css_provider_file)
css_provider.load_from_resource('/org/gnome/Music/org.gnome.Music.css')
screen = Gdk.Screen.get_default()
style_context = Gtk.StyleContext()
style_context.add_provider_for_screen(
......@@ -74,8 +72,7 @@ class Application(Gtk.Application):
def _build_app_menu(self):
action_entries = [
('about', self._about),
('help', self._help),
('quit', self.quit),
('help', self._help)
]
for action, callback in action_entries:
......@@ -113,4 +110,7 @@ class Application(Gtk.Application):
self._window.get_style_context().add_class('devel')
MediaPlayer2Service(self)
self._window.present()
# gtk_window_present does not work on Wayland.
# Use gtk_present_with_time as a workaround instead.
# See https://gitlab.gnome.org/GNOME/gtk/issues/624#note_10996
self._window.present_with_time(GLib.get_monotonic_time() / 1000)
......@@ -66,7 +66,7 @@ class GstPlayer(GObject.GObject):
Gst.init(None)
self._duration = None
self._duration = -1.
self._missing_plugin_messages = []
self._settings = Gio.Settings.new('org.gnome.Music')
......@@ -89,7 +89,8 @@ class GstPlayer(GObject.GObject):
'message::duration-changed', self._on_duration_changed)
self._bus.connect('message::new-clock', self._on_new_clock)
self.state = Playback.STOPPED
self._previous_state = Playback.STOPPED
self.props.state = Playback.STOPPED
@log
def _setup_replaygain(self):
......@@ -131,7 +132,7 @@ class GstPlayer(GObject.GObject):
# TODO: Workaround the first duration change not being emitted
# and hence smoothscale not being initialized properly.
if self.duration is None:
if self.props.duration == -1.:
self._on_duration_changed(None, None)
@log
......@@ -146,10 +147,12 @@ class GstPlayer(GObject.GObject):
# Gst.State.NULL are never async and thus don't cause a
# message. In practice, self means only Gst.State.PLAYING and
# Gst.State.PAUSED are.
current_state = self.props.state
if current_state == self._previous_state:
return
# Setting self.state triggers the property signal, which is
# used down the line.
self.state = self.state
self._previous_state = current_state
self.notify('state')
@log
def _on_duration_changed(self, bus, message):
......@@ -157,9 +160,9 @@ class GstPlayer(GObject.GObject):
Gst.Format.TIME)
if success:
self.duration = duration / Gst.SECOND
self.props.duration = duration / Gst.SECOND
else:
self.duration = None
self.props.duration = -1.
@log
def _on_bus_element(self, bus, message):
......@@ -169,7 +172,7 @@ class GstPlayer(GObject.GObject):
@log
def _on_bus_error(self, bus, message):
if self._is_missing_plugin_message(message):
self.state = Playback.PAUSED
self.props.state = Playback.PAUSED
self._handle_missing_plugins()
return True
......@@ -177,7 +180,7 @@ class GstPlayer(GObject.GObject):
debug = debug.split('\n')
debug = [(' ') + line.lstrip() for line in debug]
debug = '\n'.join(debug)
logger.warning("URI: {}".format(self.url))
logger.warning("URI: {}".format(self.props.url))
logger.warning(
"Error from element {}: {}".format(
message.src.get_name(), error.message))
......@@ -203,10 +206,12 @@ class GstPlayer(GObject.GObject):
return Playback.PLAYING
elif state == Gst.State.PAUSED:
return Playback.PAUSED
elif state == Gst.State.READY:
return Playback.LOADING
return Playback.STOPPED
@GObject.Property
@GObject.Property(type=int)
def state(self):
"""Current state of the player
......@@ -259,16 +264,16 @@ class GstPlayer(GObject.GObject):
return position
@GObject.Property
@GObject.Property(type=float)
def duration(self):
"""Total duration of current media
Total duration in seconds or None if not available
Total duration in seconds or -1. if not available
:return: duration
:rtype: float or None
:rtype: float
"""
if self.state == Playback.STOPPED:
return None
if self.props.state == Playback.STOPPED:
return -1.
return self._duration
......
......@@ -51,8 +51,7 @@ class InhibitSuspend(GObject.GObject):
self._player = player
self._inhibit_cookie = 0
self._player.connect(
'playback-status-changed', self._on_playback_status_changed)
self._player.connect('notify::state', self._on_player_state_changed)
self._settings = Gio.Settings.new('org.gnome.Music')
self._should_inhibit = self._settings.get_boolean('inhibit-suspend')
......@@ -79,14 +78,14 @@ class InhibitSuspend(GObject.GObject):
@log
def _on_inhibit_suspend_changed(self, settings, value):
self._should_inhibit = value
self._on_playback_status_changed(None)
self._on_player_state_changed(None, None)
@log
def _on_playback_status_changed(self, arguments):
if (self._player.get_playback_status() == Playback.PLAYING
or self._player.get_playback_status() == Playback.LOADING):
def _on_player_state_changed(self, klass, arguments):
if (self._player.props.state == Playback.PLAYING
or self._player.props.state == Playback.LOADING):
self._inhibit_suspend()
if (self._player.get_playback_status() == Playback.PAUSED
or self._player.get_playback_status() == Playback.STOPPED):
if (self._player.props.state == Playback.PAUSED
or self._player.props.state == Playback.STOPPED):
self._uninhibit_suspend()
......@@ -22,7 +22,7 @@
# code, but you are not obligated to do so. If you do not wish to do so,
# delete this exception statement from your version.
from gi.repository import GObject, Gio, GLib
from gi.repository import GObject, Gio, GLib, Gtk
from gnomemusic import log
......@@ -41,7 +41,7 @@ class MediaKeys(GObject.GObject):
@log
def __init__(self, player, window):
"""Intialize media keys handling
"""Initialize media keys handling
:param Player player: Player object
:param Gtk.Window window: Window to grab keys if focused
......@@ -75,22 +75,22 @@ class MediaKeys(GObject.GObject):
try:
self._media_keys_proxy = proxy.new_finish(result)
except GLib.Error as e:
print("error")
logger.warning(
"Error: Failed to contact settings daemon:", e.message)
return
self._grab_media_player_keys()
self._media_keys_proxy.connect("g-signal", self._handle_media_keys)
self._window.connect("focus-in-event", self._grab_media_player_keys)
self._ctrlr = Gtk.EventControllerKey().new(self._window)
self._ctrlr.props.propagation_phase = Gtk.PropagationPhase.CAPTURE
self._ctrlr.connect("focus-in", self._grab_media_player_keys)
@log
def _grab_media_player_keys(self, window=None, event=None):
def _grab_media_player_keys(self, controllerkey=None):
def proxy_call_finished(proxy, result, data=None):
try:
proxy.call_finish(result)
except GLib.Error as e:
print('blah')
logger.warning(
"Error: Failed to grab mediaplayer keys: {}".format(
e.message))
......
This diff is collapsed.
# Copyright 2019 The GNOME Music developers
# GNOME Music 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.
#
# GNOME Music 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 GNOME Music; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
# 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.
import os
from gi.repository import GLib, Gio, GObject
import logging
from gnomemusic import log
from gnomemusic.gstplayer import Playback
logger = logging.getLogger(__name__)
class PauseOnSuspend(GObject.GObject):
"""PauseOnSuspend object
Contains logic to pause music on system suspend
and inhibit suspend before pause.
"""
def __repr__(self):
return '<PauseOnSuspend>'
@log
def __init__(self, player):
"""Initialize pause on supend handling
:param Player player: Player object
"""
super().__init__()
self._player = player
self._init_pause_on_suspend()
self._connection = None