lybic-guiagents 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of lybic-guiagents might be problematic. Click here for more details.
- desktop_env/__init__.py +1 -0
- desktop_env/actions.py +203 -0
- desktop_env/controllers/__init__.py +0 -0
- desktop_env/controllers/python.py +471 -0
- desktop_env/controllers/setup.py +882 -0
- desktop_env/desktop_env.py +509 -0
- desktop_env/evaluators/__init__.py +5 -0
- desktop_env/evaluators/getters/__init__.py +41 -0
- desktop_env/evaluators/getters/calc.py +15 -0
- desktop_env/evaluators/getters/chrome.py +1774 -0
- desktop_env/evaluators/getters/file.py +154 -0
- desktop_env/evaluators/getters/general.py +42 -0
- desktop_env/evaluators/getters/gimp.py +38 -0
- desktop_env/evaluators/getters/impress.py +126 -0
- desktop_env/evaluators/getters/info.py +24 -0
- desktop_env/evaluators/getters/misc.py +406 -0
- desktop_env/evaluators/getters/replay.py +20 -0
- desktop_env/evaluators/getters/vlc.py +86 -0
- desktop_env/evaluators/getters/vscode.py +35 -0
- desktop_env/evaluators/metrics/__init__.py +160 -0
- desktop_env/evaluators/metrics/basic_os.py +68 -0
- desktop_env/evaluators/metrics/chrome.py +493 -0
- desktop_env/evaluators/metrics/docs.py +1011 -0
- desktop_env/evaluators/metrics/general.py +665 -0
- desktop_env/evaluators/metrics/gimp.py +637 -0
- desktop_env/evaluators/metrics/libreoffice.py +28 -0
- desktop_env/evaluators/metrics/others.py +92 -0
- desktop_env/evaluators/metrics/pdf.py +31 -0
- desktop_env/evaluators/metrics/slides.py +957 -0
- desktop_env/evaluators/metrics/table.py +585 -0
- desktop_env/evaluators/metrics/thunderbird.py +176 -0
- desktop_env/evaluators/metrics/utils.py +719 -0
- desktop_env/evaluators/metrics/vlc.py +524 -0
- desktop_env/evaluators/metrics/vscode.py +283 -0
- desktop_env/providers/__init__.py +35 -0
- desktop_env/providers/aws/__init__.py +0 -0
- desktop_env/providers/aws/manager.py +278 -0
- desktop_env/providers/aws/provider.py +186 -0
- desktop_env/providers/aws/provider_with_proxy.py +315 -0
- desktop_env/providers/aws/proxy_pool.py +193 -0
- desktop_env/providers/azure/__init__.py +0 -0
- desktop_env/providers/azure/manager.py +87 -0
- desktop_env/providers/azure/provider.py +207 -0
- desktop_env/providers/base.py +97 -0
- desktop_env/providers/gcp/__init__.py +0 -0
- desktop_env/providers/gcp/manager.py +0 -0
- desktop_env/providers/gcp/provider.py +0 -0
- desktop_env/providers/virtualbox/__init__.py +0 -0
- desktop_env/providers/virtualbox/manager.py +463 -0
- desktop_env/providers/virtualbox/provider.py +124 -0
- desktop_env/providers/vmware/__init__.py +0 -0
- desktop_env/providers/vmware/manager.py +455 -0
- desktop_env/providers/vmware/provider.py +105 -0
- gui_agents/__init__.py +0 -0
- gui_agents/agents/Action.py +209 -0
- gui_agents/agents/__init__.py +0 -0
- gui_agents/agents/agent_s.py +832 -0
- gui_agents/agents/global_state.py +610 -0
- gui_agents/agents/grounding.py +651 -0
- gui_agents/agents/hardware_interface.py +129 -0
- gui_agents/agents/manager.py +568 -0
- gui_agents/agents/translator.py +132 -0
- gui_agents/agents/worker.py +355 -0
- gui_agents/cli_app.py +560 -0
- gui_agents/core/__init__.py +0 -0
- gui_agents/core/engine.py +1496 -0
- gui_agents/core/knowledge.py +449 -0
- gui_agents/core/mllm.py +555 -0
- gui_agents/tools/__init__.py +0 -0
- gui_agents/tools/tools.py +727 -0
- gui_agents/unit_test/__init__.py +0 -0
- gui_agents/unit_test/run_tests.py +65 -0
- gui_agents/unit_test/test_manager.py +330 -0
- gui_agents/unit_test/test_worker.py +269 -0
- gui_agents/utils/__init__.py +0 -0
- gui_agents/utils/analyze_display.py +301 -0
- gui_agents/utils/common_utils.py +263 -0
- gui_agents/utils/display_viewer.py +281 -0
- gui_agents/utils/embedding_manager.py +53 -0
- gui_agents/utils/image_axis_utils.py +27 -0
- lybic_guiagents-0.1.0.dist-info/METADATA +416 -0
- lybic_guiagents-0.1.0.dist-info/RECORD +85 -0
- lybic_guiagents-0.1.0.dist-info/WHEEL +5 -0
- lybic_guiagents-0.1.0.dist-info/licenses/LICENSE +201 -0
- lybic_guiagents-0.1.0.dist-info/top_level.txt +2 -0
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import logging
|
|
3
|
+
from typing import Dict, List, Set
|
|
4
|
+
from typing import Optional, Any, Union
|
|
5
|
+
from datetime import datetime
|
|
6
|
+
import requests
|
|
7
|
+
import pandas as pd
|
|
8
|
+
|
|
9
|
+
logger = logging.getLogger("desktopenv.getter.file")
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def get_content_from_vm_file(env, config: Dict[str, Any]) -> Any:
|
|
13
|
+
"""
|
|
14
|
+
Config:
|
|
15
|
+
path (str): absolute path on the VM to fetch
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
path = config["path"]
|
|
19
|
+
file_path = get_vm_file(env, {"path": path, "dest": os.path.basename(path)})
|
|
20
|
+
file_type, file_content = config['file_type'], config['file_content']
|
|
21
|
+
if file_type == 'xlsx':
|
|
22
|
+
if file_content == 'last_row':
|
|
23
|
+
df = pd.read_excel(file_path)
|
|
24
|
+
last_row = df.iloc[-1]
|
|
25
|
+
last_row_as_list = last_row.astype(str).tolist()
|
|
26
|
+
return last_row_as_list
|
|
27
|
+
else:
|
|
28
|
+
raise NotImplementedError(f"File type {file_type} not supported")
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def get_cloud_file(env, config: Dict[str, Any]) -> Union[str, List[str]]:
|
|
32
|
+
"""
|
|
33
|
+
Config:
|
|
34
|
+
path (str|List[str]): the url to download from
|
|
35
|
+
dest (str|List[str])): file name of the downloaded file
|
|
36
|
+
multi (bool) : optional. if path and dest are lists providing
|
|
37
|
+
information of multiple files. defaults to False
|
|
38
|
+
gives (List[int]): optional. defaults to [0]. which files are directly
|
|
39
|
+
returned to the metric. if len==1, str is returned; else, list is
|
|
40
|
+
returned.
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
if not config.get("multi", False):
|
|
44
|
+
paths: List[str] = [config["path"]]
|
|
45
|
+
dests: List[str] = [config["dest"]]
|
|
46
|
+
else:
|
|
47
|
+
paths: List[str] = config["path"]
|
|
48
|
+
dests: List[str] = config["dest"]
|
|
49
|
+
cache_paths: List[str] = []
|
|
50
|
+
|
|
51
|
+
gives: Set[int] = set(config.get("gives", [0]))
|
|
52
|
+
|
|
53
|
+
for i, (p, d) in enumerate(zip(paths, dests)):
|
|
54
|
+
_path = os.path.join(env.cache_dir, d)
|
|
55
|
+
if i in gives:
|
|
56
|
+
cache_paths.append(_path)
|
|
57
|
+
|
|
58
|
+
if os.path.exists(_path):
|
|
59
|
+
#return _path
|
|
60
|
+
continue
|
|
61
|
+
|
|
62
|
+
url = p
|
|
63
|
+
response = requests.get(url, stream=True)
|
|
64
|
+
response.raise_for_status()
|
|
65
|
+
|
|
66
|
+
with open(_path, 'wb') as f:
|
|
67
|
+
for chunk in response.iter_content(chunk_size=8192):
|
|
68
|
+
if chunk:
|
|
69
|
+
f.write(chunk)
|
|
70
|
+
|
|
71
|
+
return cache_paths[0] if len(cache_paths)==1 else cache_paths
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def get_vm_file(env, config: Dict[str, Any]) -> Union[Optional[str], List[Optional[str]]]:
|
|
75
|
+
"""
|
|
76
|
+
Config:
|
|
77
|
+
path (str): absolute path on the VM to fetch
|
|
78
|
+
dest (str): file name of the downloaded file
|
|
79
|
+
multi (bool) : optional. if path and dest are lists providing
|
|
80
|
+
information of multiple files. defaults to False
|
|
81
|
+
gives (List[int]): optional. defaults to [0]. which files are directly
|
|
82
|
+
returned to the metric. if len==1, str is returned; else, list is
|
|
83
|
+
returned.
|
|
84
|
+
only support for single file now:
|
|
85
|
+
time_suffix(bool): optional. defaults to False. if True, append the current time in required format.
|
|
86
|
+
time_format(str): optional. defaults to "%Y%m%d_%H%M%S". format of the time suffix.
|
|
87
|
+
"""
|
|
88
|
+
time_format = "%Y%m%d_%H%M%S"
|
|
89
|
+
if not config.get("multi", False):
|
|
90
|
+
paths: List[str] = [config["path"]]
|
|
91
|
+
dests: List[str] = [config["dest"]]
|
|
92
|
+
if config.get("time_suffix", False):
|
|
93
|
+
time_format = config.get("time_format", time_format)
|
|
94
|
+
# Insert time before file extension.
|
|
95
|
+
dests = [f"{os.path.splitext(d)[0]}_{datetime.now().strftime(time_format)}{os.path.splitext(d)[1]}" for d in dests]
|
|
96
|
+
else:
|
|
97
|
+
paths: List[str] = config["path"]
|
|
98
|
+
dests: List[str] = config["dest"]
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
cache_paths: List[str] = []
|
|
102
|
+
|
|
103
|
+
gives: Set[int] = set(config.get("gives", [0]))
|
|
104
|
+
|
|
105
|
+
for i, (p, d) in enumerate(zip(paths, dests)):
|
|
106
|
+
_path = os.path.join(env.cache_dir, d)
|
|
107
|
+
|
|
108
|
+
try:
|
|
109
|
+
# Try to get file from VM
|
|
110
|
+
file = env.controller.get_file(p)
|
|
111
|
+
if file is None:
|
|
112
|
+
logger.warning(f"Failed to get file from VM: {p}")
|
|
113
|
+
if i in gives:
|
|
114
|
+
cache_paths.append(None)
|
|
115
|
+
continue
|
|
116
|
+
|
|
117
|
+
if i in gives:
|
|
118
|
+
cache_paths.append(_path)
|
|
119
|
+
|
|
120
|
+
# Write file with robust error handling
|
|
121
|
+
try:
|
|
122
|
+
# Ensure cache directory exists
|
|
123
|
+
os.makedirs(env.cache_dir, exist_ok=True)
|
|
124
|
+
|
|
125
|
+
with open(_path, "wb") as f:
|
|
126
|
+
f.write(file)
|
|
127
|
+
logger.info(f"Successfully saved file: {_path} ({len(file)} bytes)")
|
|
128
|
+
|
|
129
|
+
except IOError as e:
|
|
130
|
+
logger.error(f"IO error writing file {_path}: {e}")
|
|
131
|
+
if i in gives:
|
|
132
|
+
cache_paths[-1] = None # Replace the path we just added with None
|
|
133
|
+
except Exception as e:
|
|
134
|
+
logger.error(f"Unexpected error writing file {_path}: {e}")
|
|
135
|
+
if i in gives:
|
|
136
|
+
cache_paths[-1] = None
|
|
137
|
+
|
|
138
|
+
except Exception as e:
|
|
139
|
+
logger.error(f"Error processing file {p}: {e}")
|
|
140
|
+
if i in gives:
|
|
141
|
+
cache_paths.append(None)
|
|
142
|
+
|
|
143
|
+
return cache_paths[0] if len(cache_paths)==1 else cache_paths
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
def get_cache_file(env, config: Dict[str, str]) -> str:
|
|
147
|
+
"""
|
|
148
|
+
Config:
|
|
149
|
+
path (str): relative path in cache dir
|
|
150
|
+
"""
|
|
151
|
+
|
|
152
|
+
_path = os.path.join(env.cache_dir, config["path"])
|
|
153
|
+
assert os.path.exists(_path)
|
|
154
|
+
return _path
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from typing import Dict
|
|
3
|
+
import requests
|
|
4
|
+
|
|
5
|
+
logger = logging.getLogger("desktopenv.getters.general")
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def get_vm_command_line(env, config: Dict[str, str]):
|
|
9
|
+
vm_ip = env.vm_ip
|
|
10
|
+
port = env.server_port
|
|
11
|
+
command = config["command"]
|
|
12
|
+
shell = config.get("shell", False)
|
|
13
|
+
|
|
14
|
+
response = requests.post(f"http://{vm_ip}:{port}/execute", json={"command": command, "shell": shell})
|
|
15
|
+
|
|
16
|
+
print(response.json())
|
|
17
|
+
|
|
18
|
+
if response.status_code == 200:
|
|
19
|
+
return response.json()["output"]
|
|
20
|
+
else:
|
|
21
|
+
logger.error("Failed to get vm command line. Status code: %d", response.status_code)
|
|
22
|
+
return None
|
|
23
|
+
|
|
24
|
+
def get_vm_command_error(env, config: Dict[str, str]):
|
|
25
|
+
vm_ip = env.vm_ip
|
|
26
|
+
port = env.server_port
|
|
27
|
+
command = config["command"]
|
|
28
|
+
shell = config.get("shell", False)
|
|
29
|
+
|
|
30
|
+
response = requests.post(f"http://{vm_ip}:{port}/execute", json={"command": command, "shell": shell})
|
|
31
|
+
|
|
32
|
+
print(response.json())
|
|
33
|
+
|
|
34
|
+
if response.status_code == 200:
|
|
35
|
+
return response.json()["error"]
|
|
36
|
+
else:
|
|
37
|
+
logger.error("Failed to get vm command line error. Status code: %d", response.status_code)
|
|
38
|
+
return None
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def get_vm_terminal_output(env, config: Dict[str, str]):
|
|
42
|
+
return env.controller.get_terminal_output()
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import os
|
|
3
|
+
from typing import Dict
|
|
4
|
+
|
|
5
|
+
logger = logging.getLogger("desktopenv.getters.gimp")
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def get_gimp_config_file(env, config: Dict[str, str]):
|
|
9
|
+
"""
|
|
10
|
+
Gets the config setting of GIMP.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
os_type = env.vm_platform
|
|
14
|
+
print(os_type)
|
|
15
|
+
|
|
16
|
+
if os_type == "Linux":
|
|
17
|
+
config_path = \
|
|
18
|
+
env.controller.execute_python_command(f"import os; print("
|
|
19
|
+
f"os"
|
|
20
|
+
f".path.expanduser("
|
|
21
|
+
f"'~/.config/GIMP/2.10/"
|
|
22
|
+
f"{config['file_name']}'))")[
|
|
23
|
+
'output'].strip()
|
|
24
|
+
# TODO: Add support for macOS and Windows
|
|
25
|
+
else:
|
|
26
|
+
raise Exception("Unsupported operating system", os_type)
|
|
27
|
+
|
|
28
|
+
_path = os.path.join(env.cache_dir, config["dest"])
|
|
29
|
+
content = env.controller.get_file(config_path)
|
|
30
|
+
|
|
31
|
+
if not content:
|
|
32
|
+
logger.error("Failed to get GIMP config file.")
|
|
33
|
+
return None
|
|
34
|
+
|
|
35
|
+
with open(_path, "wb") as f:
|
|
36
|
+
f.write(content)
|
|
37
|
+
|
|
38
|
+
return _path
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import tempfile
|
|
3
|
+
import xml.etree.ElementTree as ET
|
|
4
|
+
import zipfile
|
|
5
|
+
from typing import Dict
|
|
6
|
+
|
|
7
|
+
from desktop_env.evaluators.getters.file import get_vm_file
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def get_background_image_in_slide(env, config: Dict[str, str]):
|
|
11
|
+
ppt_file_path, slide_index, dest = config["ppt_file_path"], int(config["slide_index"]), config["dest"]
|
|
12
|
+
image_id, image_file_path = None, None
|
|
13
|
+
|
|
14
|
+
ppt_file_localhost_path = get_vm_file(env, {"path": ppt_file_path, "dest": os.path.split(ppt_file_path)[-1]})
|
|
15
|
+
|
|
16
|
+
with zipfile.ZipFile(ppt_file_localhost_path, 'r') as myzip:
|
|
17
|
+
slide1_xml_file = 'ppt/slides/slide{}.xml'.format(slide_index + 1)
|
|
18
|
+
# firstly, check whether the background image is used in the slide
|
|
19
|
+
if slide1_xml_file not in myzip.namelist(): return None
|
|
20
|
+
with myzip.open(slide1_xml_file) as f:
|
|
21
|
+
# Parse the XML tree from the relationships file
|
|
22
|
+
tree = ET.parse(f)
|
|
23
|
+
root = tree.getroot()
|
|
24
|
+
bg_tag = "{http://schemas.openxmlformats.org/presentationml/2006/main}bgPr"
|
|
25
|
+
image_tag = "{http://schemas.openxmlformats.org/drawingml/2006/main}blip"
|
|
26
|
+
attr_tag = "{http://schemas.openxmlformats.org/officeDocument/2006/relationships}embed"
|
|
27
|
+
for child in root.iter(bg_tag):
|
|
28
|
+
try:
|
|
29
|
+
for element in child.iter(image_tag):
|
|
30
|
+
image_id = element.attrib[attr_tag]
|
|
31
|
+
break
|
|
32
|
+
except: pass
|
|
33
|
+
if image_id is not None: break
|
|
34
|
+
else: return None
|
|
35
|
+
|
|
36
|
+
# next, extract the background image from the slide
|
|
37
|
+
slide1_rels_file = 'ppt/slides/_rels/slide{}.xml.rels'.format(slide_index + 1)
|
|
38
|
+
if slide1_rels_file in myzip.namelist():
|
|
39
|
+
with myzip.open(slide1_rels_file) as f:
|
|
40
|
+
# Parse the XML tree from the relationships file
|
|
41
|
+
tree = ET.parse(f)
|
|
42
|
+
root = tree.getroot()
|
|
43
|
+
# Define the namespace used in the relationships file
|
|
44
|
+
namespaces = {'r': 'http://schemas.openxmlformats.org/package/2006/relationships'}
|
|
45
|
+
# Look for all relationship elements that have a type attribute for image
|
|
46
|
+
for rel in root.findall('r:Relationship', namespaces):
|
|
47
|
+
# Check if the relationship is for an image file
|
|
48
|
+
if 'image' in rel.attrib['Type'] and rel.attrib['Id'] == image_id:
|
|
49
|
+
target = rel.attrib['Target']
|
|
50
|
+
if target.startswith('..'):
|
|
51
|
+
# Resolve the relative path to get the correct path within the zip file
|
|
52
|
+
image_file_path = os.path.normpath(os.path.join('ppt/slides', target))
|
|
53
|
+
# Replace backslashes with forward slashes for ZIP compatibility
|
|
54
|
+
image_file_path = image_file_path.replace('\\', '/')
|
|
55
|
+
tmpdirname = os.path.dirname(ppt_file_localhost_path)
|
|
56
|
+
myzip.extract(image_file_path, tmpdirname)
|
|
57
|
+
image_file_path = os.path.join(tmpdirname, image_file_path)
|
|
58
|
+
return image_file_path
|
|
59
|
+
else: # absolute path
|
|
60
|
+
assert target.startswith("file://"), target
|
|
61
|
+
image_file_path = target[7:]
|
|
62
|
+
break
|
|
63
|
+
if image_file_path is None:
|
|
64
|
+
return None
|
|
65
|
+
|
|
66
|
+
else:
|
|
67
|
+
# Get the audio file from vm and return the file path in the host
|
|
68
|
+
return get_vm_file(env, {"path": image_file_path, "dest": dest})
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def get_audio_in_slide(env, config: Dict[str, str]):
|
|
72
|
+
ppt_file_path, slide_index, dest = config["ppt_file_path"], int(config["slide_index"]), config["dest"]
|
|
73
|
+
|
|
74
|
+
# Open the .pptx file as a zip file, fixme: now we assume there is only one audio file in the slides
|
|
75
|
+
audio_file_path = None
|
|
76
|
+
|
|
77
|
+
ppt_file_localhost_path = get_vm_file(env, {"path": ppt_file_path, "dest": os.path.split(ppt_file_path)[-1]})
|
|
78
|
+
|
|
79
|
+
with zipfile.ZipFile(ppt_file_localhost_path, 'r') as myzip:
|
|
80
|
+
# Find the relationships XML file for the first slide
|
|
81
|
+
slide1_rels_file = 'ppt/slides/_rels/slide{}.xml.rels'.format(slide_index + 1)
|
|
82
|
+
if slide1_rels_file in myzip.namelist():
|
|
83
|
+
with myzip.open(slide1_rels_file) as f:
|
|
84
|
+
# Parse the XML tree from the relationships file
|
|
85
|
+
tree = ET.parse(f)
|
|
86
|
+
root = tree.getroot()
|
|
87
|
+
# Define the namespace used in the relationships file
|
|
88
|
+
namespaces = {'r': 'http://schemas.openxmlformats.org/package/2006/relationships'}
|
|
89
|
+
# Look for all relationship elements that have a type attribute for audio
|
|
90
|
+
for rel in root.findall('r:Relationship', namespaces):
|
|
91
|
+
# Check if the relationship is for an audio file
|
|
92
|
+
if 'audio' in rel.attrib['Type']:
|
|
93
|
+
# The audio can be embedded inside the file or linked to an external file
|
|
94
|
+
# Get the target attribute which contains the audio file path
|
|
95
|
+
target = rel.attrib['Target']
|
|
96
|
+
|
|
97
|
+
if target.startswith('..'):
|
|
98
|
+
# Resolve the relative path to get the correct path within the zip file
|
|
99
|
+
audio_file_path = os.path.normpath(os.path.join('ppt/slides', target))
|
|
100
|
+
# Replace backslashes with forward slashes for ZIP compatibility
|
|
101
|
+
audio_file_path = audio_file_path.replace('\\', '/')
|
|
102
|
+
|
|
103
|
+
# Create a temporary directory to extract the audio file
|
|
104
|
+
tmpdirname = os.path.dirname(ppt_file_localhost_path)
|
|
105
|
+
myzip.extract(audio_file_path, tmpdirname)
|
|
106
|
+
audio_file_path = os.path.join(tmpdirname, audio_file_path)
|
|
107
|
+
return audio_file_path
|
|
108
|
+
# with tempfile.TemporaryDirectory() as tmpdirname:
|
|
109
|
+
# # Extract the audio file
|
|
110
|
+
# myzip.extract(audio_file_path, tmpdirname)
|
|
111
|
+
# # Get the full path of the extracted audio file
|
|
112
|
+
# extracted_audio_path = os.path.join(tmpdirname, audio_file_path)
|
|
113
|
+
# # Return the extracted audio file path
|
|
114
|
+
# audio_file_path = extracted_audio_path
|
|
115
|
+
else:
|
|
116
|
+
# the audio file is external to the .pptx file
|
|
117
|
+
# Return the audio file path
|
|
118
|
+
assert target.startswith("file://"), target
|
|
119
|
+
audio_file_path = target[7:]
|
|
120
|
+
break
|
|
121
|
+
if audio_file_path is None:
|
|
122
|
+
return None
|
|
123
|
+
|
|
124
|
+
else:
|
|
125
|
+
# Get the audio file from vm and return the file path in the host
|
|
126
|
+
return get_vm_file(env, {"path": audio_file_path, "dest": dest})
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from typing import Union
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def get_vm_screen_size(env, config: dict) -> dict:
|
|
6
|
+
return env.controller.get_vm_screen_size()
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def get_vm_window_size(env, config: dict) -> dict:
|
|
10
|
+
return env.controller.get_vm_window_size(app_class_name=config["app_class_name"])
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def get_vm_wallpaper(env, config: dict) -> Union[str, bytes]:
|
|
14
|
+
_path = os.path.join(env.cache_dir, config["dest"])
|
|
15
|
+
|
|
16
|
+
content = env.controller.get_vm_wallpaper()
|
|
17
|
+
with open(_path, "wb") as f:
|
|
18
|
+
f.write(content)
|
|
19
|
+
|
|
20
|
+
return _path
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def get_list_directory(env, config: dict) -> dict:
|
|
24
|
+
return env.controller.get_vm_directory_tree(config["path"])
|