mirror of
https://github.com/A-Star100/simpliplay-desktop.git
synced 2025-09-17 22:29:38 +00:00
Compare commits
No commits in common. "main" and "release-2.0.6.0" have entirely different histories.
main
...
release-2.
@ -26,5 +26,5 @@ ___
|
||||
Read the docs ([Electron - Tutorial](https://www.electronjs.org/docs/latest/tutorial/tutorial-prerequisites), [Neutralinojs - Your First App](https://neutralino.js.org/docs/getting-started/your-first-neutralinojs-app), [NW.js - Getting Started (For Users)](https://nwjs.readthedocs.io/en/latest/For%20Users/Getting%20Started/#write-nwjs-app))
|
||||
|
||||
## Mirrors
|
||||
Self-hosted mirror available [here](https://new-git.anirudhsevugan.me/anirudh/simpliplay-desktop/src/branch/main/).
|
||||
**The server may not always be up. If it isn't, you can contact me at: (personal at anirudhsevugan dot me)**.
|
||||
Self-hosted mirror available [here](https://git.anirudhsevugan.me/simpliplay/simpliplay-desktop-mirror).
|
||||
**The server may not always be up. You'll see a screen saying "Git is down" if the server is down, with a link to contact me (the webmaster)**.
|
||||
|
@ -1,11 +1 @@
|
||||
Source code for SimpliPlay.
|
||||
|
||||
--BUILD STUFF--
|
||||
SimpliPlay uses Electron Builder for desktop builds, but includes an example Electron Forge config that will work as expected but does not support native actions such as file picking from the explorer; the package.json uses electron-builder specific actions for that.
|
||||
|
||||
--CI/CD--
|
||||
We now use CI/CD (specifically GitHub Actions, at one point CircleCI) for builds, but Linux ARM64 snaps in particular were annoying to get started with. After multiple attempts, it finally worked as expected (with a few really stupid workarounds required that shouldn't even be needed).
|
||||
|
||||
--DEPENDENCIES--
|
||||
Other than Electron and Electron Builder, there is one more dependency called "Nothing".
|
||||
Its name is very self explanatory, isn't it?
|
||||
|
BIN
simpliplay/dmg-background.png
Normal file
BIN
simpliplay/dmg-background.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 76 KiB |
@ -6,7 +6,7 @@ const { pathToFileURL } = require("url");
|
||||
const { checkForUpdate } = require('./updateChecker');
|
||||
let gpuAccel = "";
|
||||
let didRegisterShortcuts = false;
|
||||
let version = "2.1.3.0"
|
||||
let version = "2.0.6.0"
|
||||
|
||||
if (process.platform === 'darwin') {
|
||||
if (process.argv.includes('--use-gl')) {
|
||||
|
@ -6,7 +6,7 @@ const { pathToFileURL } = require("url");
|
||||
const { checkForUpdate } = require('./updateChecker');
|
||||
let gpuAccel = "";
|
||||
let didRegisterShortcuts = false;
|
||||
let version = "2.1.4.0"
|
||||
let version = "2.0.6.0"
|
||||
|
||||
if (process.platform === 'darwin') {
|
||||
if (process.argv.includes('--use-gl')) {
|
||||
@ -321,14 +321,6 @@ addonsMenu.append(new MenuItem({
|
||||
}
|
||||
}));
|
||||
|
||||
// "Store" menu item (info dialog version)
|
||||
addonsMenu.append(new MenuItem({
|
||||
label: 'Store',
|
||||
click: () => {
|
||||
shell.openExternal("https://simpliplay.netlify.app/addons/")
|
||||
}
|
||||
}));
|
||||
|
||||
// Add the Add-ons menu only once here:
|
||||
newMenuItems.push(new MenuItem({ label: 'Add-ons', submenu: addonsMenu }));
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "SimpliPlay",
|
||||
"version": "2.1.4",
|
||||
"version": "2.0.6",
|
||||
"description": "SimpliPlay - The mission to make media playback accessible on every device, anywhere, anytime.",
|
||||
"main": "./main.js",
|
||||
"scripts": {
|
||||
@ -92,11 +92,6 @@
|
||||
"name": "FLAC Audio",
|
||||
"role": "Viewer"
|
||||
},
|
||||
{
|
||||
"ext": "opus",
|
||||
"name": "Opus Audio",
|
||||
"role": "Viewer"
|
||||
},
|
||||
{
|
||||
"ext": "mkv",
|
||||
"name": "MKV Video",
|
||||
@ -118,7 +113,7 @@
|
||||
"allowToChangeInstallationDirectory": true
|
||||
},
|
||||
"devDependencies": {
|
||||
"electron": "^38.1.0",
|
||||
"electron": "^37.3.1",
|
||||
"electron-builder": "^26.0.12"
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "SimpliPlay",
|
||||
"version": "2.1.4",
|
||||
"version": "2.0.6",
|
||||
"description": "The mission to make media playback accessible on every platform, anywhere, anytime.",
|
||||
"main": "./main.js",
|
||||
"scripts": {
|
||||
@ -23,13 +23,6 @@
|
||||
"summary": "A cross-platform, simple media player.",
|
||||
"description": "The mission to make media playback accessible on every platform, anywhere, anytime."
|
||||
},
|
||||
"nsis": {
|
||||
"oneClick": false,
|
||||
"installerIcon": "icon.ico",
|
||||
"uninstallerIcon": "icon.ico",
|
||||
"uninstallDisplayName": "simpliplay-uninstaller",
|
||||
"allowToChangeInstallationDirectory": true
|
||||
},
|
||||
"mac": {
|
||||
"target": [
|
||||
"dmg"
|
||||
@ -105,11 +98,6 @@
|
||||
"name": "FLAC Audio",
|
||||
"role": "Viewer"
|
||||
},
|
||||
{
|
||||
"ext": "opus",
|
||||
"name": "Opus Audio",
|
||||
"role": "Viewer"
|
||||
},
|
||||
{
|
||||
"ext": "mkv",
|
||||
"name": "MKV Video",
|
||||
@ -122,8 +110,16 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"nsis": {
|
||||
"oneClick": false,
|
||||
"installerIcon": "icon.ico",
|
||||
"uninstallerIcon": "icon.ico",
|
||||
"uninstallDisplayName": "simpliplay-uninstaller",
|
||||
"license": "LICENSE.md",
|
||||
"allowToChangeInstallationDirectory": true
|
||||
},
|
||||
"devDependencies": {
|
||||
"electron": "^38.1.0",
|
||||
"electron": "^37.3.1",
|
||||
"electron-builder": "^26.0.12"
|
||||
}
|
||||
}
|
||||
|
@ -66,13 +66,9 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
});
|
||||
|
||||
async function addSubtitles(url) {
|
||||
// Remove existing tracks and revoke any previous blob URLs
|
||||
// Remove existing tracks
|
||||
const existingTracks = mediaPlayer.getElementsByTagName('track');
|
||||
for (let i = existingTracks.length - 1; i >= 0; i--) {
|
||||
const track = existingTracks[i];
|
||||
if (track.src.startsWith('blob:')) URL.revokeObjectURL(track.src);
|
||||
track.remove();
|
||||
}
|
||||
for (let track of existingTracks) track.remove();
|
||||
|
||||
// Fetch subtitle content
|
||||
let text = '';
|
||||
@ -88,28 +84,26 @@ async function addSubtitles(url) {
|
||||
const firstLine = text.split(/\r?\n/)[0].trim();
|
||||
const format = firstLine.startsWith('WEBVTT') || url.toLowerCase().endsWith('.vtt') ? 'vtt' : 'srt';
|
||||
|
||||
// Determine track source
|
||||
let trackSrc = url;
|
||||
// Convert SRT → VTT if needed
|
||||
if (format === 'srt') {
|
||||
// Convert SRT → VTT
|
||||
text = 'WEBVTT\n\n' + text
|
||||
.replace(/\r+/g, '')
|
||||
.replace(/^\s+|\s+$/g, '')
|
||||
.split('\n')
|
||||
.map(line => line.replace(/(\d+):(\d+):(\d+),(\d+)/g, '$1:$2:$3.$4'))
|
||||
.join('\n');
|
||||
|
||||
// Create Blob URL for converted subtitles
|
||||
const blob = new Blob([text], { type: 'text/vtt' });
|
||||
trackSrc = URL.createObjectURL(blob);
|
||||
}
|
||||
|
||||
// Create Blob URL
|
||||
const blob = new Blob([text], { type: 'text/vtt' });
|
||||
const blobUrl = URL.createObjectURL(blob);
|
||||
|
||||
// Create and append track
|
||||
const track = document.createElement('track');
|
||||
track.kind = 'subtitles';
|
||||
track.label = 'English';
|
||||
track.srclang = 'en';
|
||||
track.src = trackSrc;
|
||||
track.src = blobUrl;
|
||||
track.default = true;
|
||||
mediaPlayer.appendChild(track);
|
||||
|
||||
@ -117,11 +111,10 @@ async function addSubtitles(url) {
|
||||
setTimeout(() => {
|
||||
for (let t of mediaPlayer.textTracks) t.mode = 'disabled';
|
||||
track.track.mode = 'showing';
|
||||
}, 50);
|
||||
}, 50); // slight delay ensures the browser registers it
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*// Handle submit subtitle URL
|
||||
function clearSubtitles() {
|
||||
const tracks = mediaPlayer.getElementsByTagName('track');
|
||||
@ -130,18 +123,14 @@ function clearSubtitles() {
|
||||
}
|
||||
}*/
|
||||
|
||||
// Handle submit subtitle URL
|
||||
function clearSubtitles() {
|
||||
const tracks = mediaPlayer.getElementsByTagName('track');
|
||||
for (let i = tracks.length - 1; i >= 0; i--) {
|
||||
const track = tracks[i];
|
||||
if (track.src.startsWith('blob:')) {
|
||||
URL.revokeObjectURL(track.src); // free memory leaks from SRT to VTT converted subtitles
|
||||
}
|
||||
track.remove();
|
||||
tracks[i].remove();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Use this function when a new video is loaded
|
||||
|
||||
submitSubtitlesBtn.addEventListener('click', () => {
|
||||
@ -272,7 +261,6 @@ const { isHLS, isDASH } = await detectStreamType(url);
|
||||
|
||||
|
||||
let previousObjectURL = null; // Store the last Object URL
|
||||
window.objectURL = previousObjectURL
|
||||
|
||||
fileInput.addEventListener('change', (event) => {
|
||||
if (hls !== null) {
|
||||
@ -293,13 +281,7 @@ const { isHLS, isDASH } = await detectStreamType(url);
|
||||
// Revoke the previous Object URL if it exists
|
||||
if (previousObjectURL) {
|
||||
URL.revokeObjectURL(previousObjectURL);
|
||||
window.objectURL = previousObjectURL
|
||||
}
|
||||
|
||||
// Revoke previous file picker Object URL
|
||||
if (window.previousDropURL) {
|
||||
URL.revokeObjectURL(window.previousDropURL);
|
||||
}
|
||||
|
||||
// Create a new Object URL for the selected file
|
||||
const fileURL = URL.createObjectURL(file);
|
||||
@ -311,7 +293,6 @@ const { isHLS, isDASH } = await detectStreamType(url);
|
||||
|
||||
// Store the new Object URL for future cleanup
|
||||
previousObjectURL = fileURL;
|
||||
fileInput.value = "";
|
||||
|
||||
// Hide dialog after selecting a file
|
||||
dialogOverlay.style.display = 'none';
|
||||
|
@ -16,103 +16,6 @@ function loadMedia(fileURL) {
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener('DOMContentLoaded', () => {
|
||||
const dropArea = document.createElement('div');
|
||||
dropArea.style.position = 'fixed';
|
||||
dropArea.style.top = '0';
|
||||
dropArea.style.left = '0';
|
||||
dropArea.style.width = '100vw';
|
||||
dropArea.style.height = '100vh';
|
||||
dropArea.style.display = 'none'; // hidden by default
|
||||
dropArea.style.zIndex = '0'; // behind everything
|
||||
dropArea.style.opacity = '0'; // invisible
|
||||
document.body.appendChild(dropArea);
|
||||
|
||||
let dragCounter = 0; // track nested dragenter/dragleave events
|
||||
|
||||
|
||||
window.addEventListener('dragenter', (e) => {
|
||||
if (e.dataTransfer.types.includes('Files')) {
|
||||
dragCounter++;
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}
|
||||
});
|
||||
|
||||
window.addEventListener('dragleave', (e) => {
|
||||
if (e.dataTransfer.types.includes('Files')) {
|
||||
dragCounter--;
|
||||
if (dragCounter <= 0) dragCounter = 0;
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}
|
||||
});
|
||||
|
||||
window.addEventListener('dragover', (e) => {
|
||||
if (e.dataTransfer.types.includes('Files')) {
|
||||
e.preventDefault(); // allow drop
|
||||
e.stopPropagation();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
let previousDropURL = null; // Store last Object URL
|
||||
window.previousDropURL = previousDropURL
|
||||
|
||||
window.addEventListener('drop', e => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
const file = e.dataTransfer.files[0];
|
||||
if (!file) return;
|
||||
|
||||
// Destroy existing HLS/DASH instances if they exist
|
||||
if (window.hls) {
|
||||
window.hls.destroy();
|
||||
window.hls = null;
|
||||
}
|
||||
if (window.dash) {
|
||||
window.dash.reset();
|
||||
window.dash = null;
|
||||
}
|
||||
|
||||
// Clear previously loaded subtitles
|
||||
const tracks = mediaElement.getElementsByTagName('track');
|
||||
for (let i = tracks.length - 1; i >= 0; i--) {
|
||||
tracks[i].remove();
|
||||
}
|
||||
|
||||
// Revoke previous Object URL
|
||||
if (previousDropURL) {
|
||||
URL.revokeObjectURL(previousDropURL);
|
||||
window.previousDropURL = previousDropURL;
|
||||
}
|
||||
|
||||
// Revoke previous file picker Object URL
|
||||
if (window.objectURL) {
|
||||
URL.revokeObjectURL(window.objectURL);
|
||||
}
|
||||
|
||||
// Create a new Object URL
|
||||
const fileURL = URL.createObjectURL(file);
|
||||
mediaElement.src = fileURL;
|
||||
|
||||
mediaElement.load();
|
||||
// Autoplay if checkbox is checked
|
||||
if (autoplayCheckbox.checked) {
|
||||
mediaElement.play().catch(err => console.warn(err));
|
||||
}
|
||||
|
||||
// Store for future cleanup
|
||||
previousDropURL = fileURL;
|
||||
|
||||
// Hide file dialog if applicable
|
||||
if (dialogOverlay) dialogOverlay.style.display = 'none';
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
|
||||
// Handle submit subtitle URL
|
||||
function clearSubtitles() {
|
||||
const tracks = mediaElement.getElementsByTagName('track');
|
||||
@ -194,7 +97,3 @@ window.electron.receive("unload-addon", (fileURL) => {
|
||||
unloadAddon(fileURL);
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user