diff --git a/python/podcast/data_migration.py b/python/podcast/data_migration.py index a2c17b3e5dd9c58e679881763b0d56e252537432..740eda61edbb29ee42e3f74b46cc8f2563cf412a 100644 --- a/python/podcast/data_migration.py +++ b/python/podcast/data_migration.py @@ -123,7 +123,7 @@ def run_migrations(strict=True): if strict: raise set_versionnumber(3) - if current_version < 4: + if current_version < 4 and start_version > 1 : db.execute_sql("UPDATE podpost set duration = duration * 1000;") set_versionnumber(4) db.execute_sql('VACUUM "main"') diff --git a/python/podcast/podpost.py b/python/podcast/podpost.py index 27fd59447797af887d96d2e880a9721035ad62f9..c7aae45881c95213cfa49d2513bf961b4b352ce0 100644 --- a/python/podcast/podpost.py +++ b/python/podcast/podpost.py @@ -252,7 +252,8 @@ class Podpost(BaseModel): "loaded": loaded, "haschapters": haschapters, "listened": self.listened or self.position > 0 and ( - self.duration - self.position < Constants().markListenedBeforeEndThreshold * 1000) + self.duration - self.position < Constants().markListenedBeforeEndThreshold * 1000), + "podcastTitle": self.podcast.title if not self.isaudio else "" } def get_image_descriptor(self): diff --git a/qml/components/PlayerHandler.qml b/qml/components/PlayerHandler.qml index 56df6224cb0a2f122e1067c1584824d664604f6b..f54558420a9620117460f5abd4d7ec3d88d390ce 100644 --- a/qml/components/PlayerHandler.qml +++ b/qml/components/PlayerHandler.qml @@ -4,8 +4,8 @@ import io.thp.pyotherside 1.4 Python { id: playerHandler - property real position: (mediaplayer.position <= 0)?positionFromDb:mediaplayer.position - property real duration: (mediaplayer.duration <= 0)?durationFromDb:mediaplayer.duration + property real position: (mediaplayer.position <= 0) ? positionFromDb : mediaplayer.position + property real duration: (mediaplayer.duration <= 0) ? durationFromDb : mediaplayer.duration property real positionSeconds: position / 1000 property real durationSeconds: duration / 1000 property real durationFromDb: 0 @@ -16,6 +16,7 @@ Python { property string playtext: "" property string firstid: "" property string firsttitle: "" + property string firstPodcastTitle: "" property var chapters property int aktchapter property double playpos: 0 @@ -52,10 +53,10 @@ Python { onPlaying: { console.info("Playing audio_url: " + audio_url + " @ rate " + playrate) - + positionFromDb = position if (audio_url != "") { - mediaplayer.source = audio_url - mediaplayer.seek(positionFromDb - 15 * 1000) + if (mediaplayer.source != audio_url) + mediaplayer.source = audio_url if (!only_start_if_playing || mediaplayer.isPlaying) { mediaplayer.play() } @@ -74,8 +75,12 @@ Python { onPausing: { mediaplayer.pause() + var pauseRewindTime = 1000 + var positionToSave = mediaplayer.position + if (mediaplayer.position > pauseRewindTime) + positionToSave = mediaplayer.position - pauseRewindTime isPlaying = false - queuehandler.updatePlayingPosition() + queuehandler.updatePlayingPosition(positionToSave) } onStopping: { mediaplayer.pause() @@ -90,13 +95,15 @@ Python { function setEpisode(data, chapterlist) { firstid = data.id firsttitle = data.title + firstPodcastTitle = data.podcastTitle chapters = chapterlist playicon = data.logo_url playtext = data.title durationFromDb = data.duration positionFromDb = data.position - console.log("setting episode: " + data.title + " url:" + data.audio_url + " duration:"+data.duration+"/"+duration) + console.log("setting episode: " + data.title + " url:" + data.audio_url + + " duration:" + data.duration + "/" + duration) } function getaktchapter() { @@ -111,7 +118,7 @@ Python { return } } - aktchapter = chapters.length -\ 1 + aktchapter = chapters.length - 1 } function nextchapter() { @@ -150,7 +157,7 @@ Python { function play() { isPlaying = true - call("QueueHandler.instance.queue_play", function () {}) + call("QueueHandler.instance.queue_play", function () { }) } function pause() { @@ -180,9 +187,9 @@ Python { } function setDuration() { - if(mediaplayer.duration > 0){ - call("QueueHandler.instance.set_duration", - [mediaplayer.duration], function () {}) + if (mediaplayer.duration > 0) { + call("QueueHandler.instance.set_duration", [mediaplayer.duration], + function () {}) } } diff --git a/qml/components/QueueHandlerPython.qml b/qml/components/QueueHandlerPython.qml index 62de9385b671d18f497a2d7f87f89ead46bedf31..62e488aedd07cfca4103d996da5c253bafd9022c 100644 --- a/qml/components/QueueHandlerPython.qml +++ b/qml/components/QueueHandlerPython.qml @@ -62,7 +62,8 @@ Python { call("QueueHandler.instance.queue_to_archive", [id], function () {}) } function queueTopToArchive(playnext) { - call("QueueHandler.instance.queue_top_to_archive",[playnext], function () {}) + call("QueueHandler.instance.queue_top_to_archive", [playnext], + function () {}) } function getQueueEntries() { @@ -71,8 +72,11 @@ Python { function getFirstEntry() { call("QueueHandler.instance.get_first_entry", function () {}) } - function updatePlayingPosition() { - call("QueueHandler.instance.update_position", [playerHandler.position], + function updatePlayingPosition(position) { + if (position === undefined) { + position = playerHandler.position + } + call("QueueHandler.instance.update_position", [position], function () {}) } function downloadAudio(podpost) { diff --git a/qml/harbour-podqast.qml b/qml/harbour-podqast.qml index 1c612a0c1b85ba0e70a4c6d6f4ba844bdcaf014d..106042c05ab47eb4fa25f7f593bdab7ca1ae570f 100644 --- a/qml/harbour-podqast.qml +++ b/qml/harbour-podqast.qml @@ -437,10 +437,9 @@ ApplicationWindow { id: loghandler } -// PodqastAudioPlayer { -// id: mediaplayer -// } - + // PodqastAudioPlayer { + // id: mediaplayer + // } PlayerHandler { id: playerHandler onAudioNotExist: { @@ -470,26 +469,19 @@ ApplicationWindow { interval: 400 repeat: false onTriggered: { - interval=10 - updateMprisMetadata() - + interval = 10 + mprisPlayer.updateMetadata() } } - + MprisPlayer { id: mprisPlayer - property string title: playerHandler.firsttitle serviceName: "podqast" identity: "podQast" supportedUriSchemes: ["file", "http"] - supportedMimeTypes: ["audio/x-vorbis-ogg", - "audio/mpeg", - "audio/mp4a-latm", - "audio/x-aiff", - "audio/ogg", - "audio/opus"] + supportedMimeTypes: ["audio/x-vorbis-ogg", "audio/mpeg", "audio/mp4a-latm", "audio/x-aiff", "audio/ogg", "audio/opus"] canControl: true canGoNext: true @@ -497,15 +489,24 @@ ApplicationWindow { canPause: true canPlay: true canSeek: true - playbackStatus: playerHandler.isPlaying ? Mpris.Playing : Mpris.Paused - - onTitleChanged: { - metaData.title = playerHandler.firsttitle - // metaData.albumArtist = playerHandler. - - var metadata = mprisPlayer.metadata - metadata[Mpris.metadataToString(Mpris.Title)] = playerHandler.firsttitle - mprisPlayer.metadata = metadata + playbackStatus: { + switch (mediaplayer.playbackState) { + case Audio.PlayingState: + return Mpris.Playing + case Audio.PausedState: + return Mpris.Paused + default: + return Mpris.Stopped + } + } + rate: playerHandler.playrate + + metaData { + url: mediaplayer.source + duration: playerHandler.duration + title: playerHandler.firsttitle + contributingArtist: playerHandler.firstPodcastTitle + artUrl: playerHandler.playicon } loopStatus: Mpris.None @@ -514,9 +515,8 @@ ApplicationWindow { onPlayPauseRequested: playerHandler.playpause() onStopRequested: playerHandler.stop() onPlayRequested: playerHandler.play() - onNextRequested: podqast.fast_forward() - onPreviousRequested: podqast.fast_backward() - + onNextRequested: playerHandler.fast_forward() + onPreviousRequested: playerHandler.fast_backward() } } diff --git a/test/__init__.py b/test/__init__.py index 4f1416b4c4bfe03937248019c308f3d75f7d4849..8e25072cdc538f6cee0b7a467fa5439d3a52f79f 100644 --- a/test/__init__.py +++ b/test/__init__.py @@ -12,6 +12,7 @@ from httpretty.utils import utf8 from test.conftest import cleanup_podcast +logger = logging.getLogger(__name__) def mock_pyotherside(): module_name = "pyotherside" @@ -19,7 +20,6 @@ def mock_pyotherside(): sys.modules[module_name] = module module.send = Mock(name=module_name + '.send') - mock_pyotherside() from podcast.archive import ArchiveFactory @@ -28,7 +28,7 @@ from podcast.podcast import Podcast from podcast.podpost import PodpostFactory os.environ["PODQAST_HOME"] = tempfile.mkdtemp() -logging.info("tempdir: %s",os.environ["PODQAST_HOME"]) +logger.info("tempdir: %s",os.environ["PODQAST_HOME"]) from podcast.constants import Constants from podcast.data_migration import setup_db @@ -51,6 +51,7 @@ def setup_inbox_with_2_posts(): @httprettified def setup_and_get_2_posts(): + logger.info("setup with dummy feed") HTTPretty.register_uri(HTTPretty.GET, 'https://freakshow.fm/feed/opus/', body=read_testdata('testdata/freakshow.rss'), adding_headers=xml_headers) cleanup_podcast() @@ -62,6 +63,7 @@ def setup_and_get_2_posts(): entry2 = podcast.get_entry(podcast.entry_ids_old_to_new[1]) assert entry2 PodpostFactory().persist(entry2) + logger.info("persisted dummy feed") return entry1, entry2 diff --git a/test/test_migration_to_v1.py b/test/test_migration_to_v1.py index 3cf10a74635a5e7c99a3231646b52f1623a0c0be..9a9f58e6d5a01eb6ded71c2bb63b93ec08308b4c 100644 --- a/test/test_migration_to_v1.py +++ b/test/test_migration_to_v1.py @@ -42,6 +42,7 @@ def test_migration_v1(): assert ilen(ExternalFactory().get_external().get_podposts()) == 0 assert ilen(InboxFactory().get_inbox().get_podposts()) == 42 assert PodpostChapter.select().count() == 9293 + assert (130 * 60 + 54) * 1000 == QueueFactory().get_queue()._get_top().duration PodcastFactory().remove_podcast("http://minkorrekt.de/feed/opus/") assert ilen(PodcastListFactory().get_podcast_list().get_podcasts()) == 24 diff --git a/test/test_podcast.py b/test/test_podcast.py index 3eda9cb654bbd517a6fce549e9958545bedd985f..f52cde851f510954bc525a6c197e91bc6894291f 100644 --- a/test/test_podcast.py +++ b/test/test_podcast.py @@ -233,14 +233,6 @@ def refreshable_podcast_fixture(request) -> Tuple[Podcast, List[Podpost]]: assert invoked > 0 -@httpretty.activate -def test_pagination(): - url_f = "https://fakefeed.com/page" - HTTPretty.register_uri(HTTPretty.GET, url_f, body=read_testdata('testdata/fakefeednohref.xml'), - adding_headers=xml_headers) - podcast, episodes = Podcast.create_from_url(url_f) - assert 3 == podcast.count_episodes() - assert 3 == len(episodes) @httpretty.activate diff --git a/test/test_podpost.py b/test/test_podpost.py index c6e6a896008e990c09f4d166946198b9c04f1519..3b8f89fda42cd0b2e6356e9d12baa8a67d95f465 100644 --- a/test/test_podpost.py +++ b/test/test_podpost.py @@ -1,7 +1,7 @@ """ Podpost tests """ - +import logging import sys import httpretty @@ -14,6 +14,8 @@ sys.path.append("../python") from podcast.podcast import Podcast from podcast.podpost import Podpost, PodpostFactory +logger = logging.getLogger(__name__) + @httpretty.activate def test_podpost_save(): @@ -25,18 +27,20 @@ def test_podpost_save(): p, episodes = Podcast.create_from_url('https://freakshow.fm/feed/opus/') e: Podpost = p.get_latest_entry() - e.position = e.duration -59*1000 + assert e.duration == 10 * 60 * 1000 + 55 * 1000 + e.position = e.duration - 59 * 1000 id1 = e.id PodpostFactory().persist(e) n = PodpostFactory().get_podpost(e.id) id2 = n.id assert type(n) == Podpost assert id1 == id2 + assert n.duration == 10 * 60 * 1000 + 55 * 1000 assert n.get_data()["listened"] @httpretty.activate -def test_podpost_save(): +def test_podpost_save2(): """ Test podpost saving """ @@ -54,6 +58,7 @@ def test_podpost_save(): assert episode.get_data()['description'] == episode.plainpart assert episode.get_data()['detail'] == episode.htmlpart + def test_persist_bulk_empty(): PodpostFactory().persist_bulk([]) @@ -66,7 +71,6 @@ def test_persist_bulk_nochapters(): PodpostFactory().persist_bulk([post]) - def test_get_data_external_audio(): post = Podpost() post.guid = "" @@ -77,18 +81,16 @@ def test_get_data_external_audio(): post.get_data() - - def test_tracker_removal(): tests = [ - ("https://dts.podtrac.com/redirect.mp3/myfeed","https://myfeed"), - ("http://dts.podtrac.com/redirect.mp3/myfeed","http://myfeed"), - ("http://www.podtrac.com/pts/redirect.mp3/myfeed","http://myfeed"), - ("https://www.podtrac.com/pts/redirect.mp3/myfeed","https://myfeed"), - ("https://notracker.ru/feed/podtrac","https://notracker.ru/feed/podtrac"), + ("https://dts.podtrac.com/redirect.mp3/myfeed", "https://myfeed"), + ("http://dts.podtrac.com/redirect.mp3/myfeed", "http://myfeed"), + ("http://www.podtrac.com/pts/redirect.mp3/myfeed", "http://myfeed"), + ("https://www.podtrac.com/pts/redirect.mp3/myfeed", "https://myfeed"), + ("https://notracker.ru/feed/podtrac", "https://notracker.ru/feed/podtrac"), ] podpost = Podpost() for given, expected in tests: podpost.href = given - assert podpost.remove_trackers() == expected \ No newline at end of file + assert podpost.remove_trackers() == expected diff --git a/test/testdata/freakshow.rss b/test/testdata/freakshow.rss index 8b035dfbe731ffb5f665ec355c5e370f317ed473..158236d5ceed30a300e1a97e29b3808f0a9d9264 100644 --- a/test/testdata/freakshow.rss +++ b/test/testdata/freakshow.rss @@ -64,7 +64,7 @@ - + 0:10:55 Metaebene Personal Media - Tim Pritlove Brot backen — Welt putzen — 36C3 245