Skip to content

Commit 9851353

Browse files
committed
output audio switcher
1 parent f5b711c commit 9851353

File tree

2 files changed

+154
-75
lines changed

2 files changed

+154
-75
lines changed

scripts/changeAudioOutput.css

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
.ufs-change-audio-output {
2+
width: 320px;
3+
height: 120px;
4+
position: fixed;
5+
left: 50%;
6+
top: 50%;
7+
transform: translate(-50%, -50%);
8+
9+
background-color: #fff;
10+
border: 1px solid rgba(0, 0, 0, .08);
11+
border-radius: 5px;
12+
z-Index: 999999;
13+
}
14+
15+
.ufs-change-audio-output .navbar {
16+
width: 100%;
17+
height: 28px;
18+
background-color: rgba(0, 0, 0, .05);
19+
}
20+
21+
.ufs-change-audio-output .close-btn {
22+
padding: 6px 8px;
23+
background-color: transparent;
24+
color: black;
25+
position: absolute;
26+
right: 0;
27+
top: 0;
28+
border: none;
29+
cursor: pointer;
30+
}
31+
32+
.ufs-change-audio-output .close-btn:hover {
33+
background-color: #e74c3c;
34+
color: white;
35+
}
36+
37+
.ufs-change-audio-output .title {
38+
font-size: 12px;
39+
position: absolute;
40+
left: 6px;
41+
top: 8px;
42+
}
43+
44+
.ufs-change-audio-output .title-link {
45+
font-weight: 500;
46+
text-decoration: none;
47+
}
48+
49+
.ufs-change-audio-output .popup-content {
50+
height: 92px;
51+
display: relative;
52+
width: 100%;
53+
}
54+
55+
.ufs-change-audio-output .bottom-area {
56+
position: absolute;
57+
left: 10px;
58+
right: 10px;
59+
bottom: 10px;
60+
}
61+
62+
.ufs-change-audio-output .submit-btn {
63+
background-color: #3498db;
64+
color: #FFF;
65+
width: 100%;
66+
padding: 6px;
67+
border: none;
68+
border-radius: 3px;
69+
cursor: pointer;
70+
}
71+
72+
.ufs-change-audio-output .submit-btn:disabled {
73+
background-color: #999;
74+
}
75+
76+
.ufs-change-audio-output .submit-btn:hover:not(:disabled) {
77+
background-color: #2a7bb1;
78+
}
79+
80+
.ufs-change-audio-output .device-selector {
81+
margin: 10px;
82+
padding: 5px;
83+
width: calc(100% - 20px);
84+
}

scripts/changeAudioOutput.js

Lines changed: 70 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -1,105 +1,110 @@
11
export default {
2-
icon: "",
2+
icon: '<i class="fa-solid fa-headphones fa-lg"></i>',
33
name: {
4-
en: "",
5-
vi: "",
4+
en: "Audio output switcher",
5+
vi: "Thay đổi đầu ra âm thanh",
66
},
77
description: {
8-
en: "",
9-
vi: "",
8+
en: "Pick a default audio output device, customizable for each browser tab.",
9+
vi: "Thay đổi đầu ra âm thanh của trang web đang mở.\nMỗi tab có thể chọn đầu ra khác nhau (tai nghe/loa).",
1010
},
1111

1212
// Fb Post: https://www.facebook.com/groups/j2team.community/posts/1362716140727169
1313
// Source: https://gist.github.com/monokaijs/44ef4bd0770f83272b83c038a2769c90
1414
onClick: async () => {
15-
await navigator.mediaDevices.getUserMedia({ audio: true, video: true });
15+
let key = "ufs-audio-output-switcher";
16+
let exist = document.querySelector("#" + key);
17+
if (exist) {
18+
exist.style.display = "";
19+
return;
20+
}
21+
22+
if (
23+
!confirm(
24+
"Vui lòng cho phép truy cập audio/video để chức năng có thể chạy."
25+
)
26+
)
27+
return;
28+
29+
function disableBtn(btn, disable = true) {
30+
if (disable) {
31+
btn.classList.add("disabled");
32+
btn.disabled = true;
33+
} else {
34+
btn.classList.remove("disabled");
35+
btn.disabled = false;
36+
}
37+
}
38+
1639
let popupParent = document.createElement("div");
17-
/* positioning for the dialog */
18-
popupParent.style.width = "320px";
19-
popupParent.style.height = "120px";
20-
popupParent.style.position = "fixed";
21-
popupParent.style.left = "50%";
22-
popupParent.style.top = "50%";
23-
popupParent.style.marginLeft = "-160px";
24-
popupParent.style.marginTop = "-60px";
25-
/* stylizing the dialog */
26-
popupParent.style.backgroundColor = "#fff";
27-
popupParent.style.border = "1px solid rgba(0, 0, 0, .08)";
28-
popupParent.style.zIndex = "999999";
40+
popupParent.id = key;
41+
popupParent.className = "ufs-change-audio-output";
2942

3043
/* navigation bar */
3144
let navbar = document.createElement("div");
32-
navbar.style.width = "100%";
33-
navbar.style.height = "28px";
34-
navbar.style.backgroundColor = "rgba(0, 0, 0, .05)";
45+
navbar.className = "navbar";
3546

3647
let closeButton = document.createElement("button");
48+
closeButton.className = "close-btn";
3749
closeButton.innerText = "Close";
38-
closeButton.style.padding = "6px 8px";
39-
closeButton.style.backgroundColor = "transparent";
40-
closeButton.style.color = "black";
41-
closeButton.style.position = "absolute";
42-
closeButton.style.right = "0";
43-
closeButton.style.top = "0";
44-
closeButton.style.border = "none";
45-
46-
navbar.appendChild(closeButton);
47-
4850
closeButton.onclick = function (e) {
49-
popupParent.parentNode.removeChild(popupParent);
50-
};
51-
closeButton.onmouseover = function (e) {
52-
e.target.style.backgroundColor = "#e74c3c";
53-
e.target.style.color = "white";
54-
};
55-
closeButton.onmouseleave = function (e) {
56-
e.target.style.backgroundColor = "transparent";
57-
e.target.style.color = "black";
51+
popupParent.style.display = "none";
5852
};
53+
navbar.appendChild(closeButton);
5954

6055
/* PLEASE DO NOT REMOVE CREDIT LINE */
6156
let popupTitle = document.createElement("div");
57+
popupTitle.className = "title";
6258
popupTitle.innerHTML =
6359
"SoundSwitcher - by <a href='https://north.studio' target='_blank'>NorthStudio</a>";
64-
popupTitle.style.fontSize = "12px";
65-
popupTitle.style.position = "absolute";
66-
popupTitle.style.left = "6px";
67-
popupTitle.style.top = "8px";
6860
navbar.appendChild(popupTitle);
6961

7062
let titleLink = popupTitle.querySelector("a");
71-
titleLink.style.fontWeight = "500";
72-
titleLink.style.textDecoration = "none";
63+
titleLink.className = "title-link";
7364

7465
let popupContent = document.createElement("div");
75-
popupContent.style.height = "92px";
76-
popupContent.style.display = "relative";
77-
popupContent.style.width = "100%";
66+
popupContent.className = "popup-content";
7867

7968
let bottomArea = document.createElement("div");
80-
bottomArea.style.position = "absolute";
81-
bottomArea.style.left = "10px";
82-
bottomArea.style.right = "10px";
83-
bottomArea.style.bottom = "10px";
69+
bottomArea.className = "bottom-area";
8470

8571
let submitButton = document.createElement("button");
86-
submitButton.style.backgroundColor = "#3498db";
87-
submitButton.style.color = "#FFF";
88-
submitButton.style.width = "100%";
89-
submitButton.style.padding = "6px";
90-
submitButton.style.border = "none";
91-
submitButton.style.borderRadius = "3px";
92-
submitButton.innerText = "Set Device";
93-
94-
submitButton.onclick = function (e) {
95-
document.querySelectorAll("audio,video").forEach((el) => {
96-
el.setSinkId(deviceSelector.value);
97-
});
72+
submitButton.className = "submit-btn";
73+
submitButton.innerText = "Waiting for permission...";
74+
disableBtn(submitButton);
75+
76+
submitButton.onclick = async function (e) {
77+
if (submitButton.disabled) return;
78+
79+
submitButton.innerText = "Setting...";
80+
disableBtn(submitButton);
81+
for (let el of Array.from(document.querySelectorAll("audio,video"))) {
82+
await el.setSinkId(deviceSelector.value);
83+
}
84+
submitButton.innerText = "Set Device";
85+
disableBtn(submitButton, false);
9886
};
9987

10088
bottomArea.appendChild(submitButton);
10189

10290
let deviceSelector = document.createElement("select");
91+
deviceSelector.className = "device-selector";
92+
93+
popupContent.appendChild(bottomArea);
94+
popupParent.appendChild(navbar);
95+
popupParent.appendChild(popupContent);
96+
document.body.appendChild(popupParent);
97+
UsefulScriptGlobalPageContext.DOM.injectCssFile(
98+
await UsefulScriptGlobalPageContext.Extension.getURL(
99+
"scripts/changeAudioOutput.css"
100+
)
101+
);
102+
103+
// ====================== Main ======================
104+
await navigator.mediaDevices.getUserMedia({ audio: true, video: true });
105+
submitButton.innerText = "Set Device";
106+
disableBtn(submitButton, false);
107+
103108
navigator.mediaDevices.enumerateDevices().then((devices) => {
104109
devices = devices.filter((x) => x.kind === "audiooutput");
105110
devices.forEach((device) => {
@@ -110,15 +115,5 @@ export default {
110115
});
111116
popupContent.appendChild(deviceSelector);
112117
});
113-
114-
deviceSelector.style.margin = "10px";
115-
deviceSelector.style.padding = "5px";
116-
deviceSelector.style.width = "calc(100% - 20px)";
117-
118-
popupContent.appendChild(bottomArea);
119-
120-
popupParent.appendChild(navbar);
121-
popupParent.appendChild(popupContent);
122-
document.body.appendChild(popupParent);
123118
},
124119
};

0 commit comments

Comments
 (0)