From 5618c9016c41e34974521c68e817687078559a2a Mon Sep 17 00:00:00 2001 From: coderkun Date: Sun, 15 Jan 2023 15:18:35 +0100 Subject: [PATCH 1/9] Always return tuple by get_albumart_now() (close #89) --- src/client.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/client.py b/src/client.py index b2a5d69..3929d26 100644 --- a/src/client.py +++ b/src/client.py @@ -653,7 +653,7 @@ class Client(Base): if album in self._albums: album = self._albums[album] if not album.get_tracks(): - return None + return (album, None) self._logger.debug("get albumart for album \"%s\"", album.get_title()) size = 1 offset = 0 From 8607bf15a90f5ba0814c97b7e35ef32e4a4632c4 Mon Sep 17 00:00:00 2001 From: coderkun Date: Sun, 8 Jan 2023 19:09:19 +0100 Subject: [PATCH 2/9] Add option to sort by last modification date (close #88) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Store the metadate “last-modified” for a track and an album and add an option sort by it. --- data/ui/library-toolbar.ui | 18 +++++++++++++++++- data/xyz.suruatoel.mcg.gschema.xml | 1 + po/de.mo | Bin 4190 -> 4246 bytes po/de.po | 22 +++++++++++++--------- po/en.mo | Bin 3931 -> 4042 bytes po/en.po | 22 +++++++++++++--------- po/mcg.pot | 16 ++++++++++------ src/client.py | 26 ++++++++++++++++++++++++++ src/librarypanel.py | 4 +++- src/utils.py | 1 + 10 files changed, 84 insertions(+), 26 deletions(-) diff --git a/data/ui/library-toolbar.ui b/data/ui/library-toolbar.ui index 97cad01..aabcc8f 100644 --- a/data/ui/library-toolbar.ui +++ b/data/ui/library-toolbar.ui @@ -129,6 +129,22 @@ 4 + + + sort by modification + True + True + False + True + sort_year + + + + False + True + 5 + + gtk-sort-descending @@ -143,7 +159,7 @@ False True - 5 + 6 diff --git a/data/xyz.suruatoel.mcg.gschema.xml b/data/xyz.suruatoel.mcg.gschema.xml index 934564c..9f50878 100644 --- a/data/xyz.suruatoel.mcg.gschema.xml +++ b/data/xyz.suruatoel.mcg.gschema.xml @@ -4,6 +4,7 @@ + diff --git a/po/de.mo b/po/de.mo index da025a58e832a15d8da250d349124781c1c8f3c1..abfee53fda80f21b12bf31bcc5049bc16bef6d96 100644 GIT binary patch delta 1618 zcmcboFio-ko)F7a1_lNOHwFd<83qOhA0`HdLyVXJ7#Np_CnBaTQd)mmT8Jsq7$!)iW?G1~V8KHnB4> zh%hiP9Asx;;ACK6xCS-g0o0<}Nlfm-ktD*qd*59D2tPenN(7OHSS9AwS`vWS7f zo`ZpbpMinFkAs0hjDdk6j)Q@Lt)78_p_Bt+aSaCpgCYY1!$b}S25ANchRqxhpPlD` z_~a@FB!q5(G%_$SJmr9d#2XF<1~~=>1};tp21y1622D@15O489tH-6cbt&4@f#}6&c(pc z&B(wY$^}ukkeh))f`NfyJvYPwC%7RYdk#w9;AW@?8}x`9;-dH5kRblX4GF6M+zbp- z3=9nXJP?gqJPZtK3=9k=JPZs13=9m>JdhB{;el9C&I55+Ee``jIRgVj7Y_r25(5JR z6EB2T<%L9v2QS3F0N#3t!Qs3R0}^>5L7mRaz#z=Pz>vcWv7mt$5_H|XkdTPnz=od7tEFfnvYj%2atG-ZGUi2me-EW(B$pMZ)VM+OE4D+UGzXAlQc z7JSOn?~p~V?g6N3r^1A{pOBpei=#heSM$YOwm ztvCY%12Y4}+YX>2jsX$}pwb9rhCKr$%(NLGaR5sCCJYP=)*wj+NN{L@QW*mSgApj0 zL8XAjTcq43-QG47Q*Gi-Cbboq>VD6{-zJ>21Es+Qh_CRF+z_IfNsEkta7l zB{MBEIk6-&KX3A4&M2Fp)Pnq?5?$Zo^vo1pr_%Id-H?1M1+D;p-JsO6%;L=aJYAQ> zl2j`NBLgF2T?0d10}BO1ODh9&Z3Dx}N?d--@h+~D3%H^uGji)1yQk)*7A2PC7g;F; z23`gR22nPMyfPaD0|x^GgBBYD10MqegE1Qe zgAfA)gA-JJC>sNVC<8-1Lo8H5F&hH|7Xt%B6B`2qD+2>VFB`<-$!rV^@eB+M^VuK{ z{LjX~APaIVJH#R@c8GdMc8EjVp?rUK1_qEHLfIh}M?vLt*&z-sWd}K|o`Inm%wS-c z#LmDV!oa|=kez{nlYxO@8`OXUP>YVTLws}wYQa^g{B5Yd2T*gqLM>$BfH+8;17r~c zgFFWV13v=;gB}M1gBSw?gB=G0gGfCC14AeW1A`(1149-E1A{aJ149o7#78SQAU;^f z0STGS91tJxw?GMtc*vfzZ66UqsRx@b;_{#;Io zxh0$o4E3O(u7pa|b3$C&2BoKRLV{`uCj$cy0|Ub*PDqsOhl-!(WMEj$$iQ$D%5UXn zV31&7V3^Dev3LzPBqTRM={?*KbB=LC9CDePp&pz_ZgE3`<}o(|gA@Y;!)K@lJ{|@J zH3kL-2_6Op0R{#Jdmczg1n@vCh~|M9n8?GxP|m=>kjKNopv1ty@C-_G@%D}*&$qz{*{``F#-n9pnRG@fZfVdi@ z%#HyPRNA0~#sEoB#taM$Rv<|Rh_AFj*^7aJ!4MR>pyJGY@\n" "Language-Team: \n" "Language: de_DE\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: Poedit 2.4.1\n" -"X-Poedit-Basepath: ../../..\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Poedit 3.2.2\n" +"X-Poedit-Basepath: ../../..\n" "X-Poedit-SourceCharset: UTF-8\n" #: data/xyz.suruatoel.mcg.gschema.xml:11 @@ -216,15 +216,19 @@ msgstr "nach Titel" msgid "sort by year" msgstr "nach Jahr" -#: data/ui/library-toolbar.ui:169 data/ui/shortcuts-dialog.ui:115 +#: data/ui/library-toolbar.ui:134 +msgid "sort by modification" +msgstr "nach Änderungsdatum" + +#: data/ui/library-toolbar.ui:185 data/ui/shortcuts-dialog.ui:115 msgid "Search the library" msgstr "Die Bibliothek durchsuchen" -#: data/ui/library-toolbar.ui:192 data/ui/playlist-toolbar.ui:15 +#: data/ui/library-toolbar.ui:208 data/ui/playlist-toolbar.ui:15 msgid "Select multiple albums" msgstr "Mehrere Alben auswählen" -#: data/ui/library-toolbar.ui:214 +#: data/ui/library-toolbar.ui:230 msgid "Settings and actions" msgstr "Einstellungen und Aktionen" @@ -353,11 +357,11 @@ msgstr "Zu MPD verbinden" msgid "Adjust the volume" msgstr "Die Lautstärke anpassen" -#: src/librarypanel.py:419 +#: src/librarypanel.py:421 msgid "Loading albums" msgstr "Alben werden geladen" -#: src/librarypanel.py:519 +#: src/librarypanel.py:521 msgid "Loading images" msgstr "Bilder werden geladen" diff --git a/po/en.mo b/po/en.mo index 39a611bfc9450b522475a80bd696a35fed4a99bd..8fa584c622e4f01f211e77efe784de52feb62f08 100644 GIT binary patch delta 1610 zcmcaDcS^qgo)F7a1_lNOHwFd<83qOhA0`HdLyVXJ7#Np_CnBaTQd)mmT8Jsq7$!)iW?G1~V8KHnB4> zh%hiP9Asx;;ACK6xCS-g0o0<}Nlfm-ktD*qd*59D2tPenN(7OHSS9AwS`vWS7f zo`ZpbpMinFkAs0hjDdk6j)Q@Lt)78_p_Bt+aSaCpgCYY1!$b}S25ANchRqxhpPlD` z_~a@FB!q5(G%_$SJmr9d#2XF<1~~=>1};tp21y1622D@15O489tH-6cbt&4@f#}6&c(p6 zgpq+klnWxhiyLC$F>Z*3H=y)=Zb-;H<7TJ_Cz^Lqi9g(sAZF%)IDm%-5|q+B5Dj`f z;6%e<29@{WfrLmj55$LQJP?a>cpzz}f(H@;H+Uc+^_2(W5Mf@3dMVy|h`|a_0S#VA zQ0wtREH>ta$h+}EeD22!aaatL&gO-LOcgIA&GbX{&*X(zG>;eJp`}ps*FojCK=tjc zhZ=MaYT;d|g&&~w4_-*30p%f3q7mSO7_80*u~?4}l4hLw7#K7e7#LFdAU^BogM`df zD7^rxZ#5qzBsTFu(oFpYK1iZ@52ZQzAwj0h4>8Dr9}z1_l8J1_p5k1_ovZ1_osY1_lRE5yt>=GN?2HnPJbsz@W;&z@W{*z#zc@ zN%|%X3=GyFNd|~_wHO!}m>3usj6k6TDg`ViPh^!>HD+L7uw-Chumu%Z3=9nF3=9me zP;D?uZ}U~wCMK4mvecr@Asi8mJh}NPnQ58Hi6xo&d6O4&M%e_V7UUO|==v6?XQt>n zm8KW#hU8l*a0U452Bnr|7H8(?>AEDAq*^H$85kMs8W`#tSST1;S{ayY8yHSj;#xVG zkz3c;JvA@2D6u5J$Vwp~KQ$$@M8R0kNY98XLKni-bxJHwEl4cMuu{;|(+8u?+T5!l b4x1dp5xiNAkC#!<7s+u7AX_Kv^XmWrcw?yT delta 1498 zcmX>le_O8po)F7a1_lNO7X}6f83qOh8zu&ZL23`gR22nPMyfPaD0|x^GgBBYD10MqegE1Qe zgAfA)gA-JJC>sNVC<8-1Lo8H5F&hH|7Xt%B6B`2qD+2>VFB`<-$!rV^@eB+M^VuK{ z{LjX~APaIVJH#R@c8GdMc8EjVp?rUK1_qEHLfIh}M?vLt*&z-sWd}K|o`Inm%wS-c z#LmDV!oa|=kez{nlYxO@8`OXUP>YVTLws}wYQa^g{B5Yd2T*gqLM>$BfH+8;17r~c zgFFWV13v=;gB}M1gBSw?gB=G0gGfCC14AeW1A`(1149-E1A{aJ149o7#78SQAU;^f z0STGS91tJxw?GMtc*vfzZ66UqsRx@b;_{#;Io zxh0$o4E3O(u7pa|b3$C&2BoKRLV{`uCj$cy0|Ub*PDqsOhl-!(WMJrJWMH@n6;J1e zSX9gnv8WYF_i#f(Vlp?xyxCCkmD~*V;6$>48)ETJZb)36fNHqS4NfEskD>BExgjCJ z!2|J`Fb~8*l01+!qRIpDc`FYjgck8Y9C84v{x}cBA!nidt336Ppt#KgvG@U0!Dk+b zOMmk~9LC8Dp(S`BX+)hDl16NJA^P2TAr^V_LefYOFT{b-Q29itzBH&g)w~eNF|7ewVi6ZV#9#q_NJxnDLqb4}AL3&J zeuzgb`5{r_$PWoY-^rCM_M9f5k^z+VCm&=HHq?g{Ees9}3=EbG3=ED?KB!y)rAH9g zmH`sdpt8jjq-*j87M95}tOE50(9#N|3WQY{7#PezLBhbmpa3cuK&1>wf`NfSfPsNQ zoPmLXnSp^pnSp`99#m2>KwJzeY(UEF7#J8-85kI}85kHO7$7O#n1O-83M9z@@ue0h zdoeID7=i);RGgVl-pDGiYQ(_6U;!#L85kI>85kJU85kIxq1s@S?&hzoO-z#w_yRVc z<6vc+{DL!ZasZd8fPt=|fv%B>f}x3(iGj9((d1IDm8KE8?x}gHMTsT(MOF#{`Kc+H yB??A*CVGZk5xNkru2W)hYC&R2hLwVzo<0~&mgUyl+{nFxX|n-eEaT)w{2Bn>#*3%` diff --git a/po/en.po b/po/en.po index 9d0eba8..ae94e2b 100644 --- a/po/en.po +++ b/po/en.po @@ -2,17 +2,17 @@ msgid "" msgstr "" "Project-Id-Version: CoverGrid (mcg)\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-09-05 15:08+0200\n" -"PO-Revision-Date: 2020-10-24 14:40+0200\n" +"POT-Creation-Date: 2023-01-08 19:06+0100\n" +"PO-Revision-Date: 2023-01-08 19:07+0100\n" "Last-Translator: coderkun \n" "Language-Team: \n" "Language: en\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: Poedit 2.4.1\n" -"X-Poedit-Basepath: ../../..\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Poedit 3.2.2\n" +"X-Poedit-Basepath: ../../..\n" "X-Poedit-SearchPath-0: mcg\n" "X-Poedit-SearchPath-1: data/ui\n" @@ -217,15 +217,19 @@ msgstr "by Title" msgid "sort by year" msgstr "by Year" -#: data/ui/library-toolbar.ui:169 data/ui/shortcuts-dialog.ui:115 +#: data/ui/library-toolbar.ui:134 +msgid "sort by modification" +msgstr "by Modification Date" + +#: data/ui/library-toolbar.ui:185 data/ui/shortcuts-dialog.ui:115 msgid "Search the library" msgstr "Search the library" -#: data/ui/library-toolbar.ui:192 data/ui/playlist-toolbar.ui:15 +#: data/ui/library-toolbar.ui:208 data/ui/playlist-toolbar.ui:15 msgid "Select multiple albums" msgstr "Select multiple albums" -#: data/ui/library-toolbar.ui:214 +#: data/ui/library-toolbar.ui:230 msgid "Settings and actions" msgstr "Settings and actions" @@ -354,11 +358,11 @@ msgstr "Connect to MPD" msgid "Adjust the volume" msgstr "Adjust the volume" -#: src/librarypanel.py:419 +#: src/librarypanel.py:421 msgid "Loading albums" msgstr "Loading albums" -#: src/librarypanel.py:519 +#: src/librarypanel.py:521 msgid "Loading images" msgstr "Loading images" diff --git a/po/mcg.pot b/po/mcg.pot index 19fd383..c409fd6 100644 --- a/po/mcg.pot +++ b/po/mcg.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: mcg\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-09-05 15:08+0200\n" +"POT-Creation-Date: 2023-01-08 19:06+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -215,15 +215,19 @@ msgstr "" msgid "sort by year" msgstr "" -#: data/ui/library-toolbar.ui:169 data/ui/shortcuts-dialog.ui:115 +#: data/ui/library-toolbar.ui:134 +msgid "sort by modification" +msgstr "" + +#: data/ui/library-toolbar.ui:185 data/ui/shortcuts-dialog.ui:115 msgid "Search the library" msgstr "" -#: data/ui/library-toolbar.ui:192 data/ui/playlist-toolbar.ui:15 +#: data/ui/library-toolbar.ui:208 data/ui/playlist-toolbar.ui:15 msgid "Select multiple albums" msgstr "" -#: data/ui/library-toolbar.ui:214 +#: data/ui/library-toolbar.ui:230 msgid "Settings and actions" msgstr "" @@ -352,11 +356,11 @@ msgstr "" msgid "Adjust the volume" msgstr "" -#: src/librarypanel.py:419 +#: src/librarypanel.py:421 msgid "Loading albums" msgstr "" -#: src/librarypanel.py:519 +#: src/librarypanel.py:521 msgid "Loading images" msgstr "" diff --git a/src/client.py b/src/client.py index 3929d26..cc043d8 100644 --- a/src/client.py +++ b/src/client.py @@ -3,6 +3,7 @@ import concurrent.futures import configparser +import dateutil.parser import logging import os import queue @@ -937,6 +938,8 @@ class Client(Base): track.set_date(song['date']) if 'albumartist' in song: track.set_albumartists(song['albumartist']) + if 'last-modified' in song: + track.set_last_modified(song['last-modified']) return track @@ -998,6 +1001,7 @@ class MCGAlbum: self._host = host self._tracks = [] self._length = 0 + self._last_modified = None self._id = Utils.generate_id(title) @@ -1057,6 +1061,9 @@ class MCGAlbum: path = os.path.dirname(track.get_file()) if path not in self._pathes: self._pathes.append(path) + if track.get_last_modified(): + if not self._last_modified or track.get_last_modified() > self._last_modified: + self._last_modified = track.get_last_modified() def get_tracks(self): @@ -1067,6 +1074,10 @@ class MCGAlbum: return self._length + def get_last_modified(self): + return self._last_modified + + def filter(self, filter_string): if len(filter_string) == 0: return True @@ -1102,6 +1113,8 @@ class MCGAlbum: value_function = "get_title" elif criterion == SortOrder.YEAR: value_function = "get_date" + elif criterion == SortOrder.MODIFIED: + value_function = "get_last_modified" value1 = getattr(album1, value_function)() value2 = getattr(album2, value_function)() @@ -1137,6 +1150,7 @@ class MCGTrack: self._track = None self._length = 0 self._date = None + self._last_modified = None def __eq__(self, other): @@ -1208,6 +1222,18 @@ class MCGTrack: return self._file + def set_last_modified(self, date_string): + if date_string: + try: + self._last_modified = dateutil.parser.isoparse(date_string) + except ValueError as e: + self._logger.debug("Invalid date format: %s", date_string) + + + def get_last_modified(self): + return self._last_modified + + class MCGPlaylistTrack(MCGTrack): diff --git a/src/librarypanel.py b/src/librarypanel.py index 48b5342..2626c7b 100644 --- a/src/librarypanel.py +++ b/src/librarypanel.py @@ -39,6 +39,7 @@ class LibraryToolbar(Gtk.ButtonBox): sort_artist = Gtk.Template.Child() sort_title = Gtk.Template.Child() sort_year = Gtk.Template.Child() + sort_modified = Gtk.Template.Child() grid_scale = Gtk.Template.Child() @@ -50,7 +51,8 @@ class LibraryToolbar(Gtk.ButtonBox): self._toolbar_sort_buttons = { SortOrder.ARTIST: self.sort_artist, SortOrder.TITLE: self.sort_title, - SortOrder.YEAR: self.sort_year + SortOrder.YEAR: self.sort_year, + SortOrder.MODIFIED: self.sort_modified } diff --git a/src/utils.py b/src/utils.py index 713c85c..e5a08bd 100644 --- a/src/utils.py +++ b/src/utils.py @@ -86,3 +86,4 @@ class SortOrder: ARTIST = 0 TITLE = 1 YEAR = 2 + MODIFIED = 3 From a1e87e89945f6f3ad6aa08430096067e36ef5b49 Mon Sep 17 00:00:00 2001 From: coderkun Date: Sun, 8 Jan 2023 19:12:40 +0100 Subject: [PATCH 3/9] =?UTF-8?q?Add=20new=20dependency=20=E2=80=9Cpython-da?= =?UTF-8?q?teutil=E2=80=9D=20to=20README?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 070cd52..083b151 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,7 @@ License: [GPL](http://www.gnu.org/licenses/gpl.html) v3 Dependencies: * [Python](http://www.python.org) 3 +* [python-dateutil](https://pypi.org/project/python-dateutil/) * [GTK](http://www.gtk.org) 3 (>= 3.22) ([python-gobject](https://live.gnome.org/PyGObject)) * [Avahi](http://www.avahi.org) (optional) * [python-keyring](http://pypi.python.org/pypi/keyring) (optional) From e976e05efea9102ede199284a1afc1053ec28fd3 Mon Sep 17 00:00:00 2001 From: coderkun Date: Wed, 18 Jan 2023 17:25:29 +0100 Subject: [PATCH 4/9] Fix setting sort order on Library panel (close #91) --- src/librarypanel.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/librarypanel.py b/src/librarypanel.py index 2626c7b..7d325dd 100644 --- a/src/librarypanel.py +++ b/src/librarypanel.py @@ -114,6 +114,12 @@ class LibraryToolbar(Gtk.ButtonBox): self.select_button.set_active(False) + def set_sort_order(self, sort): + button = self._toolbar_sort_buttons[sort] + if button and not button.get_active(): + button.set_active(True) + + @Gtk.Template(resource_path='/xyz/suruatoel/mcg/ui/library-panel.ui') @@ -389,11 +395,9 @@ class LibraryPanel(Gtk.Stack): def set_sort_order(self, sort): if self._sort_order != sort: - button = self._toolbar_sort_buttons[sort] - if button and not button.get_active(): - button.set_active(True) - self._sort_order = sort - self._library_grid_model.set_sort_func(2, self.compare_albums, self._sort_order) + self._toolbar.set_sort_order(sort) + self._sort_order = sort + self._library_grid_model.set_sort_func(2, self.compare_albums, self._sort_order) def get_sort_order(self): From 44fb332c62c0677b74e739d7b3ea02e6113ae3d2 Mon Sep 17 00:00:00 2001 From: coderkun Date: Sat, 21 Jan 2023 12:59:01 +0100 Subject: [PATCH 5/9] =?UTF-8?q?Read=20cover=20with1=20=E2=80=9Creadpicture?= =?UTF-8?q?=E2=80=9D=20command=20if=20=E2=80=9Calbumart=E2=80=9D=20is=20no?= =?UTF-8?q?t=20found=20(close=20#90)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/client.py | 109 +++++++++++++++++++++++++++++--------------------- 1 file changed, 63 insertions(+), 46 deletions(-) diff --git a/src/client.py b/src/client.py index cc043d8..5cc0b11 100644 --- a/src/client.py +++ b/src/client.py @@ -650,57 +650,25 @@ class Client(Base): def _get_albumart(self, album): - data = None if album in self._albums: album = self._albums[album] - if not album.get_tracks(): - return (album, None) self._logger.debug("get albumart for album \"%s\"", album.get_title()) - size = 1 - offset = 0 - index = 0 - # Read data until size is reached - try: - while offset < size: - self._write('albumart', args=[album.get_tracks()[0].get_file(), offset]) + # Use "albumart" command + if album.get_tracks(): + try: + return (album, self._read_binary('albumart', album.get_tracks()[0].get_file(), False)) + except CommandException as e: + # The "albumart" command throws an exception if not found + if e.get_error_number() != Client.PROTOCOL_ERROR_NOEXISTS: + raise e + # If no albumart can be found, use "readpicture" command + for track in album.get_tracks(): + data = self._read_binary('readpicture', track.get_file(), True) + if data: + return (album, data) - # Read first line which tells us whether there is an albumart - line = self._read_line() - if line.startswith(Client.PROTOCOL_ERROR): - error = line[len(Client.PROTOCOL_ERROR):].strip() - self._logger.debug("command failed: %r", error) - raise CommandException(error) - # First line is the file size - size = int(self._parse_dict([line])['size']) - self._logger.debug("size: %d", size) - # Second line is the count of bytes read - binary = int(self._parse_dict([self._read_line()])['binary']) - self._logger.debug("binary: %d", binary) - - # Create new data array on the first iteration - if not data: - data = bytearray(size) - # Create a view for the current chunk of data - data_view = memoryview(data)[offset:offset+binary] - # Read actual bytes - self._read_bytes(data_view, binary) - offset += binary - # Read line break to complete previous repsonse - self._read_line() - # Read command completion - end = self._read_line() - if not end.startswith(Client.PROTOCOL_COMPLETION): - self._logger.debug("albumart not completed") - data = None - break - except CommandException as e: - # If no albumart can be found, do not throw an exception - if e.get_error_number() == Client.PROTOCOL_ERROR_NOEXISTS: - data = None - else: - raise e - return (album, data) + return (album, None) def _get_custom(self, name): @@ -844,6 +812,55 @@ class Client(Base): return None + def _read_binary(self, command, filename, has_mimetype): + data = None + size = 1 + offset = 0 + index = 0 + + # Read data until size is reached + while offset < size: + self._write(command, args=[filename, offset]) + + # Read first line + line = self._read_line() + # Check first line for error + if line.startswith(Client.PROTOCOL_ERROR): + error = line[len(Client.PROTOCOL_ERROR):].strip() + self._logger.debug("command failed: %r", error) + raise CommandException(error) + # Check first line for completion + if line.startswith(Client.PROTOCOL_COMPLETION): + break + # First line is the file size + size = int(self._parse_dict([line])['size']) + self._logger.debug("size: %d", size) + # For some commands the second line is the mimetype + if has_mimetype: + mimetype = self._parse_dict([self._read_line()])['type'] + # Next line is the count of bytes read + binary = int(self._parse_dict([self._read_line()])['binary']) + self._logger.debug("binary: %d", binary) + + # Create new data array on the first iteration + if not data: + data = bytearray(size) + # Create a view for the current chunk of data + data_view = memoryview(data)[offset:offset+binary] + # Read actual bytes + self._read_bytes(data_view, binary) + offset += binary + # Read line break to complete previous repsonse + self._read_line() + # Read command completion + end = self._read_line() + if not end.startswith(Client.PROTOCOL_COMPLETION): + self._logger.debug("albumart not completed") + data = None + break + return data + + def _read_bytes(self, buf, nbytes): self._logger.debug("reading bytes") # Use already buffered data From bfb8eac62d8d3a39816989fdd7849c06a110f496 Mon Sep 17 00:00:00 2001 From: coderkun Date: Sat, 21 Jan 2023 17:16:31 +0100 Subject: [PATCH 6/9] Bump version to 3.2 --- data/ui/info-dialog.ui | 2 +- meson.build | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/data/ui/info-dialog.ui b/data/ui/info-dialog.ui index 99b3524..d6c0ed8 100644 --- a/data/ui/info-dialog.ui +++ b/data/ui/info-dialog.ui @@ -10,7 +10,7 @@ dialog center CoverGrid - 3.1 + 3.2 CoverGrid is a client for the Music Player Daemon, focusing on albums instead of single tracks. http://www.suruatoel.xyz/codes/mcg xyz.suruatoel.mcg diff --git a/meson.build b/meson.build index d644865..1ce0af4 100644 --- a/meson.build +++ b/meson.build @@ -1,5 +1,5 @@ project('mcg', - version: '3.1', + version: '3.2', meson_version: '>= 0.59.0', default_options: [ 'warning_level=2', From 21bd0f58321bd7b620c4ee385836bf051c761190 Mon Sep 17 00:00:00 2001 From: coderkun Date: Tue, 28 Feb 2023 12:55:26 +0100 Subject: [PATCH 7/9] Fix setting sort type on Library panel at startup (close #95) --- src/librarypanel.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/librarypanel.py b/src/librarypanel.py index 7d325dd..938d0fe 100644 --- a/src/librarypanel.py +++ b/src/librarypanel.py @@ -120,6 +120,13 @@ class LibraryToolbar(Gtk.ButtonBox): button.set_active(True) + def set_sort_type(self, sort_type): + if sort_type: + self.toolbar_sort_order_button.set_active(True) + else: + self.toolbar_sort_order_button.set_active(False) + + @Gtk.Template(resource_path='/xyz/suruatoel/mcg/ui/library-panel.ui') @@ -406,12 +413,11 @@ class LibraryPanel(Gtk.Stack): def set_sort_type(self, sort_type): if self._sort_type != sort_type: + self._toolbar.set_sort_type(sort_type) if sort_type: sort_type_gtk = Gtk.SortType.DESCENDING - self.toolbar_sort_order_button.set_active(True) else: sort_type_gtk = Gtk.SortType.ASCENDING - self.toolbar_sort_order_button.set_active(False) if self._sort_type != sort_type_gtk: self._sort_type = sort_type_gtk self._library_grid_model.set_sort_column_id(2, sort_type) From 6ba8bc550fe1f406db610e02d448271734788d6e Mon Sep 17 00:00:00 2001 From: coderkun Date: Tue, 28 Feb 2023 13:18:07 +0100 Subject: [PATCH 8/9] Bump version to 3.2.1 --- data/ui/info-dialog.ui | 2 +- meson.build | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/data/ui/info-dialog.ui b/data/ui/info-dialog.ui index d6c0ed8..bdd14f2 100644 --- a/data/ui/info-dialog.ui +++ b/data/ui/info-dialog.ui @@ -10,7 +10,7 @@ dialog center CoverGrid - 3.2 + 3.2.1 CoverGrid is a client for the Music Player Daemon, focusing on albums instead of single tracks. http://www.suruatoel.xyz/codes/mcg xyz.suruatoel.mcg diff --git a/meson.build b/meson.build index 1ce0af4..5a6d445 100644 --- a/meson.build +++ b/meson.build @@ -1,5 +1,5 @@ project('mcg', - version: '3.2', + version: '3.2.1', meson_version: '>= 0.59.0', default_options: [ 'warning_level=2', From 685349da18e3358a6022c2ea84ad41cdff55b4e8 Mon Sep 17 00:00:00 2001 From: coderkun Date: Sun, 8 Jan 2023 18:20:30 +0100 Subject: [PATCH 9/9] =?UTF-8?q?Port=20UI=20to=20GTK=E2=80=AF4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- data/gtk.css | 53 +- data/ui/album-headerbar.ui | 16 +- data/ui/connection-panel.ui | 256 +++----- data/ui/cover-panel.ui | 342 +++++------ data/ui/cover-toolbar.ui | 33 -- data/ui/gtk.menu.ui | 75 --- data/ui/info-dialog.ui | 46 -- data/ui/library-panel.ui | 586 +++++++++--------- data/ui/library-toolbar.ui | 248 -------- data/ui/playlist-panel.ui | 342 ++++++----- data/ui/playlist-toolbar.ui | 55 -- data/ui/server-panel.ui | 847 ++++++++++----------------- data/ui/server-toolbar.ui | 14 - data/ui/shortcuts-dialog.ui | 21 +- data/ui/window.ui | 299 +++------- data/xyz.suruatoel.mcg.gresource.xml | 7 +- src/albumheaderbar.py | 7 +- src/application.py | 65 +- src/client.py | 12 +- src/connectionpanel.py | 79 ++- src/coverpanel.py | 115 ++-- src/infodialog.py | 15 - src/librarypanel.py | 521 ++++++---------- src/main.py | 2 - src/meson.build | 1 - src/playlistpanel.py | 184 +++--- src/serverpanel.py | 29 +- src/shortcutsdialog.py | 4 +- src/utils.py | 48 +- src/window.py | 203 +++---- 30 files changed, 1684 insertions(+), 2841 deletions(-) delete mode 100644 data/ui/cover-toolbar.ui delete mode 100644 data/ui/gtk.menu.ui delete mode 100644 data/ui/info-dialog.ui delete mode 100644 data/ui/library-toolbar.ui delete mode 100644 data/ui/playlist-toolbar.ui delete mode 100644 data/ui/server-toolbar.ui delete mode 100644 src/infodialog.py diff --git a/data/gtk.css b/data/gtk.css index 469b262..1b361de 100644 --- a/data/gtk.css +++ b/data/gtk.css @@ -1,8 +1,20 @@ -.bg-texture { +#content_stack { box-shadow:inset 4px 4px 10px rgba(0,0,0,0.3); background-image:url('noise-texture.png'); } +#port_spinner { + background:none; + margin-top:-13px; +} +#port_spinner text { + padding-left: 0; +} + +#server_stack_sidebar { + background-color:alpha(@theme_bg_color, 1); +} + .no-bg { background:none; } @@ -18,13 +30,17 @@ font-weight:bold; } -revealer.sidebar > * { - background-color:alpha(@theme_bg_color, 0.8); - box-shadow:0 0 10px @theme_bg_color; - margin-left:20px +window.fullscreen #cover_box { + background: black; } -revealer.sidebar scale mark indicator { +#cover_info_revealer { + background-color:alpha(@theme_bg_color, 0.8); + box-shadow:0 0 10px @theme_bg_color; + margin-left:20px; +} + +#cover_info_revealer scale mark indicator { margin-right:5px; } @@ -32,24 +48,13 @@ actionbar { background-color:@theme_unfocused_bg_color; } -/* Icon View in regular mode */ -iconview.view:selected, -iconview.view:selected:focus { - background-color:@theme_selected_bg_color; +gridview child { + padding: 1px; } -iconview.view:hover { - -gtk-icon-effect:highlight; +gridview.selection child { + opacity: 0.5; } - -/* Icon View in selection mode */ -iconview.view.selection { - -gtk-icon-effect:dim; -} -iconview.view.selection:selected, -iconview.view.selection:selected:focus { - background-color:@theme_selected_bg_color; - -gtk-icon-effect:highlight; -} -iconview.view.selection:hover { - -gtk-icon-effect:none; +gridview.selection child:hover, +gridview.selection child:selected { + opacity: 1; } diff --git a/data/ui/album-headerbar.ui b/data/ui/album-headerbar.ui index 76ade01..376c07c 100644 --- a/data/ui/album-headerbar.ui +++ b/data/ui/album-headerbar.ui @@ -1,8 +1,10 @@ - - - diff --git a/data/ui/connection-panel.ui b/data/ui/connection-panel.ui index f388d43..de6bf0c 100644 --- a/data/ui/connection-panel.ui +++ b/data/ui/connection-panel.ui @@ -1,182 +1,86 @@ - - - - - 1024 - 9999 - 6600 - 1 - 100 - - diff --git a/data/ui/cover-panel.ui b/data/ui/cover-panel.ui index 304d9d0..c4557f2 100644 --- a/data/ui/cover-panel.ui +++ b/data/ui/cover-panel.ui @@ -1,199 +1,159 @@ - - - + + + diff --git a/data/ui/cover-toolbar.ui b/data/ui/cover-toolbar.ui deleted file mode 100644 index 7d3fcdd..0000000 --- a/data/ui/cover-toolbar.ui +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - diff --git a/data/ui/gtk.menu.ui b/data/ui/gtk.menu.ui deleted file mode 100644 index b944502..0000000 --- a/data/ui/gtk.menu.ui +++ /dev/null @@ -1,75 +0,0 @@ - - - -
- - win.connect - Connect - <Primary>c - - - win.play - Play - <Primary>p - - - win.clear-playlist - Clear Playlist - <Primary>r - - - win.toggle-fullscreen - Toggle Fullscreen - F11 - - - win.search-library - Search Library - <Primary>f - -
-
- - win.panel - Connection - 0 - <Primary>KP_1 - - - win.panel - Cover - 1 - <Primary>KP_2 - - - win.panel - Playlist - 2 - <Primary>KP_3 - - - win.panel - Library - 3 - <Primary>KP_4 - -
-
- - win.show-help-overlay - Keyboard Shortcuts - <Primary>k - - - app.info - Info - <Primary>i - - - app.quit - Quit - <Primary>q - -
-
-
diff --git a/data/ui/info-dialog.ui b/data/ui/info-dialog.ui deleted file mode 100644 index bdd14f2..0000000 --- a/data/ui/info-dialog.ui +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - diff --git a/data/ui/library-panel.ui b/data/ui/library-panel.ui index 0e499d9..3ac79a7 100644 --- a/data/ui/library-panel.ui +++ b/data/ui/library-panel.ui @@ -1,303 +1,339 @@ - - - diff --git a/data/ui/library-toolbar.ui b/data/ui/library-toolbar.ui deleted file mode 100644 index aabcc8f..0000000 --- a/data/ui/library-toolbar.ui +++ /dev/null @@ -1,248 +0,0 @@ - - - - - - 100 - 1000 - 150 - 1 - 10 - - - False - - - True - False - vertical - - - 350 - True - True - grid_adjustment - False - -1 - 0 - 0 - False - - - - - True - True - 0 - - - - - gtk-refresh - True - True - True - none - True - - - - False - True - 1 - - - - - True - False - vertical - - - True - False - vertical - - - False - True - 0 - - - - - True - False - Sort - - - False - True - 1 - - - - - sort by artist - True - True - False - True - sort_year - - - - False - True - 2 - - - - - sort by title - True - True - False - True - sort_year - - - - False - True - 3 - - - - - sort by year - True - True - False - True - True - - - - False - True - 4 - - - - - sort by modification - True - True - False - True - sort_year - - - - False - True - 5 - - - - - gtk-sort-descending - True - True - False - True - True - True - - - - False - True - 6 - - - - - False - True - 2 - - - - - - - diff --git a/data/ui/playlist-panel.ui b/data/ui/playlist-panel.ui index 9ee8b7a..8796afc 100644 --- a/data/ui/playlist-panel.ui +++ b/data/ui/playlist-panel.ui @@ -1,194 +1,182 @@ - - - diff --git a/data/ui/playlist-toolbar.ui b/data/ui/playlist-toolbar.ui deleted file mode 100644 index 843625c..0000000 --- a/data/ui/playlist-toolbar.ui +++ /dev/null @@ -1,55 +0,0 @@ - - - - - - diff --git a/data/ui/server-panel.ui b/data/ui/server-panel.ui index 333919d..91ffe99 100644 --- a/data/ui/server-panel.ui +++ b/data/ui/server-panel.ui @@ -1,547 +1,326 @@ - - - diff --git a/data/ui/server-toolbar.ui b/data/ui/server-toolbar.ui deleted file mode 100644 index c1857a4..0000000 --- a/data/ui/server-toolbar.ui +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - diff --git a/data/ui/shortcuts-dialog.ui b/data/ui/shortcuts-dialog.ui index 8109201..279c992 100644 --- a/data/ui/shortcuts-dialog.ui +++ b/data/ui/shortcuts-dialog.ui @@ -1,9 +1,10 @@ - + +