Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <TaskerData sr="" dvi="1" tv="6.7.3">
- <dmetric>1080.0,2400.0</dmetric>
- <Profile sr="prof401" ve="2">
- <cdate>1789166400000</cdate>
- <edate>1789166400000</edate>
- <flags>8</flags>
- <id>401</id>
- <mid0>501</mid0>
- <nme>MB V2 - Media State</nme>
- <Event sr="con0" ve="2">
- <code>2081</code>
- <pri>0</pri>
- <Bundle sr="arg0">
- <Vals sr="val">
- <net.dinglisch.android.tasker.RELEVANT_VARIABLES><StringArray sr=""/></net.dinglisch.android.tasker.RELEVANT_VARIABLES>
- <net.dinglisch.android.tasker.RELEVANT_VARIABLES-type>[Ljava.lang.String;</net.dinglisch.android.tasker.RELEVANT_VARIABLES-type>
- </Vals>
- </Bundle>
- <Str sr="arg1" ve="3" />
- <Str sr="arg2" ve="3" />
- <Str sr="arg3" ve="3" />
- <Str sr="arg4" ve="3" />
- <Int sr="arg5" val="0" />
- </Event>
- </Profile>
- <Profile sr="prof402" ve="2">
- <cdate>1789166400000</cdate>
- <edate>1789166400000</edate>
- <flags>8</flags>
- <id>402</id>
- <mid0>502</mid0>
- <nme>MB V2 - Progress</nme>
- <Event sr="con0" ve="2">
- <code>2095</code>
- <pri>0</pri>
- <Bundle sr="arg0">
- <Vals sr="val">
- <net.dinglisch.android.tasker.RELEVANT_VARIABLES><StringArray sr=""/></net.dinglisch.android.tasker.RELEVANT_VARIABLES>
- <net.dinglisch.android.tasker.RELEVANT_VARIABLES-type>[Ljava.lang.String;</net.dinglisch.android.tasker.RELEVANT_VARIABLES-type>
- </Vals>
- </Bundle>
- <Str sr="arg1" ve="3">500</Str>
- </Event>
- <State sr="con1" ve="2">
- <code>165</code>
- <ConditionList sr="if">
- <Condition sr="c0" ve="3">
- <lhs>%MBPlaying</lhs>
- <op>2</op>
- <rhs>true</rhs>
- </Condition>
- </ConditionList>
- </State>
- </Profile>
- <Profile sr="prof403" ve="2">
- <cdate>1789250000000</cdate>
- <edate>1789250000000</edate>
- <flags>8</flags>
- <id>403</id>
- <mid0>503</mid0>
- <nme>MB V2 - Live Slider</nme>
- <Event sr="con0" ve="2">
- <code>3050</code>
- <pri>0</pri>
- <Str sr="arg0" ve="3">%MBSeekLive</Str>
- <Str sr="arg1" ve="3" />
- <Int sr="arg2" val="0" />
- </Event>
- </Profile>
- <Project sr="proj0" ve="2">
- <cdate>1789166400000</cdate>
- <name>Media Bar - Tasker V2.7</name>
- <pids>401,402,403</pids>
- <tids>501,502,503</tids>
- </Project>
- <Task sr="task501">
- <cdate>1789166400000</cdate>
- <edate>1789166400000</edate>
- <id>501</id>
- <nme>MB V2 - Media State</nme>
- <pri>100</pri>
- <rty>1</rty>
- <Action sr="act0" ve="7">
- <code>474</code>
- <se>false</se>
- <Str sr="arg0" ve="3">import android.content.ComponentName;
- import android.media.MediaMetadata;
- import android.media.session.MediaController;
- import android.media.session.MediaSessionManager;
- import android.media.session.PlaybackState;
- import android.os.SystemClock;
- String visualId = "media_bar_visual";
- String touchId = "media_bar_touch";
- String visualLayout = "{\"name\":\"Media Bar Visual\",\"root\":{\"type\":\"Box\",\"id\":\"root\",\"contentAlignment\":\"TopCenter\",\"modifiers\":[{\"type\":\"FillSize\"},{\"type\":\"Background\",\"color\":\"transparent\"}],\"children\":[{\"type\":\"ProgressBar\",\"id\":\"progress\",\"style\":\"Linear\",\"mode\":\"Determinate\",\"progress\":\"0\",\"minProgress\":\"0\",\"maxProgress\":\"1000\",\"color\":\"#FFFF6D00\",\"trackColor\":\"#22000000\",\"strokeCap\":\"Round\",\"animateChanges\":\"false\",\"modifiers\":[{\"type\":\"FillWidth\"},{\"type\":\"Size\",\"height\":\"4\"}]}]}}";
- String touchLayoutTemplate = "{\"name\":\"Media Bar Touch\",\"root\":{\"type\":\"Box\",\"id\":\"root\",\"contentAlignment\":\"TopCenter\",\"modifiers\":[{\"type\":\"FillSize\"},{\"type\":\"Background\",\"color\":\"transparent\"}],\"children\":[{\"type\":\"Slider\",\"id\":\"seek\",\"min\":\"0\",\"max\":\"1000\",\"steps\":\"0\",\"value\":\"__INITIAL__\",\"thumbColor\":\"#00000000\",\"activeTrackColor\":\"#00000000\",\"inactiveTrackColor\":\"#00000000\",\"activeTickColor\":\"#00000000\",\"inactiveTickColor\":\"#00000000\",\"sliderValueState\":{\"outputVariableBindings\":{\"value\":[\"MBSeekLive\"]}},\"modifiers\":[{\"type\":\"FillWidth\"},{\"type\":\"Size\",\"height\":\"28\"}]}]}}";
- Object nls = tasker.getNotificationListener();
- if (nls == null) {
- tasker.setVariable("MBPlaying", "false");
- if (tasker.isSceneV2Active(visualId)) tasker.dismissSceneV2(visualId);
- if (tasker.isSceneV2Active(touchId)) tasker.dismissSceneV2(touchId);
- return null;
- }
- MediaSessionManager msm = (MediaSessionManager) context.getSystemService("media_session");
- ComponentName listener = new ComponentName(context, nls.getClass());
- java.util.List controllers = msm.getActiveSessions(listener);
- MediaController controller = null;
- PlaybackState chosenState = null;
- MediaMetadata chosenMetadata = null;
- if (controllers != null) {
- for (int i = 0; i < controllers.size(); i++) {
- MediaController c = (MediaController) controllers.get(i);
- PlaybackState s = c.getPlaybackState();
- MediaMetadata m = c.getMetadata();
- if (s == null || m == null) continue;
- long duration = m.getLong(MediaMetadata.METADATA_KEY_DURATION);
- if (duration <= 0) continue;
- int st = s.getState();
- if (st == PlaybackState.STATE_PLAYING ||
- st == PlaybackState.STATE_BUFFERING ||
- st == PlaybackState.STATE_CONNECTING ||
- st == PlaybackState.STATE_FAST_FORWARDING ||
- st == PlaybackState.STATE_REWINDING) {
- controller = c;
- chosenState = s;
- chosenMetadata = m;
- break;
- }
- if (controller == null && st == PlaybackState.STATE_PAUSED) {
- controller = c;
- chosenState = s;
- chosenMetadata = m;
- }
- }
- }
- if (controller == null || chosenState == null || chosenMetadata == null) {
- tasker.setVariable("MBPlaying", "false");
- if (tasker.isSceneV2Active(visualId)) tasker.dismissSceneV2(visualId);
- if (tasker.isSceneV2Active(touchId)) tasker.dismissSceneV2(touchId);
- return null;
- }
- boolean playing =
- chosenState.getState() == PlaybackState.STATE_PLAYING ||
- chosenState.getState() == PlaybackState.STATE_BUFFERING ||
- chosenState.getState() == PlaybackState.STATE_CONNECTING ||
- chosenState.getState() == PlaybackState.STATE_FAST_FORWARDING ||
- chosenState.getState() == PlaybackState.STATE_REWINDING;
- tasker.setVariable("MBPlaying", playing ? "true" : "false");
- /*
- * Detect a REAL media-item change, rather than treating every playback-state
- * callback as a new track. We store only a numeric hash in Tasker so metadata
- * punctuation cannot break Java-code substitution.
- */
- String mediaId = chosenMetadata.getString(MediaMetadata.METADATA_KEY_MEDIA_ID);
- String title = chosenMetadata.getString(MediaMetadata.METADATA_KEY_TITLE);
- String artist = chosenMetadata.getString(MediaMetadata.METADATA_KEY_ARTIST);
- String pkg = controller.getPackageName();
- if (mediaId == null) mediaId = "";
- if (title == null) title = "";
- if (artist == null) artist = "";
- if (pkg == null) pkg = "";
- long duration = chosenMetadata.getLong(MediaMetadata.METADATA_KEY_DURATION);
- String fingerprint =
- pkg + "|" + mediaId + "|" + title + "|" + artist + "|" + duration;
- String newTrackHash = String.valueOf(fingerprint.hashCode());
- String oldTrackHash = "%MBTrackHash";
- boolean trackChanged =
- oldTrackHash == null ||
- oldTrackHash.startsWith("%") ||
- !newTrackHash.equals(oldTrackHash);
- if (trackChanged) {
- long now = SystemClock.elapsedRealtime();
- tasker.setVariable("MBTrackHash", newTrackHash);
- /*
- * Scene V2 can publish Slider binding values while it is being created
- * or recomposed. For the first 3 seconds of a new media item these are
- * NEVER allowed to seek the player.
- */
- tasker.setVariable(
- "MBSeekGuardUntil",
- String.valueOf(now + 3000)
- );
- /* Reset user-gesture detection state. */
- tasker.setVariable("MBLastRaw", "");
- tasker.setVariable("MBLastRawMs", "0");
- tasker.setVariable("MBScrubActiveUntil", "0");
- tasker.setVariable("MBLastScrubMs", "0");
- /*
- * Recreate only the invisible touch scene so its Slider starts at the
- * new track's own position rather than retaining the previous track's
- * last scrub position.
- */
- if (tasker.isSceneV2Active(touchId)) {
- tasker.dismissSceneV2(touchId);
- }
- }
- long durationForPosition = duration;
- long position = chosenState.getPosition();
- /*
- * IMPORTANT:
- * On a fresh track, some media apps report a stale lastPositionUpdateTime
- * while the new item is still buffering/initialising. Extrapolating here can
- * incorrectly make a brand-new track look several seconds old and, because
- * the Slider binding initialises from this value, can cause an unwanted seek.
- *
- * For the initial/media-state update use the player's reported position
- * directly. The normal 500 ms progress task handles smooth extrapolation later.
- */
- if (position < 0) position = 0;
- if (position > durationForPosition) position = durationForPosition;
- int progress = (int)Math.round(position * 1000.0 / durationForPosition);
- /*
- * Visible bar remains 91% wide, centred, matching V2.4.
- */
- if (!tasker.isSceneV2Active(visualId)) {
- tasker.showSceneV2(
- visualLayout,
- visualId,
- "Overlay",
- "50%",
- "0",
- "91%",
- "4",
- false,
- true,
- false
- );
- }
- /*
- * Full-width touch surface.
- * The visible bar starts 4.5% in from each edge, so convert the current
- * media progress back into the Slider's full-screen coordinate system:
- *
- * rawSlider = 45 + progress * 0.91
- *
- * That means a binding initialization lands on the CURRENT media position
- * instead of accidentally seeking to the beginning.
- */
- if (!tasker.isSceneV2Active(touchId)) {
- int initialRaw = (int)Math.round(45.0 + (progress * 0.91));
- if (initialRaw < 0) initialRaw = 0;
- if (initialRaw > 1000) initialRaw = 1000;
- String touchLayout = touchLayoutTemplate.replace(
- "__INITIAL__",
- String.valueOf(initialRaw)
- );
- /*
- * Remember the Slider's initial value for diagnostics only. Actual seek
- * permission is controlled by the new-track guard plus genuine-motion
- * detection in MB V2 - Live Scrub.
- */
- tasker.setVariable("MBSeekInitRaw", String.valueOf(initialRaw));
- tasker.showSceneV2(
- touchLayout,
- touchId,
- "Overlay",
- "50%",
- "0",
- "100%",
- "28",
- true,
- true,
- false
- );
- }
- tasker.updateSceneV2(
- "progress",
- "color",
- playing ? "#FFFF6D00" : "#999E9E9E",
- visualId
- );
- tasker.updateSceneV2(
- "progress",
- "progress",
- String.valueOf(progress),
- visualId
- );
- return progress;</Str>
- <Str sr="arg1" ve="3">%mb_state_result</Str>
- <Int sr="arg2" val="0" />
- </Action>
- </Task>
- <Task sr="task502">
- <cdate>1789166400000</cdate>
- <edate>1789166400000</edate>
- <id>502</id>
- <nme>MB V2 - Progress</nme>
- <pri>101</pri>
- <rty>1</rty>
- <Action sr="act0" ve="7">
- <code>474</code>
- <se>false</se>
- <Str sr="arg0" ve="3">import android.content.ComponentName;
- import android.media.MediaMetadata;
- import android.media.session.MediaController;
- import android.media.session.MediaSessionManager;
- import android.media.session.PlaybackState;
- import android.os.SystemClock;
- String visualId = "media_bar_visual";
- if (!tasker.isSceneV2Active(visualId)) return null;
- /* Yield to live finger feedback while the Slider is moving. */
- String lastRaw = "%MBLastScrubMs";
- if (lastRaw != null && !lastRaw.startsWith("%")) {
- try {
- long last = Long.parseLong(lastRaw);
- long now = SystemClock.elapsedRealtime();
- if (now - last < 650) return null;
- } catch (Throwable ignored) {}
- }
- Object nls = tasker.getNotificationListener();
- if (nls == null) return null;
- MediaSessionManager msm = (MediaSessionManager) context.getSystemService("media_session");
- ComponentName listener = new ComponentName(context, nls.getClass());
- java.util.List controllers = msm.getActiveSessions(listener);
- if (controllers == null || controllers.isEmpty()) return null;
- MediaController controller = null;
- PlaybackState state = null;
- MediaMetadata metadata = null;
- for (int i = 0; i < controllers.size(); i++) {
- MediaController c = (MediaController) controllers.get(i);
- PlaybackState s = c.getPlaybackState();
- MediaMetadata m = c.getMetadata();
- if (s == null || m == null) continue;
- if (m.getLong(MediaMetadata.METADATA_KEY_DURATION) <= 0) continue;
- if (s.getState() == PlaybackState.STATE_PLAYING) {
- controller = c;
- state = s;
- metadata = m;
- break;
- }
- }
- if (controller == null || state == null || metadata == null) return null;
- long duration = metadata.getLong(MediaMetadata.METADATA_KEY_DURATION);
- long position = state.getPosition();
- long elapsed = SystemClock.elapsedRealtime() - state.getLastPositionUpdateTime();
- /*
- * Tasker refreshes this every 500 ms, so there is no reason to extrapolate
- * many seconds from a potentially stale MediaSession timestamp.
- */
- if (elapsed < 0) elapsed = 0;
- if (elapsed > 1500) elapsed = 1500;
- position += (long)(elapsed * state.getPlaybackSpeed());
- if (position < 0) position = 0;
- if (position > duration) position = duration;
- int progress = (int)Math.round(position * 1000.0 / duration);
- tasker.updateSceneV2(
- "progress",
- "progress",
- String.valueOf(progress),
- visualId
- );
- return progress;</Str>
- <Str sr="arg1" ve="3">%mb_tick_result</Str>
- <Int sr="arg2" val="0" />
- </Action>
- </Task>
- <Task sr="task503">
- <cdate>1789166400000</cdate>
- <edate>1789166400000</edate>
- <id>503</id>
- <nme>MB V2 - Live Scrub</nme>
- <pri>110</pri>
- <rty>1</rty>
- <Action sr="act0" ve="7">
- <code>474</code>
- <se>false</se>
- <Str sr="arg0" ve="3">import android.content.ComponentName;
- import android.media.MediaMetadata;
- import android.media.session.MediaController;
- import android.media.session.MediaSessionManager;
- import android.media.session.PlaybackState;
- import android.os.SystemClock;
- /*
- * Scene V2 Slider outputVariableBindings writes the Slider's CURRENT value
- * directly to %MBSeekLive while the thumb/finger moves.
- */
- String rawText = "%MBSeekLive";
- if (rawText == null || rawText.length() == 0 || rawText.startsWith("%")) return null;
- double raw;
- try {
- raw = Double.parseDouble(rawText);
- } catch (Throwable e) {
- return null;
- }
- if (raw < 0) raw = 0;
- if (raw > 1000) raw = 1000;
- /*
- * IMPORTANT: %MBSeekLive is a Scene V2 output binding. Tasker can change it
- * for reasons other than a real finger drag (scene creation/recomposition).
- *
- * Therefore a single variable change is NEVER enough to seek media.
- * We first require a burst of changing values that looks like an actual drag.
- */
- long now = SystemClock.elapsedRealtime();
- /* Hard block all bound Slider emissions just after a real track change. */
- String guardText = "%MBSeekGuardUntil";
- try {
- if (guardText != null && !guardText.startsWith("%")) {
- long guardUntil = Long.parseLong(guardText);
- if (now < guardUntil) {
- tasker.setVariable("MBLastRaw", String.valueOf(raw));
- tasker.setVariable("MBLastRawMs", String.valueOf(now));
- return null;
- }
- }
- } catch (Throwable ignored) {}
- /* Read previous bound value and timing. */
- double lastRaw = raw;
- long lastRawMs = 0;
- long activeUntil = 0;
- boolean haveLast = false;
- String lastRawText = "%MBLastRaw";
- String lastMsText = "%MBLastRawMs";
- String activeText = "%MBScrubActiveUntil";
- try {
- if (lastRawText != null && !lastRawText.startsWith("%") &&
- lastRawText.length() > 0) {
- lastRaw = Double.parseDouble(lastRawText);
- haveLast = true;
- }
- } catch (Throwable ignored) {}
- try {
- if (lastMsText != null && !lastMsText.startsWith("%")) {
- lastRawMs = Long.parseLong(lastMsText);
- }
- } catch (Throwable ignored) {}
- try {
- if (activeText != null && !activeText.startsWith("%")) {
- activeUntil = Long.parseLong(activeText);
- }
- } catch (Throwable ignored) {}
- double movement = Math.abs(raw - lastRaw);
- long interval = now - lastRawMs;
- /*
- * A genuine drag produces multiple DIFFERENT Slider values rapidly.
- * An automatic initialization/recomposition normally produces a single value
- * or repeats the same value.
- */
- boolean movingNow =
- haveLast &&
- movement >= 2.0 &&
- interval >= 0 &&
- interval <= 700;
- boolean scrubActive = now < activeUntil;
- if (!scrubActive && movingNow) {
- scrubActive = true;
- activeUntil = now + 900;
- tasker.setVariable(
- "MBScrubActiveUntil",
- String.valueOf(activeUntil)
- );
- } else if (scrubActive && movement >= 1.0) {
- activeUntil = now + 900;
- tasker.setVariable(
- "MBScrubActiveUntil",
- String.valueOf(activeUntil)
- );
- }
- /* Always remember this sample for the next movement test. */
- tasker.setVariable("MBLastRaw", String.valueOf(raw));
- tasker.setVariable("MBLastRawMs", String.valueOf(now));
- /*
- * First sample after idle only arms the detector. Seeking/live feedback starts
- * from the next moving sample, usually just a few pixels later.
- */
- if (!scrubActive) return null;
- /*
- * The touch surface is 100% of the display, but the visible bar is only 91%
- * wide with a 4.5% inset on each side.
- *
- * Convert full-screen finger X into the visible media range:
- * 0..45 -> 0%
- * 45..955 -> 0..100%
- * 955..1000 -> 100%
- */
- double mapped = (raw - 45.0) * 1000.0 / 910.0;
- if (mapped < 0) mapped = 0;
- if (mapped > 1000) mapped = 1000;
- int progress = (int)Math.round(mapped);
- /*
- * Mark this as live scrubbing so the normal playback tick temporarily yields.
- */
- tasker.setVariable(
- "MBLastScrubMs",
- String.valueOf(now)
- );
- /*
- * VISUAL FEEDBACK FIRST: the bar moves to the current finger position before
- * waiting for the media app to process seekTo().
- */
- if (tasker.isSceneV2Active("media_bar_visual")) {
- tasker.updateSceneV2(
- "progress",
- "progress",
- String.valueOf(progress),
- "media_bar_visual"
- );
- }
- Object nls = tasker.getNotificationListener();
- if (nls == null) return progress;
- MediaSessionManager msm = (MediaSessionManager) context.getSystemService("media_session");
- ComponentName listener = new ComponentName(context, nls.getClass());
- java.util.List controllers = msm.getActiveSessions(listener);
- if (controllers == null || controllers.isEmpty()) return progress;
- MediaController controller = null;
- MediaMetadata metadata = null;
- for (int i = 0; i < controllers.size(); i++) {
- MediaController c = (MediaController) controllers.get(i);
- PlaybackState s = c.getPlaybackState();
- MediaMetadata m = c.getMetadata();
- if (s == null || m == null) continue;
- long duration = m.getLong(MediaMetadata.METADATA_KEY_DURATION);
- if (duration <= 0) continue;
- int st = s.getState();
- if (st == PlaybackState.STATE_PLAYING) {
- controller = c;
- metadata = m;
- break;
- }
- if (controller == null && st == PlaybackState.STATE_PAUSED) {
- controller = c;
- metadata = m;
- }
- }
- if (controller == null || metadata == null) return progress;
- long duration = metadata.getLong(MediaMetadata.METADATA_KEY_DURATION);
- long target = (long)Math.round(duration * mapped / 1000.0);
- controller.getTransportControls().seekTo(target);
- return target;</Str>
- <Str sr="arg1" ve="3">%mb_live_scrub_result</Str>
- <Int sr="arg2" val="0" />
- </Action>
- </Task>
- </TaskerData>
Advertisement
Add Comment
Please, Sign In to add comment