from time import sleep
from typing import Union, Any
from enum import Enum
import AppKit
from PyXA import XABase
from PyXA import XABaseScriptable
from ..XAProtocols import XACanOpenPath, XACanPrintPath, XAClipboardCodable, XACloseable
[docs]
class XAVLCApplication(XABaseScriptable.XASBApplication, XACanOpenPath, XACanPrintPath):
"""VLC's top level scripting object.
.. versionadded:: 0.0.8
"""
[docs]
class ObjectType(Enum):
"""Types of objects that can be created using :func:`make`."""
document = "document"
def __init__(self, properties):
super().__init__(properties)
self.xa_wcls = XAVLCWindow
@property
def properties(self) -> dict:
"""All properties of the VLC application."""
return self.xa_elem.properties()
@property
def frontmost(self) -> bool:
"""Whether VLC is the active application."""
return self.xa_scel.frontmost()
@property
def name(self) -> str:
"""The name of the application."""
return self.xa_scel.name()
@property
def version(self) -> str:
"""The version of VLC.app."""
return self.xa_scel.version()
@property
def audio_desync(self) -> int:
"""The audio desynchronization preference from -2147483648 to 2147483647, where 0 is default."""
return self.xa_scel.audioDesync()
@audio_desync.setter
def audio_desync(self, audio_desync: int):
self.set_property("audioDesync", audio_desync)
@property
def audio_volume(self) -> int:
"""The volume of the current playlist item from 0 to 512, where 256 is 100%."""
return self.xa_scel.audioVolume()
@audio_volume.setter
def audio_volume(self, audio_volume: int):
self.set_property("audioVolume", audio_volume)
@property
def current_time(self) -> int:
"""The current time of the current playlist item in seconds."""
return self.xa_scel.currentTime()
@current_time.setter
def current_time(self, current_time: int):
self.set_property("currentTime", current_time)
@property
def duration_of_current_item(self) -> int:
"""The duration of the current playlist item in seconds."""
return self.xa_scel.durationOfCurrentItem()
@property
def fullscreen_mode(self) -> bool:
"""Indicates whether fullscreen is enabled or not."""
return self.xa_scel.fullscreenMode()
@fullscreen_mode.setter
def fullscreen_mode(self, fullscreen_mode: bool):
self.set_property("fullscreenMode", fullscreen_mode)
@property
def muted(self) -> bool:
"""Is VLC currently muted?"""
return self.xa_scel.muted()
@property
def name_of_current_item(self) -> str:
"""Name of the current playlist item."""
return self.xa_scel.nameOfCurrentItem()
@property
def path_of_current_item(self) -> XABase.XAPath:
"""Path to the current playlist item."""
return XABase.XAPath(self.xa_scel.pathOfCurrentItem())
@property
def playback_shows_menu(self) -> bool:
"""Indicates whether a DVD menu is currently being shown."""
return self.xa_scel.playbackShowsMenu()
@property
def playing(self) -> bool:
"""Is VLC playing an item?"""
return self.xa_scel.playing()
[docs]
def open(self, target: Union[XABase.XAURL, XABase.XAPath, str]) -> None:
"""Opens the file/website at the given filepath/URL.
:param target: The path to a file or the URL to a website to open.
:type target: Union[XABase.XAURL, XABase.XAPath, str]
:Example 1: Open files from file paths
>>> import PyXA
>>> app = PyXA.Application("VLC")
>>> app.open("/Users/exampleUser/Downloads/Example.avi")
>>>
>>> path = PyXA.XAPath("/Users/exampleUser/Documents/Example.m4v")
>>> app.open(path)
:Example 2: Open URLs
>>> import PyXA
>>> app = PyXA.Application("VLC")
>>> app.open("https://upload.wikimedia.org/wikipedia/commons/transcoded/0/0f/Baby_pelican.ogg/Baby_pelican.ogg.mp3")
>>>
>>> url = PyXA.XAURL("https://www.youtube.com/watch?v=e9B3E_DnnWw")
>>> app.open(url)
.. versionadded:: 0.0.8
"""
if isinstance(target, str):
if target.startswith("/"):
target = XABase.XAPath(target)
else:
target = XABase.XAURL(target)
self.xa_wksp.openURLs_withAppBundleIdentifier_options_additionalEventParamDescriptor_launchIdentifiers_(
[target.xa_elem], self.xa_elem.bundleIdentifier(), 0, None, None
)
[docs]
def fullscreen(self):
"""Toggle between fullscreen and windowed mode.
.. versionadded:: 0.0.8
"""
return self.xa_scel.fullscreen()
[docs]
def get_url(self, url: Union[XABase.XAURL, XABase.XAPath, str]):
"""Get a URL without playing it.
.. versionadded:: 0.0.8
"""
self.open(url)
sleep(0.01)
self.stop()
[docs]
def mute(self):
"""Mute the audio of the item or unmute it if it was muted.
.. versionadded:: 0.0.8
"""
return self.xa_scel.mute()
[docs]
def next(self):
"""Go to the next item in the playlist or the next chapter in the DVD/VCD.
.. versionadded:: 0.0.8
"""
return self.xa_scel.next()
[docs]
def open_url(self, url: Union[XABase.XAURL, XABase.XAPath, str]):
"""Open a media URL.
.. versionadded:: 0.0.8
"""
self.open(url)
[docs]
def play(self):
"""Start playing the current playlistitem or pause it when it is already playing.
.. versionadded:: 0.0.8
"""
return self.xa_scel.play()
[docs]
def previous(self):
"""Go to the previous item in the playlist or the previous chapter in the DVD/VCD.
.. versionadded:: 0.0.8
"""
return self.xa_scel.previous()
[docs]
def step_backward(self):
"""Step the current playlist item backward the specified step width (default is 2) (1=extraShort, 2=short, 3=medium, 4=long).
.. versionadded:: 0.0.8
"""
return self.xa_scel.stepBackward()
[docs]
def step_forward(self):
"""Step the current playlist item forward the specified step width (default is 2) (1=extraShort, 2=short, 3=medium, 4=long).
.. versionadded:: 0.0.8
"""
return self.xa_scel.stepForward()
[docs]
def stop(self):
"""Stop playing the current playlist item.
.. versionadded:: 0.0.8
"""
return self.xa_scel.stop()
[docs]
def volume_down(self):
"""Bring the volume down by one step. There are 32 steps from 0 to 400% volume.
.. versionadded:: 0.0.8
"""
return self.xa_scel.volumeDown()
[docs]
def volume_up(self):
"""Bring the volume up by one step. There are 32 steps from 0 to 400% volume.
.. versionadded:: 0.0.8
"""
return self.xa_scel.volumeUp()
[docs]
def documents(self, filter: Union[dict, None] = None) -> "XAVLCDocumentList":
"""Returns a list of documents, as PyXA objects, matching the given filter.
:param filter: Keys and values to filter documents by, defaults to None
:type filter: dict, optional
:return: A PyXA list object wrapping a list of documents
:rtype: XAVLCDocumentList
.. versionadded:: 0.0.8
"""
return self._new_element(self.xa_scel.documents(), XAVLCDocumentList, filter)
[docs]
def make(
self,
specifier: Union[str, "XAVLCApplication.ObjectType"],
properties: dict,
data: Any = None,
):
"""Creates a new element of the given specifier class without adding it to any list.
:param specifier: The classname of the object to create
:type specifier: Union[str, XAArcApplication.ObjectType]
:param properties: The properties to give the object
:type properties: dict
:param data: The data to give the object
:type data: Any
:return: A PyXA wrapped form of the object
:rtype: XABase.XAObject
.. versionadded:: 0.0.9
"""
if isinstance(specifier, XAVLCApplication.ObjectType):
specifier = specifier.value
if data is None:
camelized_properties = {}
if properties is None:
properties = {}
for key, value in properties.items():
if key == "url":
key = "URL"
camelized_properties[XABase.camelize(key)] = value
obj = (
self.xa_scel.classForScriptingClass_(specifier)
.alloc()
.initWithProperties_(camelized_properties)
)
else:
obj = (
self.xa_scel.classForScriptingClass_(specifier)
.alloc()
.initWithData_(data)
)
if specifier == "document":
return self._new_element(obj, XAVLCDocument)
[docs]
class XAVLCDocumentList(XABase.XAList, XACloseable, XAClipboardCodable):
"""A wrapper around a list of documents.
.. versionadded:: 0.0.8
"""
def __init__(self, properties: dict, filter: Union[dict, None] = None):
super().__init__(properties, XAVLCDocument, filter)
[docs]
def name(self) -> list[str]:
return list(self.xa_elem.arrayByApplyingSelector_("name") or [])
[docs]
def modified(self) -> list[bool]:
return list(self.xa_elem.arrayByApplyingSelector_("modified") or [])
[docs]
def path(self) -> list[XABase.XAPath]:
ls = self.xa_elem.arrayByApplyingSelector_("path") or []
return [XABase.XAPath(x) for x in ls]
[docs]
def by_name(self, name: str) -> Union["XAVLCDocument", None]:
return self.by_property("name", name)
[docs]
def by_modified(self, modified: bool) -> Union["XAVLCDocument", None]:
return self.by_property("modified", modified)
[docs]
def by_path(self, path: Union[str, XABase.XAPath]) -> Union["XAVLCDocument", None]:
if isinstance(path, str):
path = XABase.XAPath(path)
return self.by_property("path", path.xa_elem)
[docs]
def get_clipboard_representation(self) -> list[str]:
"""Gets a clipboard-codable representation of each document in the list.
When the clipboard content is set to a list of documents, the name of each document is added to the clipboard.
:return: A list of document names
:rtype: list[str]
.. versionadded:: 0.0.8
"""
return self.name()
def __repr__(self):
return "<" + str(type(self)) + str(self.name()) + ">"
[docs]
class XAVLCDocument(XABase.XAObject):
"""A document open in VLC.app."""
def __init__(self, properties):
super().__init__(properties)
@property
def properties(self) -> dict:
"""All properties of the document."""
return self.xa_elem.properties()
@property
def modified(self) -> bool:
"""Has the document been modified since the last save?"""
return self.xa_elem.modified()
@property
def name(self) -> str:
"""The document's name."""
return self.xa_elem.name()
@name.setter
def name(self, name: str):
self.set_property("name", name)
@property
def path(self) -> XABase.XAPath:
"""The document's path."""
return XABase.XAPath(self.xa_elem.path())
@path.setter
def path(self, path: Union[str, XABase.XAPath]):
if isinstance(path, str):
path = XABase.XAPath(path)
self.set_property("path", path.xa_elem)
def __repr__(self):
return "<" + str(type(self)) + str(self.name) + ">"
[docs]
class XAVLCWindow(XABaseScriptable.XASBWindow):
"""A window of VLC.app.
.. versionadded:: 0.0.8
"""
def __init__(self, properties):
super().__init__(properties)
@property
def document(self) -> XAVLCDocument:
"""The document whose contents are being displayed in the window."""
return self.xa_elem.document()
@document.setter
def document(self, document: XAVLCDocument):
self.set_property("document", document.xa_elem)
@property
def floating(self) -> bool:
"""Whether the window floats."""
return self.xa_elem.floating()
@property
def modal(self) -> bool:
"""Whether the window is the application's current modal window."""
return self.xa_elem.modal()
@property
def titled(self) -> bool:
"""Whether the window has a title bar."""
return self.xa_elem.titled()