[FileItem][Cleanup] Add getter/setter for start/end offset
[xbmc.git] / xbmc / interfaces / builtins / PlayerBuiltins.cpp
blob3310ad167c6766588a046b1555da353c3c408c12
1 /*
2 * Copyright (C) 2005-2018 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
7 */
9 #include "PlayerBuiltins.h"
11 #include "Application.h"
12 #include "FileItem.h"
13 #include "GUIUserMessages.h"
14 #include "PartyModeManager.h"
15 #include "PlayListPlayer.h"
16 #include "SeekHandler.h"
17 #include "ServiceBroker.h"
18 #include "filesystem/Directory.h"
19 #include "guilib/GUIComponent.h"
20 #include "guilib/GUIWindowManager.h"
21 #include "pvr/PVRManager.h"
22 #include "pvr/channels/PVRChannel.h"
23 #include "pvr/guilib/PVRGUIActions.h"
24 #include "pvr/recordings/PVRRecording.h"
25 #include "settings/MediaSettings.h"
26 #include "settings/Settings.h"
27 #include "settings/SettingsComponent.h"
28 #include "storage/MediaManager.h"
29 #include "utils/FileExtensionProvider.h"
30 #include "utils/StringUtils.h"
31 #include "utils/URIUtils.h"
32 #include "utils/log.h"
33 #include "video/PlayerController.h"
34 #include "video/windows/GUIWindowVideoBase.h"
35 #include "view/GUIViewState.h"
37 #include <math.h>
39 #ifdef HAS_DVD_DRIVE
40 #include "Autorun.h"
41 #endif
43 /*! \brief Clear current playlist
44 * \param params (ignored)
46 static int ClearPlaylist(const std::vector<std::string>& params)
48 CServiceBroker::GetPlaylistPlayer().Clear();
50 return 0;
53 /*! \brief Start a playlist from a given offset.
54 * \param params The parameters.
55 * \details params[0] = Position in playlist or playlist type.
56 * params[1] = Position in playlist if params[0] is playlist type (optional).
58 static int PlayOffset(const std::vector<std::string>& params)
60 // playlist.playoffset(offset)
61 // playlist.playoffset(music|video,offset)
62 std::string strPos = params[0];
63 std::string paramlow(params[0]);
64 StringUtils::ToLower(paramlow);
65 if (params.size() > 1)
67 // ignore any other parameters if present
68 std::string strPlaylist = params[0];
69 strPos = params[1];
71 int iPlaylist = PLAYLIST_NONE;
72 if (paramlow == "music")
73 iPlaylist = PLAYLIST_MUSIC;
74 else if (paramlow == "video")
75 iPlaylist = PLAYLIST_VIDEO;
77 // unknown playlist
78 if (iPlaylist == PLAYLIST_NONE)
80 CLog::Log(LOGERROR, "Playlist.PlayOffset called with unknown playlist: {}", strPlaylist);
81 return false;
84 // user wants to play the 'other' playlist
85 if (iPlaylist != CServiceBroker::GetPlaylistPlayer().GetCurrentPlaylist())
87 g_application.StopPlaying();
88 CServiceBroker::GetPlaylistPlayer().Reset();
89 CServiceBroker::GetPlaylistPlayer().SetCurrentPlaylist(iPlaylist);
92 // play the desired offset
93 int pos = atol(strPos.c_str());
94 // playlist is already playing
95 if (g_application.GetAppPlayer().IsPlaying())
96 CServiceBroker::GetPlaylistPlayer().PlayNext(pos);
97 // we start playing the 'other' playlist so we need to use play to initialize the player state
98 else
99 CServiceBroker::GetPlaylistPlayer().Play(pos, "");
101 return 0;
104 /*! \brief Control player.
105 * \param params The parameters
106 * \details params[0] = Control to execute.
107 * params[1] = "notify" to notify user (optional, certain controls).
109 static int PlayerControl(const std::vector<std::string>& params)
111 g_application.ResetScreenSaver();
112 g_application.WakeUpScreenSaverAndDPMS();
114 std::string paramlow(params[0]);
115 StringUtils::ToLower(paramlow);
117 if (paramlow == "play")
118 { // play/pause
119 // either resume playing, or pause
120 if (g_application.GetAppPlayer().IsPlaying())
122 if (g_application.GetAppPlayer().GetPlaySpeed() != 1)
123 g_application.GetAppPlayer().SetPlaySpeed(1);
124 else
125 g_application.GetAppPlayer().Pause();
128 else if (paramlow == "stop")
130 g_application.StopPlaying();
132 else if (StringUtils::StartsWithNoCase(params[0], "frameadvance"))
134 std::string strFrames;
135 if (params[0].size() == 12)
136 CLog::Log(LOGERROR, "PlayerControl(frameadvance(n)) called with no argument");
137 else if (params[0].size() < 15) // arg must be at least "(N)"
138 CLog::Log(LOGERROR, "PlayerControl(frameadvance(n)) called with invalid argument: \"{}\"",
139 params[0].substr(13));
140 else
142 strFrames = params[0].substr(13);
143 StringUtils::TrimRight(strFrames, ")");
144 float frames = (float) atof(strFrames.c_str());
145 g_application.GetAppPlayer().FrameAdvance(frames);
147 else if (paramlow =="rewind" || paramlow == "forward")
149 if (g_application.GetAppPlayer().IsPlaying() && !g_application.GetAppPlayer().IsPaused())
151 float playSpeed = g_application.GetAppPlayer().GetPlaySpeed();
153 if (paramlow == "rewind" && playSpeed == 1) // Enables Rewinding
154 playSpeed *= -2;
155 else if (paramlow == "rewind" && playSpeed > 1) //goes down a notch if you're FFing
156 playSpeed /= 2;
157 else if (paramlow == "forward" && playSpeed < 1) //goes up a notch if you're RWing
159 playSpeed /= 2;
160 if (playSpeed == -1)
161 playSpeed = 1;
163 else
164 playSpeed *= 2;
166 if (playSpeed > 32 || playSpeed < -32)
167 playSpeed = 1;
169 g_application.GetAppPlayer().SetPlaySpeed(playSpeed);
172 else if (paramlow =="tempoup" || paramlow == "tempodown")
174 if (g_application.GetAppPlayer().SupportsTempo() &&
175 g_application.GetAppPlayer().IsPlaying() && !g_application.GetAppPlayer().IsPaused())
177 float playTempo = g_application.GetAppPlayer().GetPlayTempo();
178 if (paramlow == "tempodown")
179 playTempo -= 0.1f;
180 else if (paramlow == "tempoup")
181 playTempo += 0.1f;
183 g_application.GetAppPlayer().SetTempo(playTempo);
186 else if (StringUtils::StartsWithNoCase(params[0], "tempo"))
188 if (params[0].size() == 5)
189 CLog::Log(LOGERROR, "PlayerControl(tempo(n)) called with no argument");
190 else if (params[0].size() < 8) // arg must be at least "(N)"
191 CLog::Log(LOGERROR, "PlayerControl(tempo(n)) called with invalid argument: \"{}\"",
192 params[0].substr(6));
193 else
195 CApplicationPlayer& player = g_application.GetAppPlayer();
196 if (player.SupportsTempo() && player.IsPlaying() && !player.IsPaused())
198 std::string strTempo = params[0].substr(6);
199 StringUtils::TrimRight(strTempo, ")");
200 float playTempo = strtof(strTempo.c_str(), nullptr);
202 player.SetTempo(playTempo);
206 else if (paramlow == "next")
208 g_application.OnAction(CAction(ACTION_NEXT_ITEM));
210 else if (paramlow == "previous")
212 g_application.OnAction(CAction(ACTION_PREV_ITEM));
214 else if (paramlow == "bigskipbackward")
216 if (g_application.GetAppPlayer().IsPlaying())
217 g_application.GetAppPlayer().Seek(false, true);
219 else if (paramlow == "bigskipforward")
221 if (g_application.GetAppPlayer().IsPlaying())
222 g_application.GetAppPlayer().Seek(true, true);
224 else if (paramlow == "smallskipbackward")
226 if (g_application.GetAppPlayer().IsPlaying())
227 g_application.GetAppPlayer().Seek(false, false);
229 else if (paramlow == "smallskipforward")
231 if (g_application.GetAppPlayer().IsPlaying())
232 g_application.GetAppPlayer().Seek(true, false);
234 else if (StringUtils::StartsWithNoCase(params[0], "seekpercentage"))
236 std::string offset;
237 if (params[0].size() == 14)
238 CLog::Log(LOGERROR,"PlayerControl(seekpercentage(n)) called with no argument");
239 else if (params[0].size() < 17) // arg must be at least "(N)"
240 CLog::Log(LOGERROR, "PlayerControl(seekpercentage(n)) called with invalid argument: \"{}\"",
241 params[0].substr(14));
242 else
244 // Don't bother checking the argument: an invalid arg will do seek(0)
245 offset = params[0].substr(15);
246 StringUtils::TrimRight(offset, ")");
247 float offsetpercent = (float) atof(offset.c_str());
248 if (offsetpercent < 0 || offsetpercent > 100)
249 CLog::Log(LOGERROR, "PlayerControl(seekpercentage(n)) argument, {:f}, must be 0-100",
250 offsetpercent);
251 else if (g_application.GetAppPlayer().IsPlaying())
252 g_application.SeekPercentage(offsetpercent);
255 else if (paramlow == "showvideomenu")
257 if( g_application.GetAppPlayer().IsPlaying() )
258 g_application.GetAppPlayer().OnAction(CAction(ACTION_SHOW_VIDEOMENU));
260 else if (StringUtils::StartsWithNoCase(params[0], "partymode"))
262 std::string strXspPath;
263 //empty param=music, "music"=music, "video"=video, else xsp path
264 PartyModeContext context = PARTYMODECONTEXT_MUSIC;
265 if (params[0].size() > 9)
267 if (params[0].size() == 16 && StringUtils::EndsWithNoCase(params[0], "video)"))
268 context = PARTYMODECONTEXT_VIDEO;
269 else if (params[0].size() != 16 || !StringUtils::EndsWithNoCase(params[0], "music)"))
271 strXspPath = params[0].substr(10);
272 StringUtils::TrimRight(strXspPath, ")");
273 context = PARTYMODECONTEXT_UNKNOWN;
276 if (g_partyModeManager.IsEnabled())
277 g_partyModeManager.Disable();
278 else
279 g_partyModeManager.Enable(context, strXspPath);
281 else if (paramlow == "random" || paramlow == "randomoff" || paramlow == "randomon")
283 // get current playlist
284 int iPlaylist = CServiceBroker::GetPlaylistPlayer().GetCurrentPlaylist();
286 // reverse the current setting
287 bool shuffled = CServiceBroker::GetPlaylistPlayer().IsShuffled(iPlaylist);
288 if ((shuffled && paramlow == "randomon") || (!shuffled && paramlow == "randomoff"))
289 return 0;
291 // check to see if we should notify the user
292 bool notify = (params.size() == 2 && StringUtils::EqualsNoCase(params[1], "notify"));
293 CServiceBroker::GetPlaylistPlayer().SetShuffle(iPlaylist, !shuffled, notify);
295 // save settings for now playing windows
296 switch (iPlaylist)
298 case PLAYLIST_MUSIC:
299 CMediaSettings::GetInstance().SetMusicPlaylistShuffled(CServiceBroker::GetPlaylistPlayer().IsShuffled(iPlaylist));
300 CServiceBroker::GetSettingsComponent()->GetSettings()->Save();
301 break;
302 case PLAYLIST_VIDEO:
303 CMediaSettings::GetInstance().SetVideoPlaylistShuffled(CServiceBroker::GetPlaylistPlayer().IsShuffled(iPlaylist));
304 CServiceBroker::GetSettingsComponent()->GetSettings()->Save();
305 default:
306 break;
309 // send message
310 CGUIMessage msg(GUI_MSG_PLAYLISTPLAYER_RANDOM, 0, 0, iPlaylist, CServiceBroker::GetPlaylistPlayer().IsShuffled(iPlaylist));
311 CServiceBroker::GetGUI()->GetWindowManager().SendThreadMessage(msg);
313 else if (StringUtils::StartsWithNoCase(params[0], "repeat"))
315 // get current playlist
316 int iPlaylist = CServiceBroker::GetPlaylistPlayer().GetCurrentPlaylist();
317 PLAYLIST::REPEAT_STATE previous_state = CServiceBroker::GetPlaylistPlayer().GetRepeat(iPlaylist);
319 std::string paramlow(params[0]);
320 StringUtils::ToLower(paramlow);
322 PLAYLIST::REPEAT_STATE state;
323 if (paramlow == "repeatall")
324 state = PLAYLIST::REPEAT_ALL;
325 else if (paramlow == "repeatone")
326 state = PLAYLIST::REPEAT_ONE;
327 else if (paramlow == "repeatoff")
328 state = PLAYLIST::REPEAT_NONE;
329 else if (previous_state == PLAYLIST::REPEAT_NONE)
330 state = PLAYLIST::REPEAT_ALL;
331 else if (previous_state == PLAYLIST::REPEAT_ALL)
332 state = PLAYLIST::REPEAT_ONE;
333 else
334 state = PLAYLIST::REPEAT_NONE;
336 if (state == previous_state)
337 return 0;
339 // check to see if we should notify the user
340 bool notify = (params.size() == 2 && StringUtils::EqualsNoCase(params[1], "notify"));
341 CServiceBroker::GetPlaylistPlayer().SetRepeat(iPlaylist, state, notify);
343 // save settings for now playing windows
344 switch (iPlaylist)
346 case PLAYLIST_MUSIC:
347 CMediaSettings::GetInstance().SetMusicPlaylistRepeat(state == PLAYLIST::REPEAT_ALL);
348 CServiceBroker::GetSettingsComponent()->GetSettings()->Save();
349 break;
350 case PLAYLIST_VIDEO:
351 CMediaSettings::GetInstance().SetVideoPlaylistRepeat(state == PLAYLIST::REPEAT_ALL);
352 CServiceBroker::GetSettingsComponent()->GetSettings()->Save();
355 // send messages so now playing window can get updated
356 CGUIMessage msg(GUI_MSG_PLAYLISTPLAYER_REPEAT, 0, 0, iPlaylist, (int)state);
357 CServiceBroker::GetGUI()->GetWindowManager().SendThreadMessage(msg);
359 else if (StringUtils::StartsWithNoCase(params[0], "resumelivetv"))
361 CFileItem& fileItem(g_application.CurrentFileItem());
362 std::shared_ptr<PVR::CPVRChannel> channel = fileItem.HasPVRRecordingInfoTag() ? fileItem.GetPVRRecordingInfoTag()->Channel() : std::shared_ptr<PVR::CPVRChannel>();
364 if (channel)
366 const std::shared_ptr<PVR::CPVRChannelGroupMember> groupMember =
367 CServiceBroker::GetPVRManager().GUIActions()->GetChannelGroupMember(channel);
368 if (!groupMember)
370 CLog::Log(LOGERROR, "ResumeLiveTv could not obtain channel group member for channel: {}",
371 channel->ChannelName());
372 return false;
375 CFileItem playItem(groupMember);
376 if (!g_application.PlayMedia(playItem, "", channel->IsRadio() ? PLAYLIST_MUSIC : PLAYLIST_VIDEO))
378 CLog::Log(LOGERROR, "ResumeLiveTv could not play channel: {}", channel->ChannelName());
379 return false;
383 else if (paramlow == "reset")
385 g_application.OnAction(CAction(ACTION_PLAYER_RESET));
388 return 0;
391 /*! \brief Play currently inserted DVD.
392 * \param params The parameters.
393 * \details params[0] = "restart" to restart from resume point (optional).
395 static int PlayDVD(const std::vector<std::string>& params)
397 #ifdef HAS_DVD_DRIVE
398 bool restart = false;
399 if (!params.empty() && StringUtils::EqualsNoCase(params[0], "restart"))
400 restart = true;
401 MEDIA_DETECT::CAutorun::PlayDisc(CServiceBroker::GetMediaManager().GetDiscPath(), true, restart);
402 #endif
404 return 0;
407 /*! \brief Start playback of media.
408 * \param params The parameters.
409 * \details params[0] = URL to media to play (optional).
410 * params[1,...] = "isdir" if media is a directory (optional).
411 * params[1,...] = "1" to start playback in fullscreen (optional).
412 * params[1,...] = "resume" to force resuming (optional).
413 * params[1,...] = "noresume" to force not resuming (optional).
414 * params[1,...] = "playoffset=<offset>" to start playback from a given position in a playlist (optional).
416 static int PlayMedia(const std::vector<std::string>& params)
418 CFileItem item(params[0], false);
419 if (URIUtils::HasSlashAtEnd(params[0]))
420 item.m_bIsFolder = true;
422 // restore to previous window if needed
423 if( CServiceBroker::GetGUI()->GetWindowManager().GetActiveWindow() == WINDOW_SLIDESHOW ||
424 CServiceBroker::GetGUI()->GetWindowManager().GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO ||
425 CServiceBroker::GetGUI()->GetWindowManager().GetActiveWindow() == WINDOW_FULLSCREEN_GAME ||
426 CServiceBroker::GetGUI()->GetWindowManager().GetActiveWindow() == WINDOW_VISUALISATION )
427 CServiceBroker::GetGUI()->GetWindowManager().PreviousWindow();
429 // reset screensaver
430 g_application.ResetScreenSaver();
431 g_application.WakeUpScreenSaverAndDPMS();
433 // ask if we need to check guisettings to resume
434 bool askToResume = true;
435 int playOffset = 0;
436 for (unsigned int i = 1 ; i < params.size() ; i++)
438 if (StringUtils::EqualsNoCase(params[i], "isdir"))
439 item.m_bIsFolder = true;
440 else if (params[i] == "1") // set fullscreen or windowed
441 CMediaSettings::GetInstance().SetMediaStartWindowed(true);
442 else if (StringUtils::EqualsNoCase(params[i], "resume"))
444 // force the item to resume (if applicable) (see CApplication::PlayMedia)
445 item.SetStartOffset(STARTOFFSET_RESUME);
446 askToResume = false;
448 else if (StringUtils::EqualsNoCase(params[i], "noresume"))
450 // force the item to start at the beginning (m_lStartOffset is initialized to 0)
451 askToResume = false;
453 else if (StringUtils::StartsWithNoCase(params[i], "playoffset=")) {
454 playOffset = atoi(params[i].substr(11).c_str()) - 1;
455 item.SetProperty("playlist_starting_track", playOffset);
459 if (!item.m_bIsFolder && item.IsPlugin())
460 item.SetProperty("IsPlayable", true);
462 if ( askToResume == true )
464 if ( CGUIWindowVideoBase::ShowResumeMenu(item) == false )
465 return false;
467 if (item.m_bIsFolder || item.IsPlayList())
469 CFileItemList items;
470 std::string extensions = CServiceBroker::GetFileExtensionProvider().GetVideoExtensions() + "|" + CServiceBroker::GetFileExtensionProvider().GetMusicExtensions();
471 if (item.IsPlayList())
472 CUtil::GetRecursiveListing(item.GetPath(), items, extensions, XFILE::DIR_FLAG_DEFAULTS);
473 else
474 XFILE::CDirectory::GetDirectory(item.GetPath(), items, extensions, XFILE::DIR_FLAG_DEFAULTS);
476 if (!items.IsEmpty()) // fall through on non expandable playlist
478 bool containsMusic = false, containsVideo = false;
479 for (int i = 0; i < items.Size(); i++)
481 bool isVideo = items[i]->IsVideo();
482 containsMusic |= !isVideo;
483 containsVideo |= isVideo;
485 if (containsMusic && containsVideo)
486 break;
489 std::unique_ptr<CGUIViewState> state(CGUIViewState::GetViewState(containsVideo ? WINDOW_VIDEO_NAV : WINDOW_MUSIC_NAV, items));
490 if (state)
491 items.Sort(state->GetSortMethod());
492 else
493 items.Sort(SortByLabel, SortOrderAscending);
495 int playlist = containsVideo? PLAYLIST_VIDEO : PLAYLIST_MUSIC;
496 // Mixed playlist item played by music player, mixed content folder has music removed
497 if (containsMusic && containsVideo)
499 if (item.IsPlayList())
500 playlist = PLAYLIST_MUSIC;
501 else
503 for (int i = items.Size() - 1; i >= 0; i--) //remove music entries
505 if (!items[i]->IsVideo())
506 items.Remove(i);
511 CServiceBroker::GetPlaylistPlayer().ClearPlaylist(playlist);
512 CServiceBroker::GetPlaylistPlayer().Add(playlist, items);
513 CServiceBroker::GetPlaylistPlayer().SetCurrentPlaylist(playlist);
514 CServiceBroker::GetPlaylistPlayer().Play(playOffset, "");
515 return 0;
518 if ((item.IsAudio() || item.IsVideo()) && !item.IsSmartPlayList())
519 CServiceBroker::GetPlaylistPlayer().Play(std::make_shared<CFileItem>(item), "");
520 else
521 g_application.PlayMedia(item, "", PLAYLIST_NONE);
523 return 0;
526 /*! \brief Start playback with a given playback core.
527 * \param params The parameters.
528 * \details params[0] = Name of playback core.
530 static int PlayWith(const std::vector<std::string>& params)
532 g_application.OnAction(CAction(ACTION_PLAYER_PLAY, params[0]));
534 return 0;
537 /*! \brief Seek in currently playing media.
538 * \param params The parameters.
539 * \details params[0] = Number of seconds to seek.
541 static int Seek(const std::vector<std::string>& params)
543 if (g_application.GetAppPlayer().IsPlaying())
544 g_application.GetAppPlayer().GetSeekHandler().SeekSeconds(atoi(params[0].c_str()));
546 return 0;
549 static int SubtitleShiftUp(const std::vector<std::string>& params)
551 CAction action{ACTION_SUBTITLE_VSHIFT_UP};
552 if (!params.empty() && params[0] == "save")
553 action.SetText("save");
554 CPlayerController::GetInstance().OnAction(action);
555 return 0;
558 static int SubtitleShiftDown(const std::vector<std::string>& params)
560 CAction action{ACTION_SUBTITLE_VSHIFT_DOWN};
561 if (!params.empty() && params[0] == "save")
562 action.SetText("save");
563 CPlayerController::GetInstance().OnAction(action);
564 return 0;
567 // Note: For new Texts with comma add a "\" before!!! Is used for table text.
569 /// \page page_List_of_built_in_functions
570 /// \section built_in_functions_12 Player built-in's
572 /// -----------------------------------------------------------------------------
574 /// \table_start
575 /// \table_h2_l{
576 /// Function,
577 /// Description }
578 /// \table_row2_l{
579 /// <b>`PlaysDisc(parm)`</b>\n
580 /// <b>`PlayDVD(param)`</b>(deprecated)
581 /// ,
582 /// Plays the inserted disc\, like CD\, DVD or Blu-ray\, in the disc drive.
583 /// @param[in] param "restart" to restart from resume point (optional)
584 /// }
585 /// \table_row2_l{
586 /// <b>`PlayerControl(control[\,param])`</b>
587 /// ,
588 /// Allows control of music and videos. <br>
589 /// <br>
590 /// | Control | Video playback behaviour | Audio playback behaviour | Added in |
591 /// |:------------------------|:---------------------------------------|:----------------------------|:------------|
592 /// | Play | Play/Pause | Play/Pause | |
593 /// | Stop | Stop | Stop | |
594 /// | Forward | Fast Forward | Fast Forward | |
595 /// | Rewind | Rewind | Rewind | |
596 /// | Next | Next chapter or movie in playlists | Next track | |
597 /// | Previous | Previous chapter or movie in playlists | Previous track | |
598 /// | TempoUp | Increases playback speed | none | Kodi v18 |
599 /// | TempoDown | Decreases playback speed | none | Kodi v18 |
600 /// | Tempo(n) | Sets playback speed to given value | none | Kodi v19 |
601 /// | BigSkipForward | Big Skip Forward | Big Skip Forward | Kodi v15 |
602 /// | BigSkipBackward | Big Skip Backward | Big Skip Backward | Kodi v15 |
603 /// | SmallSkipForward | Small Skip Forward | Small Skip Forward | Kodi v15 |
604 /// | SmallSkipBackward | Small Skip Backward | Small Skip Backward | Kodi v15 |
605 /// | SeekPercentage(n) | Seeks to given percentage | Seeks to given percentage | |
606 /// | Random * | Toggle Random Playback | Toggle Random Playback | |
607 /// | RandomOn | Sets 'Random' to 'on' | Sets 'Random' to 'on' | |
608 /// | RandomOff | Sets 'Random' to 'off' | Sets 'Random' to 'off' | |
609 /// | Repeat * | Cycles through repeat modes | Cycles through repeat modes | |
610 /// | RepeatOne | Repeats a single video | Repeats a single track | |
611 /// | RepeatAll | Repeat all videos in a list | Repeats all tracks in a list| |
612 /// | RepeatOff | Sets 'Repeat' to 'off' | Sets 'Repeat' to 'off' | |
613 /// | Partymode(music) ** | none | Toggles music partymode | |
614 /// | Partymode(video) ** | Toggles video partymode | none | |
615 /// | Partymode(path to .xsp) | Partymode for *.xsp-file | Partymode for *.xsp-file | |
616 /// | ShowVideoMenu | Shows the DVD/BR menu if available | none | |
617 /// | FrameAdvance(n) *** | Advance video by _n_ frames | none | Kodi v18 |
618 /// | SubtitleShiftUp(save) | Shift up the subtitle position, add "save" to save the change permanently | none | Kodi v20 |
619 /// | SubtitleShiftDown(save) | Shift down the subtitle position, add "save" to save the change permanently | none | Kodi v20 |
620 /// <br>
621 /// '*' = For these controls\, the PlayerControl built-in function can make use of the 'notify'-parameter. For example: PlayerControl(random\, notify)
622 /// <br>
623 /// '**' = If no argument is given for 'partymode'\, the control will default to music.
624 /// <br>
625 /// '***' = This only works if the player is paused.
626 /// <br>
627 /// @param[in] control Control to execute.
628 /// @param[in] param "notify" to notify user (optional\, certain controls).
630 /// @note 'TempoUp' or 'TempoDown' only works if "Sync playback to display" is enabled.
631 /// @note 'Next' will behave differently while using video playlists. In those\, chapters will be ignored and the next movie will be played.
632 /// }
633 /// \table_row2_l{
634 /// <b>`Playlist.Clear`</b>
635 /// ,
636 /// Clear the current playlist
637 /// @param[in] (ignored)
638 /// }
639 /// \table_row2_l{
640 /// <b>`Playlist.PlayOffset(positionType[\,position])`</b>
641 /// ,
642 /// Start playing from a particular offset in the playlist
643 /// @param[in] positionType Position in playlist or playlist type.
644 /// @param[in] position Position in playlist if params[0] is playlist type (optional).
645 /// }
646 /// \table_row2_l{
647 /// <b>`PlayMedia(media[\,isdir][\,1]\,[playoffset=xx])`</b>
648 /// ,
649 /// Plays the media. This can be a playlist\, music\, or video file\, directory\,
650 /// plugin or an Url. The optional parameter "\,isdir" can be used for playing
651 /// a directory. "\,1" will start the media without switching to fullscreen.
652 /// If media is a playlist\, you can use playoffset=xx where xx is
653 /// the position to start playback from.
654 /// @param[in] media URL to media to play (optional).
655 /// @param[in] isdir Set "isdir" if media is a directory (optional).
656 /// @param[in] windowed Set "1" to start playback without switching to fullscreen (optional).
657 /// @param[in] resume Set "resume" to force resuming (optional).
658 /// @param[in] noresume Set "noresume" to force not resuming (optional).
659 /// @param[in] playeroffset Set "playoffset=<offset>" to start playback from a given position in a playlist (optional).
660 /// }
661 /// \table_row2_l{
662 /// <b>`PlayWith(core)`</b>
663 /// ,
664 /// Play the selected item with the specified player core.
665 /// @param[in] core Name of playback core.
666 /// }
667 /// \table_row2_l{
668 /// <b>`Seek(seconds)`</b>
669 /// ,
670 /// Seeks to the specified relative amount of seconds within the current
671 /// playing media. A negative value will seek backward and a positive value forward.
672 /// @param[in] seconds Number of seconds to seek.
673 /// }
674 /// \table_end
677 // clang-format off
678 CBuiltins::CommandMap CPlayerBuiltins::GetOperations() const
680 return {
681 {"playdisc", {"Plays the inserted disc, like CD, DVD or Blu-ray, in the disc drive.", 0, PlayDVD}},
682 {"playdvd", {"Plays the inserted disc, like CD, DVD or Blu-ray, in the disc drive.", 0, PlayDVD}},
683 {"playlist.clear", {"Clear the current playlist", 0, ClearPlaylist}},
684 {"playlist.playoffset", {"Start playing from a particular offset in the playlist", 1, PlayOffset}},
685 {"playercontrol", {"Control the music or video player", 1, PlayerControl}},
686 {"playmedia", {"Play the specified media file (or playlist)", 1, PlayMedia}},
687 {"playwith", {"Play the selected item with the specified core", 1, PlayWith}},
688 {"seek", {"Performs a seek in seconds on the current playing media file", 1, Seek}},
689 {"subtitleshiftup", {"Shift up the subtitle position", 0, SubtitleShiftUp}},
690 {"subtitleshiftdown", {"Shift down the subtitle position", 0, SubtitleShiftDown}},
693 // clang-format on