Source: modalPlayback.js

  1. "use strict";
  2. // SPDX-License-Identifier: GPL-3.0-or-later
  3. // myMPD (c) 2018-2025 Juergen Mang <mail@jcgames.de>
  4. // https://github.com/jcorporation/mympd
  5. /** @module modalPlayback_js */
  6. /**
  7. * Initialization function for the playback settings elements
  8. * @returns {void}
  9. */
  10. function initModalSettingsPlayback() {
  11. // cache for the form field containers
  12. const forms = {};
  13. // create the fields
  14. createForm(settingsPlaybackFields, 'modalPlayback', forms);
  15. initElements(elGetById('modalPlayback'));
  16. uiElements.modalPlaybackJukeboxCollapse = BSN.Collapse.getInstance(elGetById('modalPlaybackJukeboxCollapse'));
  17. elGetById('modalPlaybackJukeboxModeGroup').addEventListener('mouseup', function() {
  18. setTimeout(function() {
  19. toggleJukeboxSettings();
  20. checkConsume();
  21. }, 100);
  22. });
  23. elGetById('modalPlaybackConsumeGroup').addEventListener('mouseup', function() {
  24. setTimeout(function() {
  25. checkConsume();
  26. }, 100);
  27. });
  28. elGetById('modalPlaybackPresetsList').addEventListener('click', function(event) {
  29. event.stopPropagation();
  30. event.preventDefault();
  31. if (event.target.nodeName === 'TD') {
  32. if (event.target.parentNode.classList.contains('not-clickable') === false) {
  33. // @ts-ignore
  34. btnWaiting(event.target, true);
  35. applyPreset(getData(event.target.parentNode, 'name'));
  36. }
  37. }
  38. else if (event.target.nodeName === 'A') {
  39. deletePreset(event.target, getData(event.target.parentNode.parentNode, 'name'));
  40. }
  41. }, false);
  42. elGetById('modalPlayback').addEventListener('show.bs.modal', function() {
  43. getSettings(function(obj) {
  44. if (parseSettings(obj) === true) {
  45. cleanupModalId('modalPlayback');
  46. populatePlaybackFrm();
  47. }
  48. });
  49. });
  50. }
  51. /**
  52. * Populates the presets lists
  53. * @returns {void}
  54. */
  55. function populateListPresets() {
  56. const presetsEl = elGetById('modalPlaybackNameInput');
  57. presetsEl.value = '';
  58. setData(presetsEl, 'value', '');
  59. elClear(presetsEl.filterResult);
  60. const table = elGetById('modalPlaybackPresetsList');
  61. const presetsList = table.querySelector('tbody');
  62. elClear(presetsList);
  63. for (const preset of settings.partition.presets) {
  64. presetsEl.addFilterResultPlain(preset);
  65. presetsList.appendChild(createPresetsListRow(preset));
  66. }
  67. if (settings.partition.presets.length === 0) {
  68. presetsList.appendChild(emptyMsgEl(2, 'table'));
  69. }
  70. populatePresetDropdowns();
  71. }
  72. /**
  73. * Toggles the mpd playback mode
  74. * @param {string} option playback option to toggle
  75. * @returns {void}
  76. */
  77. //eslint-disable-next-line no-unused-vars
  78. function togglePlaymode(option) {
  79. let value;
  80. let title;
  81. switch(option) {
  82. case 'random':
  83. case 'repeat':
  84. if (settings.partition[option] === true) {
  85. value = false;
  86. title = 'Disable ' + option;
  87. }
  88. else {
  89. value = true;
  90. title = 'Enable ' + option;
  91. }
  92. break;
  93. case 'consume':
  94. if (settings.partition.consume === '0') {
  95. if (features.featConsumeOneshot === true) {
  96. value = 'oneshot';
  97. title = 'Enable consume oneshot';
  98. }
  99. else {
  100. value = '1';
  101. title = 'Enable consume mode';
  102. }
  103. }
  104. else if (settings.partition.consume === 'oneshot') {
  105. value = '1';
  106. title = 'Enable consume mode';
  107. }
  108. else if (settings.partition.consume === '1') {
  109. value = '0';
  110. title = 'Disable consume mode';
  111. }
  112. break;
  113. case 'single':
  114. if (settings.partition.single === '0') {
  115. value = 'oneshot';
  116. title = 'Enable single oneshot';
  117. }
  118. else if (settings.partition.single === 'oneshot') {
  119. value = '1';
  120. title = 'Enable single mode';
  121. }
  122. else if (settings.partition.single === '1') {
  123. value = '0';
  124. title = 'Disable single mode';
  125. }
  126. break;
  127. default:
  128. logError('Invalid playmode option: ' + option);
  129. }
  130. const params = {};
  131. params[option] = value;
  132. sendAPI('MYMPD_API_PLAYER_OPTIONS_SET', params, null, false);
  133. showNotification(tn(title), 'queue', 'info');
  134. }
  135. /**
  136. * Checks the state of the consume mode
  137. * @returns {void}
  138. */
  139. function checkConsume() {
  140. const stateConsume = getBtnGroupValueId('modalPlaybackConsumeGroup');
  141. const stateJukeboxMode = getBtnGroupValueId('modalPlaybackJukeboxModeGroup');
  142. if (stateJukeboxMode !== 'off' &&
  143. stateConsume !== '1')
  144. {
  145. elShowId('modalPlaybackConsumeWarn');
  146. }
  147. else {
  148. elHideId('modalPlaybackConsumeWarn');
  149. }
  150. }
  151. /**
  152. * Toggle jukebox setting elements
  153. * @returns {void}
  154. */
  155. function toggleJukeboxSettings() {
  156. const value = getBtnGroupValueId('modalPlaybackJukeboxModeGroup');
  157. const songOnlyInputs = elGetById('modalPlaybackJukeboxCollapse').querySelectorAll('.jukeboxSongOnly');
  158. if (value === 'album') {
  159. elGetById('modalPlaybackJukeboxQueueLengthInput').value = '1';
  160. toggleBtnChkId('modalPlaybackJukeboxIgnoreHatedInput', false);
  161. elGetById('modalPlaybackJukeboxPlaylistInput').value = tn('Database');
  162. setDataId('modalPlaybackJukeboxPlaylistInput', 'value', 'Database');
  163. const select = elGetById('modalPlaybackJukeboxUniqTagInput');
  164. elClear(select);
  165. for (const tag of ['Album', tagAlbumArtist]) {
  166. select.appendChild(
  167. elCreateTextTn('option', {"value": tag}, tag)
  168. );
  169. }
  170. // hide rows that are not configurable in jukebox album mode
  171. for (const input of songOnlyInputs) {
  172. elHide(input.closest('.row'));
  173. }
  174. }
  175. else if (value === 'song') {
  176. addTagListSelect('modalPlaybackJukeboxUniqTagInput', 'tagListBrowse');
  177. // show rows that are configurable in jukebox song mode only
  178. for (const input of songOnlyInputs) {
  179. elShow(input.closest('.row'));
  180. }
  181. }
  182. if (value !== 'off') {
  183. toggleBtnGroupValueId('modalPlaybackConsumeGroup', '1');
  184. toggleBtnGroupValueId('modalPlaybackSingleGroup', '0');
  185. }
  186. if (features.featStickers === false) {
  187. elShowId('modalPlaybackPlaybackStatisticsWarn');
  188. elHide(elGetById('modalPlaybackJukeboxLastPlayedInput').closest('.row'));
  189. elHide(elGetById('modalPlaybackJukeboxIgnoreHatedInput').closest('.row'));
  190. toggleBtnChkId('modalPlaybackJukeboxIgnoreHatedInput', false);
  191. }
  192. else {
  193. elHideId('modalPlaybackPlaybackStatisticsWarn');
  194. elShow(elGetById('modalPlaybackJukeboxLastPlayedInput').closest('.row'));
  195. }
  196. }
  197. /**
  198. * Creates a row for the presets tables
  199. * @param {string} preset preset name
  200. * @returns {HTMLElement} the row
  201. */
  202. function createPresetsListRow(preset) {
  203. const row = elCreateNodes('tr', {"data-title-phrase": "Load preset", "title": tn("Load preset")}, [
  204. elCreateText('td', {}, preset),
  205. elCreateNode('td', {"data-col": "Action"},
  206. elCreateText('a', {"class": ["mi", "color-darkgrey"], "href": "#", "data-title-phrase": "Delete", "phrase": tn('Delete')}, 'delete')
  207. )
  208. ]);
  209. setData(row, 'name', preset);
  210. return row;
  211. }
  212. /**
  213. * Populates the playback settings modal
  214. * @returns {void}
  215. */
  216. function populatePlaybackFrm() {
  217. jsonToForm(settings.partition, settingsPlaybackFields, 'modalPlayback');
  218. toggleBtnGroupValueCollapse(elGetById('modalPlaybackJukeboxModeGroup'), 'modalPlaybackJukeboxCollapse', settings.partition.jukeboxMode);
  219. toggleJukeboxSettings();
  220. elGetById('modalPlaybackJukeboxUniqTagInput').value = settings.partition.jukeboxUniqTag;
  221. populateListPresets();
  222. if (settings.partition.mpdConnected === true) {
  223. if (features.featPlaylists === true) {
  224. filterPlaylistsSelect(0, 'modalPlaybackJukeboxPlaylistInput', '', settings.partition.jukeboxPlaylist);
  225. setDataId('modalPlaybackJukeboxPlaylistInput', 'value', settings.partition.jukeboxPlaylist);
  226. }
  227. else {
  228. elGetById('modalPlaybackJukeboxPlaylistInput').value = tn('Database');
  229. setDataId('modalPlaybackJukeboxPlaylistInput', 'value', 'Database');
  230. }
  231. toggleBtnGroupValueId('modalPlaybackConsumeGroup', settings.partition.consume);
  232. toggleBtnGroupValueId('modalPlaybackSingleGroup', settings.partition.single);
  233. toggleBtnGroupValueId('modalPlaybackReplaygainGroup', settings.partition.replaygain);
  234. if (features.featTags === false) {
  235. elGetById('modalPlaybackJukeboxModeGroup').children[1].classList.add('rounded-end');
  236. }
  237. else {
  238. elGetById('modalPlaybackJukeboxModeGroup').children[1].classList.remove('rounded-end');
  239. }
  240. }
  241. checkConsume();
  242. }
  243. /**
  244. * Saves the playback settings
  245. * @param {Element} target triggering element
  246. * @returns {void}
  247. */
  248. //eslint-disable-next-line no-unused-vars
  249. function saveSettingsPlayback(target) {
  250. cleanupModalId('modalPlayback');
  251. const params = {};
  252. if (formToJson('modalPlayback', params, settingsPlaybackFields) === true) {
  253. params.jukeboxMode = getBtnGroupValueId('modalPlaybackJukeboxModeGroup');
  254. params.consume = getBtnGroupValueId('modalPlaybackConsumeGroup');
  255. params.single = getBtnGroupValueId('modalPlaybackSingleGroup');
  256. params.replaygain = getBtnGroupValueId('modalPlaybackReplaygainGroup');
  257. //set preset name to blank string if not defined, else it is not send to the api
  258. params.name = getDataId('modalPlaybackNameInput', 'value');
  259. if (params.name === undefined) {
  260. params.name = '';
  261. }
  262. btnWaiting(target, true);
  263. sendAPI("MYMPD_API_PLAYER_OPTIONS_SET", params, modalClose, true);
  264. }
  265. }