Skip to content

Commit 015d18f

Browse files
committed
Add MovieBulletCommentsPlayer bridge
1 parent 569ad54 commit 015d18f

1 file changed

Lines changed: 194 additions & 0 deletions

File tree

Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
package org.schabi.newpipe.player.bulletComments;
2+
3+
import android.annotation.SuppressLint;
4+
import android.util.Log;
5+
6+
import org.schabi.newpipe.extractor.bulletComments.BulletCommentsExtractor;
7+
import org.schabi.newpipe.extractor.bulletComments.BulletCommentsInfo;
8+
import org.schabi.newpipe.extractor.bulletComments.BulletCommentsInfoItem;
9+
import org.schabi.newpipe.extractor.exceptions.ParsingException;
10+
import org.schabi.newpipe.util.ExtractorHelper;
11+
import org.schabi.newpipe.views.BulletCommentsView;
12+
13+
import java.time.Duration;
14+
import java.util.Arrays;
15+
import java.util.List;
16+
import java.util.Objects;
17+
18+
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
19+
import io.reactivex.rxjava3.schedulers.Schedulers;
20+
21+
public class MovieBulletCommentsPlayer {
22+
public MovieBulletCommentsPlayer(final BulletCommentsView bulletCommentsView) {
23+
super();
24+
this.bulletCommentsView = bulletCommentsView;
25+
}
26+
27+
private final String TAG = "MovieBCPlayer";
28+
protected int serviceId;
29+
protected String url;
30+
protected final BulletCommentsView bulletCommentsView;
31+
protected List<BulletCommentsInfoItem> commentsInfoItems;
32+
private BulletCommentsExtractor extractor;
33+
public boolean isRoundPlayStream = false;
34+
35+
/**
36+
* Set data. Call before init().
37+
*
38+
* @param newServiceId Service id.
39+
* @param newUrl Url.
40+
*/
41+
public void setInitialData(final int newServiceId, final String newUrl) {
42+
Log.d(TAG, "setInitialData() serviceId=" + newServiceId + " url=" + newUrl);
43+
this.serviceId = newServiceId;
44+
this.url = newUrl;
45+
}
46+
47+
public final Duration interval = Duration.ofMillis(50);
48+
protected boolean isLoading = false;
49+
50+
/**
51+
* Fetch comments and init. Call after setInitialData().
52+
*/
53+
@SuppressLint("CheckResult")
54+
public void init() {
55+
Log.d(TAG, "init() called for url=" + this.url);
56+
this.bulletCommentsView.clearComments();
57+
isLoading = true;
58+
try {
59+
ExtractorHelper.getBulletCommentsInfo(this.serviceId, this.url, false)
60+
.filter(Objects::nonNull)
61+
.map((BulletCommentsInfo commentsInfo) -> {
62+
extractor = commentsInfo.getBulletCommentsExtractor();
63+
extractor.reconnect();
64+
return commentsInfo.getRelatedItems();
65+
}
66+
)
67+
.filter(Objects::nonNull)
68+
.map(s -> s.stream().toArray(BulletCommentsInfoItem[]::new))
69+
.subscribeOn(Schedulers.io())
70+
.observeOn(AndroidSchedulers.mainThread())
71+
.subscribe((BulletCommentsInfoItem[] newCommentsInfoItems) -> {
72+
this.commentsInfoItems = Arrays.asList(newCommentsInfoItems);
73+
Log.d(TAG, "init() success: got "
74+
+ newCommentsInfoItems.length
75+
+ " initial comments for " + this.url);
76+
if (extractor != null) {
77+
Log.d(TAG, "init() extractor isLive=" + extractor.isLive()
78+
+ " isDisabled=" + extractor.isDisabled());
79+
}
80+
isLoading = false;
81+
},
82+
throwable -> Log.e(TAG, Log.getStackTraceString(throwable))
83+
);
84+
} catch (final Exception e) {
85+
Log.e(TAG, Log.getStackTraceString(e));
86+
}
87+
}
88+
89+
protected Duration lastPosition = Duration.ZERO;
90+
91+
/**
92+
* Draw all comments which duration is between last
93+
* drawUntilPosition and current drawUntilPosition.
94+
*
95+
* @param drawUntilPosition Duration to draw comments until.
96+
*/
97+
public void drawComments(final Duration drawUntilPosition) {
98+
if (isLoading) {
99+
return;
100+
}
101+
Log.v(TAG, "drawComments() position=" + drawUntilPosition.toMillis()
102+
+ "ms extractor=" + (extractor != null ? "yes" : "null"));
103+
final BulletCommentsInfoItem[] nextCommentsInfoItems;
104+
if (extractor.isDisabled()) {
105+
return;
106+
}
107+
if (extractor != null && extractor.isLive()) {
108+
// have to put all messages we get to the pool as they only appear once
109+
try {
110+
nextCommentsInfoItems = extractor.getLiveMessages()
111+
.stream().toArray(BulletCommentsInfoItem[]::new);
112+
if (drawUntilPosition.compareTo(Duration.ofSeconds(Long.MAX_VALUE)) != 0) {
113+
extractor.setCurrentPlayPosition(drawUntilPosition.toMillis());
114+
}
115+
} catch (final ParsingException e) {
116+
Log.e(TAG, "drawComments() getLiveMessages failed", e);
117+
throw new RuntimeException(e);
118+
}
119+
} else { // we can filter the messages because we have the full list
120+
if (drawUntilPosition.toString().equals("PT0.049S")) {
121+
return;
122+
}
123+
nextCommentsInfoItems = commentsInfoItems
124+
.stream()
125+
.filter(item -> {
126+
final Duration d = item.getDuration();
127+
return d.compareTo(lastPosition) >= 0
128+
&& d.compareTo(drawUntilPosition) < 0;
129+
}
130+
)
131+
.toArray(BulletCommentsInfoItem[]::new);
132+
}
133+
Log.v(TAG, "drawComments() drawing " + nextCommentsInfoItems.length + " comments");
134+
bulletCommentsView.drawComments(nextCommentsInfoItems, drawUntilPosition);
135+
this.lastPosition = drawUntilPosition;
136+
}
137+
138+
/**
139+
* Resume comments. (Avoids drawing massive comments after skipping.)
140+
*
141+
* @param currentPosition Current position.
142+
*/
143+
public void start(final Duration currentPosition) {
144+
Log.d(TAG, "start() position=" + currentPosition.toMillis() + "ms");
145+
this.lastPosition = currentPosition;
146+
bulletCommentsView.resumeComments();
147+
}
148+
149+
/**
150+
* Pause comments.
151+
*/
152+
public void pause() {
153+
Log.d(TAG, "pause() called");
154+
bulletCommentsView.pauseComments();
155+
}
156+
157+
/**
158+
* Clear comments.
159+
*/
160+
public void clear() {
161+
Log.d(TAG, "clear() called");
162+
bulletCommentsView.clearComments();
163+
}
164+
165+
public void disconnect() {
166+
Log.d(TAG, "disconnect() called");
167+
if (extractor != null && extractor.isLive()) {
168+
extractor.disconnect();
169+
}
170+
}
171+
172+
/**
173+
* Draw all comments after max(movieDuration - interval, lastPosition).
174+
*
175+
* @param movieDuration The duration of the movie, used to avoid drawing too many comments.
176+
*/
177+
public void complete(final Duration movieDuration) {
178+
Log.d(TAG, "complete() called");
179+
if (lastPosition == null) {
180+
return; //is actually finished
181+
}
182+
final Duration minimumLastPosition = movieDuration.minus(interval);
183+
if (minimumLastPosition.compareTo(lastPosition) >= 0) {
184+
lastPosition = minimumLastPosition;
185+
}
186+
187+
//Show all comments.
188+
drawComments(Duration.ofSeconds(Long.MAX_VALUE));
189+
}
190+
191+
public String getUrl() {
192+
return url;
193+
}
194+
}

0 commit comments

Comments
 (0)