Commit graph

1191 commits

Author SHA1 Message Date
Yevhen Babiichuk (DustDFG)
d6be966db3 Replace Illegal{State,Argument} exceptions with more idiomatic kotlin code 2026-02-08 21:59:10 +08:00
AbsurdlyLongUsername
1554f77762 Fix additional setRecovery from rebase errors 2026-02-05 11:17:30 +00:00
AbsurdlyLongUsername
118def08b4 Add conditional guard to prevent useVideoAndSubtitles overwriting recovery position that was set in Player.handleIntent for RESUME_PLAYBACK when resuming playback 2026-02-05 05:05:41 +00:00
AbsurdlyLongUsername
725cb70cbd Update useVideoAndSubtitles rename in comment 2026-02-05 05:05:40 +00:00
AbsurdlyLongUsername
5525d206dc Small refactor getPlayQueueFromCache 2026-02-05 05:05:40 +00:00
Stypox
c2723096ab
Avoid rebuilding BackgroundPlayerUi if already in place 2026-01-28 02:39:56 +01:00
Stypox
216867c597
Address review comments 2026-01-28 02:20:33 +01:00
AudricV
1d8ea0181f
Disable fetching video and text tracks in background player
This reduces data usage for manifest sources with demuxed audio and
video, such as livestreams, for non-HLS sources only due to an
ExoPlayer bug.
2026-01-28 02:13:14 +01:00
AudricV
4648cac9c6
Allow changing video and text tracks state without stream info
This allows disabling these track types when stream info has been not
loaded while the ExoPlayer instance is.

It is now possible to do so with the background player, in order to
disable fetching video and text tracks for manifest sources,
especially used for livestreams.

Also set the recovery first before reloading play queue manager in the
useVideoAndSubtitles method of the Player class.
2026-01-28 02:13:14 +01:00
AudricV
0578e7fde0
Rename useVideoSource to useVideoAndSubtitles in Player
As both subtitles and video tracks are disabled in this method, the
goal of this rename is to highlight disabling/enabled subtitles.
2026-01-28 02:13:14 +01:00
AudricV
c670ad80ee
Use DASH first instead of HLS and YouTube's DASH parser for lives 2026-01-28 02:13:14 +01:00
AudricV
077f34c922
Add a YouTube DASH manifest parser to make live DASH manifests usable
This is a hacky solution, a better one should be investigated and used.
2026-01-28 02:13:14 +01:00
AudricV
25b133946d
[YouTube] Adapt YoutubeHttpDataSource to TVHTML5 client removal in NPE 2026-01-23 22:04:05 +01:00
Aayush Gupta
8c5f13ab5c ktlint: Fix function-signature violations
Signed-off-by: Aayush Gupta <aayushgupta219@gmail.com>
2026-01-24 00:32:03 +08:00
Aayush Gupta
7d5647b0ba ktlint: Fix standard_argument-list-wrapping violations
Signed-off-by: Aayush Gupta <aayushgupta219@gmail.com>
2026-01-24 00:31:44 +08:00
Aayush Gupta
9b7874ff51 ktlint: Fix blank-line-between-when-conditions violations
Signed-off-by: Aayush Gupta <aayushgupta219@gmail.com>
2026-01-24 00:31:44 +08:00
Aayush Gupta
ff2390b144 ktlint: Fix enum wrapping violations
Signed-off-by: Aayush Gupta <aayushgupta219@gmail.com>
2026-01-24 00:31:44 +08:00
Aayush Gupta
81fd089a32 ktlint: Fix block comment violations
Signed-off-by: Aayush Gupta <aayushgupta219@gmail.com>
2026-01-24 00:31:44 +08:00
Aayush Gupta
555cd3acb7 ktlint: Fix standard_kdoc violations
Signed-off-by: Aayush Gupta <aayushgupta219@gmail.com>
2026-01-24 00:31:44 +08:00
Aayush Gupta
80a543e7ab ktlint: Fix violation related to comment placement
Signed-off-by: Aayush Gupta <aayushgupta219@gmail.com>
2026-01-24 00:31:14 +08:00
Aayush Gupta
c76d14dfd4 ktlint: Drop unused trailing commas
Signed-off-by: Aayush Gupta <aayushgupta219@gmail.com>
2026-01-24 00:31:14 +08:00
Aayush Gupta
0641c19388 ktlint: Fix multi-line if-else violations
Signed-off-by: Aayush Gupta <aayushgupta219@gmail.com>
2026-01-24 00:31:14 +08:00
Aayush Gupta
f23d8eff57 ktlint: Order imports in lexicographic order
Signed-off-by: Aayush Gupta <aayushgupta219@gmail.com>
2026-01-24 00:31:13 +08:00
TobiGr
4ed2b9748f Merge branch 'master' into dev 2026-01-11 22:53:11 +01:00
Tobi
680235ad51
Merge pull request #12922 from TobiGr/enqueue-ui
[PlayQueue] Fix incorrect UI states of PlayQueue items
2026-01-07 04:01:51 -08:00
Yevhen Babiichuk (DustDFG)
3ffcf11a3a Merge inheritors of newpipe/player/playqueue/PlayQueueEvent and
convert it to kotlin
2026-01-01 23:05:16 +02:00
Yevhen Babiichuk (DustDFG)
d9682f5e0a Convert newpipe/player/PlayerType to kotlin 2026-01-01 15:33:32 +02:00
tobigr
465979e677 Do not change the aspectRation if the renderer is disabled 2025-12-29 16:41:25 +01:00
Yevhen Babiichuk (DustDFG)
c2f526d5b3 Use context.getString() shorthand instead of context.getResources().getString()
Cherry-picked from #12949 / 4360c1b8735c073b95a162324b2814cc5a5b4ecd
2025-12-27 23:12:37 +01:00
TobiGr
f7ff5db4b5 [PlayQueue] Fix incorrect UI states of PlayQueue items
onNext() is called after onSubscribe() when creating a PlayQueueAdapter. For that reason the last broadcasted event is applied to the UI state although it is already reflected in the PlayQueue that was used to initialize the adapter.

This is the intended behavior of the previously used event broadcaster of the type BehaviorSubject<>. The broadcaster's type was changed to PublishSubject<> which does not emit the last event after onSubscribe().

Ref: https://github.com/TeamNewPipe/NewPipe/issues/9669
2025-12-20 18:28:45 +01:00
Aayush Gupta
77bea1ac68 Player: Enqueue next on the existing playQueue
Fixes 150649aea9

Signed-off-by: Aayush Gupta <aayushgupta219@gmail.com>
2025-12-13 17:03:54 +08:00
Tobi
f836f5e75d
Merge pull request #12746 from TeamNewPipe/kspMigration
Migrate from KAPT to KSP
2025-11-07 07:41:56 -08:00
Aayush Gupta
4422b55ab4 Migrate database logic to Kotlin
Room has been convereted into a KMP library in the latest stable releases and
annotation processing requires KSP which only generates kotlin classes

Signed-off-by: Aayush Gupta <aayushgupta219@gmail.com>
2025-11-03 16:14:29 +08:00
litetex
c81148ae0a
[Popup player] Workaround that UI elements are pushed off screen 2025-10-21 18:09:06 +02:00
litetex
56a09220ee
Remove not needed viability control
This is done by the parent
2025-10-17 20:15:24 +02:00
jianing liu
fbc664d0da [player] Prevent long audio track label from pushing controls off-screen
- audioTrackTextView: layout_width=0dp + layout_weight=1
- Make it singleLine with ellipsize="end"
- When not fullscreen, hide metadataView so an empty weighted container doesn’t reserve space
- Result: controls stay visible on small screens; longer labels can use space on larger screens
2025-10-14 12:58:51 +08:00
Thonsi
59dfdda95e remove isUsingDSP 2025-10-01 15:56:08 +00:00
Stypox
aa2b4821e2
Post dummy notification then close player service on invalid intent
This should solve "Context.startForegroundService() did not then call Service.startForeground()" according to https://github.com/TeamNewPipe/NewPipe/issues/12489#issuecomment-3290318112
2025-09-17 11:50:46 +02:00
Stypox
92a07a3445
Use tryBindIfNeeded(), send player started only if player!=null
This commit fixes one way ghost notifications could be produced (although I don't know if there are other ways). This is the call chain that would lead to ghost notifications being created:
1. the system starts `PlayerService` to query information from it, without providing `SHOULD_START_FOREGROUND_EXTRA=true`, so NewPipe does not start the player nor show any notification, as expected
2. the `PlayerHolder::serviceConnection.onServiceConnected()` gets called by the system to inform `PlayerHolder` that the player started
3. `PlayerHolder`  notifies `MainActivity` that the player has started (although in fact only the service has started), by sending a `ACTION_PLAYER_STARTED` broadcast
4. `MainActivity` receives the `ACTION_PLAYER_STARTED` broadcast and brings up the mini-player, but then also tries to make `PlayerHolder` bind to `PlayerService` just in case it was not bound yet, but does so using `PlayerHolder::startService()` instead of the more passive `PlayerHolder::tryBindIfNeeded()`
5. `PlayerHolder::startService()` sends an intent to the `PlayerService` again, this time with `startForegroundService` and with `SHOULD_START_FOREGROUND_EXTRA=true`
6. the `PlayerService` receives the intent and due to `SHOULD_START_FOREGROUND_EXTRA=true` decides to start up the player and show a dummy notification

Steps 3 and 4 are wrong, and this commit fixes them:
3. `PlayerHolder` will now broadcast `ACTION_PLAYER_STARTED` when the service connects, only if the player is not-null
4. `PlayerHolder::tryBindIfNeeded()` is now used to passively try to bind, instead of `PlayerHolder::startService()`
2025-09-17 11:49:16 +02:00
Isira Seneviratne
89c4eb5237 Refactor player intent logic 2025-09-08 07:56:13 +05:30
Profpatsch
1723bf0e8a Player/handleIntent: keep current player when clicking timestamp
This was always a bit weird, that clicking a timestamp would
unconditionally switch to the popup player.

With the new enum, it’s trivial to change it to always stay at the
selected player now ;)
2025-09-06 17:40:18 +02:00
Profpatsch
eb277fe14b Player/handleIntent: call handleIntentPost unconditionally
We always need to handleIntentPost otherwise the VideoDetailFragment
is not setup correctly.
2025-09-06 15:31:14 +02:00
Profpatsch
d77771a60c Player/handleIntent: fix enqueue if player not running
In 063dcd41e57c46721f1691cd57d21fbde75a35ea I falsely claimed that the
fallthrough case is always degenerate, but it kinda somehow still
worked because if you long-click on e.g. the popup button, it would
call enqueue, but if nothing was running yet it would fallthrough to
the very last case and start the player with the video.

So let’s return to that and add a TODO for further refactoring in the
future.
2025-09-06 15:09:11 +02:00
Profpatsch
150649aea9 Player/handleIntent: Don’t delete queue when clicking on timestamp
Fixes https://github.com/TeamNewPipe/NewPipe/issues/11013

We finally are at the point where we can have good logic around
clicking on timestamps.

This is pretty straightforward:

1) if we are already playing the stream (usual case), we skip to the
   correct second directly
2) If we don’t have a queue yet, create a trivial one with the stream
3) If we have a queue, we insert the video as next item and start
  playing it.

The skipping logic in 1) is similar to the one further down in the old
optimization block, but will always correctly fire for timestamps now.
I copied it because it’s not quite the same code, and moving into a
separate method at this stage would complicate the code too much.
2025-09-06 15:09:11 +02:00
Profpatsch
3803d49489 Player/handleIntent: separate out the timestamp request into enum
Instead of implicitely reconstructing whether the intent was
intended (lol) to be a timestamp change, we create a new kind of
intent that *only* sets the data we need to switch to a new timestamp.

This means that the logic of what to do (opening a popup player) gets
moved from `InternalUrlsHandler.playOnPopup` to the
`Player.handleIntent` method, we only pass that we want to jump to a
new timestamp. Thus, the stream is now loaded *after* sending the
intent instead of before sending.

This is somewhat messy right now and still does not fix the issue of
queue deletion, but from now on the queue logic should get more
straightforward to implement.

In the end, everything should be a giant switch. Thus we don’t
fall-through anymore, but run the post-setup code manually by calling
`handeIntentPost` and then returning.
2025-09-06 15:06:53 +02:00
Profpatsch
25a4a9a253 Player/handleIntent: move prefs parameters into initPlayback
They are just read from the player preferences and don’t influence the
branching, no need to read them in the intent parsing logic.
2025-09-06 15:04:06 +02:00
Profpatsch
d534946550 Player: inline repeat mode cycling 2025-09-06 15:04:06 +02:00
Profpatsch
8fb3e90fe1 Player: remove unused REPEAT_MODE intent key 2025-09-06 15:04:06 +02:00
Profpatsch
5750ef6aa8 Player/handleIntent: start converting intent data to enum
The goal here is to convert all player intents to use a single enum
with extra data for each case. The queue ones are pretty easy, they
don’t carry any extra data. We fall through for everything else for
now.
2025-09-06 15:04:06 +02:00
Profpatsch
ab7d1377e5 Player/handleIntent: always early return on ENQUEUE an ENQUEUE_NEXT
We can do this, because:

1. if `playQueue` is not null, we return early
2. if `playQueue` is null and we need to enqueue:
  - the only “proper” case that could be triggered is
    the `RESUME_PLAYBACK` case, which is never `true` for the queuing
    intents, see the comment in `NavigationHelper.enqueueOnPlayer`
  - the generic `else` case is degenerate, because it would crash on
  `playQueue` being `null`.

This makes some sense, because there is no way to trigger the
enqueueing logic via the UI currently if there is no video playing
yet, in which case `playQueue` is not `null`.

So we need to transform this whole if desaster into a big switch.
2025-09-06 15:04:06 +02:00