76 Commits

Author SHA1 Message Date
Bart De Vries
e9111eb011
Workaround for a qtmultimedia backend issue
Qt multimedia with the ffmpeg backend suddenly started sending
LoadedMedia signals in the PlayingState, even though that should not be
a valid combination according to the docs.  This is messing up the
AudioManager.
2024-04-25 13:44:31 +02:00
Tobias Fella
eb74c913a9 Simplify author handling
- Don't make them QObjects; those are heavy and there's no reason for that
- In fact, don't make them objects at all; we're only using them in string form anyway
2024-01-11 21:52:10 +01:00
Tobias Fella
fe6626ebeb Remove some empty descructors 2024-01-11 21:52:10 +01:00
Bart De Vries
9483607a20 Make playPause() also work when player is in stopped state 2023-12-04 13:43:55 +01:00
Bart De Vries
52a1f08e02 Add a switch to globally enable/disable network status checks
Make error reporting less ambiguous: report either "no connection" or
"not allowed on metered connection".  Also show hint how to disable
network status checking altogether.

BUG: 475400
2023-11-07 21:06:19 +00:00
Bart De Vries
0e2fbd547a Restructure files: add utils directory 2023-10-26 09:52:23 +02:00
Bart De Vries
af6e581bee Fix and prevent nullptr dereferences in AudioManager
This would happen when the current track is changed to "no track".
Signals from the backend KMediaSession would still trigger duration()
calls which would try to dereference the pointer to the current track
entry.
2023-07-27 13:33:41 +02:00
Bart De Vries
21952c67e9 Make grace time configurable for marking episodes as played
BUG: 468687
2023-06-09 11:11:42 +00:00
Bart De Vries
0c54ab7edf Refactor to use QNetworkInformation instead of SolidExtras for Qt6
SolidExtras will still be used for the Qt5 version for the time being.
This refactoring makes it trivial to rip out SolidExtras once the jump
to Qt6-only will be made.
2023-06-02 19:11:10 +02:00
Bart De Vries
eac74ecbbb [KMediaSession] Only send MRPIS2 positionChanged signal on seek
Stop spamming the DBus with positionChanged signals if playback is
progressing at the nominal playback rate.  This brings the
implementation in line with the MPRIS2 player spec.  The previous
implementation was causing android battery drain issues with KDEConnect
constantly updating the position (and player details) on the notification
widget.
This implementation will still send the current playback position every
10 seconds to ensure that clients that don't implement the standard
properly or did not receive previous messages, will still get regularly
updated.
This also fixes correct signaling of playback rate changes over DBus.
2023-06-01 10:42:58 +02:00
Harry Kaimenas
39f215c897 Add adjustable seek times
Make seek times adjustable. Expose seek time under Playback Settings.
Set min time allowed in seconds to 1 and max time in seconds to 300.

FEATURE: 468686
2023-05-11 07:26:31 +00:00
Bart De Vries
56b30203eb Remove "new" status when starting playback of an episode
Before the introduction of streaming, the "status" would be removed when
an episode was downloaded or marked as played, which made sense.  With
the introduction of streaming it makes sense to also remove the "new"
status when (streaming) playback starts.  At that point in time the
episode should indeed no longer considered to be "new".
2023-03-15 12:52:24 +01:00
Bart De Vries
7dcf3c52e2 Fix directly jumping to chapter on a non-playing track 2023-02-27 15:04:01 +01:00
Bart De Vries
eedfc28f8f Handle stream redirects through qt rather than libVLC/gstreamer
libVLC has a hardcoded maximum number of redirects. Several podcasts
need more than this number.  Therefore we resolve the final url through
QNetworkReply and send the final url to the audio player.
2023-02-23 18:37:52 +01:00
Bart De Vries
e6fee85f4e Solve issues with playback signals firing while changing tracks 2023-02-20 11:34:49 +01:00
Bart De Vries
780e63c2f2 [KMediaSession] Allow app and desktop entry name to be set in constructor 2023-02-16 13:32:52 +01:00
Bart De Vries
acd1a55aae Fix minor issue with network connect check in AudioManager
AudioManager was reporting no connectivity in case the networkstatus was
reported as being "Unknown".  We might as well attempt to stream in that
case.  If there is no connectivity, it will fail anyway with another
useful error message.
2023-01-19 20:43:27 +01:00
Bart De Vries
eb07e67f70 [KMediaSession] Implement dynamic audio backend framework
KMediaSession is an audio player library that has an API which is close
to QMediaPlayer and which allows to use --- and dynamically switch
between --- different audio backends. At this moment there is
implementation for libVLC, gstreamer and QtMultimedia. Only QtMultimedia
is a hard dependency in order to at least have one functional backend on
all platforms; all other dependencies are optional.

KMediaSession has out-of-the-box, built-in MPRIS2 support, sleep inhibit,
and basic metadata support.

BUG: 462358

Closes #35
2023-01-16 15:36:54 +01:00
Bart De Vries
562c76c799 Implement streaming support
This implements support for streaming episodes rather than downloading them
first.
This introduces a new setting: prioritizeStreaming. If it's set to false
(default) then a streaming play button is only added to the EntryPage.  If
it is set to true, then the streaming play button will also appear on the
Entry delegates instead of the download button.
There is a separate setting to decide if streaming is also allowed on
metered connections.

FEATURE: 438864
2022-10-19 14:49:56 +02:00
Bart De Vries
5f94b4a357 Add sleep timer
FEATURE: 443400
2022-06-30 08:21:09 +00:00
Bart De Vries
e62d17f9b0 Adjust time left on episodes according to current playback rate
This new feature is implemented behind a switch in the settings (default
is off).

FEATURE: 452135
2022-06-01 21:08:27 +02:00
Bart De Vries
f861f4e802 Add podcast subscription and episode play state synchronization
This implements the gpodder API from scratch.  It turned out that
libmygpo-qt has several critical bugs, and there's no response to pull
requests upstream.  So using that library was not an option.

The implementation into kasts consists of the following:
- Can sync with gpodder.net or with a nextcloud server that has the
  nextcloud-gpodder app installed.  (This app is mostly API compatible
  with gpodder.)
- Passwords are stored using qtkeychain.  If the keychain is
  unavailable it will fallback to file.
- It syncs podcast subscriptions and episode play positions, including
  marking episodes as played. Episodes that have a non-zero play
  position will be added to the queue automatically.
- It will check for a metered connection before syncing.  This is
  coupled to the allowMeteredFeedUpdates setting.
- Full synchronization can be performed either manually (from the
  settings page) or through automatic triggers: on startup and/or on
  feed refresh.
- There is an additional possibility to trigger quick upload-only syncs
  to make sure that the local changes are immediately uploaded to the
  server (if the connection allows).  This will trigger when
  subscriptions are added or removed, when the pause/play button is
  toggled or an episode is marked as played.
- This implements a few safeguards to avoid having multiple feed URLS
  pointing to the same underlying feed (e.g. http vs https).  This
  solves part of #17

Solves #13
2021-10-29 18:47:55 +02:00
Bart De Vries
117f314d0d Move models to dedicated directory 2021-09-18 19:07:15 +02:00
Yuri Chornoivan
9384f3c073 Fix minor typo 2021-07-27 12:53:21 +03:00
Bart De Vries
a15e2dbe5d Make storage path configurable
This adds a new setting to the Settings page.
Existing enclosures and images will be moved to the new location
(first copied, then deleted in the original location).  If any of
the copy actions fail, the operation is aborted and the original
path is restored.
The StorageMoveJob is set up in such a way that it's easy to add other
files or subfolders in the future.

Solves #15
2021-07-24 20:43:11 +02:00
Bart De Vries
b9b82d783f Also add title argument to Error elsewhere 2021-07-14 22:32:14 +02:00
Bart De Vries
8cd1237540 Mark another TODO as solved: make a setting for removing played episodes from queue 2021-07-06 22:36:51 +02:00
Bart De Vries
73b2cf565c Fix recursive loop when last track finishes playing 2021-07-06 19:21:57 +02:00
Bart De Vries
9731795e62 Solve deadlock in startup between ErrorLogModel and AudioManager 2021-07-06 17:03:25 +02:00
Bart De Vries
d2cee8a066 Add error overlay for Invalid Media
This implements a TODO mentioned in the sources.
2021-07-04 16:52:05 +02:00
Bart De Vries
a331366d41 Replace Audio prepare hack by nicer, asynchronous solution
The main bits of this implementation are:
- Start a new track in paused state.  We don't care about the actual
  media state or player state that QMediaPlayer is reporting.  We will
  deal with that when the audio actually starts playing.
- If a player position needs to be restored, we set d->m_pendingSeek to
  the position that needs to be seeked.  We don't actually seek because
  we have no idea what state the player is in yet.
- On the positionChanged signal of QMP, and if the media is buffered, we
  check if there is pendingSeek value set which is set to a different
  value than the current player position.  If so, we call
  d->m_player.setPosition().  If we have arrived at the correct
  position, then we reset d->m_pendingSeek to -1.
- In the position(), duration() and seek() methods, we return sensible
  values, even QMP is not.  So, we report the duration from the
  enclosure, the position from d->m_pendingSeek, and let seek() change
  the value of d->m_PendingSeek (if it's not -1) to the new seek
  position.
- When there's a pending seek, we set the notifyInterval to shorter
  interval to reduce the startup audio glitch as much as possible.  We
  then reset it to the default of 1000 msec.

This was tested on linux and android.
2021-06-20 19:14:07 +02:00
Bart De Vries
8437a44a7b Remove obsolete timeString method 2021-06-05 11:59:57 +02:00
Tobias Fella
3f1f3045ec Port away from KDeclarative 2021-06-03 16:23:06 +02:00
Bart De Vries
9d78b5b488 Run clang-format 2021-05-28 23:16:35 +02:00
Bart De Vries
3983e09634 Use qCDebug in AudioManager 2021-05-28 22:55:18 +02:00
Bart De Vries
b776dd22cb Contextualize singleShots 2021-05-28 16:54:00 +02:00
Bart De Vries
858601aec3 Change from old style connects to function pointers 2021-05-28 16:49:55 +02:00
Bart De Vries
99c1424327 Add setting to continue playback after end of current track 2021-05-23 21:35:38 +02:00
Swapnil Tripathi
21e9d0b9a7 Fix segfault when removing feeds with currently playing entries 2021-05-22 09:05:33 +00:00
Bart De Vries
34c5e5309c Implement timeString method to create HH:mm:ss strings from qint64
This method is now used in all places where a HH:mm:ss string is
required.
2021-05-02 09:42:49 +02:00
Bart De Vries
1b1654d1f4 Apply clang-format 2021-05-01 21:35:37 +02:00
Bart De Vries
d1618943f5 Update based on review by Tobias Fella 2021-05-01 21:09:07 +02:00
Bart De Vries
6edbd91f18 Set setPreventSleep in play() and pause()
Making it toggle based on the playerState did not work properly because
the stream is toggling between pause and play several times in the
prepareAudioStream method.
2021-04-30 21:45:11 +02:00
Bart De Vries
cbf0d9c622 Comment out some qDebug() statements 2021-04-30 19:13:43 +02:00
Bart De Vries
ead73ac2fe Safeguard against QMediaPlayer::InvalidMedia
In case of the InvalidMedia status, skip to next track and delete the
invalid enclosure.
2021-04-30 11:57:39 +02:00
Bart De Vries
36ad248e55 Do some additional checks on entry before loading in AudioManager 2021-04-29 11:28:59 +02:00
Bart De Vries
51db7ea1cf Only use custom gst-pipeline on linux
GStreamer is not used as QMediaPlayer backend on other platforms, so
audio will not start with a custom gst-pipeline on Android and Windows.
Still needs a solution to get rid of the horrible pitch change on
Android and Windows, though.
2021-04-23 10:55:59 +02:00
Bart De Vries
e2d59a69b0 Move audio positioning hack into a separate method
This allows the hack to be re-used in the play() method.  Apparently on
some systems the stream becomes unresponsive again after pausing.  So
probably it's required to ensure that the stream is fully seekable and
buffered before restarting playback.
2021-04-22 16:48:13 +02:00
Bart De Vries
6c7a271970 Use custom gst-pipeline to avoid pitch changes when audio is sped up 2021-04-21 20:25:01 +02:00
Bart De Vries
7be1ed28ec Disable debug output in audiomanager 2021-04-21 14:53:03 +02:00