iopenpod 1.0.47__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- iopenpod-1.0.47/.flake8 +3 -0
- iopenpod-1.0.47/.gitattributes +2 -0
- iopenpod-1.0.47/.github/ISSUE_TEMPLATE/bug_report.md +31 -0
- iopenpod-1.0.47/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
- iopenpod-1.0.47/.github/workflows/flatpak.yml +114 -0
- iopenpod-1.0.47/.github/workflows/health.yml +38 -0
- iopenpod-1.0.47/.github/workflows/release.yml +286 -0
- iopenpod-1.0.47/.gitignore +179 -0
- iopenpod-1.0.47/ArtworkDB_Parser/__init__.py +3 -0
- iopenpod-1.0.47/ArtworkDB_Parser/chunk_parser.py +66 -0
- iopenpod-1.0.47/ArtworkDB_Parser/constants.py +37 -0
- iopenpod-1.0.47/ArtworkDB_Parser/mhfd_parser.py +61 -0
- iopenpod-1.0.47/ArtworkDB_Parser/mhii_parser.py +52 -0
- iopenpod-1.0.47/ArtworkDB_Parser/mhli_parser.py +16 -0
- iopenpod-1.0.47/ArtworkDB_Parser/mhni_parser.py +196 -0
- iopenpod-1.0.47/ArtworkDB_Parser/mhod_parser.py +73 -0
- iopenpod-1.0.47/ArtworkDB_Parser/mhsd_parser.py +16 -0
- iopenpod-1.0.47/ArtworkDB_Parser/parser.py +15 -0
- iopenpod-1.0.47/ArtworkDB_Writer/__init__.py +63 -0
- iopenpod-1.0.47/ArtworkDB_Writer/art_extractor.py +303 -0
- iopenpod-1.0.47/ArtworkDB_Writer/artwork_writer.py +1139 -0
- iopenpod-1.0.47/ArtworkDB_Writer/ithmb_codecs.py +631 -0
- iopenpod-1.0.47/ArtworkDB_Writer/rgb565.py +250 -0
- iopenpod-1.0.47/GUI/__init__.py +3 -0
- iopenpod-1.0.47/GUI/app.py +1871 -0
- iopenpod-1.0.47/GUI/auto_updater.py +590 -0
- iopenpod-1.0.47/GUI/fonts.py +88 -0
- iopenpod-1.0.47/GUI/glyphs.py +104 -0
- iopenpod-1.0.47/GUI/hidpi.py +79 -0
- iopenpod-1.0.47/GUI/imgMaker.py +588 -0
- iopenpod-1.0.47/GUI/ipod_images.py +68 -0
- iopenpod-1.0.47/GUI/notifications.py +121 -0
- iopenpod-1.0.47/GUI/styles.py +1847 -0
- iopenpod-1.0.47/GUI/widgets/MBGridView.py +504 -0
- iopenpod-1.0.47/GUI/widgets/MBGridViewItem.py +180 -0
- iopenpod-1.0.47/GUI/widgets/MBListView.py +2878 -0
- iopenpod-1.0.47/GUI/widgets/__init__.py +0 -0
- iopenpod-1.0.47/GUI/widgets/backupBrowser.py +1245 -0
- iopenpod-1.0.47/GUI/widgets/browserChrome.py +115 -0
- iopenpod-1.0.47/GUI/widgets/devicePicker.py +444 -0
- iopenpod-1.0.47/GUI/widgets/dropOverlay.py +107 -0
- iopenpod-1.0.47/GUI/widgets/formatters.py +286 -0
- iopenpod-1.0.47/GUI/widgets/gridHeaderBar.py +141 -0
- iopenpod-1.0.47/GUI/widgets/musicBrowser.py +399 -0
- iopenpod-1.0.47/GUI/widgets/photoBrowser.py +1045 -0
- iopenpod-1.0.47/GUI/widgets/photoTile.py +190 -0
- iopenpod-1.0.47/GUI/widgets/photoViewer.py +358 -0
- iopenpod-1.0.47/GUI/widgets/playlistBrowser.py +1426 -0
- iopenpod-1.0.47/GUI/widgets/playlistEditor.py +1387 -0
- iopenpod-1.0.47/GUI/widgets/podcastBrowser.py +1856 -0
- iopenpod-1.0.47/GUI/widgets/podcastSearchDialog.py +343 -0
- iopenpod-1.0.47/GUI/widgets/scrollingLabel.py +96 -0
- iopenpod-1.0.47/GUI/widgets/selectiveSyncBrowser.py +1839 -0
- iopenpod-1.0.47/GUI/widgets/settingsPage.py +2533 -0
- iopenpod-1.0.47/GUI/widgets/sidebar.py +1096 -0
- iopenpod-1.0.47/GUI/widgets/syncReview.py +2828 -0
- iopenpod-1.0.47/GUI/widgets/trackListTitleBar.py +218 -0
- iopenpod-1.0.47/LICENSE +21 -0
- iopenpod-1.0.47/PKG-INFO +234 -0
- iopenpod-1.0.47/PLAN.md +76 -0
- iopenpod-1.0.47/PodcastManager/__init__.py +1 -0
- iopenpod-1.0.47/PodcastManager/downloader.py +481 -0
- iopenpod-1.0.47/PodcastManager/feed_parser.py +287 -0
- iopenpod-1.0.47/PodcastManager/itunes_search.py +89 -0
- iopenpod-1.0.47/PodcastManager/models.py +241 -0
- iopenpod-1.0.47/PodcastManager/podcast_sync.py +629 -0
- iopenpod-1.0.47/PodcastManager/subscription_store.py +193 -0
- iopenpod-1.0.47/README.md +203 -0
- iopenpod-1.0.47/SQLiteDB_Writer/__init__.py +21 -0
- iopenpod-1.0.47/SQLiteDB_Writer/_helpers.py +64 -0
- iopenpod-1.0.47/SQLiteDB_Writer/cbk_writer.py +171 -0
- iopenpod-1.0.47/SQLiteDB_Writer/dynamic_writer.py +124 -0
- iopenpod-1.0.47/SQLiteDB_Writer/extras_writer.py +82 -0
- iopenpod-1.0.47/SQLiteDB_Writer/genius_writer.py +56 -0
- iopenpod-1.0.47/SQLiteDB_Writer/library_writer.py +1184 -0
- iopenpod-1.0.47/SQLiteDB_Writer/locations_writer.py +145 -0
- iopenpod-1.0.47/SQLiteDB_Writer/sqlite_writer.py +211 -0
- iopenpod-1.0.47/SyncEngine/__init__.py +135 -0
- iopenpod-1.0.47/SyncEngine/_db_io.py +244 -0
- iopenpod-1.0.47/SyncEngine/_formats.py +60 -0
- iopenpod-1.0.47/SyncEngine/_playlist_builder.py +397 -0
- iopenpod-1.0.47/SyncEngine/_track_conversion.py +388 -0
- iopenpod-1.0.47/SyncEngine/audio_fingerprint.py +454 -0
- iopenpod-1.0.47/SyncEngine/backup_manager.py +1268 -0
- iopenpod-1.0.47/SyncEngine/contracts.py +114 -0
- iopenpod-1.0.47/SyncEngine/dependency_manager.py +292 -0
- iopenpod-1.0.47/SyncEngine/fingerprint_diff_engine.py +1604 -0
- iopenpod-1.0.47/SyncEngine/integrity.py +328 -0
- iopenpod-1.0.47/SyncEngine/itunes_prefs.py +563 -0
- iopenpod-1.0.47/SyncEngine/mapping.py +389 -0
- iopenpod-1.0.47/SyncEngine/pc_library.py +1499 -0
- iopenpod-1.0.47/SyncEngine/photos.py +2092 -0
- iopenpod-1.0.47/SyncEngine/playlist_parser.py +181 -0
- iopenpod-1.0.47/SyncEngine/quick_writes.py +538 -0
- iopenpod-1.0.47/SyncEngine/scrobbler.py +590 -0
- iopenpod-1.0.47/SyncEngine/spl_evaluator.py +567 -0
- iopenpod-1.0.47/SyncEngine/sync_executor.py +2090 -0
- iopenpod-1.0.47/SyncEngine/transcode_cache.py +692 -0
- iopenpod-1.0.47/SyncEngine/transcoder.py +1274 -0
- iopenpod-1.0.47/app_core/__init__.py +122 -0
- iopenpod-1.0.47/app_core/bootstrap.py +220 -0
- iopenpod-1.0.47/app_core/context.py +157 -0
- iopenpod-1.0.47/app_core/controllers.py +335 -0
- iopenpod-1.0.47/app_core/device_identity.py +110 -0
- iopenpod-1.0.47/app_core/errors.py +19 -0
- iopenpod-1.0.47/app_core/jobs.py +1765 -0
- iopenpod-1.0.47/app_core/progress.py +210 -0
- iopenpod-1.0.47/app_core/runtime.py +928 -0
- iopenpod-1.0.47/app_core/services.py +440 -0
- iopenpod-1.0.47/app_core/sync_options.py +13 -0
- iopenpod-1.0.47/app_core/sync_plan_builder.py +203 -0
- iopenpod-1.0.47/app_core/sync_review_model.py +161 -0
- iopenpod-1.0.47/assets/fonts/NotoEmoji-Regular.ttf +0 -0
- iopenpod-1.0.47/assets/fonts/NotoSans-Italic.ttf +0 -0
- iopenpod-1.0.47/assets/fonts/NotoSans-Regular.ttf +0 -0
- iopenpod-1.0.47/assets/fonts/NotoSansMono-Regular.ttf +0 -0
- iopenpod-1.0.47/assets/fonts/NotoSansSymbols2-Regular.ttf +0 -0
- iopenpod-1.0.47/assets/fonts/README.md +17 -0
- iopenpod-1.0.47/assets/glyphs/advisory-clean.svg +5 -0
- iopenpod-1.0.47/assets/glyphs/advisory-explicit.svg +8 -0
- iopenpod-1.0.47/assets/glyphs/annotation-dots.svg +6 -0
- iopenpod-1.0.47/assets/glyphs/annotation-warning.svg +5 -0
- iopenpod-1.0.47/assets/glyphs/archive.svg +5 -0
- iopenpod-1.0.47/assets/glyphs/arrow-down.svg +4 -0
- iopenpod-1.0.47/assets/glyphs/arrow-left.svg +4 -0
- iopenpod-1.0.47/assets/glyphs/arrow-right.svg +4 -0
- iopenpod-1.0.47/assets/glyphs/arrow-up.svg +4 -0
- iopenpod-1.0.47/assets/glyphs/book.svg +4 -0
- iopenpod-1.0.47/assets/glyphs/box.svg +7 -0
- iopenpod-1.0.47/assets/glyphs/broadcast.svg +8 -0
- iopenpod-1.0.47/assets/glyphs/chart.svg +6 -0
- iopenpod-1.0.47/assets/glyphs/check-circle.svg +4 -0
- iopenpod-1.0.47/assets/glyphs/check.svg +3 -0
- iopenpod-1.0.47/assets/glyphs/chevron-down.svg +3 -0
- iopenpod-1.0.47/assets/glyphs/chevron-left.svg +3 -0
- iopenpod-1.0.47/assets/glyphs/chevron-right.svg +3 -0
- iopenpod-1.0.47/assets/glyphs/chevron-up.svg +3 -0
- iopenpod-1.0.47/assets/glyphs/clock.svg +4 -0
- iopenpod-1.0.47/assets/glyphs/close-circle.svg +5 -0
- iopenpod-1.0.47/assets/glyphs/close.svg +4 -0
- iopenpod-1.0.47/assets/glyphs/cloud.svg +3 -0
- iopenpod-1.0.47/assets/glyphs/code.svg +4 -0
- iopenpod-1.0.47/assets/glyphs/download.svg +5 -0
- iopenpod-1.0.47/assets/glyphs/edit.svg +4 -0
- iopenpod-1.0.47/assets/glyphs/eject.svg +4 -0
- iopenpod-1.0.47/assets/glyphs/film.svg +10 -0
- iopenpod-1.0.47/assets/glyphs/filter.svg +3 -0
- iopenpod-1.0.47/assets/glyphs/flag.svg +3 -0
- iopenpod-1.0.47/assets/glyphs/floppy-disc.svg +5 -0
- iopenpod-1.0.47/assets/glyphs/folder.svg +4 -0
- iopenpod-1.0.47/assets/glyphs/grid.svg +6 -0
- iopenpod-1.0.47/assets/glyphs/heart.svg +3 -0
- iopenpod-1.0.47/assets/glyphs/home.svg +4 -0
- iopenpod-1.0.47/assets/glyphs/minus.svg +3 -0
- iopenpod-1.0.47/assets/glyphs/monitor.svg +4 -0
- iopenpod-1.0.47/assets/glyphs/music.svg +5 -0
- iopenpod-1.0.47/assets/glyphs/photo.svg +3 -0
- iopenpod-1.0.47/assets/glyphs/plus.svg +4 -0
- iopenpod-1.0.47/assets/glyphs/refresh.svg +6 -0
- iopenpod-1.0.47/assets/glyphs/search.svg +3 -0
- iopenpod-1.0.47/assets/glyphs/settings-sliders.svg +8 -0
- iopenpod-1.0.47/assets/glyphs/settings.svg +4 -0
- iopenpod-1.0.47/assets/glyphs/shield-warning.svg +5 -0
- iopenpod-1.0.47/assets/glyphs/spinner.svg +1 -0
- iopenpod-1.0.47/assets/glyphs/star.svg +3 -0
- iopenpod-1.0.47/assets/glyphs/tablet.svg +4 -0
- iopenpod-1.0.47/assets/glyphs/trash.svg +5 -0
- iopenpod-1.0.47/assets/glyphs/user.svg +4 -0
- iopenpod-1.0.47/assets/glyphs/video.svg +4 -0
- iopenpod-1.0.47/assets/glyphs/warning-triangle.svg +5 -0
- iopenpod-1.0.47/assets/glyphs/wifi-no-connection.svg +7 -0
- iopenpod-1.0.47/assets/glyphs/wifi.svg +6 -0
- iopenpod-1.0.47/assets/icons/icon-128.png +0 -0
- iopenpod-1.0.47/assets/icons/icon-16.png +0 -0
- iopenpod-1.0.47/assets/icons/icon-24.png +0 -0
- iopenpod-1.0.47/assets/icons/icon-256.png +0 -0
- iopenpod-1.0.47/assets/icons/icon-32.png +0 -0
- iopenpod-1.0.47/assets/icons/icon-48.png +0 -0
- iopenpod-1.0.47/assets/icons/icon-64.png +0 -0
- iopenpod-1.0.47/assets/icons/icon.ico +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod1.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod11-Black.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod11-Silver.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod11B-Black.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod12-Black.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod12-Blue.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod12-Green.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod12-Pink.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod12-Red.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod12-Silver.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod128.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod130-Blue.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod130-Green.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod130-Orange.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod130-Pink.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod130-Silver.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod130C-Blue.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod130C-Green.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod130C-Purple.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod130C-Red.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod130F-Blue.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod130F-Gold.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod130F-Green.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod130F-Pink.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod130F-Red.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod132-Blue.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod132-DarkGray.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod132-Green.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod132-Pink.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod132-Silver.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod132B-Silver.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod133-Blue.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod133-Green.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod133-Orange.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod133-Pink.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod133-Silver.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod133B-Blue.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod133B-DarkGray.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod133B-Green.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod133B-Pink.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod133B-Purple.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod133B-Red.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod133B-Silver.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod133B-SpaceGray.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod133B-Yellow.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod133D-Blue.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod133D-Gold.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod133D-Pink.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod133D-Red.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod133D-Silver.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod133D-SpaceGray.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod15-Black.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod15-Blue.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod15-Green.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod15-Orange.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod15-Pink.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod15-Purple.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod15-Red.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod15-Silver.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod15-Yellow.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod16-Black.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod16-Blue.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod16-Green.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod16-Orange.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod16-Pink.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod16-Purple.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod16-Red.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod16-Silver.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod16-Yellow.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod17-Blue.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod17-DarkGray.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod17-Green.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod17-Orange.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod17-Pink.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod17-Red.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod17-Silver.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod18-Blue.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod18-DarkGray.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod18-Green.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod18-Pink.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod18-Purple.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod18-Red.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod18-Silver.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod18-SpaceGray.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod18-Yellow.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod18A-Blue.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod18A-Gold.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod18A-Pink.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod18A-Red.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod18A-Silver.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod18A-SpaceGray.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod2.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod3-Blue.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod3-Gold.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod3-Green.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod3-Pink.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod3-Silver.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod3B-Blue.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod3B-Green.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod3B-Pink.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod4-BlackRed.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod4-White.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod5-BlackRed.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod5-White.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod6-Black.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod6-BlackRed.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod6-White.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod7-Black.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod7-White.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod9-Black.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod9-Blue.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod9-Green.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod9-Pink.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod9-Red.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPod9-Silver.png +0 -0
- iopenpod-1.0.47/assets/ipod_images/iPodGeneric.png +0 -0
- iopenpod-1.0.47/assets/screenshots/backup.png +0 -0
- iopenpod-1.0.47/assets/screenshots/devicepicker.png +0 -0
- iopenpod-1.0.47/assets/screenshots/hero.png +0 -0
- iopenpod-1.0.47/assets/screenshots/lightmode.png +0 -0
- iopenpod-1.0.47/assets/screenshots/managetracks.png +0 -0
- iopenpod-1.0.47/assets/screenshots/playlists.png +0 -0
- iopenpod-1.0.47/assets/screenshots/podcasts.png +0 -0
- iopenpod-1.0.47/assets/screenshots/smartplaylist.png +0 -0
- iopenpod-1.0.47/assets/screenshots/syncreview.png +0 -0
- iopenpod-1.0.47/docs/SYNC.md +651 -0
- iopenpod-1.0.47/docs/TESTING_PLAN.md +165 -0
- iopenpod-1.0.47/docs/deep_analysis_theories.md +348 -0
- iopenpod-1.0.47/docs/google9044a61ef03e1fae.html +1 -0
- iopenpod-1.0.47/docs/iTunesCDB-internals.md +717 -0
- iopenpod-1.0.47/docs/index.html +1052 -0
- iopenpod-1.0.47/docs/iokit-scsi-vpd.md +308 -0
- iopenpod-1.0.47/docs/ipod-firmware-restore.md +548 -0
- iopenpod-1.0.47/docs/robots.txt +4 -0
- iopenpod-1.0.47/docs/sitemap.xml +9 -0
- iopenpod-1.0.47/entitlements.plist +11 -0
- iopenpod-1.0.47/flatpak/iOpenPod-wrapper.sh +7 -0
- iopenpod-1.0.47/flatpak/io.github.therealsavi.iOpenPod.desktop +9 -0
- iopenpod-1.0.47/flatpak/io.github.therealsavi.iOpenPod.metainfo.xml +46 -0
- iopenpod-1.0.47/flatpak/io.github.therealsavi.iOpenPod.yml +86 -0
- iopenpod-1.0.47/iTunesDB_Analyzer/__init__.py +5 -0
- iopenpod-1.0.47/iTunesDB_Analyzer/__main__.py +4 -0
- iopenpod-1.0.47/iTunesDB_Analyzer/bridge.py +446 -0
- iopenpod-1.0.47/iTunesDB_Analyzer/cli.py +318 -0
- iopenpod-1.0.47/iTunesDB_Analyzer/field_schema.py +391 -0
- iopenpod-1.0.47/iTunesDB_Analyzer/hypothesis_db.py +398 -0
- iopenpod-1.0.47/iTunesDB_Analyzer/models.py +113 -0
- iopenpod-1.0.47/iTunesDB_Analyzer/passes.py +674 -0
- iopenpod-1.0.47/iTunesDB_Analyzer/reports.py +248 -0
- iopenpod-1.0.47/iTunesDB_Parser/__init__.py +22 -0
- iopenpod-1.0.47/iTunesDB_Parser/_parsing.py +69 -0
- iopenpod-1.0.47/iTunesDB_Parser/chunk_parser.py +143 -0
- iopenpod-1.0.47/iTunesDB_Parser/exceptions.py +59 -0
- iopenpod-1.0.47/iTunesDB_Parser/ipod_library.py +134 -0
- iopenpod-1.0.47/iTunesDB_Parser/mhbd_parser.py +38 -0
- iopenpod-1.0.47/iTunesDB_Parser/mhia_parser.py +26 -0
- iopenpod-1.0.47/iTunesDB_Parser/mhii_parser.py +29 -0
- iopenpod-1.0.47/iTunesDB_Parser/mhip_parser.py +26 -0
- iopenpod-1.0.47/iTunesDB_Parser/mhit_parser.py +29 -0
- iopenpod-1.0.47/iTunesDB_Parser/mhod_parser.py +612 -0
- iopenpod-1.0.47/iTunesDB_Parser/mhsd_parser.py +29 -0
- iopenpod-1.0.47/iTunesDB_Parser/mhyp_parser.py +33 -0
- iopenpod-1.0.47/iTunesDB_Parser/otg.py +187 -0
- iopenpod-1.0.47/iTunesDB_Parser/parser.py +112 -0
- iopenpod-1.0.47/iTunesDB_Parser/playcounts.py +260 -0
- iopenpod-1.0.47/iTunesDB_Shared/__init__.py +33 -0
- iopenpod-1.0.47/iTunesDB_Shared/constants.py +378 -0
- iopenpod-1.0.47/iTunesDB_Shared/extraction.py +99 -0
- iopenpod-1.0.47/iTunesDB_Shared/field_base.py +414 -0
- iopenpod-1.0.47/iTunesDB_Shared/mhbd_defs.py +48 -0
- iopenpod-1.0.47/iTunesDB_Shared/mhia_defs.py +21 -0
- iopenpod-1.0.47/iTunesDB_Shared/mhii_defs.py +18 -0
- iopenpod-1.0.47/iTunesDB_Shared/mhip_defs.py +26 -0
- iopenpod-1.0.47/iTunesDB_Shared/mhit_defs.py +141 -0
- iopenpod-1.0.47/iTunesDB_Shared/mhod_defs.py +586 -0
- iopenpod-1.0.47/iTunesDB_Shared/mhsd_defs.py +15 -0
- iopenpod-1.0.47/iTunesDB_Shared/mhyp_defs.py +35 -0
- iopenpod-1.0.47/iTunesDB_Writer/__init__.py +148 -0
- iopenpod-1.0.47/iTunesDB_Writer/hash58.py +280 -0
- iopenpod-1.0.47/iTunesDB_Writer/hash72.py +476 -0
- iopenpod-1.0.47/iTunesDB_Writer/hashab.py +287 -0
- iopenpod-1.0.47/iTunesDB_Writer/mhbd_writer.py +1151 -0
- iopenpod-1.0.47/iTunesDB_Writer/mhip_writer.py +138 -0
- iopenpod-1.0.47/iTunesDB_Writer/mhit_writer.py +385 -0
- iopenpod-1.0.47/iTunesDB_Writer/mhla_writer.py +217 -0
- iopenpod-1.0.47/iTunesDB_Writer/mhli_writer.py +136 -0
- iopenpod-1.0.47/iTunesDB_Writer/mhlp_writer.py +238 -0
- iopenpod-1.0.47/iTunesDB_Writer/mhlt_writer.py +59 -0
- iopenpod-1.0.47/iTunesDB_Writer/mhod52_writer.py +334 -0
- iopenpod-1.0.47/iTunesDB_Writer/mhod_spl_writer.py +283 -0
- iopenpod-1.0.47/iTunesDB_Writer/mhod_writer.py +434 -0
- iopenpod-1.0.47/iTunesDB_Writer/mhsd_writer.py +101 -0
- iopenpod-1.0.47/iTunesDB_Writer/mhyp_writer.py +538 -0
- iopenpod-1.0.47/iTunesDB_Writer/wasm/calcHashAB.wasm +0 -0
- iopenpod-1.0.47/infrastructure/__init__.py +1 -0
- iopenpod-1.0.47/infrastructure/settings_paths.py +83 -0
- iopenpod-1.0.47/infrastructure/settings_persistence.py +93 -0
- iopenpod-1.0.47/infrastructure/settings_runtime.py +441 -0
- iopenpod-1.0.47/infrastructure/settings_schema.py +94 -0
- iopenpod-1.0.47/infrastructure/settings_secrets.py +127 -0
- iopenpod-1.0.47/infrastructure/version.py +18 -0
- iopenpod-1.0.47/ipod_device/__init__.py +131 -0
- iopenpod-1.0.47/ipod_device/artwork.py +173 -0
- iopenpod-1.0.47/ipod_device/artwork_presets.py +114 -0
- iopenpod-1.0.47/ipod_device/authority.py +671 -0
- iopenpod-1.0.47/ipod_device/capabilities.py +737 -0
- iopenpod-1.0.47/ipod_device/checksum.py +41 -0
- iopenpod-1.0.47/ipod_device/diagnostic_log.py +178 -0
- iopenpod-1.0.47/ipod_device/dump.py +496 -0
- iopenpod-1.0.47/ipod_device/eject.py +1007 -0
- iopenpod-1.0.47/ipod_device/images.py +409 -0
- iopenpod-1.0.47/ipod_device/info.py +2408 -0
- iopenpod-1.0.47/ipod_device/lookup.py +171 -0
- iopenpod-1.0.47/ipod_device/models.py +509 -0
- iopenpod-1.0.47/ipod_device/scanner.py +2496 -0
- iopenpod-1.0.47/ipod_device/sysinfo.py +528 -0
- iopenpod-1.0.47/ipod_device/usb_backend.py +132 -0
- iopenpod-1.0.47/ipod_device/vpd_iokit.py +618 -0
- iopenpod-1.0.47/ipod_device/vpd_libusb.py +1354 -0
- iopenpod-1.0.47/ipod_device/vpd_linux.py +267 -0
- iopenpod-1.0.47/ipod_device/vpd_usb_control.py +215 -0
- iopenpod-1.0.47/ipod_device/vpd_windows.py +310 -0
- iopenpod-1.0.47/main.py +9 -0
- iopenpod-1.0.47/pyi_rth_macos_nsapp.py +33 -0
- iopenpod-1.0.47/pyproject.toml +134 -0
- iopenpod-1.0.47/scripts/__init__.py +1 -0
- iopenpod-1.0.47/scripts/architecture_rules.json +97 -0
- iopenpod-1.0.47/scripts/check_architecture.py +626 -0
- iopenpod-1.0.47/tests/fixtures/artworkdb/.gitkeep +1 -0
- iopenpod-1.0.47/tests/fixtures/device_metadata/.gitkeep +1 -0
- iopenpod-1.0.47/tests/fixtures/itunesdb/.gitkeep +1 -0
- iopenpod-1.0.47/tests/fixtures/sync_plans/.gitkeep +1 -0
- iopenpod-1.0.47/tests/fixtures/sysinfo/.gitkeep +1 -0
- iopenpod-1.0.47/tests/test_architecture_checks.py +281 -0
- iopenpod-1.0.47/tests/test_backup_jobs.py +85 -0
- iopenpod-1.0.47/tests/test_device_identity_helpers.py +90 -0
- iopenpod-1.0.47/tests/test_device_scan_jobs.py +13 -0
- iopenpod-1.0.47/tests/test_device_session_snapshots.py +60 -0
- iopenpod-1.0.47/tests/test_main_window_navigation.py +141 -0
- iopenpod-1.0.47/tests/test_photo_edit_state_builder.py +19 -0
- iopenpod-1.0.47/tests/test_podcast_plan_worker.py +65 -0
- iopenpod-1.0.47/tests/test_quick_writes.py +112 -0
- iopenpod-1.0.47/tests/test_settings_persistence.py +60 -0
- iopenpod-1.0.47/tests/test_settings_secrets.py +32 -0
- iopenpod-1.0.47/tests/test_settings_snapshot.py +29 -0
- iopenpod-1.0.47/tests/test_sync_plan_builder.py +189 -0
- iopenpod-1.0.47/tests/test_sync_review_model.py +81 -0
- iopenpod-1.0.47/tests/test_sync_tool_availability.py +91 -0
- iopenpod-1.0.47/uv.lock +913 -0
iopenpod-1.0.47/.flake8
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Bug Report
|
|
3
|
+
about: Report a bug with iOpenPod
|
|
4
|
+
title: "[Bug] "
|
|
5
|
+
labels: bug
|
|
6
|
+
assignees: ''
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
**Describe the bug**
|
|
11
|
+
A clear description of what the bug is.
|
|
12
|
+
|
|
13
|
+
**iPod model**
|
|
14
|
+
e.g., iPod Classic 6th Gen (160GB), iPod Nano 3G
|
|
15
|
+
|
|
16
|
+
**To reproduce**
|
|
17
|
+
Steps to reproduce the behavior:
|
|
18
|
+
1. Go to '...'
|
|
19
|
+
2. Click on '...'
|
|
20
|
+
3. See error
|
|
21
|
+
|
|
22
|
+
**Expected behavior**
|
|
23
|
+
What you expected to happen.
|
|
24
|
+
|
|
25
|
+
**Screenshots / logs**
|
|
26
|
+
If applicable, add screenshots or paste the logs from `~/iOpenPod/`.
|
|
27
|
+
|
|
28
|
+
**Environment**
|
|
29
|
+
- OS: [e.g., Windows 11, Ubuntu 24.04, macOS 15]
|
|
30
|
+
- Python version: [e.g., 3.13.1]
|
|
31
|
+
- iOpenPod version/commit: [e.g., v1.0.0 or commit hash]
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Feature Request
|
|
3
|
+
about: Suggest an idea for iOpenPod
|
|
4
|
+
title: "[Feature] "
|
|
5
|
+
labels: enhancement
|
|
6
|
+
assignees: ''
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
**Is your feature request related to a problem?**
|
|
11
|
+
A clear description of the problem. e.g., "I'm frustrated when..."
|
|
12
|
+
|
|
13
|
+
**Describe the solution you'd like**
|
|
14
|
+
What you'd like to see happen.
|
|
15
|
+
|
|
16
|
+
**Describe alternatives you've considered**
|
|
17
|
+
Any alternative solutions or workarounds.
|
|
18
|
+
|
|
19
|
+
**Additional context**
|
|
20
|
+
Any other context, screenshots, or references.
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
name: Flatpak
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
inputs:
|
|
6
|
+
tag_name:
|
|
7
|
+
description: "Release tag (for example: v1.2.3)"
|
|
8
|
+
required: true
|
|
9
|
+
type: string
|
|
10
|
+
|
|
11
|
+
permissions:
|
|
12
|
+
contents: write # needed to upload assets to the GitHub Release
|
|
13
|
+
|
|
14
|
+
jobs:
|
|
15
|
+
flatpak:
|
|
16
|
+
runs-on: ubuntu-latest
|
|
17
|
+
|
|
18
|
+
steps:
|
|
19
|
+
- uses: actions/checkout@v4
|
|
20
|
+
with:
|
|
21
|
+
ref: ${{ github.event.inputs.tag_name }}
|
|
22
|
+
|
|
23
|
+
- name: Update metainfo release version/date
|
|
24
|
+
run: |
|
|
25
|
+
python -c "
|
|
26
|
+
from datetime import datetime, timezone
|
|
27
|
+
import xml.etree.ElementTree as ET
|
|
28
|
+
|
|
29
|
+
path = 'flatpak/io.github.therealsavi.iOpenPod.metainfo.xml'
|
|
30
|
+
version = '${{ github.event.inputs.tag_name }}'.lstrip('v.')
|
|
31
|
+
date = datetime.now(timezone.utc).strftime('%Y-%m-%d')
|
|
32
|
+
|
|
33
|
+
tree = ET.parse(path)
|
|
34
|
+
root = tree.getroot()
|
|
35
|
+
releases = root.find('releases')
|
|
36
|
+
if releases is None:
|
|
37
|
+
releases = ET.SubElement(root, 'releases')
|
|
38
|
+
release = releases.find('release')
|
|
39
|
+
if release is None:
|
|
40
|
+
release = ET.SubElement(releases, 'release')
|
|
41
|
+
|
|
42
|
+
release.set('version', version)
|
|
43
|
+
release.set('date', date)
|
|
44
|
+
tree.write(path, encoding='UTF-8', xml_declaration=True)
|
|
45
|
+
|
|
46
|
+
print(f'Updated {path} -> version={version}, date={date}')
|
|
47
|
+
"
|
|
48
|
+
|
|
49
|
+
# ── Python + uv ───────────────────────────────────────────────────
|
|
50
|
+
- uses: actions/setup-python@v5
|
|
51
|
+
with:
|
|
52
|
+
python-version: "3.13"
|
|
53
|
+
|
|
54
|
+
- name: Install uv
|
|
55
|
+
uses: astral-sh/setup-uv@v4
|
|
56
|
+
|
|
57
|
+
# Qt runtime libraries required for the PyInstaller build step.
|
|
58
|
+
- name: Install Linux system dependencies
|
|
59
|
+
run: |
|
|
60
|
+
sudo apt-get update
|
|
61
|
+
sudo apt-get install -y libegl1 libxkbcommon0 libdbus-1-3
|
|
62
|
+
|
|
63
|
+
- name: Install project dependencies
|
|
64
|
+
run: uv sync
|
|
65
|
+
|
|
66
|
+
# ── Build the PyInstaller one-folder bundle ───────────────────────
|
|
67
|
+
- name: Build with PyInstaller
|
|
68
|
+
run: uv run pyinstaller iOpenPod.spec --noconfirm
|
|
69
|
+
|
|
70
|
+
# ── Package as a Flatpak bundle ───────────────────────────────────
|
|
71
|
+
- name: Install Flatpak tooling
|
|
72
|
+
run: |
|
|
73
|
+
sudo apt-get update
|
|
74
|
+
sudo apt-get install -y flatpak flatpak-builder xvfb
|
|
75
|
+
sudo flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo
|
|
76
|
+
sudo flatpak remote-modify --enable flathub
|
|
77
|
+
flatpak --system remotes --show-details
|
|
78
|
+
|
|
79
|
+
- name: Install Flatpak SDK/runtime
|
|
80
|
+
run: |
|
|
81
|
+
sudo flatpak install -y --system flathub \
|
|
82
|
+
org.freedesktop.Sdk//25.08 \
|
|
83
|
+
org.freedesktop.Sdk.Locale//25.08 \
|
|
84
|
+
org.freedesktop.Platform//25.08 \
|
|
85
|
+
org.freedesktop.Platform.GL.default//25.08 \
|
|
86
|
+
org.freedesktop.Platform.openh264//2.5.1
|
|
87
|
+
|
|
88
|
+
- name: Build Flatpak bundle
|
|
89
|
+
uses: flatpak/flatpak-github-actions/flatpak-builder@v6
|
|
90
|
+
with:
|
|
91
|
+
bundle: iOpenPod-Linux.flatpak
|
|
92
|
+
manifest-path: flatpak/io.github.therealsavi.iOpenPod.yml
|
|
93
|
+
cache-key: flatpak-builder-${{ github.sha }}
|
|
94
|
+
|
|
95
|
+
# ── Checksum ──────────────────────────────────────────────────────
|
|
96
|
+
- name: Generate SHA-256 checksum
|
|
97
|
+
run: |
|
|
98
|
+
python -c "
|
|
99
|
+
import hashlib, pathlib
|
|
100
|
+
p = pathlib.Path('iOpenPod-Linux.flatpak')
|
|
101
|
+
h = hashlib.sha256(p.read_bytes()).hexdigest()
|
|
102
|
+
out = f'{h} {p.name}\n'
|
|
103
|
+
pathlib.Path(p.name + '.sha256').write_text(out)
|
|
104
|
+
print(out.strip())
|
|
105
|
+
"
|
|
106
|
+
|
|
107
|
+
# ── Attach to GitHub Release ──────────────────────────────────────
|
|
108
|
+
- name: Upload Flatpak bundle to release
|
|
109
|
+
uses: softprops/action-gh-release@v2
|
|
110
|
+
with:
|
|
111
|
+
tag_name: ${{ github.event.inputs.tag_name }}
|
|
112
|
+
files: |
|
|
113
|
+
iOpenPod-Linux.flatpak
|
|
114
|
+
iOpenPod-Linux.flatpak.sha256
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
name: Health
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
push:
|
|
6
|
+
branches:
|
|
7
|
+
- main
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
health:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
steps:
|
|
13
|
+
- uses: actions/checkout@v4
|
|
14
|
+
|
|
15
|
+
- uses: actions/setup-python@v5
|
|
16
|
+
with:
|
|
17
|
+
python-version: "3.11"
|
|
18
|
+
|
|
19
|
+
- name: Install uv
|
|
20
|
+
uses: astral-sh/setup-uv@v4
|
|
21
|
+
|
|
22
|
+
- name: Install project and dev dependencies
|
|
23
|
+
run: uv sync --all-groups
|
|
24
|
+
|
|
25
|
+
- name: Ruff
|
|
26
|
+
run: uv run ruff check app_core scripts tests main.py SyncEngine/contracts.py SyncEngine/quick_writes.py
|
|
27
|
+
|
|
28
|
+
- name: Mypy
|
|
29
|
+
run: uv run mypy
|
|
30
|
+
|
|
31
|
+
- name: Pytest
|
|
32
|
+
run: uv run pytest
|
|
33
|
+
|
|
34
|
+
- name: Architecture checks
|
|
35
|
+
run: uv run python scripts/check_architecture.py
|
|
36
|
+
|
|
37
|
+
- name: Packaging smoke test
|
|
38
|
+
run: uv build
|
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
# Build multi-platform binaries and publish a GitHub Release on every tag.
|
|
2
|
+
#
|
|
3
|
+
# Trigger: push a tag like v1.0.0 (or v1.2.3-beta.1, etc.)
|
|
4
|
+
#
|
|
5
|
+
# git tag v1.0.0
|
|
6
|
+
# git push origin v1.0.0
|
|
7
|
+
|
|
8
|
+
name: Release
|
|
9
|
+
|
|
10
|
+
on:
|
|
11
|
+
push:
|
|
12
|
+
tags:
|
|
13
|
+
- "v*"
|
|
14
|
+
|
|
15
|
+
permissions:
|
|
16
|
+
actions: write # needed to dispatch the Flatpak workflow
|
|
17
|
+
contents: write # needed to create GitHub Releases
|
|
18
|
+
|
|
19
|
+
jobs:
|
|
20
|
+
# ── Build matrix ────────────────────────────────────────────────────────
|
|
21
|
+
build:
|
|
22
|
+
strategy:
|
|
23
|
+
fail-fast: false
|
|
24
|
+
matrix:
|
|
25
|
+
include:
|
|
26
|
+
- os: windows-latest
|
|
27
|
+
artifact: iOpenPod-Windows
|
|
28
|
+
archive_name: iOpenPod-Windows.zip
|
|
29
|
+
|
|
30
|
+
- os: macos-14 # Apple Silicon (arm64); Intel Macs use Rosetta 2
|
|
31
|
+
artifact: iOpenPod-macOS
|
|
32
|
+
archive_name: iOpenPod-macOS.zip
|
|
33
|
+
|
|
34
|
+
- os: ubuntu-22.04
|
|
35
|
+
artifact: iOpenPod-Linux
|
|
36
|
+
archive_name: iOpenPod-Linux.tar.gz
|
|
37
|
+
appimage_name: iOpenPod-Linux-x86_64.AppImage
|
|
38
|
+
|
|
39
|
+
runs-on: ${{ matrix.os }}
|
|
40
|
+
|
|
41
|
+
steps:
|
|
42
|
+
- uses: actions/checkout@v4
|
|
43
|
+
|
|
44
|
+
# ── Python + uv ─────────────────────────────────────────────────
|
|
45
|
+
- uses: actions/setup-python@v5
|
|
46
|
+
with:
|
|
47
|
+
python-version: "3.13"
|
|
48
|
+
|
|
49
|
+
- name: Install uv
|
|
50
|
+
uses: astral-sh/setup-uv@v4
|
|
51
|
+
|
|
52
|
+
# Linux: install Qt runtime deps (no display needed for build)
|
|
53
|
+
- name: Install Linux system dependencies
|
|
54
|
+
if: runner.os == 'Linux'
|
|
55
|
+
run: |
|
|
56
|
+
sudo apt-get update
|
|
57
|
+
sudo apt-get install -y libegl1 libxkbcommon0 libdbus-1-3
|
|
58
|
+
|
|
59
|
+
- name: Install project dependencies
|
|
60
|
+
run: uv sync
|
|
61
|
+
|
|
62
|
+
# ── PyInstaller build ───────────────────────────────────────────
|
|
63
|
+
- name: Build with PyInstaller
|
|
64
|
+
run: uv run pyinstaller iOpenPod.spec --noconfirm
|
|
65
|
+
|
|
66
|
+
# ── Package archive ─────────────────────────────────────────────
|
|
67
|
+
# macOS: ad-hoc sign all binaries so Gatekeeper doesn't kill the app
|
|
68
|
+
- name: Ad-hoc codesign (macOS)
|
|
69
|
+
if: runner.os == 'macOS'
|
|
70
|
+
run: |
|
|
71
|
+
# Re-sign every Mach-O binary inside the bundle (inside-out).
|
|
72
|
+
# --options runtime is intentionally omitted: Hardened Runtime
|
|
73
|
+
# triggers strict PAC checks in CoreFoundation on macOS 26+
|
|
74
|
+
# that crash PyInstaller-frozen Qt apps during bundle init.
|
|
75
|
+
# Hardened Runtime is only needed for notarization (we don't notarize).
|
|
76
|
+
find dist/iOpenPod.app/Contents/Frameworks \
|
|
77
|
+
dist/iOpenPod.app/Contents/Resources \
|
|
78
|
+
-type f -perm +111 -print0 \
|
|
79
|
+
| xargs -0 file \
|
|
80
|
+
| grep -i 'mach-o' \
|
|
81
|
+
| cut -d: -f1 \
|
|
82
|
+
| while read f; do
|
|
83
|
+
codesign --force --sign - "$f"
|
|
84
|
+
done
|
|
85
|
+
codesign --force --sign - dist/iOpenPod.app/Contents/MacOS/iOpenPod
|
|
86
|
+
codesign --force --sign - dist/iOpenPod.app
|
|
87
|
+
# Verify
|
|
88
|
+
codesign --verify --deep --strict dist/iOpenPod.app
|
|
89
|
+
echo "Code signing verified OK"
|
|
90
|
+
|
|
91
|
+
- name: Create archive (Windows)
|
|
92
|
+
if: runner.os == 'Windows'
|
|
93
|
+
run: Compress-Archive -Path dist\iOpenPod\* -DestinationPath iOpenPod-Windows.zip
|
|
94
|
+
shell: pwsh
|
|
95
|
+
|
|
96
|
+
- name: Create archive (macOS)
|
|
97
|
+
if: runner.os == 'macOS'
|
|
98
|
+
run: cd dist && ditto -c -k --keepParent --sequesterRsrc iOpenPod.app ../${{ matrix.archive_name }}
|
|
99
|
+
|
|
100
|
+
- name: Create archive (Linux)
|
|
101
|
+
if: runner.os == 'Linux'
|
|
102
|
+
run: cd dist && tar czf ../${{ matrix.archive_name }} iOpenPod/
|
|
103
|
+
|
|
104
|
+
- name: Build AppImage (Linux)
|
|
105
|
+
if: runner.os == 'Linux'
|
|
106
|
+
run: |
|
|
107
|
+
curl -L --fail -o appimagetool-x86_64.AppImage \
|
|
108
|
+
https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage
|
|
109
|
+
chmod +x appimagetool-x86_64.AppImage
|
|
110
|
+
|
|
111
|
+
rm -rf AppDir
|
|
112
|
+
mkdir -p AppDir/usr/bin AppDir/usr/share/applications
|
|
113
|
+
|
|
114
|
+
# Preserve PyInstaller one-folder layout so the binary can load _internal/*.
|
|
115
|
+
cp -a dist/iOpenPod/. AppDir/usr/bin/
|
|
116
|
+
|
|
117
|
+
cat > AppDir/iOpenPod.desktop <<'EOF'
|
|
118
|
+
[Desktop Entry]
|
|
119
|
+
Type=Application
|
|
120
|
+
Name=iOpenPod
|
|
121
|
+
Exec=iOpenPod
|
|
122
|
+
Icon=iOpenPod
|
|
123
|
+
Categories=AudioVideo;Utility;
|
|
124
|
+
Terminal=false
|
|
125
|
+
EOF
|
|
126
|
+
cp AppDir/iOpenPod.desktop AppDir/usr/share/applications/iOpenPod.desktop
|
|
127
|
+
|
|
128
|
+
cat > AppDir/AppRun <<'EOF'
|
|
129
|
+
#!/bin/sh
|
|
130
|
+
HERE="$(dirname "$(readlink -f "$0")")"
|
|
131
|
+
APPBIN="$HERE/usr/bin"
|
|
132
|
+
|
|
133
|
+
export PATH="$APPBIN:$PATH"
|
|
134
|
+
export LD_LIBRARY_PATH="$APPBIN/_internal:$APPBIN/_internal/Qt/lib:$APPBIN/_internal/lib:${LD_LIBRARY_PATH:-}"
|
|
135
|
+
export QT_PLUGIN_PATH="$APPBIN/_internal/plugins:${QT_PLUGIN_PATH:-}"
|
|
136
|
+
export QML2_IMPORT_PATH="$APPBIN/_internal/qml:${QML2_IMPORT_PATH:-}"
|
|
137
|
+
|
|
138
|
+
exec "$APPBIN/iOpenPod" "$@"
|
|
139
|
+
EOF
|
|
140
|
+
chmod +x AppDir/AppRun
|
|
141
|
+
|
|
142
|
+
cp assets/icons/icon-256.png AppDir/iOpenPod.png
|
|
143
|
+
|
|
144
|
+
ARCH=x86_64 ./appimagetool-x86_64.AppImage --appimage-extract-and-run \
|
|
145
|
+
AppDir "${{ matrix.appimage_name }}"
|
|
146
|
+
|
|
147
|
+
# ── Checksums ───────────────────────────────────────────────────
|
|
148
|
+
- name: Generate SHA-256 checksum
|
|
149
|
+
run: |
|
|
150
|
+
python -c "
|
|
151
|
+
import hashlib, pathlib, sys
|
|
152
|
+
p = pathlib.Path('${{ matrix.archive_name }}')
|
|
153
|
+
h = hashlib.sha256(p.read_bytes()).hexdigest()
|
|
154
|
+
out = f'{h} {p.name}\n'
|
|
155
|
+
pathlib.Path(p.name + '.sha256').write_text(out)
|
|
156
|
+
print(out.strip())
|
|
157
|
+
"
|
|
158
|
+
|
|
159
|
+
- name: Generate SHA-256 checksum (Linux AppImage)
|
|
160
|
+
if: runner.os == 'Linux'
|
|
161
|
+
run: |
|
|
162
|
+
python -c "
|
|
163
|
+
import hashlib, pathlib
|
|
164
|
+
p = pathlib.Path('${{ matrix.appimage_name }}')
|
|
165
|
+
h = hashlib.sha256(p.read_bytes()).hexdigest()
|
|
166
|
+
out = f'{h} {p.name}\n'
|
|
167
|
+
pathlib.Path(p.name + '.sha256').write_text(out)
|
|
168
|
+
print(out.strip())
|
|
169
|
+
"
|
|
170
|
+
|
|
171
|
+
- name: Upload build artifact
|
|
172
|
+
uses: actions/upload-artifact@v4
|
|
173
|
+
with:
|
|
174
|
+
name: ${{ matrix.artifact }}
|
|
175
|
+
path: |
|
|
176
|
+
${{ matrix.archive_name }}
|
|
177
|
+
${{ matrix.archive_name }}.sha256
|
|
178
|
+
|
|
179
|
+
- name: Upload AppImage artifact (Linux)
|
|
180
|
+
if: runner.os == 'Linux'
|
|
181
|
+
uses: actions/upload-artifact@v4
|
|
182
|
+
with:
|
|
183
|
+
name: iOpenPod-Linux-AppImage
|
|
184
|
+
path: |
|
|
185
|
+
${{ matrix.appimage_name }}
|
|
186
|
+
${{ matrix.appimage_name }}.sha256
|
|
187
|
+
|
|
188
|
+
# ── Build Python distributions for PyPI ─────────────────────────────────
|
|
189
|
+
python-dist:
|
|
190
|
+
runs-on: ubuntu-latest
|
|
191
|
+
steps:
|
|
192
|
+
- uses: actions/checkout@v4
|
|
193
|
+
|
|
194
|
+
- uses: actions/setup-python@v5
|
|
195
|
+
with:
|
|
196
|
+
python-version: "3.13"
|
|
197
|
+
|
|
198
|
+
- name: Install uv
|
|
199
|
+
uses: astral-sh/setup-uv@v4
|
|
200
|
+
|
|
201
|
+
- name: Verify tag matches package version
|
|
202
|
+
run: |
|
|
203
|
+
python - <<'PY'
|
|
204
|
+
import os
|
|
205
|
+
import pathlib
|
|
206
|
+
import tomllib
|
|
207
|
+
|
|
208
|
+
pyproject = tomllib.loads(pathlib.Path("pyproject.toml").read_text(encoding="utf-8"))
|
|
209
|
+
version = pyproject["project"]["version"]
|
|
210
|
+
tag_name = os.environ["GITHUB_REF_NAME"]
|
|
211
|
+
expected_tag = f"v{version}"
|
|
212
|
+
if tag_name != expected_tag:
|
|
213
|
+
raise SystemExit(
|
|
214
|
+
f"Refusing to publish: tag {tag_name!r} does not match pyproject version {version!r}"
|
|
215
|
+
)
|
|
216
|
+
print(f"Publishing Python package version {version} from tag {tag_name}")
|
|
217
|
+
PY
|
|
218
|
+
|
|
219
|
+
- name: Build Python distributions
|
|
220
|
+
run: uv build
|
|
221
|
+
|
|
222
|
+
- name: Upload Python distribution artifact
|
|
223
|
+
uses: actions/upload-artifact@v4
|
|
224
|
+
with:
|
|
225
|
+
name: iopenpod-python-dist
|
|
226
|
+
if-no-files-found: error
|
|
227
|
+
path: |
|
|
228
|
+
dist/*.whl
|
|
229
|
+
dist/*.tar.gz
|
|
230
|
+
|
|
231
|
+
# ── Publish GitHub Release ──────────────────────────────────────────────
|
|
232
|
+
release:
|
|
233
|
+
needs:
|
|
234
|
+
- build
|
|
235
|
+
- python-dist
|
|
236
|
+
runs-on: ubuntu-latest
|
|
237
|
+
steps:
|
|
238
|
+
- uses: actions/download-artifact@v4
|
|
239
|
+
with:
|
|
240
|
+
pattern: iOpenPod-*
|
|
241
|
+
merge-multiple: true
|
|
242
|
+
|
|
243
|
+
- name: Create GitHub Release
|
|
244
|
+
uses: softprops/action-gh-release@v2
|
|
245
|
+
with:
|
|
246
|
+
generate_release_notes: true
|
|
247
|
+
files: |
|
|
248
|
+
*.zip
|
|
249
|
+
*.tar.gz
|
|
250
|
+
*.AppImage
|
|
251
|
+
*.sha256
|
|
252
|
+
|
|
253
|
+
# ── Publish to PyPI via Trusted Publishing ──────────────────────────────
|
|
254
|
+
pypi-publish:
|
|
255
|
+
needs: release
|
|
256
|
+
runs-on: ubuntu-latest
|
|
257
|
+
environment:
|
|
258
|
+
name: pypi
|
|
259
|
+
permissions:
|
|
260
|
+
id-token: write
|
|
261
|
+
steps:
|
|
262
|
+
- uses: actions/download-artifact@v4
|
|
263
|
+
with:
|
|
264
|
+
name: iopenpod-python-dist
|
|
265
|
+
path: dist
|
|
266
|
+
|
|
267
|
+
- name: Publish package distributions to PyPI
|
|
268
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
269
|
+
|
|
270
|
+
trigger-flatpak:
|
|
271
|
+
needs: release
|
|
272
|
+
runs-on: ubuntu-latest
|
|
273
|
+
steps:
|
|
274
|
+
- name: Trigger Flatpak workflow
|
|
275
|
+
uses: actions/github-script@v7
|
|
276
|
+
with:
|
|
277
|
+
script: |
|
|
278
|
+
await github.rest.actions.createWorkflowDispatch({
|
|
279
|
+
owner: context.repo.owner,
|
|
280
|
+
repo: context.repo.repo,
|
|
281
|
+
workflow_id: 'flatpak.yml',
|
|
282
|
+
ref: context.ref.replace('refs/tags/', ''),
|
|
283
|
+
inputs: {
|
|
284
|
+
tag_name: context.ref.replace('refs/tags/', '')
|
|
285
|
+
}
|
|
286
|
+
})
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
# Byte-compiled / optimized / DLL files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
|
|
6
|
+
# C extensions
|
|
7
|
+
*.so
|
|
8
|
+
|
|
9
|
+
# Distribution / packaging
|
|
10
|
+
.Python
|
|
11
|
+
build/
|
|
12
|
+
develop-eggs/
|
|
13
|
+
dist/
|
|
14
|
+
downloads/
|
|
15
|
+
eggs/
|
|
16
|
+
.eggs/
|
|
17
|
+
lib/
|
|
18
|
+
lib64/
|
|
19
|
+
parts/
|
|
20
|
+
sdist/
|
|
21
|
+
var/
|
|
22
|
+
wheels/
|
|
23
|
+
share/python-wheels/
|
|
24
|
+
*.egg-info/
|
|
25
|
+
.installed.cfg
|
|
26
|
+
*.egg
|
|
27
|
+
MANIFEST
|
|
28
|
+
|
|
29
|
+
# PyInstaller
|
|
30
|
+
# Usually these files are written by a python script from a template
|
|
31
|
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
|
32
|
+
*.manifest
|
|
33
|
+
*.spec
|
|
34
|
+
|
|
35
|
+
# Installer logs
|
|
36
|
+
pip-log.txt
|
|
37
|
+
pip-delete-this-directory.txt
|
|
38
|
+
|
|
39
|
+
# Unit test / coverage reports
|
|
40
|
+
htmlcov/
|
|
41
|
+
.tox/
|
|
42
|
+
.nox/
|
|
43
|
+
.coverage
|
|
44
|
+
.coverage.*
|
|
45
|
+
.cache
|
|
46
|
+
nosetests.xml
|
|
47
|
+
coverage.xml
|
|
48
|
+
*.cover
|
|
49
|
+
*.py,cover
|
|
50
|
+
.hypothesis/
|
|
51
|
+
.pytest_cache/
|
|
52
|
+
.tmp/
|
|
53
|
+
pytest-tmp/
|
|
54
|
+
cover/
|
|
55
|
+
|
|
56
|
+
# Translations
|
|
57
|
+
*.mo
|
|
58
|
+
*.pot
|
|
59
|
+
|
|
60
|
+
# Django stuff:
|
|
61
|
+
*.log
|
|
62
|
+
local_settings.py
|
|
63
|
+
db.sqlite3
|
|
64
|
+
db.sqlite3-journal
|
|
65
|
+
|
|
66
|
+
# Flask stuff:
|
|
67
|
+
instance/
|
|
68
|
+
.webassets-cache
|
|
69
|
+
|
|
70
|
+
# Scrapy stuff:
|
|
71
|
+
.scrapy
|
|
72
|
+
|
|
73
|
+
# Sphinx documentation
|
|
74
|
+
docs/_build/
|
|
75
|
+
|
|
76
|
+
# PyBuilder
|
|
77
|
+
.pybuilder/
|
|
78
|
+
target/
|
|
79
|
+
|
|
80
|
+
# Jupyter Notebook
|
|
81
|
+
.ipynb_checkpoints
|
|
82
|
+
|
|
83
|
+
# IPython
|
|
84
|
+
profile_default/
|
|
85
|
+
ipython_config.py
|
|
86
|
+
|
|
87
|
+
# pyenv
|
|
88
|
+
# For a library or package, you might want to ignore these files since the code is
|
|
89
|
+
# intended to run in multiple environments; otherwise, check them in:
|
|
90
|
+
# .python-version
|
|
91
|
+
|
|
92
|
+
# pipenv
|
|
93
|
+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
|
94
|
+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
|
95
|
+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
|
96
|
+
# install all needed dependencies.
|
|
97
|
+
#Pipfile.lock
|
|
98
|
+
|
|
99
|
+
# poetry
|
|
100
|
+
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
|
101
|
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
102
|
+
# commonly ignored for libraries.
|
|
103
|
+
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
|
104
|
+
#poetry.lock
|
|
105
|
+
|
|
106
|
+
# pdm
|
|
107
|
+
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
|
108
|
+
#pdm.lock
|
|
109
|
+
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
|
|
110
|
+
# in version control.
|
|
111
|
+
# https://pdm.fming.dev/#use-with-ide
|
|
112
|
+
.pdm.toml
|
|
113
|
+
|
|
114
|
+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
|
115
|
+
__pypackages__/
|
|
116
|
+
|
|
117
|
+
# Celery stuff
|
|
118
|
+
celerybeat-schedule
|
|
119
|
+
celerybeat.pid
|
|
120
|
+
|
|
121
|
+
# SageMath parsed files
|
|
122
|
+
*.sage.py
|
|
123
|
+
|
|
124
|
+
# Environments
|
|
125
|
+
.env
|
|
126
|
+
.venv
|
|
127
|
+
env/
|
|
128
|
+
venv/
|
|
129
|
+
ENV/
|
|
130
|
+
env.bak/
|
|
131
|
+
venv.bak/
|
|
132
|
+
|
|
133
|
+
# Spyder project settings
|
|
134
|
+
.spyderproject
|
|
135
|
+
.spyproject
|
|
136
|
+
|
|
137
|
+
# Rope project settings
|
|
138
|
+
.ropeproject
|
|
139
|
+
|
|
140
|
+
# mkdocs documentation
|
|
141
|
+
/site
|
|
142
|
+
|
|
143
|
+
# mypy
|
|
144
|
+
.mypy_cache/
|
|
145
|
+
.dmypy.json
|
|
146
|
+
dmypy.json
|
|
147
|
+
|
|
148
|
+
# Pyre type checker
|
|
149
|
+
.pyre/
|
|
150
|
+
|
|
151
|
+
# pytype static type analyzer
|
|
152
|
+
.pytype/
|
|
153
|
+
|
|
154
|
+
# Cython debug symbols
|
|
155
|
+
cython_debug/
|
|
156
|
+
|
|
157
|
+
# PyCharm
|
|
158
|
+
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
|
159
|
+
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
|
160
|
+
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
|
161
|
+
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
|
162
|
+
#.idea/
|
|
163
|
+
/iTunes
|
|
164
|
+
/testData
|
|
165
|
+
/ipodTestData
|
|
166
|
+
/compendium
|
|
167
|
+
|
|
168
|
+
# macOS
|
|
169
|
+
.DS_Store
|
|
170
|
+
|
|
171
|
+
# VS Code
|
|
172
|
+
.vscode/
|
|
173
|
+
|
|
174
|
+
# GitHub Copilot
|
|
175
|
+
.github/copilot-instructions.md
|
|
176
|
+
|
|
177
|
+
# Claude Code
|
|
178
|
+
.claude/
|
|
179
|
+
CLAUDE.md
|