Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Buffering #38

Merged
merged 7 commits into from
Feb 15, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
adding buffered indicator to skeleton theme
  • Loading branch information
tomhazledine committed Feb 15, 2024
commit a524b2af6d775838aa2f37274d2be982c10326c3
18 changes: 10 additions & 8 deletions src/js/Picobel.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { parseOptions } from "./core/setup";
import { findAudio, getRawData } from "./core/data";
import { findAudio, getRawData, pollForLoadingStatus } from "./core/data";
import { generateMarkup, elementHooks } from "./markup";
import { _setupLocalListeners } from "./core/events";
import { canplaythrough } from "./core/audio-functions";
import { loadedmetadata } from "./core/audio-functions";

/**
* ---------------------------------------------------------------------------
Expand Down Expand Up @@ -74,15 +74,17 @@ export const picobel = (rawOptions = {}) => {
// Setup event listeners
state.audioNodes = _setupLocalListeners(state.audioNodes);

const intervalState = {};

// Check status
state.audioNodes.forEach(node => {
state.audioNodes.forEach((node, i) => {
const { readyState } = node;
if (readyState === 4) {
canplaythrough(node);
if (readyState >= 1) {
loadedmetadata(node);
}

pollForLoadingStatus(node, intervalState);
});

return {
state
};
return { state };
};
22 changes: 17 additions & 5 deletions src/js/core/audio-functions.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,16 +55,20 @@ export const updateProgress = node => {
stop(node);
}
let progressPercent = ((progress / duration) * 100).toFixed(2);
``;
if (node.elements.progressBar) {
node.elements.progressBar.value = progressPercent;
node.elements.indicator.style.width = progressPercent + "%";
node.elements.playhead.style.left = progressPercent + "%";
if (node.elements.progressRange) {
node.elements.progressRange.value = progressPercent;
node.elements.progressIndicator.style.width = progressPercent + "%";
node.elements.progressPlayhead.style.left = progressPercent + "%";
}
};

export const canplaythrough = node => {
setLengthDisplay(node);
// setBuffered(node, node.duration);
loadedmetadata(node);
};

export const loadedmetadata = node => {
node.elements.wrapper.classList.remove("loading");
let meta = getMeta(node);
setMeta(meta, node.elements);
Expand Down Expand Up @@ -141,3 +145,11 @@ export const mute = node => {
button.innerHTML = "Mute";
}
};

export const setBuffered = (node, buffered) => {
const duration = node.duration;
let bufferedPercent = ((buffered / duration) * 100).toFixed(2);
if (node.elements.progressBackground) {
node.elements.progressBackground.style.width = bufferedPercent + "%";
}
};
55 changes: 52 additions & 3 deletions src/js/core/data.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { getFileType, getFileName } from "../utils/helpers";
import { errors, setBuffered } from "./audio-functions";

// Return an array of all the <audio> elements found on the page.
export const findAudio = context => {
// Get all the <audio> occurrences in the page.
let audioElements = context.getElementsByTagName("audio");
const audioElements = context.getElementsByTagName("audio");
// Save our audioElements as an array (so we can manipulate the DOM but
// still access our items).
let items = [].slice.call(audioElements);
return items;
return [...audioElements];
};

// Build an array of classes to add to each new "player" element
Expand Down Expand Up @@ -46,3 +46,52 @@ export const getMeta = item => {
}
return meta;
};

export const checkURL = async url => {
try {
const response = await fetch(url);
console.log({ url, response });
return response.ok; // URL is valid and reachable
} catch (error) {
console.error(error.message);
// Handle the error accordingly (e.g., set an error state or use a fallback URL)
return null; // Indicate failure
}
};

export const pollForLoadingStatus = async (node, intervalState) => {
const interval = 1000; // Poll every 1000 milliseconds (1 second)
let isFullyBuffered = false; // Flag to track buffering status
let checks = 0;
const maxChecks = 15;

const checkBufferedStatus = () => {
checks++;
// Assuming there's at least one range buffered
if (node.buffered.length > 0) {
const bufferedEnd = node.buffered.end(node.buffered.length - 1);
const duration = node.duration;

setBuffered(node, bufferedEnd);

// Check if the audio is fully buffered
if (bufferedEnd >= duration) {
isFullyBuffered = true;
// If fully buffered, clear the interval
clearInterval(intervalState[node.currentSrc]);
}
}
if (checks >= maxChecks && node.buffered.length <= 0) {
errors(node);
clearInterval(intervalState[node.currentSrc]);
}
};

// Set up the interval to check buffering status
intervalState[node.currentSrc] = setInterval(checkBufferedStatus, interval);

// Optional: Clear interval on page unload or when no longer needed to avoid memory leaks
window.addEventListener("unload", () =>
clearInterval(intervalState[node.currentSrc])
);
};
17 changes: 11 additions & 6 deletions src/js/core/events.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ export const _setupLocalListeners = nodes => {
() => PicobelAudio.canplaythrough(node),
false
);
node.addEventListener(
"loadedmetadata",
() => PicobelAudio.loadedmetadata(node),
false
);
node.addEventListener("error", () => PicobelAudio.errors(node), false);

// DOM interaction event listeners
Expand All @@ -23,22 +28,22 @@ export const _setupLocalListeners = nodes => {
false
);
}
if (node.elements.progressBar) {
node.elements.progressBar.addEventListener(
if (node.elements.progressRange) {
node.elements.progressRange.addEventListener(
"input",
e => PicobelAudio.sliderScrub(e, node),
false
);
}
if (node.elements.progressBar) {
node.elements.progressBar.addEventListener(
if (node.elements.progressRange) {
node.elements.progressRange.addEventListener(
"focus",
() => PicobelAudio.sliderFocus(node, true),
false
);
}
if (node.elements.progressBar) {
node.elements.progressBar.addEventListener(
if (node.elements.progressRange) {
node.elements.progressRange.addEventListener(
"blur",
() => PicobelAudio.sliderFocus(node, false),
false
Expand Down
9 changes: 6 additions & 3 deletions src/js/markup/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,13 +69,16 @@ export const elementHooks = (nodes, context, namespace) =>
progressWrapper: wrapper.querySelector(
`.${namespace}__progress-slider__replacement`
),
progressBar: wrapper.querySelector(
progressRange: wrapper.querySelector(
`.${namespace}__progress-slider__range`
),
playhead: wrapper.querySelector(
progressPlayhead: wrapper.querySelector(
`.${namespace}__progress-slider__playhead`
),
indicator: wrapper.querySelector(
progressBackground: wrapper.querySelector(
`.${namespace}__progress-slider__background`
),
progressIndicator: wrapper.querySelector(
`.${namespace}__progress-slider__indicator`
),
volumeWrapper: wrapper.querySelector(
Expand Down