From c15514b41683863ab5c1bfa69f74113b8161bb2c Mon Sep 17 00:00:00 2001 From: Heimen Stoffels Date: Sat, 18 Feb 2023 14:15:35 +0100 Subject: [PATCH 01/36] Updated Dutch translation --- po/nl.po | 44 ++++++++++++++++---------------------------- 1 file changed, 16 insertions(+), 28 deletions(-) diff --git a/po/nl.po b/po/nl.po index 67136a16..e1f6c509 100644 --- a/po/nl.po +++ b/po/nl.po @@ -12,7 +12,7 @@ msgstr "" "Project-Id-Version: gPodder\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2023-02-17 19:06-0700\n" -"PO-Revision-Date: 2022-09-26 18:20+0200\n" +"PO-Revision-Date: 2023-02-18 14:15+0100\n" "Last-Translator: Heimen Stoffels \n" "Language-Team: Dutch\n" "Language: nl\n" @@ -20,7 +20,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -"X-Generator: Poedit 3.1.1\n" +"X-Generator: Poedit 3.2.2\n" #: src/gpodder/config.py:53 #, python-format @@ -479,10 +479,8 @@ msgstr[0] "%(count)d gedeeltelijk bestand" msgstr[1] "%(count)d gedeeltelijke bestanden" #: src/gpodder/gtkui/main.py:444 -#, fuzzy -#| msgid "Clean-up" msgid "Cleaning up..." -msgstr "Opruiming" +msgstr "Bezig met opruimen…" #: src/gpodder/gtkui/main.py:559 msgid "Action" @@ -696,10 +694,8 @@ msgstr "Bezig met verwijderen" #: src/gpodder/gtkui/main.py:1725 src/gpodder/gtkui/main.py:3310 #: src/gpodder/gtkui/main.py:3391 -#, fuzzy -#| msgid "Updating" msgid "Updating..." -msgstr "Bijwerken" +msgstr "Bezig met bijwerken…" #: src/gpodder/gtkui/main.py:1787 msgid "Start download now" @@ -860,10 +856,8 @@ msgid "Episode details" msgstr "Details van aflevering" #: src/gpodder/gtkui/main.py:2180 share/gpodder/ui/gtk/menus.ui.h:31 -#, fuzzy -#| msgid "Select _none" msgid "Select channel" -msgstr "_Niets selecteren" +msgstr "Kies een kanaal" #: src/gpodder/gtkui/main.py:2370 msgid "Please check your media player settings in the preferences dialog." @@ -1953,29 +1947,21 @@ msgstr "" #: share/gpodder/extensions/rename_download.py:54 #: share/gpodder/extensions/rename_download.py:61 #: share/gpodder/extensions/rename_download.py:80 -#, fuzzy -#| msgid "Downloaded episodes" msgid "Rename all downloaded episodes" -msgstr "Gedownloade afleveringen" +msgstr "Alle gedownloade afleveringen hernoemen" #: share/gpodder/extensions/rename_download.py:60 -#, fuzzy -#| msgid "Downloaded episodes" msgid "No downloaded episodes to rename" -msgstr "Gedownloade afleveringen" +msgstr "Er zijn geen gedownloade afleveringen" #: share/gpodder/extensions/rename_download.py:66 -#, fuzzy -#| msgid "Downloaded episodes" msgid "Renaming all downloaded episodes" -msgstr "Gedownloade afleveringen" +msgstr "Bezig met hernoemen…" #: share/gpodder/extensions/rename_download.py:79 -#, fuzzy, python-format -#| msgid "%(count)d new episode" -#| msgid_plural "%(count)d new episodes" +#, python-format msgid "Renamed %(count)d downloaded episodes" -msgstr "%(count)d nieuwe aflevering" +msgstr "Er zijn %(count)d afleveringen hernoemd" #: share/gpodder/extensions/rm_ogg_cover.py:37 msgid "Remove cover art from OGG files" @@ -2134,13 +2120,15 @@ msgstr "" #: share/gpodder/extensions/youtube-dl.py:586 msgid "Embed all available subtitles to downloaded video" -msgstr "" +msgstr "Alle beschikbare ondertitelingen in video's opnemen" #: share/gpodder/extensions/youtube-dl.py:593 msgid "" "The \"ffmpeg\" command was not found. FFmpeg is required for embedding " "subtitles." msgstr "" +"‘ffmpeg’ is niet aangetroffen. FFmpeg is vereist voor het opnemen van " +"ondertitelingen." #: share/gpodder/extensions/youtube-dl.py:602 msgid "youtube-dl" @@ -2292,7 +2280,7 @@ msgstr "Audiospeler:" #: share/gpodder/ui/gtk/gpodderpreferences.ui.h:6 msgid "Find as you type" -msgstr "" +msgstr "Zoeken tijdens het typen" #: share/gpodder/ui/gtk/gpodderpreferences.ui.h:7 msgid "General" @@ -2332,7 +2320,7 @@ msgstr "Maximaal aantal afleveringen per podcast:" #: share/gpodder/ui/gtk/gpodderpreferences.ui.h:18 msgid "Consider only episodes added in the update as new" -msgstr "" +msgstr "Alleen bijgewerkte afleveringen markeren als nieuw" #: share/gpodder/ui/gtk/gpodderpreferences.ui.h:19 msgid "When new episodes are found:" @@ -2556,7 +2544,7 @@ msgstr "Altijd nieuwe afleveringen tonen" #: share/gpodder/ui/gtk/menus.ui.h:47 msgid "Trim episode title prefix" -msgstr "" +msgstr "Voorvoegsel van afleveringen inkorten" #: share/gpodder/ui/gtk/menus.ui.h:48 msgid "Episode descriptions" From 69a7089f94db0082a574e8544bd15ab69f93fc97 Mon Sep 17 00:00:00 2001 From: Karl Ove Hufthammer Date: Sun, 19 Feb 2023 09:18:01 +0100 Subject: [PATCH 02/36] Update Norwegian Nynorsk translation for 3.11.1 release --- po/nn.po | 36 +++++++++++++++++------------------- 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/po/nn.po b/po/nn.po index 17151710..442ec76e 100644 --- a/po/nn.po +++ b/po/nn.po @@ -4,13 +4,13 @@ # Translators: # Thomas Perl , 2006. # Torstein Adolf Winterseth , 2009, 2010. -# Karl Ove Hufthammer , 2019, 2020, 2021, 2022. +# Karl Ove Hufthammer , 2019, 2020, 2021, 2022, 2023. msgid "" msgstr "" "Project-Id-Version: gPodder\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2023-02-17 19:06-0700\n" -"PO-Revision-Date: 2022-09-28 20:51+0200\n" +"PO-Revision-Date: 2023-02-19 09:11+0100\n" "Last-Translator: Karl Ove Hufthammer \n" "Language-Team: Norwegian Nynorsk \n" "Language: nn\n" @@ -18,7 +18,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -"X-Generator: Lokalize 22.08.1\n" +"X-Generator: Lokalize 22.12.2\n" #: src/gpodder/config.py:53 #, python-format @@ -477,10 +477,9 @@ msgstr[0] "%(count)d delvis nedlasta fil" msgstr[1] "%(count)d delvis nedlasta filer" #: src/gpodder/gtkui/main.py:444 -#, fuzzy #| msgid "Clean-up" msgid "Cleaning up..." -msgstr "Opprydding" +msgstr "Ryddar opp …" #: src/gpodder/gtkui/main.py:559 msgid "Action" @@ -698,10 +697,9 @@ msgstr "Fjernar" # Faneoverskrift i innstillingane. #: src/gpodder/gtkui/main.py:1725 src/gpodder/gtkui/main.py:3310 #: src/gpodder/gtkui/main.py:3391 -#, fuzzy #| msgid "Updating" msgid "Updating..." -msgstr "Oppdatering" +msgstr "Oppdaterer …" #: src/gpodder/gtkui/main.py:1787 msgid "Start download now" @@ -865,10 +863,9 @@ msgid "Episode details" msgstr "Episodedetaljar" #: src/gpodder/gtkui/main.py:2180 share/gpodder/ui/gtk/menus.ui.h:31 -#, fuzzy #| msgid "Select _none" msgid "Select channel" -msgstr "Vel _ingen" +msgstr "Vel kanal" #: src/gpodder/gtkui/main.py:2370 msgid "Please check your media player settings in the preferences dialog." @@ -1568,8 +1565,7 @@ msgstr "storleik: %s" #: src/gpodder/gtkui/desktop/exportlocal.py:50 #, python-format msgid "Export remaining %(count)d episode to this folder with its default name" -msgid_plural "" -"Export remaining %(count)d episodes to this folder with their default name" +msgid_plural "Export remaining %(count)d episodes to this folder with their default name" msgstr[0] "" "Eksporter gjenståande %(count)d episode til denne mappa, med standardnamn" msgstr[1] "" @@ -1956,29 +1952,26 @@ msgstr "Endra namn på episodane til «.»" #: share/gpodder/extensions/rename_download.py:54 #: share/gpodder/extensions/rename_download.py:61 #: share/gpodder/extensions/rename_download.py:80 -#, fuzzy #| msgid "Downloaded episodes" msgid "Rename all downloaded episodes" -msgstr "Nedlasta episodar" +msgstr "Endra namn på alle nedlasta episodar" #: share/gpodder/extensions/rename_download.py:60 -#, fuzzy #| msgid "Downloaded episodes" msgid "No downloaded episodes to rename" -msgstr "Nedlasta episodar" +msgstr "Ingen nedlasta episodar å endra namn på" #: share/gpodder/extensions/rename_download.py:66 -#, fuzzy #| msgid "Downloaded episodes" msgid "Renaming all downloaded episodes" -msgstr "Nedlasta episodar" +msgstr "Endrar namn på alle nedlasta episodar" #: share/gpodder/extensions/rename_download.py:79 -#, fuzzy, python-format +#, python-format #| msgid "%(count)d new episode" #| msgid_plural "%(count)d new episodes" msgid "Renamed %(count)d downloaded episodes" -msgstr "%(count)d ny episode" +msgstr "Endra namn på %(count)d nedlasta episodar" #: share/gpodder/extensions/rm_ogg_cover.py:37 msgid "Remove cover art from OGG files" @@ -2139,12 +2132,14 @@ msgstr "" #: share/gpodder/extensions/youtube-dl.py:586 msgid "Embed all available subtitles to downloaded video" msgstr "" +"Bygg alle tilgjengelege undertekstar inn i nedlasta videofil" #: share/gpodder/extensions/youtube-dl.py:593 msgid "" "The \"ffmpeg\" command was not found. FFmpeg is required for embedding " "subtitles." msgstr "" +"Fann ikkje programfila «ffmpeg». Du treng FFmpeg for å byggja inn undertekstar." #: share/gpodder/extensions/youtube-dl.py:602 msgid "youtube-dl" @@ -2299,6 +2294,7 @@ msgstr "Lydavspelar:" #: share/gpodder/ui/gtk/gpodderpreferences.ui.h:6 msgid "Find as you type" msgstr "" +"Kontinuerleg søk" #: share/gpodder/ui/gtk/gpodderpreferences.ui.h:7 msgid "General" @@ -2339,6 +2335,7 @@ msgstr "Øvre grense på episodar per podkast:" #: share/gpodder/ui/gtk/gpodderpreferences.ui.h:18 msgid "Consider only episodes added in the update as new" msgstr "" +"Rekn berre episodar lagde til i oppdateringa som nye" #: share/gpodder/ui/gtk/gpodderpreferences.ui.h:19 msgid "When new episodes are found:" @@ -2561,6 +2558,7 @@ msgstr "Vis alltid nye episodar" #: share/gpodder/ui/gtk/menus.ui.h:47 msgid "Trim episode title prefix" msgstr "" +"Fjern prefiks frå episodetitlar" #: share/gpodder/ui/gtk/menus.ui.h:48 msgid "Episode descriptions" From 3cef7a3e1185ebbe83f22f50ca6410d21d62ec44 Mon Sep 17 00:00:00 2001 From: Teemu Ikonen Date: Sun, 19 Feb 2023 15:55:21 +0200 Subject: [PATCH 03/36] appdata: Fix syntax, add 3.9-series release dates --- share/metainfo/org.gpodder.gpodder.appdata.xml | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/share/metainfo/org.gpodder.gpodder.appdata.xml b/share/metainfo/org.gpodder.gpodder.appdata.xml index 3031e5db..8625faad 100644 --- a/share/metainfo/org.gpodder.gpodder.appdata.xml +++ b/share/metainfo/org.gpodder.gpodder.appdata.xml @@ -44,7 +44,7 @@ none none - + The main window https://raw.githubusercontent.com/flathub/org.gpodder.gpodder/master/screenshot.png @@ -74,7 +74,7 @@ - +

This is a bugfix release, shortly after 3.10.4, for the Rename after Download extension.

@@ -85,5 +85,12 @@ + + + + + + + From 530d026516aa6952bf5a5a01cb8df0f990e97fa5 Mon Sep 17 00:00:00 2001 From: Teemu Ikonen Date: Sun, 19 Feb 2023 14:02:38 +0200 Subject: [PATCH 04/36] appdata: Add release 3.11.1 --- share/metainfo/org.gpodder.gpodder.appdata.xml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/share/metainfo/org.gpodder.gpodder.appdata.xml b/share/metainfo/org.gpodder.gpodder.appdata.xml index 8625faad..d7bd350d 100644 --- a/share/metainfo/org.gpodder.gpodder.appdata.xml +++ b/share/metainfo/org.gpodder.gpodder.appdata.xml @@ -51,6 +51,17 @@
+ + +

Major changes:

+
    +
  • new yt-dlp to fix the recent YouTube change
  • +
  • fix multiple bugs that caused gPodder to freeze or appear frozen
  • +
  • embed subtitles in videos with youtube-dl extension
  • +
  • performance improvements
  • +
+
+

This release contains a year's worth of improvements. Major changes:

From 34d7d5da2b31ec12d069b0f9c06a08ac8e8375e4 Mon Sep 17 00:00:00 2001 From: auouymous Date: Mon, 20 Feb 2023 04:06:05 -0700 Subject: [PATCH 05/36] Fix typo in label. Reported-by: Karl Ove Hufthammer --- share/gpodder/extensions/youtube-dl.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/share/gpodder/extensions/youtube-dl.py b/share/gpodder/extensions/youtube-dl.py index d9a1a74f..610d4ab1 100644 --- a/share/gpodder/extensions/youtube-dl.py +++ b/share/gpodder/extensions/youtube-dl.py @@ -583,7 +583,7 @@ class gPodderExtension: box.pack_start(Gtk.HSeparator(), False, False, 0) - checkbox = Gtk.CheckButton(_('Embed all available subtitles to downloaded video')) + checkbox = Gtk.CheckButton(_('Embed all available subtitles in downloaded video')) checkbox.set_active(self.container.config.embed_subtitles) checkbox.connect('toggled', self.toggle_embed_subtitles) box.pack_start(checkbox, False, False, 0) From ceabe3db0ad289cbfc323eecb9a631dd36bac6a2 Mon Sep 17 00:00:00 2001 From: auouymous Date: Tue, 21 Feb 2023 14:54:07 -0700 Subject: [PATCH 06/36] Add all python versions to test matrix. --- .github/workflows/linttest.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/linttest.yml b/.github/workflows/linttest.yml index 9e57a803..06d74f73 100644 --- a/.github/workflows/linttest.yml +++ b/.github/workflows/linttest.yml @@ -12,7 +12,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: ['3.10'] + python-version: ['3.7', '3.8', '3.9', '3.10', '3.11'] steps: - uses: actions/checkout@v3 From 081fcd674801d3bab58171f630d6e7bc56b06b4d Mon Sep 17 00:00:00 2001 From: auouymous Date: Tue, 21 Feb 2023 15:03:05 -0700 Subject: [PATCH 07/36] Require python 3.7. --- CONTRIBUTING.md | 2 +- README.md | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c6b198b1..815e3954 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -3,7 +3,7 @@ ## Getting started Before you begin: -- Ensure you are using Python 3.5+ +- Ensure you are using Python 3.7+ - Check out the [existing issues](https://github.com/gpodder/gpodder/issues) Contributions are made to this repo via Issues and Pull Requests (PRs). Make sure to search for existing Issues and PRs before creating your own. diff --git a/README.md b/README.md index 2c7d0f9a..63063770 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ along with this program. If not, see . ## Dependencies -- [Python 3.5](http://python.org/) or newer +- [Python 3.7](http://python.org/) or newer - [Podcastparser](http://gpodder.org/podcastparser/) 0.6.0 or newer - [mygpoclient](http://gpodder.org/mygpoclient/) 1.7 or newer - [requests](https://requests.readthedocs.io) 2.24.0 or newer @@ -135,7 +135,7 @@ into an alternative root (default /) and prefix (default /usr): [*Debian*](https://wiki.debian.org/Python#Deviations_from_upstream) and *Ubuntu* use `dist-packages` instead of `site-packages` for third party installs, so you'll want something like: - sudo python3 setup.py install --root / --prefix /usr/local --optimize=1 --install-lib=/usr/local/lib/python3.5/dist-packages + sudo python3 setup.py install --root / --prefix /usr/local --optimize=1 --install-lib=/usr/local/lib/python3.10/dist-packages In fact, first try running `python -c "import sys; print(sys.path)"` to check what is the exact path. It depends on your version of python. From 8d31d9dd402b55b39825bb8d885a93e095a1095e Mon Sep 17 00:00:00 2001 From: auouymous Date: Tue, 21 Feb 2023 21:23:47 -0700 Subject: [PATCH 08/36] Display feed name when logging update errors. Avoids worthless log entries such as "Error: not found". --- src/gpodder/gtkui/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gpodder/gtkui/main.py b/src/gpodder/gtkui/main.py index 2b810d99..9a7dfb3f 100644 --- a/src/gpodder/gtkui/main.py +++ b/src/gpodder/gtkui/main.py @@ -2886,7 +2886,7 @@ class gPodder(BuilderWidget, dbus.service.Object): else: channel._update_error = '?' nr_update_errors += 1 - logger.error('Error: %s', message, exc_info=(e.__class__ not in [ + logger.error('Error updating feed: %s: %s', channel.title, message, exc_info=(e.__class__ not in [ gpodder.feedcore.BadRequest, gpodder.feedcore.AuthenticationRequired, gpodder.feedcore.Unsubscribe, From 353a4cc8b69cdbf3a7a9357114e4edb3cd516121 Mon Sep 17 00:00:00 2001 From: auouymous Date: Sat, 4 Mar 2023 19:26:36 -0700 Subject: [PATCH 09/36] Add EQL adjectives 'failed' and 'paused'. Allowing all failed downloads to be filtered with `(failed)`, all paused episodes with `(paused)`, and all downloading episodes, excluding paused episodes with `(downloading and not paused)`. --- src/gpodder/query.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/gpodder/query.py b/src/gpodder/query.py index 8ebbb1f8..9144ba34 100644 --- a/src/gpodder/query.py +++ b/src/gpodder/query.py @@ -101,6 +101,11 @@ class Matcher(object): return episode.file_type() == k elif k == 'torrent': return episode.url.endswith('.torrent') or 'torrent' in episode.mime_type + elif k == 'paused': + return (episode.download_task is not None + and episode.download_task.status in (episode.download_task.PAUSED, episode.download_task.PAUSING)) + elif k == 'failed': + return (episode.download_task is not None and episode.download_task.status == episode.download_task.FAILED) # Nouns (for comparisons) if k in ('megabytes', 'mb'): From 3d690633eeed914e7a1bb2b44c35dc959f41df3e Mon Sep 17 00:00:00 2001 From: auouymous Date: Sun, 5 Mar 2023 22:33:39 -0700 Subject: [PATCH 10/36] Add empty custom_downloader field in SyncTask to prevent exception. filename generated by yt-dlp. Reported in https://github.com/gpodder/gpodder/issues/1348#issuecomment-1445273299 --- src/gpodder/sync.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/gpodder/sync.py b/src/gpodder/sync.py index 6587f100..d336d7e2 100644 --- a/src/gpodder/sync.py +++ b/src/gpodder/sync.py @@ -745,6 +745,7 @@ class SyncTask(download.DownloadTask): self.speed = 0.0 self.progress = 0.0 self.error_message = None + self.custom_downloader = None # Have we already shown this task in a notification? self._notification_shown = False From 1725b471fa0cf1c942c9766b13c9e2061b1b6423 Mon Sep 17 00:00:00 2001 From: auouymous Date: Sat, 11 Mar 2023 03:15:29 -0700 Subject: [PATCH 11/36] Do not move window if maximised. The delayed move can reposition the window after it has been maximized. --- src/gpodder/gtkui/config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gpodder/gtkui/config.py b/src/gpodder/gtkui/config.py index 19d68d52..5eea4e75 100644 --- a/src/gpodder/gtkui/config.py +++ b/src/gpodder/gtkui/config.py @@ -186,7 +186,7 @@ class UIConfig(config.Config): # https://github.com/gpodder/gpodder/pull/933#issuecomment-818039693 if cfg.x == -1 or cfg.y == -1: window.set_position(Gtk.WindowPosition.CENTER_ON_PARENT) - else: + elif not cfg.maximized: window.move(cfg.x, cfg.y) # From Gtk docs: most window managers ignore requests for initial window # positions (instead using a user-defined placement algorithm) and honor From ab7b93d4d71403981a1e16bb1c0aec881bc08f35 Mon Sep 17 00:00:00 2001 From: auouymous Date: Sat, 11 Mar 2023 16:10:27 -0700 Subject: [PATCH 12/36] Fix commit 1725b471fa0cf1c942c9766b13c9e2061b1b6423. The window manager needs a position to unmaximize window to. --- src/gpodder/gtkui/config.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/gpodder/gtkui/config.py b/src/gpodder/gtkui/config.py index 5eea4e75..67ab8f91 100644 --- a/src/gpodder/gtkui/config.py +++ b/src/gpodder/gtkui/config.py @@ -186,14 +186,16 @@ class UIConfig(config.Config): # https://github.com/gpodder/gpodder/pull/933#issuecomment-818039693 if cfg.x == -1 or cfg.y == -1: window.set_position(Gtk.WindowPosition.CENTER_ON_PARENT) - elif not cfg.maximized: + else: window.move(cfg.x, cfg.y) # From Gtk docs: most window managers ignore requests for initial window # positions (instead using a user-defined placement algorithm) and honor # requests after the window has already been shown. # Move it a second time after the window has been shown. - # The first move reduces chance of window jumping. - util.idle_add(window.move, cfg.x, cfg.y) + # The first move reduces chance of window jumping, + # and gives the window manager a position to unmaximize to. + if not cfg.maximized: + util.idle_add(window.move, cfg.x, cfg.y) # Ignore events while we're connecting to the window self.__ignore_window_events = True From 7323e0c604392879b5d57dc7623583961a8b0fe1 Mon Sep 17 00:00:00 2001 From: auouymous Date: Sat, 11 Mar 2023 20:52:05 -0700 Subject: [PATCH 13/36] Refactor _receive_configure_event(). Add comment about bug when state event is sent after configure event. --- src/gpodder/gtkui/config.py | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/gpodder/gtkui/config.py b/src/gpodder/gtkui/config.py index 67ab8f91..4e156bea 100644 --- a/src/gpodder/gtkui/config.py +++ b/src/gpodder/gtkui/config.py @@ -203,14 +203,18 @@ class UIConfig(config.Config): # Get window state, correct size comes from window.get_size(), # see https://developer.gnome.org/SaveWindowState/ def _receive_configure_event(widget, event): - x_pos, y_pos = widget.get_position() - width_size, height_size = widget.get_size() - maximized = bool(event.window.get_state() & Gdk.WindowState.MAXIMIZED) - if not self.__ignore_window_events and not maximized: - cfg.x = x_pos - cfg.y = y_pos - cfg.width = width_size - cfg.height = height_size + if not self.__ignore_window_events: + # TODO: The maximize event might arrive after the configure event. + # This causes the maximized size to be saved, and restoring the + # window will not save its smaller size. Delaying the save with + # idle_add() is not enough time for the state event to arrive. + if not bool(event.window.get_state() & Gdk.WindowState.MAXIMIZED): + x_pos, y_pos = widget.get_position() + width_size, height_size = widget.get_size() + cfg.x = x_pos + cfg.y = y_pos + cfg.width = width_size + cfg.height = height_size window.connect('configure-event', _receive_configure_event) From 14efcd52dfe8c172d7763f95d48766c46e451045 Mon Sep 17 00:00:00 2001 From: auouymous Date: Sun, 26 Mar 2023 04:36:09 -0600 Subject: [PATCH 14/36] Log 'from' and 'to' sizes when syncing files. --- src/gpodder/sync.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/gpodder/sync.py b/src/gpodder/sync.py index d336d7e2..c459d218 100644 --- a/src/gpodder/sync.py +++ b/src/gpodder/sync.py @@ -536,9 +536,9 @@ class MP3PlayerDevice(Device): # Assume same size and don't sync again pass if not to_file_exists or from_size != to_size: - logger.info('Copying %s => %s', - os.path.basename(from_file), - to_file.get_uri()) + logger.info('Copying %s (%d bytes) => %s (%d bytes)', + os.path.basename(from_file), from_size, + to_file.get_uri(), to_size) from_file = Gio.File.new_for_path(from_file) try: def hookconvert(current_bytes, total_bytes, user_data): From ddbae467efc614d8d682b987704b32ebd17f089b Mon Sep 17 00:00:00 2001 From: auouymous Date: Sun, 2 Apr 2023 22:52:37 -0600 Subject: [PATCH 15/36] Raise exception when gpodder.net queries fail. This avoids JSON warnings when gpodder.net requests fail with "500 Internal Server" errors. --- src/gpodder/directory.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/gpodder/directory.py b/src/gpodder/directory.py index e2ff7091..a5b8f835 100644 --- a/src/gpodder/directory.py +++ b/src/gpodder/directory.py @@ -86,8 +86,12 @@ def directory_entry_from_opml(url): def directory_entry_from_mygpo_json(url): + r = util.urlopen(url) + if not r.ok: + raise Exception('%s: %d %s' % (url, r.status_code, r.reason)) + return [DirectoryEntry(d['title'], d['url'], d['logo_url'], d['subscribers'], d['description']) - for d in util.urlopen(url).json()] + for d in r.json()] class GPodderNetSearchProvider(Provider): @@ -150,7 +154,13 @@ class GPodderNetTagsProvider(Provider): return directory_entry_from_mygpo_json('http://gpodder.net/api/2/tag/%s/50.json' % urllib.parse.quote(tag)) def get_tags(self): - return [DirectoryTag(d['tag'], d['usage']) for d in util.urlopen('http://gpodder.net/api/2/tags/40.json').json()] + url = 'http://gpodder.net/api/2/tags/40.json' + + r = util.urlopen(url) + if not r.ok: + raise Exception('%s: %d %s' % (url, r.status_code, r.reason)) + + return [DirectoryTag(d['tag'], d['usage']) for d in r.json()] class SoundcloudSearchProvider(Provider): From 43eb6ca5f57cee468ea41646f1d73de66756562c Mon Sep 17 00:00:00 2001 From: auouymous Date: Sun, 2 Apr 2023 23:17:13 -0600 Subject: [PATCH 16/36] Log exceptions when searching for podcasts on gpodder.net. --- src/gpodder/gtkui/desktop/podcastdirectory.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/gpodder/gtkui/desktop/podcastdirectory.py b/src/gpodder/gtkui/desktop/podcastdirectory.py index 00554a58..850c7909 100644 --- a/src/gpodder/gtkui/desktop/podcastdirectory.py +++ b/src/gpodder/gtkui/desktop/podcastdirectory.py @@ -279,12 +279,15 @@ class gPodderPodcastDirectory(BuilderWidget): @self.obtain_podcasts_with def load_data(): - if self.current_provider.kind == directory.Provider.PROVIDER_SEARCH: - return self.current_provider.on_search(query) - elif self.current_provider.kind == directory.Provider.PROVIDER_URL: - return self.current_provider.on_url(query) - elif self.current_provider.kind == directory.Provider.PROVIDER_FILE: - return self.current_provider.on_file(query) + try: + if self.current_provider.kind == directory.Provider.PROVIDER_SEARCH: + return self.current_provider.on_search(query) + elif self.current_provider.kind == directory.Provider.PROVIDER_URL: + return self.current_provider.on_url(query) + elif self.current_provider.kind == directory.Provider.PROVIDER_FILE: + return self.current_provider.on_file(query) + except Exception as e: + logger.warning('Got exception while loading podcasts: %s', e) def on_can_subscribe_changed(self, can_subscribe): self.btnOK.set_sensitive(can_subscribe) From b0ce535ca9ba2018d04218809b88f448e2030d30 Mon Sep 17 00:00:00 2001 From: auouymous Date: Sat, 29 Apr 2023 21:10:33 -0600 Subject: [PATCH 17/36] Add a View menu option to show time in the episode released column. --- share/gpodder/ui/gtk/menus.ui | 4 ++++ src/gpodder/config.py | 1 + src/gpodder/gtkui/main.py | 17 +++++++++++++++-- src/gpodder/gtkui/model.py | 4 +++- src/gpodder/model.py | 11 +++++++++-- 5 files changed, 32 insertions(+), 5 deletions(-) diff --git a/share/gpodder/ui/gtk/menus.ui b/share/gpodder/ui/gtk/menus.ui index c3f3d2f7..a993a049 100644 --- a/share/gpodder/ui/gtk/menus.ui +++ b/share/gpodder/ui/gtk/menus.ui @@ -241,6 +241,10 @@ Episode descriptions <Primary>d + + win.viewShowEpisodeReleasedTime + Show episode released time + win.viewCtrlClickToSortEpisodes Require control click to sort episodes diff --git a/src/gpodder/config.py b/src/gpodder/config.py index 36350fbd..b5b6902f 100644 --- a/src/gpodder/config.py +++ b/src/gpodder/config.py @@ -171,6 +171,7 @@ defaults = { 'always_show_new': True, 'trim_title_prefix': True, 'descriptions': True, + 'show_released_time': False, 'ctrl_click_to_sort': False, 'columns': int('110', 2), # bitfield of visible columns }, diff --git a/src/gpodder/gtkui/main.py b/src/gpodder/gtkui/main.py index 9a7dfb3f..8b53b7d3 100644 --- a/src/gpodder/gtkui/main.py +++ b/src/gpodder/gtkui/main.py @@ -319,6 +319,11 @@ class gPodder(BuilderWidget, dbus.service.Object): action.connect('activate', self.on_item_view_show_episode_description_toggled) g.add_action(action) + action = Gio.SimpleAction.new_stateful( + 'viewShowEpisodeReleasedTime', None, GLib.Variant.new_boolean(self.config.ui.gtk.episode_list.show_released_time)) + action.connect('activate', self.on_item_view_show_episode_released_time_toggled) + g.add_action(action) + action = Gio.SimpleAction.new_stateful( 'viewCtrlClickToSortEpisodes', None, GLib.Variant.new_boolean(self.config.ui.gtk.episode_list.ctrl_click_to_sort)) action.connect('activate', self.on_item_view_ctrl_click_to_sort_episodes_toggled) @@ -926,7 +931,9 @@ class gPodder(BuilderWidget, dbus.service.Object): timecolumn.set_sort_column_id(EpisodeListModel.C_TOTAL_TIME) releasecell = Gtk.CellRendererText() - releasecolumn = Gtk.TreeViewColumn(_('Released'), releasecell, text=EpisodeListModel.C_PUBLISHED_TEXT) + releasecolumn = Gtk.TreeViewColumn(_('Released')) + releasecolumn.pack_start(releasecell, True) + releasecolumn.add_attribute(releasecell, 'markup', EpisodeListModel.C_PUBLISHED_TEXT) releasecolumn.set_sort_column_id(EpisodeListModel.C_PUBLISHED) sizetimecell = Gtk.CellRendererText() @@ -1365,7 +1372,8 @@ class gPodder(BuilderWidget, dbus.service.Object): def _on_config_changed(self, name, old_value, new_value): if name == 'ui.gtk.toolbar': self.toolbar.set_property('visible', new_value) - elif name in ('ui.gtk.episode_list.descriptions', + elif name in ('ui.gtk.episode_list.show_released_time', + 'ui.gtk.episode_list.descriptions', 'ui.gtk.episode_list.trim_title_prefix', 'ui.gtk.episode_list.always_show_new'): self.update_episode_list_model() @@ -3507,6 +3515,11 @@ class gPodder(BuilderWidget, dbus.service.Object): self.config.ui.gtk.episode_list.descriptions = not state action.set_state(GLib.Variant.new_boolean(not state)) + def on_item_view_show_episode_released_time_toggled(self, action, param): + state = action.get_state() + self.config.ui.gtk.episode_list.show_released_time = not state + action.set_state(GLib.Variant.new_boolean(not state)) + def on_item_view_ctrl_click_to_sort_episodes_toggled(self, action, param): state = action.get_state() self.config.ui.gtk.episode_list.ctrl_click_to_sort = not state diff --git a/src/gpodder/gtkui/model.py b/src/gpodder/gtkui/model.py index df2d4c22..1c278df6 100644 --- a/src/gpodder/gtkui/model.py +++ b/src/gpodder/gtkui/model.py @@ -128,7 +128,7 @@ class BackgroundUpdate(object): model.C_URL, episode.url, model.C_TITLE, episode.title, model.C_EPISODE, episode, - model.C_PUBLISHED_TEXT, episode.cute_pubdate(), + model.C_PUBLISHED_TEXT, episode.cute_pubdate(show_time=self.model._config_ui_gtk_episode_list_show_released_time), model.C_PUBLISHED, episode.published, ) update_fields = model.get_update_fields(episode) @@ -215,11 +215,13 @@ class EpisodeListModel(Gtk.ListStore): self._config_ui_gtk_episode_list_always_show_new = False self._config_ui_gtk_episode_list_trim_title_prefix = False self._config_ui_gtk_episode_list_descriptions = False + self._config_ui_gtk_episode_list_show_released_time = False def cache_config(self, config): self._config_ui_gtk_episode_list_always_show_new = config.ui.gtk.episode_list.always_show_new self._config_ui_gtk_episode_list_trim_title_prefix = config.ui.gtk.episode_list.trim_title_prefix self._config_ui_gtk_episode_list_descriptions = config.ui.gtk.episode_list.descriptions + self._config_ui_gtk_episode_list_show_released_time = config.ui.gtk.episode_list.show_released_time def _format_filesize(self, episode): if episode.file_size > 0: diff --git a/src/gpodder/model.py b/src/gpodder/model.py index fed62f84..0b07d4d7 100644 --- a/src/gpodder/model.py +++ b/src/gpodder/model.py @@ -842,11 +842,18 @@ class PodcastEpisode(PodcastModelObject): self.title, self.cute_pubdate()) - def cute_pubdate(self): + def cute_pubdate(self, show_time=False): result = util.format_date(self.published) if result is None: return '(%s)' % _('unknown') - else: + + try: + if show_time: + timestamp = datetime.datetime.fromtimestamp(self.published) + return '{}\n{}'.format(timestamp.strftime('%H:%M'), result) + else: + return result + except: return result pubdate_prop = property(fget=cute_pubdate) From df4195dc5cc527c41ed3c6a1f798a61478728a0c Mon Sep 17 00:00:00 2001 From: auouymous Date: Sat, 29 Apr 2023 21:41:38 -0600 Subject: [PATCH 18/36] Add a View menu option to right align the episode released column. --- share/gpodder/ui/gtk/menus.ui | 4 ++++ src/gpodder/config.py | 1 + src/gpodder/gtkui/main.py | 30 +++++++++++++++++++++++++++--- 3 files changed, 32 insertions(+), 3 deletions(-) diff --git a/share/gpodder/ui/gtk/menus.ui b/share/gpodder/ui/gtk/menus.ui index a993a049..080563e0 100644 --- a/share/gpodder/ui/gtk/menus.ui +++ b/share/gpodder/ui/gtk/menus.ui @@ -245,6 +245,10 @@ win.viewShowEpisodeReleasedTime Show episode released time + + win.viewRightAlignEpisodeReleasedColumn + Right align episode released column + win.viewCtrlClickToSortEpisodes Require control click to sort episodes diff --git a/src/gpodder/config.py b/src/gpodder/config.py index b5b6902f..485b392e 100644 --- a/src/gpodder/config.py +++ b/src/gpodder/config.py @@ -172,6 +172,7 @@ defaults = { 'trim_title_prefix': True, 'descriptions': True, 'show_released_time': False, + 'right_align_released_column': False, 'ctrl_click_to_sort': False, 'columns': int('110', 2), # bitfield of visible columns }, diff --git a/src/gpodder/gtkui/main.py b/src/gpodder/gtkui/main.py index 8b53b7d3..ea9c58ce 100644 --- a/src/gpodder/gtkui/main.py +++ b/src/gpodder/gtkui/main.py @@ -194,6 +194,8 @@ class gPodder(BuilderWidget, dbus.service.Object): self.create_actions() + self.releasecell = None + # Init the treeviews that we use self.init_podcast_list_treeview() self.init_episode_list_treeview() @@ -324,6 +326,12 @@ class gPodder(BuilderWidget, dbus.service.Object): action.connect('activate', self.on_item_view_show_episode_released_time_toggled) g.add_action(action) + action = Gio.SimpleAction.new_stateful( + 'viewRightAlignEpisodeReleasedColumn', None, + GLib.Variant.new_boolean(self.config.ui.gtk.episode_list.right_align_released_column)) + action.connect('activate', self.on_item_view_right_align_episode_released_column_toggled) + g.add_action(action) + action = Gio.SimpleAction.new_stateful( 'viewCtrlClickToSortEpisodes', None, GLib.Variant.new_boolean(self.config.ui.gtk.episode_list.ctrl_click_to_sort)) action.connect('activate', self.on_item_view_ctrl_click_to_sort_episodes_toggled) @@ -879,6 +887,14 @@ class gPodder(BuilderWidget, dbus.service.Object): return False + def align_releasecell(self): + if self.config.ui.gtk.episode_list.right_align_released_column: + self.releasecell.set_property('xalign', 1) + self.releasecell.set_property('alignment', Pango.Alignment.RIGHT) + else: + self.releasecell.set_property('xalign', 0) + self.releasecell.set_property('alignment', Pango.Alignment.LEFT) + def init_episode_list_treeview(self): self.episode_list_model.set_view_mode(self.config.ui.gtk.episode_list.view_mode) @@ -930,10 +946,11 @@ class gPodder(BuilderWidget, dbus.service.Object): timecolumn = Gtk.TreeViewColumn(_('Duration'), timecell, text=EpisodeListModel.C_TIME) timecolumn.set_sort_column_id(EpisodeListModel.C_TOTAL_TIME) - releasecell = Gtk.CellRendererText() + self.releasecell = Gtk.CellRendererText() + self.align_releasecell() releasecolumn = Gtk.TreeViewColumn(_('Released')) - releasecolumn.pack_start(releasecell, True) - releasecolumn.add_attribute(releasecell, 'markup', EpisodeListModel.C_PUBLISHED_TEXT) + releasecolumn.pack_start(self.releasecell, True) + releasecolumn.add_attribute(self.releasecell, 'markup', EpisodeListModel.C_PUBLISHED_TEXT) releasecolumn.set_sort_column_id(EpisodeListModel.C_PUBLISHED) sizetimecell = Gtk.CellRendererText() @@ -3520,6 +3537,13 @@ class gPodder(BuilderWidget, dbus.service.Object): self.config.ui.gtk.episode_list.show_released_time = not state action.set_state(GLib.Variant.new_boolean(not state)) + def on_item_view_right_align_episode_released_column_toggled(self, action, param): + state = action.get_state() + self.config.ui.gtk.episode_list.right_align_released_column = not state + action.set_state(GLib.Variant.new_boolean(not state)) + self.align_releasecell() + self.treeAvailable.queue_draw() + def on_item_view_ctrl_click_to_sort_episodes_toggled(self, action, param): state = action.get_state() self.config.ui.gtk.episode_list.ctrl_click_to_sort = not state From 5224565642c6d9ccfa059a653d63d310a2889d95 Mon Sep 17 00:00:00 2001 From: auouymous Date: Sat, 29 Apr 2023 22:11:27 -0600 Subject: [PATCH 19/36] Always show released time in shownotes. --- src/gpodder/gtkui/shownotes.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/gpodder/gtkui/shownotes.py b/src/gpodder/gtkui/shownotes.py index a906e835..94dba29f 100644 --- a/src/gpodder/gtkui/shownotes.py +++ b/src/gpodder/gtkui/shownotes.py @@ -16,6 +16,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . # +import datetime import html import logging from urllib.parse import urlparse @@ -201,7 +202,8 @@ class gPodderShownotesText(gPodderShownotes): heading = episode.title subheading = _('from %s') % (episode.channel.title) details = self.details_fmt % { - 'date': util.format_date(episode.published), + 'date': '{} {}'.format(datetime.datetime.fromtimestamp(episode.published).strftime('%H:%M'), + util.format_date(episode.published)), 'size': util.format_filesize(episode.file_size, digits=1) if episode.file_size > 0 else "-", 'duration': episode.get_play_info_string()} @@ -342,7 +344,8 @@ class gPodderShownotesHTML(gPodderShownotes): heading = '

%s

' % html.escape(episode.title) subheading = _('from %s') % html.escape(episode.channel.title) details = '%s' % html.escape(self.details_fmt % { - 'date': util.format_date(episode.published), + 'date': '{} {}'.format(datetime.datetime.fromtimestamp(episode.published).strftime('%H:%M'), + util.format_date(episode.published)), 'size': util.format_filesize(episode.file_size, digits=1) if episode.file_size > 0 else "-", 'duration': episode.get_play_info_string()}) From b53ba83d22d6cfcf912d58d8adfe9b2a037a299f Mon Sep 17 00:00:00 2001 From: auouymous Date: Tue, 23 May 2023 14:13:24 -0600 Subject: [PATCH 20/36] Fix issue retrieving channel ID for Youtube pages. The channelId meta tag was removed from the HTML. Changing to the channel_id in RSS feed URL tag should be stable. --- src/gpodder/youtube.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gpodder/youtube.py b/src/gpodder/youtube.py index efdc28f3..f0e52f97 100644 --- a/src/gpodder/youtube.py +++ b/src/gpodder/youtube.py @@ -440,7 +440,7 @@ def get_channel_id_url(url, feed_data=None): else: r = feed_data # video page may contain corrupt HTML/XML, search for tag to avoid exception - m = re.search(r'', r.text) + m = re.search(r'channel_id=([^"]+)">', r.text) if m: channel_id = m.group(1) else: From b1492e60e52637e2beee518cfd82622413f1060f Mon Sep 17 00:00:00 2001 From: Teemu Ikonen Date: Thu, 29 Jun 2023 23:11:14 +0300 Subject: [PATCH 21/36] youtube-dl: Use 'color': 'no_color' param in yt-dlp This prevents unnecessary warnings from yt-dlp. --- share/gpodder/extensions/youtube-dl.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/share/gpodder/extensions/youtube-dl.py b/share/gpodder/extensions/youtube-dl.py index 610d4ab1..cd4557d5 100644 --- a/share/gpodder/extensions/youtube-dl.py +++ b/share/gpodder/extensions/youtube-dl.py @@ -296,9 +296,14 @@ class gPodderYoutubeDL(download.CustomDownloader): os.makedirs(cachedir, exist_ok=True) self._ydl_opts = { 'cachedir': cachedir, - 'no_color': True, # prevent escape codes in desktop notifications on errors 'noprogress': True, # prevent progress bar from appearing in console } + # prevent escape codes in desktop notifications on errors + if program_name == 'yt-dlp': + self._ydl_opts['color'] = 'no_color' + else: + self._ydl_opts['no_color'] = True + if gpodder.verbose: self._ydl_opts['verbose'] = True else: From d64eb6e0b2541e0d35f89fe08f5f0ae818c4f116 Mon Sep 17 00:00:00 2001 From: Teemu Ikonen Date: Thu, 29 Jun 2023 23:12:05 +0300 Subject: [PATCH 22/36] youtube-dl: In yt-dlp _VALID_URL_RE is now an iterable of regexes --- share/gpodder/extensions/youtube-dl.py | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/share/gpodder/extensions/youtube-dl.py b/share/gpodder/extensions/youtube-dl.py index cd4557d5..b3bd5799 100644 --- a/share/gpodder/extensions/youtube-dl.py +++ b/share/gpodder/extensions/youtube-dl.py @@ -9,6 +9,7 @@ import os import re import sys import time +from collections.abc import Iterable try: import yt_dlp as youtube_dl @@ -311,7 +312,7 @@ class gPodderYoutubeDL(download.CustomDownloader): # Don't create downloaders for URLs supported by these youtube-dl extractors self.ie_blacklist = ["Generic"] # Cache URL regexes from youtube-dl matches here, seed with youtube regex - self.regex_cache = [re.compile(r'https://www.youtube.com/watch\?v=.+')] + self.regex_cache = [(re.compile(r'https://www.youtube.com/watch\?v=.+'),)] # #686 on windows without a console, sys.stdout is None, causing exceptions # when adding podcasts. # See https://docs.python.org/3/library/sys.html#sys.__stderr__ Note @@ -453,12 +454,11 @@ class gPodderYoutubeDL(download.CustomDownloader): def is_supported_url(self, url): if url is None: return False - if self.regex_cache[0].match(url) is not None: - return True - for r in self.regex_cache[1:]: - if r.match(url) is not None: - self.regex_cache.remove(r) - self.regex_cache.insert(0, r) + for i, res in enumerate(self.regex_cache): + if next(filter(None, (r.match(url) for r in res)), None) is not None: + if i > 0: + self.regex_cache.remove(res) + self.regex_cache.insert(0, res) return True with youtube_dl.YoutubeDL(self._ydl_opts) as ydl: # youtube-dl returns a list, yt-dlp returns a dict @@ -467,7 +467,9 @@ class gPodderYoutubeDL(download.CustomDownloader): ies = ydl._ies.values() for ie in ies: if ie.suitable(url) and ie.ie_key() not in self.ie_blacklist: - self.regex_cache.insert(0, ie._VALID_URL_RE) + self.regex_cache.insert( + 0, (ie._VALID_URL_RE if isinstance(ie._VALID_URL_RE, Iterable) + else (ie._VALID_URL_RE,))) return True return False From fccea8a6d99c53cabc201253cddd84284b2ea139 Mon Sep 17 00:00:00 2001 From: auouymous Date: Fri, 30 Jun 2023 16:18:54 -0600 Subject: [PATCH 23/36] Bump required yt-dlp version for changes in #1520. --- share/gpodder/extensions/youtube-dl.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/share/gpodder/extensions/youtube-dl.py b/share/gpodder/extensions/youtube-dl.py index b3bd5799..f009da14 100644 --- a/share/gpodder/extensions/youtube-dl.py +++ b/share/gpodder/extensions/youtube-dl.py @@ -14,7 +14,7 @@ from collections.abc import Iterable try: import yt_dlp as youtube_dl program_name = 'yt-dlp' - want_ytdl_version = '2023.02.17' + want_ytdl_version = '2023.06.22' except: import youtube_dl program_name = 'youtube-dl' From a224c47b156374c4d6bff3f586be7de9022c7ffe Mon Sep 17 00:00:00 2001 From: alexis26 Date: Sun, 2 Jul 2023 08:34:10 +0200 Subject: [PATCH 24/36] Update fr.po Hi, I just change one line (875) --- po/fr.po | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/po/fr.po b/po/fr.po index d0397656..c2d7fb6c 100644 --- a/po/fr.po +++ b/po/fr.po @@ -872,7 +872,7 @@ msgstr "Détails de l'épisode" #, fuzzy #| msgid "Select _none" msgid "Select channel" -msgstr "Sélectionner _aucun" +msgstr "Sélectionner le Podcast de cet épisode" #: src/gpodder/gtkui/main.py:2370 msgid "Please check your media player settings in the preferences dialog." From 8a995cb0979fd83f0f59364b52f23287b38c64d3 Mon Sep 17 00:00:00 2001 From: luzpaz Date: Fri, 14 Jul 2023 12:13:50 +0000 Subject: [PATCH 25/36] Fix various typos Found via `codespell -q 3 -S *.po -L bloc,extracter,parms` --- setup.py | 2 +- share/gpodder/examples/hello_world.py | 2 +- share/gpodder/extensions/enqueue_in_mediaplayer.py | 2 +- share/gpodder/extensions/notification-win32.py | 2 +- share/gpodder/extensions/rockbox_coverart.py | 2 +- share/gpodder/extensions/tagging.py | 2 +- share/gpodder/extensions/youtube-dl.py | 4 ++-- src/gpodder/download.py | 4 ++-- src/gpodder/gtkui/base.py | 6 +++--- src/gpodder/gtkui/draw.py | 4 ++-- src/gpodder/gtkui/main.py | 2 +- src/gpodder/model.py | 2 +- src/gpodder/sync.py | 4 ++-- src/gpodder/util.py | 8 ++++---- tools/mac-osx/adjust-modifiers.xsl | 2 +- tools/mac-osx/launcher.py | 4 ++-- tools/win_installer/misc/win_installer.nsi | 2 +- 17 files changed, 27 insertions(+), 27 deletions(-) diff --git a/setup.py b/setup.py index 050be572..86963fc5 100644 --- a/setup.py +++ b/setup.py @@ -25,7 +25,7 @@ from distutils.core import setup installing = ('install' in sys.argv and '--help' not in sys.argv) -# distutils depends on setup.py beeing executed from the same dir. +# distutils depends on setup.py being executed from the same dir. # Most of our custom commands work either way, but this makes # it work in all cases. os.chdir(os.path.dirname(os.path.realpath(__file__))) diff --git a/share/gpodder/examples/hello_world.py b/share/gpodder/examples/hello_world.py index be4a30b0..28c03ec2 100644 --- a/share/gpodder/examples/hello_world.py +++ b/share/gpodder/examples/hello_world.py @@ -60,7 +60,7 @@ class gPodderExtension: # # https://docs.python.org/3/library/subprocess.html#subprocess.Popen # -# This is expecially important for extensions responding to +# This is especially important for extensions responding to # on_episode_downloaded(), which runs whenever a download finishes. # # Otherwise that process will inherit ALL file descriptors gPodder diff --git a/share/gpodder/extensions/enqueue_in_mediaplayer.py b/share/gpodder/extensions/enqueue_in_mediaplayer.py index 5673ae87..1ff7c563 100644 --- a/share/gpodder/extensions/enqueue_in_mediaplayer.py +++ b/share/gpodder/extensions/enqueue_in_mediaplayer.py @@ -242,7 +242,7 @@ RESUMERS = [ # with https://github.com/Serranya/deadbeef-mpris2-plugin MPRISResumer('resume in deadbeef', 'DeaDBeeF', ['deadbeef'], 'org.mpris.MediaPlayer2.DeaDBeeF'), - # the gPodder Dowloads directory must be in gmusicbrowser's library + # the gPodder Downloads directory must be in gmusicbrowser's library MPRISResumer('resume in gmusicbrowser', 'gmusicbrowser', ['gmusicbrowser'], 'org.mpris.MediaPlayer2.gmusicbrowser'), # Audacious doesn't implement MPRIS2.OpenUri diff --git a/share/gpodder/extensions/notification-win32.py b/share/gpodder/extensions/notification-win32.py index c99f3796..52703874 100644 --- a/share/gpodder/extensions/notification-win32.py +++ b/share/gpodder/extensions/notification-win32.py @@ -100,7 +100,7 @@ try {{ [Windows.UI.Notifications.ToastNotificationManager]::CreateToastNotifier($APP_ID).Show($toast) Remove-Item -LiteralPath $MyInvocation.MyCommand.Path -Force # Delete this script temp file. }} else {{ - # use older Baloon notification when not on Windows 10 + # use older Balloon notification when not on Windows 10 [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") $o = New-Object System.Windows.Forms.NotifyIcon diff --git a/share/gpodder/extensions/rockbox_coverart.py b/share/gpodder/extensions/rockbox_coverart.py index d3f90b86..10a22d2a 100644 --- a/share/gpodder/extensions/rockbox_coverart.py +++ b/share/gpodder/extensions/rockbox_coverart.py @@ -39,7 +39,7 @@ class gPodderExtension: device_folder = device.get_episode_folder_on_device(episode) episode_art = os.path.join(episode_folder, "folder.jpg") device_art = os.path.join(device_folder, self.config.art_name_on_device) - # make sure we have art to copy and it doesnt already exist + # make sure we have art to copy and it doesn't already exist if os.path.isfile(episode_art) and not os.path.isfile(device_art): logger.info('Syncing cover art for %s', episode.channel.title) # copy and rename art diff --git a/share/gpodder/extensions/tagging.py b/share/gpodder/extensions/tagging.py index 29d98dbe..ff666363 100644 --- a/share/gpodder/extensions/tagging.py +++ b/share/gpodder/extensions/tagging.py @@ -131,7 +131,7 @@ class AudioFile(object): def get_cover_picture(self, cover): """ Returns mutagen Picture class for the cover image - Usefull for OGG and FLAC format + Useful for OGG and FLAC format Picture type = cover image see http://flac.sourceforge.net/documentation_tools_flac.html#encoding_options diff --git a/share/gpodder/extensions/youtube-dl.py b/share/gpodder/extensions/youtube-dl.py index f009da14..058e4ce4 100644 --- a/share/gpodder/extensions/youtube-dl.py +++ b/share/gpodder/extensions/youtube-dl.py @@ -42,7 +42,7 @@ __doc__ = 'https://gpodder.github.io/docs/extensions/youtubedl.html' want_ytdl_version_msg = _('Your version of youtube-dl/yt-dlp %(have_version)s has known issues, please upgrade to %(want_version)s or newer.') DefaultConfig = { - # youtube-dl downloads and parses each video page to get informations about it, which is very slow. + # youtube-dl downloads and parses each video page to get information about it, which is very slow. # Set to False to fall back to the fast but limited (only 15 episodes) gpodder code 'manage_channel': True, # If for some reason youtube-dl download doesn't work for you, you can fallback to gpodder code. @@ -390,7 +390,7 @@ class gPodderYoutubeDL(download.CustomDownloader): """ Fetch a channel or playlist contents. - Doesn't yet fetch video entry informations, so we only get the video id and title. + Doesn't yet fetch video entry information, so we only get the video id and title. """ # Duplicate a bit of the YoutubeDL machinery here because we only # want to parse the channel/playlist first, not to fetch video entries. diff --git a/src/gpodder/download.py b/src/gpodder/download.py index 3ee02cdf..df8e87b9 100644 --- a/src/gpodder/download.py +++ b/src/gpodder/download.py @@ -170,7 +170,7 @@ class ContentRange(object): return None value = value.strip() if not value.startswith('bytes '): - # Unparseable + # Unparsable return None value = value[len('bytes '):].strip() if '/' not in value: @@ -588,7 +588,7 @@ class DownloadTask(object): _('Finished'), _('Failed'), _('Cancelling'), _('Cancelled'), _('Pausing'), _('Paused')) (NEW, QUEUED, DOWNLOADING, DONE, FAILED, CANCELLING, CANCELLED, PAUSING, PAUSED) = list(range(9)) - # Wheter this task represents a file download or a device sync operation + # Whether this task represents a file download or a device sync operation ACTIVITY_DOWNLOAD, ACTIVITY_SYNCHRONIZE = list(range(2)) # Minimum time between progress updates (in seconds) diff --git a/src/gpodder/gtkui/base.py b/src/gpodder/gtkui/base.py index 25cf3f3e..fd092423 100644 --- a/src/gpodder/gtkui/base.py +++ b/src/gpodder/gtkui/base.py @@ -74,7 +74,7 @@ class GtkBuilderWidget(object): Convert widget names to attributes of this object. It means a widget named vbox-dialog in GtkBuilder - is refered using self.vbox_dialog in the code. + is referred using self.vbox_dialog in the code. """ for widget in self.builder.get_objects(): # Just to be safe - every widget from the builder is buildable @@ -100,7 +100,7 @@ class GtkBuilderWidget(object): def new(self): """ Method called when the user interface is loaded and ready to be used. - At this moment, the widgets are loaded and can be refered as self.widget_name + At this moment, the widgets are loaded and can be referred as self.widget_name """ def main(self): @@ -132,7 +132,7 @@ class GtkBuilderWidget(object): """ Starts the main loop of processing events checking for Control-C. - The default implementation checks wheter a Control-C is pressed, + The default implementation checks whether a Control-C is pressed, then calls on_keyboard_interrupt(). Use this method for starting programs. diff --git a/src/gpodder/gtkui/draw.py b/src/gpodder/gtkui/draw.py index f6afa428..f2904b3d 100644 --- a/src/gpodder/gtkui/draw.py +++ b/src/gpodder/gtkui/draw.py @@ -77,7 +77,7 @@ def draw_rounded_rectangle(ctx, x, y, w, h, r=10, left_side_width=None, def rounded_rectangle(ctx, x, y, width, height, radius=4.): - """Simple rounded rectangle algorithmn + """Simple rounded rectangle algorithm http://www.cairographics.org/samples/rounded_rectangle/ """ @@ -126,7 +126,7 @@ def draw_text_box_centered(ctx, widget, w_width, w_height, text, font_desc=None, def draw_cake(percentage, text=None, emblem=None, size=None): # Download percentage bar icon - it turns out the cake is a lie (d'oh!) - # ..but the inital idea was to have a cake-style indicator, but that + # ..but the initial idea was to have a cake-style indicator, but that # didn't work as well as the progress bar, but the name stuck.. if size is None: diff --git a/src/gpodder/gtkui/main.py b/src/gpodder/gtkui/main.py index ea9c58ce..5742c78e 100644 --- a/src/gpodder/gtkui/main.py +++ b/src/gpodder/gtkui/main.py @@ -398,7 +398,7 @@ class gPodder(BuilderWidget, dbus.service.Object): def inject_extensions_menu(self): """ Update Extras/Extensions menu. - Called at startup and when en/dis-abling extenstions. + Called at startup and when en/dis-abling extensions. """ def gen_callback(label, callback): return lambda action, param: callback() diff --git a/src/gpodder/model.py b/src/gpodder/model.py index 0b07d4d7..02018f4f 100644 --- a/src/gpodder/model.py +++ b/src/gpodder/model.py @@ -1283,7 +1283,7 @@ class PodcastChannel(PodcastModelObject): # This *might* cause episodes to be skipped if there were more than # limit.episodes items added to the feed between updates. - # The benefit is that it prevents old episodes from apearing as new + # The benefit is that it prevents old episodes from appearing as new # in certain situations (see bug #340). self.db.purge(max_episodes, self.id) # TODO: Remove from self.children! diff --git a/src/gpodder/sync.py b/src/gpodder/sync.py index c459d218..1b0e5148 100644 --- a/src/gpodder/sync.py +++ b/src/gpodder/sync.py @@ -113,7 +113,7 @@ def episode_filename_on_device(config, episode): """ # get the local file from_file = episode.local_filename(create=False) - # get the formated base name + # get the formatted base name filename_base = util.sanitize_filename(episode.sync_filename( config.device_sync.custom_sync_name_enabled, config.device_sync.custom_sync_name), @@ -829,7 +829,7 @@ class SyncTask(download.DownloadTask): if self.status != SyncTask.DOWNLOADING: return False - # We are synching this file right now + # We are syncing this file right now self._notification_shown = False sync_result = SyncTask.DOWNLOADING diff --git a/src/gpodder/util.py b/src/gpodder/util.py index bd5757fb..61218469 100644 --- a/src/gpodder/util.py +++ b/src/gpodder/util.py @@ -294,7 +294,7 @@ def normalize_feed_url(url): if scheme not in ('http', 'https', 'ftp', 'file'): return None - # urlunsplit might return "a slighty different, but equivalent URL" + # urlunsplit might return "a slightly different, but equivalent URL" return urllib.parse.urlunsplit((scheme, netloc, path, query, fragment)) @@ -842,7 +842,7 @@ def extract_hyperlinked_text(html): def nice_html_description(img, description): """ - basic html formating + hyperlink highlighting + video thumbnail + basic html formatting + hyperlink highlighting + video thumbnail """ description = re.sub(r'''https?://[^\s]+''', r'''\g<0>''', @@ -1278,7 +1278,7 @@ def get_real_url(url): def find_command(command): """ Searches the system's PATH for a specific command that is - executable by the user. Returns the first occurence of an + executable by the user. Returns the first occurrence of an executable binary in the PATH, or None if the command is not available. @@ -2229,7 +2229,7 @@ class Popen(subprocess.Popen): def _parse_mimetype_sorted_dictitems(mimetype): - """ python 3.5 unorderd dict compat for doctest. don't use! """ + """ python 3.5 unordered dict compat for doctest. don't use! """ r = parse_mimetype(mimetype) return r[0], r[1], sorted(r[2].items()) diff --git a/tools/mac-osx/adjust-modifiers.xsl b/tools/mac-osx/adjust-modifiers.xsl index dd5babab..6d17fd98 100644 --- a/tools/mac-osx/adjust-modifiers.xsl +++ b/tools/mac-osx/adjust-modifiers.xsl @@ -1,5 +1,5 @@ -