Skip to content

Commit

Permalink
[script.timers] 4.0.0
Browse files Browse the repository at this point in the history
  • Loading branch information
Heckie75 committed Aug 31, 2024
1 parent 4408c11 commit eca0a93
Show file tree
Hide file tree
Showing 24 changed files with 971 additions and 261 deletions.
2 changes: 2 additions & 0 deletions script.timers/addon.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import migration
import service
from resources.lib.utils import housekeeper

if __name__ == "__main__":

migration.migrate()
housekeeper.cleanup_outdated_timers()
service.run()
17 changes: 9 additions & 8 deletions script.timers/addon.xml
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<addon id="script.timers" name="Timers" version="3.9.3" provider-name="Heckie">
<addon id="script.timers" name="Timers" version="4.0.0" provider-name="Heckie">
<requires>
<import addon="xbmc.python" version="3.0.0" />
</requires>
<extension point="xbmc.service" library="addon.py" />
<extension point="xbmc.service" library="addon.py" />
<extension point="xbmc.python.script" library="script.py" />
<extension point="kodi.context.item">
<menu id="kodi.core.main">
Expand Down Expand Up @@ -66,6 +66,13 @@
<website>https://github.com/Heckie75/kodi-addon-timers</website>
<source>https://github.com/Heckie75/kodi-addon-timers</source>
<news>
v4.0.0 (2024-08-31)
- New Feature: programming timers with full date (not only day within upcoming 7 days, feature request #34)
- Added Preset of implicitly extra time / offset for EPG timers
- Improved stop behavior of overlapping media timers acc. its priority
- Bugfix / Workaround: [Kodi v21] Settings dialog is broken, issue #43
- Bugfix: [Kodi v21] Addon can't play PVR items anymore, issue #42

v3.9.3 (2024-08-02)
- Bugfix: Fixed that 'running-high-prio-fading-only-timer' prevents starting other media timers within its period

Expand All @@ -87,12 +94,6 @@ v3.7.0 (2023-06-30)
- If you stop explicitly playback while a start-stop-timer is running there won't be another stop action anymore when this timer runs out.
- Added workaround that streamed video (probably mpeg-dash) immediately stops after timer has started (only happened if 'seek to correct time if timer starts belatedly' is activated)

v3.6.0 (2023-04-16)
- Smart shuffle mode for slideshows (try randomly to find folder that fits into timeframe)
- Fixed resuming slideshow at right position
- Fixed resuming of enclosing timers especially combination of concurrent media types like video, audio or slideshow
- Improved notifications and competitive behavior (introduced extra low priority)

Complete changelog see https://github.com/Heckie75/kodi-addon-timers
</news>
<assets>
Expand Down
17 changes: 17 additions & 0 deletions script.timers/migration.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from resources.lib.timer.storage import Storage
from resources.lib.utils.settings_utils import (
activate_on_settings_changed_events, deactivate_on_settings_changed_events)
from resources.lib.utils.system_utils import get_kodi_version


def migrate_from_1_to_2(addon: xbmcaddon.Addon) -> int:
Expand Down Expand Up @@ -220,6 +221,18 @@ def migrate_from_6_to_7(addon: xbmcaddon.Addon) -> int:
return 7


def migrate_from_7_to_8(addon: xbmcaddon.Addon) -> int:

storage = Storage()
items = storage._load_from_storage()
for item in items:
item["date"] = ""

storage._save_to_storage(items)

return 8


def migrate() -> None:

addon = xbmcaddon.Addon()
Expand All @@ -246,6 +259,10 @@ def migrate() -> None:
if settingsVersion == 6:
settingsVersion = migrate_from_6_to_7(addon)

if settingsVersion == 7:
settingsVersion = migrate_from_7_to_8(addon)

addon.setSettingInt("settingsVersion", settingsVersion)
addon.setSettingInt("kodiVersion", int(get_kodi_version() * 100))

activate_on_settings_changed_events()
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,14 @@ msgctxt "#32042"
msgid "from"
msgstr "von"

msgctxt "#32043"
msgid "specific date"
msgstr "spezifisches Datum"

msgctxt "#32044"
msgid "Date"
msgstr "Datum"

msgctxt "#32050"
msgid "This timer interrupts other timers"
msgstr "Dieser Timer unterbricht andere Timer"
Expand Down Expand Up @@ -526,12 +534,12 @@ msgid "Pause from"
msgstr "Pausiere von"

msgctxt "#32170"
msgid "Offset"
msgstr "Versatz"
msgid "Real-time clock"
msgstr "Zeitgeber"

msgctxt "#32171"
msgid "Offset for timers in seconds"
msgstr "Versatz für Timer in Sekunden"
msgid "Offset for real-time clock in seconds"
msgstr "Versatz für Zeitgeber in Sekunden"

msgctxt "#32180"
msgid "Presets for epg quick timer"
Expand All @@ -549,6 +557,38 @@ msgctxt "#32183"
msgid "always ask"
msgstr "jedes mal fragen"

msgctxt "#32184"
msgid "Offset at start"
msgstr "Versatz zum Start"

msgctxt "#32185"
msgid "Offset at end"
msgstr "Versatz zum Ende"

msgctxt "#32186"
msgid "Offset for TV programs"
msgstr "Versatz für TV-Sendungen"

msgctxt "#32187"
msgid "Offset for radio programs"
msgstr "Versatz für Radiosendungen"

msgctxt "#32190"
msgid "Housekeeping"
msgstr "Haushaltung"

msgctxt "#32191"
msgid "Cleanup missed timers at startup"
msgstr "Räume verpasste Timer beim Starten auf"

msgctxt "#32192"
msgid "Cleanup missed timers when Kodi starts. This can happen if Kodi was not running when timer has been scheduled."
msgstr "Räume verpasste Timer auf wenn Kodi gestartet wird. Das passiert, wenn Kodi nicht lief während ein Timer geplant war."

msgctxt "#32193"
msgid ""
msgstr ""

msgctxt "#32200"
msgid "Monday"
msgstr "Montag"
Expand Down Expand Up @@ -851,4 +891,12 @@ msgstr "Bestimme die Strategie für die Priorität neuer Quicktimer."

msgctxt "#32387"
msgid "Mediatype is normally determined automatically. Set type manually e.g. if resuming doesn't work as expected."
msgstr "Die Medienart wird automatisch ermittelt. Setze die Art manuell, z.B. wenn die Fortsetzung nicht richtig funktioniert."
msgstr "Die Medienart wird automatisch ermittelt. Setze die Art manuell, z.B. wenn die Fortsetzung nicht richtig funktioniert."

msgctxt "#32388"
msgid "Schedule this timer with full date and not only by day within one week."
msgstr "Programmiere diesen Timer zu einem Datum und nicht nur an einem Tag innerhalb einer Woche."

msgctxt "#32385"
msgid "You can set an offset in seconds that is preset for EPG timers."
msgstr "Optional kann ein Versatz in Sekunden angegeben werden, der für EPG Timer voreingestellt wird."
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,14 @@ msgctxt "#32042"
msgid "from"
msgstr ""

msgctxt "#32043"
msgid "specific date"
msgstr ""

msgctxt "#32044"
msgid "Date"
msgstr ""

msgctxt "#32050"
msgid "This timer interrupts other timers"
msgstr ""
Expand Down Expand Up @@ -526,11 +534,11 @@ msgid "Pause from"
msgstr ""

msgctxt "#32170"
msgid "Offset"
msgid "Real-time clock"
msgstr ""

msgctxt "#32171"
msgid "Offset for timers in seconds"
msgid "Offset for real-time clock in seconds"
msgstr ""

msgctxt "#32180"
Expand All @@ -549,6 +557,38 @@ msgctxt "#32183"
msgid "always ask"
msgstr ""

msgctxt "#32184"
msgid "Offset at start"
msgstr ""

msgctxt "#32185"
msgid "Offset at end"
msgstr ""

msgctxt "#32186"
msgid "Offset for TV programs"
msgstr ""

msgctxt "#32187"
msgid "Offset for radio programs"
msgstr ""

msgctxt "#32190"
msgid "Housekeeping"
msgstr ""

msgctxt "#32191"
msgid "Cleanup missed timers at startup"
msgstr ""

msgctxt "#32192"
msgid "Cleanup missed timers when Kodi starts. This can happen if Kodi was not running when timer has been scheduled."
msgstr ""

msgctxt "#32193"
msgid ""
msgstr ""

msgctxt "#32200"
msgid "Monday"
msgstr ""
Expand Down Expand Up @@ -851,4 +891,8 @@ msgstr ""

msgctxt "#32387"
msgid "Mediatype is normally determined automatically. Set type manually e.g. if resuming doesn't work as expected."
msgstr ""
msgstr ""

msgctxt "#32388"
msgid "Schedule this timer with full date and not only by day within one week."
msgstr ""
68 changes: 53 additions & 15 deletions script.timers/resources/lib/contextmenu/abstract_set_timer.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
import time
from datetime import datetime
from datetime import datetime, timedelta

import xbmc
import xbmcaddon
import xbmcgui
from resources.lib.contextmenu import pvr_utils
from resources.lib.player.mediatype import VIDEO, SCRIPT
from resources.lib.player.mediatype import SCRIPT, VIDEO
from resources.lib.timer.concurrency import determine_overlappings
from resources.lib.timer.storage import Storage
from resources.lib.timer.timer import (END_TYPE_DURATION, END_TYPE_NO,
END_TYPE_TIME, FADE_OFF,
MEDIA_ACTION_START_STOP,
SYSTEM_ACTION_NONE, Timer)
SYSTEM_ACTION_NONE, TIMER_BY_DATE,
Timer)
from resources.lib.utils import datetime_utils, vfs_utils
from resources.lib.utils.settings_utils import (CONFIRM_CUSTOM, CONFIRM_ESCAPE,
CONFIRM_NO, CONFIRM_YES,
Expand Down Expand Up @@ -58,6 +59,13 @@ def __init__(self, label: str, path: str, timerid=-1) -> None:
else:
timer.days = days

if timer.is_timer_by_date():
date = self.ask_date(timer.label, path, is_epg, timer)
if date == None:
return
else:
timer.set_timer_by_date(date)

starttime = self.ask_starttime(timer.label, path, is_epg, timer)
if starttime == None:
return
Expand Down Expand Up @@ -103,8 +111,10 @@ def __init__(self, label: str, path: str, timerid=-1) -> None:
timer.vol_max = vol_max

timer.init()
now = datetime.today()
timer.to_timer_by_date(base=now)
overlappings = determine_overlappings(
timer, self.storage.load_timers_from_storage(), ignore_extra_prio=True)
timer, self.storage.load_timers_from_storage(), ignore_extra_prio=True, to_display=True, base=now)
if overlappings:
answer = self.handle_overlapping_timers(
timer, overlapping_timers=overlappings)
Expand All @@ -131,7 +141,7 @@ def is_supported(self, label: str, path: str) -> bool:
elif vfs_utils.is_pvr(path):
return vfs_utils.is_pvr_channel(path) or vfs_utils.is_pvr_recording(path) or xbmc.getCondVisibility("Window.IsVisible(tvguide)|Window.IsVisible(radioguide)")
else:
return vfs_utils.is_script(path) or vfs_utils.is_external(path) or not vfs_utils.is_folder(path) or vfs_utils.has_items_in_path(path)
return vfs_utils.is_script(path) or vfs_utils.is_audio_plugin(path) or vfs_utils.is_video_plugin(path) or vfs_utils.is_external(path) or not vfs_utils.is_folder(path) or vfs_utils.has_items_in_path(path)

def perform_ahead(self, timer: Timer) -> bool:

Expand All @@ -153,6 +163,14 @@ def ask_days(self, label: str, path: str, is_epg: bool, timer: Timer) -> 'list[i
else:
return [datetime.today().weekday()]

def ask_date(self, label: str, path: str, is_epg: bool, timer: Timer) -> str:

if is_epg:
return timer.date

else:
return datetime_utils.to_date_str(datetime.today())

def ask_starttime(self, label: str, path: str, is_epg: bool, timer: Timer) -> str:

if is_epg:
Expand Down Expand Up @@ -218,35 +236,55 @@ def _get_timer_preselection(self, timerid: int, label: str, path: str) -> 'tuple
timer.path = pvr_channel_path
startDate = datetime_utils.parse_xbmc_shortdate(
xbmc.getInfoLabel("ListItem.Date").split(" ")[0])
timer.days = [startDate.weekday()]
timer.start = xbmc.getInfoLabel("ListItem.StartTime")
duration = xbmc.getInfoLabel("ListItem.Duration")
if len(duration) == 5:
timer.duration = "00:%s" % duration[:2]

elif len(duration) == 9:
timer.set_timer_by_date(
date=datetime_utils.to_date_str(startDate))
start = datetime_utils.parse_time(
xbmc.getInfoLabel("ListItem.StartTime"))
start_offset = timedelta(
seconds=self.addon.getSettingInt("epg_tv_offset_start" if vfs_utils.is_pvr_tv_channel(pvr_channel_path) else "epg_radio_offset_start"))
start += start_offset
timer.start, timer.start_offset = datetime_utils.format_from_timedelta(
start)

s_duration = xbmc.getInfoLabel("ListItem.Duration")
if len(s_duration) == 5:
s_duration = "00:%s" % s_duration[:2]

elif len(s_duration) == 9:
return None, False

else:
timer.duration = duration[:5]
s_duration = s_duration[:5]

td_duration = datetime_utils.parse_time(
s_duration) - start_offset
td_duration += timedelta(seconds=self.addon.getSettingInt(
"epg_tv_offset_end" if vfs_utils.is_pvr_tv_channel(pvr_channel_path) else "epg_radio_offset_end"))

td_start = datetime_utils.parse_time(timer.start)
timer.duration, timer.duration_offset = datetime_utils.format_from_timedelta(
td_duration)

td_start = datetime_utils.parse_time(
timer.start) + timedelta(seconds=timer.start_offset)
if not is_epg:

if not timer.days or timer.days == [datetime_utils.WEEKLY]:
now = datetime_utils.DateTimeDelta.now()
timer.days.append(now.dt.weekday() if not td_start.seconds or td_start.seconds >
now.td.seconds else (now.dt.weekday() + 1) % 7)

timer.date = datetime_utils.to_date_str(now.dt)

if vfs_utils.is_favourites(path):
timer.path = vfs_utils.get_favourites_target(path)
else:
timer.path = path

timer.duration = timer.get_duration()

timer.end = datetime_utils.format_from_seconds(
(td_start + datetime_utils.parse_time(timer.duration)).seconds)
timer.end, timer.end_offset = datetime_utils.format_from_timedelta(
td_start + datetime_utils.parse_time(timer.duration) + timedelta(seconds=timer.duration_offset))

if vfs_utils.is_script(timer.path):
timer.media_type = SCRIPT
Expand Down
Loading

0 comments on commit eca0a93

Please sign in to comment.