1 """System Bridge Media Source Implementation."""
3 from __future__
import annotations
5 from systembridgemodels.media_directories
import MediaDirectory
6 from systembridgemodels.media_files
import MediaFile, MediaFiles
7 from systembridgemodels.media_get_files
import MediaGetFiles
22 from .const
import DOMAIN
23 from .coordinator
import SystemBridgeDataUpdateCoordinator
27 """Set up SystemBridge media source."""
32 """Provide System Bridge media files as a media source."""
38 """Initialize source."""
41 self.hass: HomeAssistant = hass
45 item: MediaSourceItem,
47 """Resolve media to a url."""
48 entry_id, path, mime_type = item.identifier.split(
"~~", 2)
49 entry = self.hass.config_entries.async_get_entry(entry_id)
51 raise ValueError(
"Invalid entry")
52 path_split = path.split(
"/", 1)
54 f
"{_build_base_url(entry)}&base={path_split[0]}&path={path_split[1]}",
60 item: MediaSourceItem,
61 ) -> BrowseMediaSource:
63 if not item.identifier:
66 if "~~" not in item.identifier:
67 entry = self.hass.config_entries.async_get_entry(item.identifier)
69 raise ValueError(
"Invalid entry")
70 coordinator: SystemBridgeDataUpdateCoordinator = self.hass.data[DOMAIN].
get(
73 directories = await coordinator.websocket_client.get_directories()
76 entry_id, path = item.identifier.split(
"~~", 1)
77 entry = self.hass.config_entries.async_get_entry(entry_id)
79 raise ValueError(
"Invalid entry")
81 coordinator = self.hass.data[DOMAIN].
get(entry.entry_id)
83 path_split = path.split(
"/", 1)
85 files = await coordinator.websocket_client.get_files(
88 path=path_split[1]
if len(path_split) > 1
else None,
95 """Build bridges for System Bridge media."""
99 identifier=entry.entry_id,
100 media_class=MediaClass.DIRECTORY,
101 media_content_type=
"",
106 children_media_class=MediaClass.DIRECTORY,
108 for entry
in self.hass.config_entries.async_entries(DOMAIN)
109 if entry.entry_id
is not None
115 media_class=MediaClass.DIRECTORY,
116 media_content_type=
"",
121 children_media_class=MediaClass.DIRECTORY,
128 """Build base url for System Bridge media."""
130 f
"http://{entry.data[CONF_HOST]}:{entry.data[CONF_PORT]}"
131 f
"/api/media/file/data?token={entry.data[CONF_TOKEN]}"
137 media_directories: list[MediaDirectory],
138 ) -> BrowseMediaSource:
139 """Build base categories for System Bridge media."""
143 media_class=MediaClass.DIRECTORY,
144 media_content_type=
"",
151 identifier=f
"{entry.entry_id}~~{directory.key}",
152 media_class=MediaClass.DIRECTORY,
153 media_content_type=
"",
154 title=f
"{directory.key[:1].capitalize()}{directory.key[1:]}",
158 children_media_class=MediaClass.DIRECTORY,
160 for directory
in media_directories
162 children_media_class=MediaClass.DIRECTORY,
168 media_files: MediaFiles,
171 ) -> BrowseMediaSource:
172 """Fetch requested files."""
175 identifier=identifier,
176 media_class=MediaClass.DIRECTORY,
177 media_content_type=
"",
178 title=f
"{entry.title} - {path}",
183 for file
in media_files.files
187 and file.mime_type
is not None
188 and file.mime_type.startswith(MEDIA_MIME_TYPES)
196 media_file: MediaFile,
197 ) -> BrowseMediaSource:
198 """Build individual media item."""
200 if media_file.is_file
and media_file.mime_type
is not None:
201 ext = f
"~~{media_file.mime_type}"
203 if media_file.is_directory
or media_file.mime_type
is None:
204 media_class = MediaClass.DIRECTORY
206 media_class = MEDIA_CLASS_MAP[media_file.mime_type.split(
"/", 1)[0]]
210 identifier=f
"{path}/{media_file.name}{ext}",
211 media_class=media_class,
212 media_content_type=media_file.mime_type,
213 title=media_file.name,
214 can_play=media_file.is_file,
215 can_expand=media_file.is_directory,
web.Response get(self, web.Request request, str config_key)