├── README.md
└── workflow
├── 1450496C-74BC-4EDE-930B-ADC6027C5449.png
├── 5F417B1B-FC67-40CE-8084-167913379DDE.png
├── 692C13A0-ADC1-4E71-8FA4-0157FF14C88F.png
├── 7155F88D-55F6-4608-BC2E-554BA0780537.png
├── 71AAE21C-028C-45CE-AB44-1378572652A9.png
├── 864A20DF-C5E2-444E-B084-9CD126BED7DF.png
├── 9F22BA12-18B5-4FA5-B429-12DB07DBDC90.png
├── A0CE40D8-D874-48D7-903B-0C91A6B2F7DC.png
├── AD6FA975-C31E-4D56-BF48-EBBC634EB89E.png
├── AFF1A33C-2AE0-4CA1-8B00-04BB87A5F7FE.png
├── B066EEAB-4F3C-4516-9F00-E8FD7A5439B6.png
├── C0967D8A-BEF8-44B5-BF2A-06BD127C8D73.png
├── CBBA9D5E-DB01-490E-9C0F-F33A07F09E3A.png
├── List Filter Images
├── 3ab9aedf8fbd94a12254709139ffcee0a288338b.png
└── b171fc8163f973fcfe9f43d328811fe1096dcebe.png
├── _remote
├── images
│ ├── items
│ │ ├── 40AD86DC-2F23-492C-B2D1-08929C492E0B.png
│ │ ├── 7A4C66E5-7DBE-4D49-B3F9-7B48997E5DE4.png
│ │ ├── 87ADC83C-BEC2-4413-9593-B84836DF334E.png
│ │ ├── 9EE11D58-1E5E-4998-9244-816938F5E03C.png
│ │ ├── AC51B392-A245-467B-BE86-56F7A911784C.png
│ │ ├── C966F8A3-DEF0-4959-AFB3-02D7591DDC07.png
│ │ ├── DD79A2C0-84C6-4BBF-BF3E-F30DA82567A2.png
│ │ └── E689AAFE-047D-4F33-AF0F-F4C0162707BA.png
│ └── pages
│ │ └── 1087F40F-223B-4FD8-9D7E-3E3AFBBFCB28.png
└── pages
│ ├── C7966D69-3C00-4D1C-8C90-FC19D2DEE491.data
│ └── pages.data
├── icon.png
├── icons
├── input.png
├── input_selected.png
├── output.png
└── output_selected.png
├── info.plist
└── main.swift
/README.md:
--------------------------------------------------------------------------------
1 | # Alfred App Audio Switcher Workflow
2 | This is a workflow for [Alfred](https://alfred.app/).
3 |
4 | ## About the Workflow
5 | This workflow supports quickly switching sound input and output devices.
6 |
7 | It offers hotkeys to quickly switch between three input favorites and output favorites.
8 | You can also use a single hotkey to rotate among the favorites in sequence.
9 | Those can also be triggered using Alfred Remote.
10 |
11 | ### Listing Devices
12 | Once installed, use the `fetchaudiodevices` command in Alfred. Once you have selected either "Outputs" or "Inputs",
13 | the workflow will copy a list of devices to the Clipboard. This is a convenience feature to support filling the
14 | *Ignorelist*, *Output Favorites* and *Input Favorites*. (See below)
15 |
16 | ### Parameter Examples
17 |
18 | #### Ignorelist
19 | The value
20 | ```
21 | External Headphones
22 | iPhone Microphone
23 | ```
24 | causes both listed devices not to be listed when selecting inputs or outputs.
25 |
26 |
27 | #### Output Favorites
28 | The value
29 | ```
30 | MacBook Pro Speakers
31 | RØDE Connect Virtual
32 | External Screen
33 | ```
34 | means the following:
35 | - *⌘ + F1* will select MacBook Pro Speakers.
36 | - *⌘ + F2* will select RØDE Connect Virtual.
37 | - *⌘ + F3* will select External Screen.
38 |
39 | #### Input Favorites
40 | The value
41 | ```
42 | MacBook Pro Microphone
43 | RØDE Connect Stream
44 | ```
45 | means the following:
46 | - *⌥ + F1* will select MacBook Pro Microphone.
47 | - *⌥ + F2* will select RØDE Connect Stream.
48 | - *⌥ + F3* will have no effect.
49 |
50 | ## Like this Workflow?
51 | [](https://buymeacoffee.com/tobimende)
52 |
--------------------------------------------------------------------------------
/workflow/1450496C-74BC-4EDE-930B-ADC6027C5449.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TobiasMende/alfred-audio-switcher/ea1993a5a654515e2a412763fc70242e96ea8141/workflow/1450496C-74BC-4EDE-930B-ADC6027C5449.png
--------------------------------------------------------------------------------
/workflow/5F417B1B-FC67-40CE-8084-167913379DDE.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TobiasMende/alfred-audio-switcher/ea1993a5a654515e2a412763fc70242e96ea8141/workflow/5F417B1B-FC67-40CE-8084-167913379DDE.png
--------------------------------------------------------------------------------
/workflow/692C13A0-ADC1-4E71-8FA4-0157FF14C88F.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TobiasMende/alfred-audio-switcher/ea1993a5a654515e2a412763fc70242e96ea8141/workflow/692C13A0-ADC1-4E71-8FA4-0157FF14C88F.png
--------------------------------------------------------------------------------
/workflow/7155F88D-55F6-4608-BC2E-554BA0780537.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TobiasMende/alfred-audio-switcher/ea1993a5a654515e2a412763fc70242e96ea8141/workflow/7155F88D-55F6-4608-BC2E-554BA0780537.png
--------------------------------------------------------------------------------
/workflow/71AAE21C-028C-45CE-AB44-1378572652A9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TobiasMende/alfred-audio-switcher/ea1993a5a654515e2a412763fc70242e96ea8141/workflow/71AAE21C-028C-45CE-AB44-1378572652A9.png
--------------------------------------------------------------------------------
/workflow/864A20DF-C5E2-444E-B084-9CD126BED7DF.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TobiasMende/alfred-audio-switcher/ea1993a5a654515e2a412763fc70242e96ea8141/workflow/864A20DF-C5E2-444E-B084-9CD126BED7DF.png
--------------------------------------------------------------------------------
/workflow/9F22BA12-18B5-4FA5-B429-12DB07DBDC90.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TobiasMende/alfred-audio-switcher/ea1993a5a654515e2a412763fc70242e96ea8141/workflow/9F22BA12-18B5-4FA5-B429-12DB07DBDC90.png
--------------------------------------------------------------------------------
/workflow/A0CE40D8-D874-48D7-903B-0C91A6B2F7DC.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TobiasMende/alfred-audio-switcher/ea1993a5a654515e2a412763fc70242e96ea8141/workflow/A0CE40D8-D874-48D7-903B-0C91A6B2F7DC.png
--------------------------------------------------------------------------------
/workflow/AD6FA975-C31E-4D56-BF48-EBBC634EB89E.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TobiasMende/alfred-audio-switcher/ea1993a5a654515e2a412763fc70242e96ea8141/workflow/AD6FA975-C31E-4D56-BF48-EBBC634EB89E.png
--------------------------------------------------------------------------------
/workflow/AFF1A33C-2AE0-4CA1-8B00-04BB87A5F7FE.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TobiasMende/alfred-audio-switcher/ea1993a5a654515e2a412763fc70242e96ea8141/workflow/AFF1A33C-2AE0-4CA1-8B00-04BB87A5F7FE.png
--------------------------------------------------------------------------------
/workflow/B066EEAB-4F3C-4516-9F00-E8FD7A5439B6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TobiasMende/alfred-audio-switcher/ea1993a5a654515e2a412763fc70242e96ea8141/workflow/B066EEAB-4F3C-4516-9F00-E8FD7A5439B6.png
--------------------------------------------------------------------------------
/workflow/C0967D8A-BEF8-44B5-BF2A-06BD127C8D73.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TobiasMende/alfred-audio-switcher/ea1993a5a654515e2a412763fc70242e96ea8141/workflow/C0967D8A-BEF8-44B5-BF2A-06BD127C8D73.png
--------------------------------------------------------------------------------
/workflow/CBBA9D5E-DB01-490E-9C0F-F33A07F09E3A.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TobiasMende/alfred-audio-switcher/ea1993a5a654515e2a412763fc70242e96ea8141/workflow/CBBA9D5E-DB01-490E-9C0F-F33A07F09E3A.png
--------------------------------------------------------------------------------
/workflow/List Filter Images/3ab9aedf8fbd94a12254709139ffcee0a288338b.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TobiasMende/alfred-audio-switcher/ea1993a5a654515e2a412763fc70242e96ea8141/workflow/List Filter Images/3ab9aedf8fbd94a12254709139ffcee0a288338b.png
--------------------------------------------------------------------------------
/workflow/List Filter Images/b171fc8163f973fcfe9f43d328811fe1096dcebe.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TobiasMende/alfred-audio-switcher/ea1993a5a654515e2a412763fc70242e96ea8141/workflow/List Filter Images/b171fc8163f973fcfe9f43d328811fe1096dcebe.png
--------------------------------------------------------------------------------
/workflow/_remote/images/items/40AD86DC-2F23-492C-B2D1-08929C492E0B.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TobiasMende/alfred-audio-switcher/ea1993a5a654515e2a412763fc70242e96ea8141/workflow/_remote/images/items/40AD86DC-2F23-492C-B2D1-08929C492E0B.png
--------------------------------------------------------------------------------
/workflow/_remote/images/items/7A4C66E5-7DBE-4D49-B3F9-7B48997E5DE4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TobiasMende/alfred-audio-switcher/ea1993a5a654515e2a412763fc70242e96ea8141/workflow/_remote/images/items/7A4C66E5-7DBE-4D49-B3F9-7B48997E5DE4.png
--------------------------------------------------------------------------------
/workflow/_remote/images/items/87ADC83C-BEC2-4413-9593-B84836DF334E.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TobiasMende/alfred-audio-switcher/ea1993a5a654515e2a412763fc70242e96ea8141/workflow/_remote/images/items/87ADC83C-BEC2-4413-9593-B84836DF334E.png
--------------------------------------------------------------------------------
/workflow/_remote/images/items/9EE11D58-1E5E-4998-9244-816938F5E03C.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TobiasMende/alfred-audio-switcher/ea1993a5a654515e2a412763fc70242e96ea8141/workflow/_remote/images/items/9EE11D58-1E5E-4998-9244-816938F5E03C.png
--------------------------------------------------------------------------------
/workflow/_remote/images/items/AC51B392-A245-467B-BE86-56F7A911784C.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TobiasMende/alfred-audio-switcher/ea1993a5a654515e2a412763fc70242e96ea8141/workflow/_remote/images/items/AC51B392-A245-467B-BE86-56F7A911784C.png
--------------------------------------------------------------------------------
/workflow/_remote/images/items/C966F8A3-DEF0-4959-AFB3-02D7591DDC07.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TobiasMende/alfred-audio-switcher/ea1993a5a654515e2a412763fc70242e96ea8141/workflow/_remote/images/items/C966F8A3-DEF0-4959-AFB3-02D7591DDC07.png
--------------------------------------------------------------------------------
/workflow/_remote/images/items/DD79A2C0-84C6-4BBF-BF3E-F30DA82567A2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TobiasMende/alfred-audio-switcher/ea1993a5a654515e2a412763fc70242e96ea8141/workflow/_remote/images/items/DD79A2C0-84C6-4BBF-BF3E-F30DA82567A2.png
--------------------------------------------------------------------------------
/workflow/_remote/images/items/E689AAFE-047D-4F33-AF0F-F4C0162707BA.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TobiasMende/alfred-audio-switcher/ea1993a5a654515e2a412763fc70242e96ea8141/workflow/_remote/images/items/E689AAFE-047D-4F33-AF0F-F4C0162707BA.png
--------------------------------------------------------------------------------
/workflow/_remote/images/pages/1087F40F-223B-4FD8-9D7E-3E3AFBBFCB28.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TobiasMende/alfred-audio-switcher/ea1993a5a654515e2a412763fc70242e96ea8141/workflow/_remote/images/pages/1087F40F-223B-4FD8-9D7E-3E3AFBBFCB28.png
--------------------------------------------------------------------------------
/workflow/_remote/pages/C7966D69-3C00-4D1C-8C90-FC19D2DEE491.data:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | gridsize
6 | 4
7 | hidelabels
8 |
9 | iconid
10 | 1087F40F-223B-4FD8-9D7E-3E3AFBBFCB28
11 | iconisuserspecified
12 |
13 | items
14 |
15 |
16 | actionconfig
17 |
18 | autoworkflowuid
19 |
20 | confirm
21 |
22 | triggerid
23 | io.mende.audioswitcher.out
24 |
25 | actionuid
26 | remote.alfred.runworkflow
27 | buttoniconid
28 | 40AD86DC-2F23-492C-B2D1-08929C492E0B
29 | buttonlabel
30 | Select Output
31 | itemuid
32 | 005EAC2D-B938-4C5C-8561-F50457AB0B50
33 |
34 |
35 | actionconfig
36 |
37 | autoworkflowuid
38 |
39 | confirm
40 |
41 | triggerid
42 | io.mende.audioswitcher.in
43 |
44 | actionuid
45 | remote.alfred.runworkflow
46 | buttoniconid
47 | 87ADC83C-BEC2-4413-9593-B84836DF334E
48 | buttonlabel
49 | Select Input
50 | itemuid
51 | 75670CDA-C99C-4766-805C-60F5BBA8D1A8
52 |
53 |
54 |
55 |
56 | actionconfig
57 |
58 | autoworkflowuid
59 |
60 | confirm
61 |
62 | triggerid
63 | io.mende.audioswitcher.out1
64 |
65 | actionuid
66 | remote.alfred.runworkflow
67 | buttoniconid
68 | DD79A2C0-84C6-4BBF-BF3E-F30DA82567A2
69 | buttonlabel
70 | Select Output 1
71 | itemuid
72 | 6E42C8C1-CCC5-4E1A-92A6-70DE3109840D
73 |
74 |
75 | actionconfig
76 |
77 | autoworkflowuid
78 |
79 | confirm
80 |
81 | triggerid
82 | io.mende.audioswitcher.out2
83 |
84 | actionuid
85 | remote.alfred.runworkflow
86 | buttoniconid
87 | E689AAFE-047D-4F33-AF0F-F4C0162707BA
88 | buttonlabel
89 | Select Output 2
90 | itemuid
91 | ECF88431-BA01-4627-B690-EC1C5698DB22
92 |
93 |
94 | actionconfig
95 |
96 | autoworkflowuid
97 |
98 | confirm
99 |
100 | triggerid
101 | io.mende.audioswitcher.out3
102 |
103 | actionuid
104 | remote.alfred.runworkflow
105 | buttoniconid
106 | C966F8A3-DEF0-4959-AFB3-02D7591DDC07
107 | buttonlabel
108 | Select Output 3
109 | itemuid
110 | 21C9200A-0FC8-4E1E-B75B-F2162281402A
111 |
112 |
113 |
114 | actionconfig
115 |
116 | autoworkflowuid
117 |
118 | confirm
119 |
120 | triggerid
121 | io.mende.audioswitcher.in1
122 |
123 | actionuid
124 | remote.alfred.runworkflow
125 | buttoniconid
126 | 9EE11D58-1E5E-4998-9244-816938F5E03C
127 | buttonlabel
128 | Select Input 1
129 | itemuid
130 | 6A6B50F8-B17E-4129-B736-C259BE1B6312
131 |
132 |
133 | actionconfig
134 |
135 | autoworkflowuid
136 |
137 | confirm
138 |
139 | triggerid
140 | io.mende.audioswitcher.in2
141 |
142 | actionuid
143 | remote.alfred.runworkflow
144 | buttoniconid
145 | 7A4C66E5-7DBE-4D49-B3F9-7B48997E5DE4
146 | buttonlabel
147 | Select Input 2
148 | itemuid
149 | 6FEAAFA1-D37B-4A92-916A-81840C79F805
150 |
151 |
152 | actionconfig
153 |
154 | autoworkflowuid
155 |
156 | confirm
157 |
158 | triggerid
159 | io.mende.audioswitcher.in3
160 |
161 | actionuid
162 | remote.alfred.runworkflow
163 | buttoniconid
164 | AC51B392-A245-467B-BE86-56F7A911784C
165 | buttonlabel
166 | Select Input 3
167 | itemuid
168 | A36A4EAA-DDFC-458B-B32F-855B916722F9
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 | itemsall
177 |
178 |
179 | actionconfig
180 |
181 | autoworkflowuid
182 |
183 | confirm
184 |
185 | triggerid
186 | io.mende.audioswitcher.out
187 |
188 | actionuid
189 | remote.alfred.runworkflow
190 | buttoniconid
191 | 40AD86DC-2F23-492C-B2D1-08929C492E0B
192 | buttonlabel
193 | Select Output
194 | itemuid
195 | 005EAC2D-B938-4C5C-8561-F50457AB0B50
196 |
197 |
198 | actionconfig
199 |
200 | autoworkflowuid
201 |
202 | confirm
203 |
204 | triggerid
205 | io.mende.audioswitcher.in
206 |
207 | actionuid
208 | remote.alfred.runworkflow
209 | buttoniconid
210 | 87ADC83C-BEC2-4413-9593-B84836DF334E
211 | buttonlabel
212 | Select Input
213 | itemuid
214 | 75670CDA-C99C-4766-805C-60F5BBA8D1A8
215 |
216 |
217 |
218 |
219 | actionconfig
220 |
221 | autoworkflowuid
222 |
223 | confirm
224 |
225 | triggerid
226 | io.mende.audioswitcher.out1
227 |
228 | actionuid
229 | remote.alfred.runworkflow
230 | buttoniconid
231 | DD79A2C0-84C6-4BBF-BF3E-F30DA82567A2
232 | buttonlabel
233 | Select Output 1
234 | itemuid
235 | 6E42C8C1-CCC5-4E1A-92A6-70DE3109840D
236 |
237 |
238 | actionconfig
239 |
240 | autoworkflowuid
241 |
242 | confirm
243 |
244 | triggerid
245 | io.mende.audioswitcher.out2
246 |
247 | actionuid
248 | remote.alfred.runworkflow
249 | buttoniconid
250 | E689AAFE-047D-4F33-AF0F-F4C0162707BA
251 | buttonlabel
252 | Select Output 2
253 | itemuid
254 | ECF88431-BA01-4627-B690-EC1C5698DB22
255 |
256 |
257 | actionconfig
258 |
259 | autoworkflowuid
260 |
261 | confirm
262 |
263 | triggerid
264 | io.mende.audioswitcher.out3
265 |
266 | actionuid
267 | remote.alfred.runworkflow
268 | buttoniconid
269 | C966F8A3-DEF0-4959-AFB3-02D7591DDC07
270 | buttonlabel
271 | Select Output 3
272 | itemuid
273 | 21C9200A-0FC8-4E1E-B75B-F2162281402A
274 |
275 |
276 |
277 | actionconfig
278 |
279 | autoworkflowuid
280 |
281 | confirm
282 |
283 | triggerid
284 | io.mende.audioswitcher.in1
285 |
286 | actionuid
287 | remote.alfred.runworkflow
288 | buttoniconid
289 | 9EE11D58-1E5E-4998-9244-816938F5E03C
290 | buttonlabel
291 | Select Input 1
292 | itemuid
293 | 6A6B50F8-B17E-4129-B736-C259BE1B6312
294 |
295 |
296 | actionconfig
297 |
298 | autoworkflowuid
299 |
300 | confirm
301 |
302 | triggerid
303 | io.mende.audioswitcher.in2
304 |
305 | actionuid
306 | remote.alfred.runworkflow
307 | buttoniconid
308 | 7A4C66E5-7DBE-4D49-B3F9-7B48997E5DE4
309 | buttonlabel
310 | Select Input 2
311 | itemuid
312 | 6FEAAFA1-D37B-4A92-916A-81840C79F805
313 |
314 |
315 | actionconfig
316 |
317 | autoworkflowuid
318 |
319 | confirm
320 |
321 | triggerid
322 | io.mende.audioswitcher.in3
323 |
324 | actionuid
325 | remote.alfred.runworkflow
326 | buttoniconid
327 | AC51B392-A245-467B-BE86-56F7A911784C
328 | buttonlabel
329 | Select Input 3
330 | itemuid
331 | A36A4EAA-DDFC-458B-B32F-855B916722F9
332 |
333 |
334 |
335 |
336 |
337 |
338 |
339 |
340 |
341 |
342 |
343 |
344 |
345 |
346 |
347 |
348 |
349 |
350 |
351 |
352 |
353 |
354 |
355 |
356 |
357 |
358 |
359 | subtitle
360 | Switching inputs and outputs
361 | title
362 | Audio Switcher
363 |
364 |
365 |
--------------------------------------------------------------------------------
/workflow/_remote/pages/pages.data:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | pages
6 |
7 | C7966D69-3C00-4D1C-8C90-FC19D2DEE491
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/workflow/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TobiasMende/alfred-audio-switcher/ea1993a5a654515e2a412763fc70242e96ea8141/workflow/icon.png
--------------------------------------------------------------------------------
/workflow/icons/input.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TobiasMende/alfred-audio-switcher/ea1993a5a654515e2a412763fc70242e96ea8141/workflow/icons/input.png
--------------------------------------------------------------------------------
/workflow/icons/input_selected.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TobiasMende/alfred-audio-switcher/ea1993a5a654515e2a412763fc70242e96ea8141/workflow/icons/input_selected.png
--------------------------------------------------------------------------------
/workflow/icons/output.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TobiasMende/alfred-audio-switcher/ea1993a5a654515e2a412763fc70242e96ea8141/workflow/icons/output.png
--------------------------------------------------------------------------------
/workflow/icons/output_selected.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TobiasMende/alfred-audio-switcher/ea1993a5a654515e2a412763fc70242e96ea8141/workflow/icons/output_selected.png
--------------------------------------------------------------------------------
/workflow/info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | bundleid
6 | io.mende.alfredapp-audioswitcher
7 | category
8 | Tools
9 | connections
10 |
11 | 00704246-FE25-4B27-86E9-2EB6EDF00D67
12 |
13 |
14 | destinationuid
15 | 09EBB07A-0EF4-4CDB-96E1-7A4EDC0561F4
16 | modifiers
17 | 0
18 | modifiersubtext
19 |
20 | vitoclose
21 |
22 |
23 |
24 | 01427E94-9408-4123-A9BC-DF6185AB3A85
25 |
26 |
27 | destinationuid
28 | 39B059B1-CD01-4C2D-8907-1E2F9262CD04
29 | modifiers
30 | 0
31 | modifiersubtext
32 |
33 | vitoclose
34 |
35 |
36 |
37 | 1450496C-74BC-4EDE-930B-ADC6027C5449
38 |
39 |
40 | destinationuid
41 | FCE19CD4-E3AE-4361-8B59-F357914A629C
42 | modifiers
43 | 0
44 | modifiersubtext
45 |
46 | vitoclose
47 |
48 |
49 |
50 | 1AF283DE-8EDC-4006-AD54-91F4C226E5C9
51 |
52 |
53 | destinationuid
54 | BA2ED978-7611-4D11-9EA1-8A0A1E275FD0
55 | modifiers
56 | 0
57 | modifiersubtext
58 |
59 | vitoclose
60 |
61 |
62 |
63 | 3AE8EB58-5F7D-49B6-98C1-4BAE5E79FC2E
64 |
65 |
66 | destinationuid
67 | 39B059B1-CD01-4C2D-8907-1E2F9262CD04
68 | modifiers
69 | 0
70 | modifiersubtext
71 |
72 | vitoclose
73 |
74 |
75 |
76 | 3B2897E7-E242-4504-A297-602265B0011F
77 |
78 |
79 | destinationuid
80 | 39B059B1-CD01-4C2D-8907-1E2F9262CD04
81 | modifiers
82 | 0
83 | modifiersubtext
84 |
85 | vitoclose
86 |
87 |
88 |
89 | 5F417B1B-FC67-40CE-8084-167913379DDE
90 |
91 |
92 | destinationuid
93 | BA2ED978-7611-4D11-9EA1-8A0A1E275FD0
94 | modifiers
95 | 0
96 | modifiersubtext
97 |
98 | vitoclose
99 |
100 |
101 |
102 | 692C13A0-ADC1-4E71-8FA4-0157FF14C88F
103 |
104 |
105 | destinationuid
106 | 01427E94-9408-4123-A9BC-DF6185AB3A85
107 | modifiers
108 | 0
109 | modifiersubtext
110 |
111 | vitoclose
112 |
113 |
114 |
115 | 6CDEB1A2-F0E3-4C17-955A-7AA171D8C899
116 |
117 |
118 | destinationuid
119 | 3B2897E7-E242-4504-A297-602265B0011F
120 | modifiers
121 | 0
122 | modifiersubtext
123 |
124 | vitoclose
125 |
126 |
127 |
128 | 6EEBB03A-5A12-4883-BEF4-2DAC11BF0FC0
129 |
130 |
131 | destinationuid
132 | 3B2897E7-E242-4504-A297-602265B0011F
133 | modifiers
134 | 0
135 | modifiersubtext
136 |
137 | vitoclose
138 |
139 |
140 |
141 | 7155F88D-55F6-4608-BC2E-554BA0780537
142 |
143 |
144 | destinationuid
145 | F6A49F45-6CB5-4CDF-BB3E-79B7715ACA0F
146 | modifiers
147 | 0
148 | modifiersubtext
149 |
150 | vitoclose
151 |
152 |
153 |
154 | 71AAE21C-028C-45CE-AB44-1378572652A9
155 |
156 |
157 | destinationuid
158 | 1450496C-74BC-4EDE-930B-ADC6027C5449
159 | modifiers
160 | 0
161 | modifiersubtext
162 |
163 | vitoclose
164 |
165 |
166 |
167 | 7A1840A7-3844-4206-9B9E-B0602C41361E
168 |
169 |
170 | destinationuid
171 | F6A49F45-6CB5-4CDF-BB3E-79B7715ACA0F
172 | modifiers
173 | 0
174 | modifiersubtext
175 |
176 | vitoclose
177 |
178 |
179 |
180 | 82D538CB-521F-4F59-99A5-91AFC57E3CF3
181 |
182 |
183 | destinationuid
184 | F6A49F45-6CB5-4CDF-BB3E-79B7715ACA0F
185 | modifiers
186 | 0
187 | modifiersubtext
188 |
189 | vitoclose
190 |
191 |
192 |
193 | 86324099-F14A-4ADC-9C93-992F23163004
194 |
195 |
196 | destinationuid
197 | 01427E94-9408-4123-A9BC-DF6185AB3A85
198 | modifiers
199 | 0
200 | modifiersubtext
201 |
202 | vitoclose
203 |
204 |
205 |
206 | 864A20DF-C5E2-444E-B084-9CD126BED7DF
207 |
208 |
209 | destinationuid
210 | 3B2897E7-E242-4504-A297-602265B0011F
211 | modifiers
212 | 0
213 | modifiersubtext
214 |
215 | vitoclose
216 |
217 |
218 |
219 | 9D6F6749-4476-48A0-BF59-8B80656B1F51
220 |
221 |
222 | destinationuid
223 | 3B2897E7-E242-4504-A297-602265B0011F
224 | modifiers
225 | 0
226 | modifiersubtext
227 |
228 | vitoclose
229 |
230 |
231 |
232 | 9F22BA12-18B5-4FA5-B429-12DB07DBDC90
233 |
234 |
235 | destinationuid
236 | C46B89C0-5C32-4E45-84C4-714DAA27F2BD
237 | modifiers
238 | 0
239 | modifiersubtext
240 |
241 | vitoclose
242 |
243 |
244 |
245 | A0CE40D8-D874-48D7-903B-0C91A6B2F7DC
246 |
247 |
248 | destinationuid
249 | 3B2897E7-E242-4504-A297-602265B0011F
250 | modifiers
251 | 0
252 | modifiersubtext
253 |
254 | vitoclose
255 |
256 |
257 |
258 | A3266036-2FB4-4E74-B315-F9951154B58F
259 |
260 |
261 | destinationuid
262 | F6A49F45-6CB5-4CDF-BB3E-79B7715ACA0F
263 | modifiers
264 | 0
265 | modifiersubtext
266 |
267 | vitoclose
268 |
269 |
270 |
271 | AD6FA975-C31E-4D56-BF48-EBBC634EB89E
272 |
273 |
274 | destinationuid
275 | 3B2897E7-E242-4504-A297-602265B0011F
276 | modifiers
277 | 0
278 | modifiersubtext
279 |
280 | vitoclose
281 |
282 |
283 |
284 | AFF1A33C-2AE0-4CA1-8B00-04BB87A5F7FE
285 |
286 |
287 | destinationuid
288 | B066EEAB-4F3C-4516-9F00-E8FD7A5439B6
289 | modifiers
290 | 0
291 | modifiersubtext
292 |
293 | vitoclose
294 |
295 |
296 |
297 | B066EEAB-4F3C-4516-9F00-E8FD7A5439B6
298 |
299 |
300 | destinationuid
301 | 3AE8EB58-5F7D-49B6-98C1-4BAE5E79FC2E
302 | modifiers
303 | 0
304 | modifiersubtext
305 |
306 | vitoclose
307 |
308 |
309 |
310 | BA2ED978-7611-4D11-9EA1-8A0A1E275FD0
311 |
312 |
313 | destinationuid
314 | 39B059B1-CD01-4C2D-8907-1E2F9262CD04
315 | modifiers
316 | 0
317 | modifiersubtext
318 |
319 | vitoclose
320 |
321 |
322 |
323 | C0967D8A-BEF8-44B5-BF2A-06BD127C8D73
324 |
325 |
326 | destinationuid
327 | F6A49F45-6CB5-4CDF-BB3E-79B7715ACA0F
328 | modifiers
329 | 0
330 | modifiersubtext
331 |
332 | vitoclose
333 |
334 |
335 |
336 | C46B89C0-5C32-4E45-84C4-714DAA27F2BD
337 |
338 |
339 | destinationuid
340 | 00704246-FE25-4B27-86E9-2EB6EDF00D67
341 | modifiers
342 | 0
343 | modifiersubtext
344 |
345 | vitoclose
346 |
347 |
348 |
349 | CBBA9D5E-DB01-490E-9C0F-F33A07F09E3A
350 |
351 |
352 | destinationuid
353 | F6A49F45-6CB5-4CDF-BB3E-79B7715ACA0F
354 | modifiers
355 | 0
356 | modifiersubtext
357 |
358 | vitoclose
359 |
360 |
361 |
362 | F6A49F45-6CB5-4CDF-BB3E-79B7715ACA0F
363 |
364 |
365 | destinationuid
366 | 39B059B1-CD01-4C2D-8907-1E2F9262CD04
367 | modifiers
368 | 0
369 | modifiersubtext
370 |
371 | vitoclose
372 |
373 |
374 |
375 | FCE19CD4-E3AE-4361-8B59-F357914A629C
376 |
377 |
378 | destinationuid
379 | 39B059B1-CD01-4C2D-8907-1E2F9262CD04
380 | modifiers
381 | 0
382 | modifiersubtext
383 |
384 | vitoclose
385 |
386 |
387 |
388 |
389 | createdby
390 | Tobias Mende
391 | description
392 | Swiftly switch audio output and input devices
393 | disabled
394 |
395 | name
396 | Audio Switcher
397 | objects
398 |
399 |
400 | config
401 |
402 | concurrently
403 |
404 | escaping
405 | 102
406 | script
407 | ./main.swift switch_by_id output $1
408 | scriptargtype
409 | 1
410 | scriptfile
411 |
412 | type
413 | 11
414 |
415 | type
416 | alfred.workflow.action.script
417 | uid
418 | 3AE8EB58-5F7D-49B6-98C1-4BAE5E79FC2E
419 | version
420 | 2
421 |
422 |
423 | config
424 |
425 | alfredfiltersresults
426 |
427 | alfredfiltersresultsmatchmode
428 | 2
429 | argumenttreatemptyqueryasnil
430 |
431 | argumenttrimmode
432 | 0
433 | argumenttype
434 | 1
435 | escaping
436 | 102
437 | keyword
438 | {var:output_keyword}
439 | queuedelaycustom
440 | 3
441 | queuedelayimmediatelyinitially
442 |
443 | queuedelaymode
444 | 0
445 | queuemode
446 | 1
447 | runningsubtext
448 | Please Wait
449 | script
450 | ./main.swift list output "$ignorelist" "$outputs"
451 | scriptargtype
452 | 1
453 | scriptfile
454 |
455 | subtext
456 | Select an Output Device
457 | title
458 | Audio Outputs
459 | type
460 | 11
461 | withspace
462 |
463 |
464 | type
465 | alfred.workflow.input.scriptfilter
466 | uid
467 | B066EEAB-4F3C-4516-9F00-E8FD7A5439B6
468 | version
469 | 3
470 |
471 |
472 | config
473 |
474 | argument
475 |
476 | argumenttype
477 | 0
478 | triggerid
479 | io.mende.audioswitcher.out
480 | triggername
481 | Select Output
482 | workflowonly
483 |
484 |
485 | type
486 | alfred.workflow.trigger.remote
487 | uid
488 | AFF1A33C-2AE0-4CA1-8B00-04BB87A5F7FE
489 | version
490 | 1
491 |
492 |
493 | config
494 |
495 | argument
496 |
497 | argumenttype
498 | 0
499 | triggerid
500 | io.mende.audioswitcher.in
501 | triggername
502 | Select Input
503 | workflowonly
504 |
505 |
506 | type
507 | alfred.workflow.trigger.remote
508 | uid
509 | 71AAE21C-028C-45CE-AB44-1378572652A9
510 | version
511 | 1
512 |
513 |
514 | config
515 |
516 | alfredfiltersresults
517 |
518 | alfredfiltersresultsmatchmode
519 | 2
520 | argumenttreatemptyqueryasnil
521 |
522 | argumenttrimmode
523 | 0
524 | argumenttype
525 | 1
526 | escaping
527 | 102
528 | keyword
529 | {var:input_keyword}
530 | queuedelaycustom
531 | 3
532 | queuedelayimmediatelyinitially
533 |
534 | queuedelaymode
535 | 0
536 | queuemode
537 | 1
538 | runningsubtext
539 | Please Wait
540 | script
541 | ./main.swift list input "$ignorelist" "$inputs"
542 | scriptargtype
543 | 1
544 | scriptfile
545 |
546 | subtext
547 | Select an Input Device
548 | title
549 | Audio Inputs
550 | type
551 | 11
552 | withspace
553 |
554 |
555 | type
556 | alfred.workflow.input.scriptfilter
557 | uid
558 | 1450496C-74BC-4EDE-930B-ADC6027C5449
559 | version
560 | 3
561 |
562 |
563 | config
564 |
565 | concurrently
566 |
567 | escaping
568 | 68
569 | script
570 | ./main.swift switch_by_id input $1
571 | scriptargtype
572 | 1
573 | scriptfile
574 |
575 | type
576 | 11
577 |
578 | type
579 | alfred.workflow.action.script
580 | uid
581 | FCE19CD4-E3AE-4361-8B59-F357914A629C
582 | version
583 | 2
584 |
585 |
586 | config
587 |
588 | argument
589 | 0
590 | argumenttype
591 | 3
592 | triggerid
593 | io.mende.audioswitcher.out1
594 | triggername
595 | Select Output 1
596 | workflowonly
597 |
598 |
599 | type
600 | alfred.workflow.trigger.remote
601 | uid
602 | AD6FA975-C31E-4D56-BF48-EBBC634EB89E
603 | version
604 | 1
605 |
606 |
607 | config
608 |
609 | action
610 | 0
611 | argument
612 | 3
613 | argumenttext
614 | 0
615 | focusedappvariable
616 |
617 | focusedappvariablename
618 |
619 | hotkey
620 | 122
621 | hotmod
622 | 9437184
623 | hotstring
624 | F1
625 | leftcursor
626 |
627 | modsmode
628 | 0
629 | relatedAppsMode
630 | 0
631 |
632 | type
633 | alfred.workflow.trigger.hotkey
634 | uid
635 | 6CDEB1A2-F0E3-4C17-955A-7AA171D8C899
636 | version
637 | 2
638 |
639 |
640 | config
641 |
642 | argument
643 | 1
644 | argumenttype
645 | 3
646 | triggerid
647 | io.mende.audioswitcher.out2
648 | triggername
649 | Select Output 2
650 | workflowonly
651 |
652 |
653 | type
654 | alfred.workflow.trigger.remote
655 | uid
656 | 864A20DF-C5E2-444E-B084-9CD126BED7DF
657 | version
658 | 1
659 |
660 |
661 | config
662 |
663 | concurrently
664 |
665 | escaping
666 | 68
667 | script
668 | ./main.swift switch_by_name output $1 "$outputs"
669 | scriptargtype
670 | 1
671 | scriptfile
672 |
673 | type
674 | 11
675 |
676 | type
677 | alfred.workflow.action.script
678 | uid
679 | 3B2897E7-E242-4504-A297-602265B0011F
680 | version
681 | 2
682 |
683 |
684 | config
685 |
686 | action
687 | 0
688 | argument
689 | 3
690 | argumenttext
691 | 1
692 | focusedappvariable
693 |
694 | focusedappvariablename
695 |
696 | hotkey
697 | 120
698 | hotmod
699 | 9437184
700 | hotstring
701 | F2
702 | leftcursor
703 |
704 | modsmode
705 | 0
706 | relatedAppsMode
707 | 0
708 |
709 | type
710 | alfred.workflow.trigger.hotkey
711 | uid
712 | 6EEBB03A-5A12-4883-BEF4-2DAC11BF0FC0
713 | version
714 | 2
715 |
716 |
717 | config
718 |
719 | argument
720 | 2
721 | argumenttype
722 | 3
723 | triggerid
724 | io.mende.audioswitcher.out3
725 | triggername
726 | Select Output 3
727 | workflowonly
728 |
729 |
730 | type
731 | alfred.workflow.trigger.remote
732 | uid
733 | A0CE40D8-D874-48D7-903B-0C91A6B2F7DC
734 | version
735 | 1
736 |
737 |
738 | config
739 |
740 | lastpathcomponent
741 |
742 | onlyshowifquerypopulated
743 |
744 | removeextension
745 |
746 | text
747 |
748 | title
749 | Switched to {query}
750 |
751 | type
752 | alfred.workflow.output.notification
753 | uid
754 | 39B059B1-CD01-4C2D-8907-1E2F9262CD04
755 | version
756 | 1
757 |
758 |
759 | config
760 |
761 | action
762 | 0
763 | argument
764 | 3
765 | argumenttext
766 | 2
767 | focusedappvariable
768 |
769 | focusedappvariablename
770 |
771 | hotkey
772 | 99
773 | hotmod
774 | 9437184
775 | hotstring
776 | F3
777 | leftcursor
778 |
779 | modsmode
780 | 0
781 | relatedAppsMode
782 | 0
783 |
784 | type
785 | alfred.workflow.trigger.hotkey
786 | uid
787 | 9D6F6749-4476-48A0-BF59-8B80656B1F51
788 | version
789 | 2
790 |
791 |
792 | config
793 |
794 | argument
795 | 0
796 | argumenttype
797 | 3
798 | triggerid
799 | io.mende.audioswitcher.in1
800 | triggername
801 | Select Input 1
802 | workflowonly
803 |
804 |
805 | type
806 | alfred.workflow.trigger.remote
807 | uid
808 | 7155F88D-55F6-4608-BC2E-554BA0780537
809 | version
810 | 1
811 |
812 |
813 | config
814 |
815 | action
816 | 0
817 | argument
818 | 3
819 | argumenttext
820 | 0
821 | focusedappvariable
822 |
823 | focusedappvariablename
824 |
825 | hotkey
826 | 122
827 | hotmod
828 | 8912896
829 | hotstring
830 | F1
831 | leftcursor
832 |
833 | modsmode
834 | 0
835 | relatedAppsMode
836 | 0
837 |
838 | type
839 | alfred.workflow.trigger.hotkey
840 | uid
841 | 7A1840A7-3844-4206-9B9E-B0602C41361E
842 | version
843 | 2
844 |
845 |
846 | config
847 |
848 | argument
849 | 1
850 | argumenttype
851 | 3
852 | triggerid
853 | io.mende.audioswitcher.in2
854 | triggername
855 | Select Input 2
856 | workflowonly
857 |
858 |
859 | type
860 | alfred.workflow.trigger.remote
861 | uid
862 | C0967D8A-BEF8-44B5-BF2A-06BD127C8D73
863 | version
864 | 1
865 |
866 |
867 | config
868 |
869 | concurrently
870 |
871 | escaping
872 | 68
873 | script
874 | ./main.swift switch_by_name input $1 "$inputs"
875 | scriptargtype
876 | 1
877 | scriptfile
878 |
879 | type
880 | 11
881 |
882 | type
883 | alfred.workflow.action.script
884 | uid
885 | F6A49F45-6CB5-4CDF-BB3E-79B7715ACA0F
886 | version
887 | 2
888 |
889 |
890 | config
891 |
892 | action
893 | 0
894 | argument
895 | 3
896 | argumenttext
897 | 1
898 | focusedappvariable
899 |
900 | focusedappvariablename
901 |
902 | hotkey
903 | 120
904 | hotmod
905 | 8912896
906 | hotstring
907 | F2
908 | leftcursor
909 |
910 | modsmode
911 | 0
912 | relatedAppsMode
913 | 0
914 |
915 | type
916 | alfred.workflow.trigger.hotkey
917 | uid
918 | 82D538CB-521F-4F59-99A5-91AFC57E3CF3
919 | version
920 | 2
921 |
922 |
923 | config
924 |
925 | argument
926 | 2
927 | argumenttype
928 | 3
929 | triggerid
930 | io.mende.audioswitcher.in3
931 | triggername
932 | Select Input 3
933 | workflowonly
934 |
935 |
936 | type
937 | alfred.workflow.trigger.remote
938 | uid
939 | CBBA9D5E-DB01-490E-9C0F-F33A07F09E3A
940 | version
941 | 1
942 |
943 |
944 | config
945 |
946 | action
947 | 0
948 | argument
949 | 3
950 | argumenttext
951 | 2
952 | focusedappvariable
953 |
954 | focusedappvariablename
955 |
956 | hotkey
957 | 99
958 | hotmod
959 | 8912896
960 | hotstring
961 | F3
962 | leftcursor
963 |
964 | modsmode
965 | 0
966 | relatedAppsMode
967 | 0
968 |
969 | type
970 | alfred.workflow.trigger.hotkey
971 | uid
972 | A3266036-2FB4-4E74-B315-F9951154B58F
973 | version
974 | 2
975 |
976 |
977 | config
978 |
979 | argument
980 |
981 | argumenttype
982 | 0
983 | triggerid
984 | io.mende.audioswitcher.rotateout
985 | triggername
986 | Rotate Output
987 | workflowonly
988 |
989 |
990 | type
991 | alfred.workflow.trigger.remote
992 | uid
993 | 5F417B1B-FC67-40CE-8084-167913379DDE
994 | version
995 | 1
996 |
997 |
998 | config
999 |
1000 | concurrently
1001 |
1002 | escaping
1003 | 68
1004 | script
1005 | ./main.swift rotate_favorites output "$outputs"
1006 | scriptargtype
1007 | 1
1008 | scriptfile
1009 |
1010 | type
1011 | 11
1012 |
1013 | type
1014 | alfred.workflow.action.script
1015 | uid
1016 | BA2ED978-7611-4D11-9EA1-8A0A1E275FD0
1017 | version
1018 | 2
1019 |
1020 |
1021 | config
1022 |
1023 | action
1024 | 0
1025 | argument
1026 | 0
1027 | focusedappvariable
1028 |
1029 | focusedappvariablename
1030 |
1031 | hotkey
1032 | 111
1033 | hotmod
1034 | 9437184
1035 | hotstring
1036 | F12
1037 | leftcursor
1038 |
1039 | modsmode
1040 | 0
1041 | relatedAppsMode
1042 | 0
1043 |
1044 | type
1045 | alfred.workflow.trigger.hotkey
1046 | uid
1047 | 1AF283DE-8EDC-4006-AD54-91F4C226E5C9
1048 | version
1049 | 2
1050 |
1051 |
1052 | config
1053 |
1054 | argument
1055 |
1056 | argumenttype
1057 | 0
1058 | triggerid
1059 | io.mende.audioswitcher.rotatein
1060 | triggername
1061 | Rotate Input
1062 | workflowonly
1063 |
1064 |
1065 | type
1066 | alfred.workflow.trigger.remote
1067 | uid
1068 | 692C13A0-ADC1-4E71-8FA4-0157FF14C88F
1069 | version
1070 | 1
1071 |
1072 |
1073 | config
1074 |
1075 | concurrently
1076 |
1077 | escaping
1078 | 68
1079 | script
1080 | ./main.swift rotate_favorites input "$inputs"
1081 | scriptargtype
1082 | 1
1083 | scriptfile
1084 |
1085 | type
1086 | 11
1087 |
1088 | type
1089 | alfred.workflow.action.script
1090 | uid
1091 | 01427E94-9408-4123-A9BC-DF6185AB3A85
1092 | version
1093 | 2
1094 |
1095 |
1096 | config
1097 |
1098 | action
1099 | 0
1100 | argument
1101 | 0
1102 | focusedappvariable
1103 |
1104 | focusedappvariablename
1105 |
1106 | hotkey
1107 | 111
1108 | hotmod
1109 | 8912896
1110 | hotstring
1111 | F12
1112 | leftcursor
1113 |
1114 | modsmode
1115 | 0
1116 | relatedAppsMode
1117 | 0
1118 |
1119 | type
1120 | alfred.workflow.trigger.hotkey
1121 | uid
1122 | 86324099-F14A-4ADC-9C93-992F23163004
1123 | version
1124 | 2
1125 |
1126 |
1127 | config
1128 |
1129 | autopaste
1130 |
1131 | clipboardtext
1132 | {query}
1133 | ignoredynamicplaceholders
1134 |
1135 | transient
1136 |
1137 |
1138 | type
1139 | alfred.workflow.output.clipboard
1140 | uid
1141 | 00704246-FE25-4B27-86E9-2EB6EDF00D67
1142 | version
1143 | 3
1144 |
1145 |
1146 | config
1147 |
1148 | lastpathcomponent
1149 |
1150 | onlyshowifquerypopulated
1151 |
1152 | removeextension
1153 |
1154 | text
1155 | {query}
1156 | title
1157 | Devices copied to clipboard
1158 |
1159 | type
1160 | alfred.workflow.output.notification
1161 | uid
1162 | 09EBB07A-0EF4-4CDB-96E1-7A4EDC0561F4
1163 | version
1164 | 1
1165 |
1166 |
1167 | config
1168 |
1169 | concurrently
1170 |
1171 | escaping
1172 | 68
1173 | script
1174 | ./main.swift print_device_names $1
1175 | scriptargtype
1176 | 1
1177 | scriptfile
1178 |
1179 | type
1180 | 11
1181 |
1182 | type
1183 | alfred.workflow.action.script
1184 | uid
1185 | C46B89C0-5C32-4E45-84C4-714DAA27F2BD
1186 | version
1187 | 2
1188 |
1189 |
1190 | config
1191 |
1192 | argumenttrimmode
1193 | 0
1194 | argumenttype
1195 | 2
1196 | fixedorder
1197 |
1198 | items
1199 | [{"imagefile":"b171fc8163f973fcfe9f43d328811fe1096dcebe.png","title":"Outputs","arg":"output","subtitle":"Choose to Copy"},{"imagefile":"3ab9aedf8fbd94a12254709139ffcee0a288338b.png","title":"Inputs","arg":"input","subtitle":"Choose to Copy"}]
1200 | keyword
1201 | fetchaudiodevices
1202 | matchmode
1203 | 0
1204 | runningsubtext
1205 |
1206 | subtext
1207 | Choose which devices to copy to clipboard
1208 | title
1209 | Fetch Audio Devices
1210 | withspace
1211 |
1212 |
1213 | type
1214 | alfred.workflow.input.listfilter
1215 | uid
1216 | 9F22BA12-18B5-4FA5-B429-12DB07DBDC90
1217 | version
1218 | 1
1219 |
1220 |
1221 | readme
1222 | # Audio Switcher
1223 | This workflow supports quickly switching sound input and output devices.
1224 |
1225 | It offers hotkeys to quickly switch between three input favorites and output favorites.
1226 | You can also use a single hotkey to rotate among the favorites in sequence.
1227 | Those can also be triggered using Alfred Remote.
1228 |
1229 | ## Listing Devices
1230 | Once installed, use the `fetchaudiodevices` command in Alfred. Once you have selected either "Outputs" or "Inputs",
1231 | the workflow will copy a list of devices to the Clipboard. This is a convenience feature to support filling the
1232 | *Ignorelist*, *Output Favorites* and *Input Favorites*. (See below)
1233 |
1234 | ## Parameter Examples
1235 |
1236 | ### Ignorelist
1237 | The value
1238 | ```
1239 | External Headphones
1240 | iPhone Microphone
1241 | ```
1242 | causes both listed devices not to be listed when selecting inputs or outputs.
1243 |
1244 |
1245 | ### Output Favorites
1246 | The value
1247 | ```
1248 | MacBook Pro Speakers
1249 | RØDE Connect Virtual
1250 | External Screen
1251 | ```
1252 | means the following:
1253 | - *⌘ + F1* will select MacBook Pro Speakers.
1254 | - *⌘ + F2* will select RØDE Connect Virtual.
1255 | - *⌘ + F3* will select External Screen.
1256 | - *⌘ + F12* will rotate among these three outputs.
1257 |
1258 | ### Input Favorites
1259 | The value
1260 | ```
1261 | MacBook Pro Microphone
1262 | RØDE Connect Stream
1263 | ```
1264 | means the following:
1265 | - *⌥ + F1* will select MacBook Pro Microphone.
1266 | - *⌥ + F2* will select RØDE Connect Stream.
1267 | - *⌥ + F3* will have no effect.
1268 | - *⌥ + F12* will rotate among these two outputs.
1269 |
1270 | ## Friendly Names
1271 | You might want to specify friendly names for your inputs and outputs. For this you can use the favorite lists and add a freindly name separated by a semicolon (`;`). Example:
1272 | ```
1273 | MacBook Pro Speakers;Mac
1274 | RØDE Connect Virtual;RØDE
1275 | External Screen
1276 | ```
1277 |
1278 | For entries without a friendly name, the official name will be used.
1279 | Friendly names are used in the `in` and `out` lists in this workflow.
1280 | uidata
1281 |
1282 | 00704246-FE25-4B27-86E9-2EB6EDF00D67
1283 |
1284 | xpos
1285 | 685
1286 | ypos
1287 | 1415
1288 |
1289 | 01427E94-9408-4123-A9BC-DF6185AB3A85
1290 |
1291 | note
1292 | rotateInput
1293 | xpos
1294 | 630
1295 | ypos
1296 | 1230
1297 |
1298 | 09EBB07A-0EF4-4CDB-96E1-7A4EDC0561F4
1299 |
1300 | xpos
1301 | 950
1302 | ypos
1303 | 1415
1304 |
1305 | 1450496C-74BC-4EDE-930B-ADC6027C5449
1306 |
1307 | xpos
1308 | 405
1309 | ypos
1310 | 180
1311 |
1312 | 1AF283DE-8EDC-4006-AD54-91F4C226E5C9
1313 |
1314 | xpos
1315 | 200
1316 | ypos
1317 | 1065
1318 |
1319 | 39B059B1-CD01-4C2D-8907-1E2F9262CD04
1320 |
1321 | xpos
1322 | 985
1323 | ypos
1324 | 545
1325 |
1326 | 3AE8EB58-5F7D-49B6-98C1-4BAE5E79FC2E
1327 |
1328 | note
1329 | setOutput
1330 | xpos
1331 | 630
1332 | ypos
1333 | 40
1334 |
1335 | 3B2897E7-E242-4504-A297-602265B0011F
1336 |
1337 | note
1338 | setOutput
1339 | xpos
1340 | 630
1341 | ypos
1342 | 435
1343 |
1344 | 5F417B1B-FC67-40CE-8084-167913379DDE
1345 |
1346 | xpos
1347 | 390
1348 | ypos
1349 | 1040
1350 |
1351 | 692C13A0-ADC1-4E71-8FA4-0157FF14C88F
1352 |
1353 | xpos
1354 | 395
1355 | ypos
1356 | 1205
1357 |
1358 | 6CDEB1A2-F0E3-4C17-955A-7AA171D8C899
1359 |
1360 | xpos
1361 | 210
1362 | ypos
1363 | 330
1364 |
1365 | 6EEBB03A-5A12-4883-BEF4-2DAC11BF0FC0
1366 |
1367 | xpos
1368 | 205
1369 | ypos
1370 | 440
1371 |
1372 | 7155F88D-55F6-4608-BC2E-554BA0780537
1373 |
1374 | xpos
1375 | 390
1376 | ypos
1377 | 675
1378 |
1379 | 71AAE21C-028C-45CE-AB44-1378572652A9
1380 |
1381 | xpos
1382 | 210
1383 | ypos
1384 | 180
1385 |
1386 | 7A1840A7-3844-4206-9B9E-B0602C41361E
1387 |
1388 | xpos
1389 | 200
1390 | ypos
1391 | 690
1392 |
1393 | 82D538CB-521F-4F59-99A5-91AFC57E3CF3
1394 |
1395 | xpos
1396 | 200
1397 | ypos
1398 | 800
1399 |
1400 | 86324099-F14A-4ADC-9C93-992F23163004
1401 |
1402 | xpos
1403 | 200
1404 | ypos
1405 | 1230
1406 |
1407 | 864A20DF-C5E2-444E-B084-9CD126BED7DF
1408 |
1409 | xpos
1410 | 405
1411 | ypos
1412 | 430
1413 |
1414 | 9D6F6749-4476-48A0-BF59-8B80656B1F51
1415 |
1416 | xpos
1417 | 200
1418 | ypos
1419 | 550
1420 |
1421 | 9F22BA12-18B5-4FA5-B429-12DB07DBDC90
1422 |
1423 | xpos
1424 | 190
1425 | ypos
1426 | 1415
1427 |
1428 | A0CE40D8-D874-48D7-903B-0C91A6B2F7DC
1429 |
1430 | xpos
1431 | 405
1432 | ypos
1433 | 535
1434 |
1435 | A3266036-2FB4-4E74-B315-F9951154B58F
1436 |
1437 | xpos
1438 | 200
1439 | ypos
1440 | 910
1441 |
1442 | AD6FA975-C31E-4D56-BF48-EBBC634EB89E
1443 |
1444 | xpos
1445 | 405
1446 | ypos
1447 | 325
1448 |
1449 | AFF1A33C-2AE0-4CA1-8B00-04BB87A5F7FE
1450 |
1451 | xpos
1452 | 210
1453 | ypos
1454 | 40
1455 |
1456 | B066EEAB-4F3C-4516-9F00-E8FD7A5439B6
1457 |
1458 | xpos
1459 | 405
1460 | ypos
1461 | 40
1462 |
1463 | BA2ED978-7611-4D11-9EA1-8A0A1E275FD0
1464 |
1465 | note
1466 | rotateOutput
1467 | xpos
1468 | 630
1469 | ypos
1470 | 1065
1471 |
1472 | C0967D8A-BEF8-44B5-BF2A-06BD127C8D73
1473 |
1474 | xpos
1475 | 395
1476 | ypos
1477 | 795
1478 |
1479 | C46B89C0-5C32-4E45-84C4-714DAA27F2BD
1480 |
1481 | note
1482 | fetchaudiodevices
1483 | xpos
1484 | 435
1485 | ypos
1486 | 1415
1487 |
1488 | CBBA9D5E-DB01-490E-9C0F-F33A07F09E3A
1489 |
1490 | xpos
1491 | 395
1492 | ypos
1493 | 900
1494 |
1495 | F6A49F45-6CB5-4CDF-BB3E-79B7715ACA0F
1496 |
1497 | note
1498 | setInput
1499 | xpos
1500 | 630
1501 | ypos
1502 | 795
1503 |
1504 | FCE19CD4-E3AE-4361-8B59-F357914A629C
1505 |
1506 | note
1507 | setInput
1508 | xpos
1509 | 630
1510 | ypos
1511 | 180
1512 |
1513 |
1514 | userconfigurationconfig
1515 |
1516 |
1517 | config
1518 |
1519 | default
1520 | out
1521 | placeholder
1522 |
1523 | required
1524 |
1525 | trim
1526 |
1527 |
1528 | description
1529 | Alfred Keyword to show available outputs.
1530 | label
1531 | Keyword for Output Selection
1532 | type
1533 | textfield
1534 | variable
1535 | output_keyword
1536 |
1537 |
1538 | config
1539 |
1540 | default
1541 | in
1542 | placeholder
1543 |
1544 | required
1545 |
1546 | trim
1547 |
1548 |
1549 | description
1550 | Alfred Keyword to show available inputs.
1551 | label
1552 | Keyword for Input Selection
1553 | type
1554 | textfield
1555 | variable
1556 | input_keyword
1557 |
1558 |
1559 | config
1560 |
1561 | default
1562 |
1563 | required
1564 |
1565 | trim
1566 |
1567 | verticalsize
1568 | 9
1569 |
1570 | description
1571 | Devices to Ignore (one per line), both input and output.
1572 | label
1573 | Ignorelist
1574 | type
1575 | textarea
1576 | variable
1577 | ignorelist
1578 |
1579 |
1580 | config
1581 |
1582 | default
1583 |
1584 | required
1585 |
1586 | trim
1587 |
1588 | verticalsize
1589 | 6
1590 |
1591 | description
1592 | List of up to three output names (one per line) – Hint: Get them from the "fetchaudiodevices" command
1593 | label
1594 | Output Favorites
1595 | type
1596 | textarea
1597 | variable
1598 | outputs
1599 |
1600 |
1601 | config
1602 |
1603 | default
1604 |
1605 | required
1606 |
1607 | trim
1608 |
1609 | verticalsize
1610 | 6
1611 |
1612 | description
1613 | List of up to three input names (one per line) – Hint: Get them from the "fetchaudiodevices" command
1614 | label
1615 | Input Favorites
1616 | type
1617 | textarea
1618 | variable
1619 | inputs
1620 |
1621 |
1622 | version
1623 | 1.3.0
1624 | webaddress
1625 | https://github.com/TobiasMende/alfred-audio-switcher
1626 |
1627 |
1628 |
--------------------------------------------------------------------------------
/workflow/main.swift:
--------------------------------------------------------------------------------
1 | #!/usr/bin/swift
2 | import Foundation
3 | import CoreAudio
4 |
5 | let arguments = CommandLine.arguments
6 | guard arguments.count > 2 else {
7 | printUsageAndExit()
8 | exit(1)
9 | }
10 |
11 | let command = arguments[1]
12 | let type = arguments[2] == "input" ? DeviceType.input : DeviceType.output
13 |
14 | if command == "list" {
15 | printDeviceItems(type: type)
16 | } else if command == "switch_by_id" && arguments.count > 3 {
17 | switchDeviceById(type: type, deviceIDAsString: arguments[3])
18 | } else if command == "print_device_names" {
19 | printDeviceNames(type: type)
20 | } else if command == "switch_by_name" && arguments.count > 3 {
21 | switchDeviceByDeviceIndexAndList(type: type, deviceIndexAsString: arguments[3])
22 | } else if command == "rotate_favorites" && arguments.count > 2 {
23 | rotateFavorites(type: type)
24 | }else {
25 | printUsageAndExit()
26 | }
27 |
28 |
29 | enum DeviceType {
30 | case input, output
31 | }
32 |
33 | func createPropertyAddress(selector: AudioObjectPropertySelector) -> AudioObjectPropertyAddress {
34 | return AudioObjectPropertyAddress(
35 | mSelector: selector,
36 | mScope: kAudioObjectPropertyScopeGlobal,
37 | mElement: kAudioObjectPropertyElementMain
38 | )
39 | }
40 |
41 | func getPropertyAddress(type: DeviceType) -> AudioObjectPropertyAddress {
42 | let propertySelector: AudioObjectPropertySelector = (type == .input) ? kAudioHardwarePropertyDefaultInputDevice : kAudioHardwarePropertyDefaultOutputDevice
43 | return createPropertyAddress(selector: propertySelector)
44 | }
45 |
46 | func getAudioDeviceNameById(deviceID: AudioDeviceID) -> String {
47 | guard let deviceName = getDeviceName(deviceID: deviceID) else {
48 | fatalError("Error: Unable to get name for device ID \(deviceID)")
49 | }
50 |
51 | return deviceName
52 | }
53 |
54 | func getAudioDeviceIdByName(deviceName: String, type: DeviceType) -> AudioDeviceID? {
55 | let devices = getAudioDeviceList(type: type)
56 |
57 | let foundDevice = devices.first { device in
58 | device.name == deviceName
59 | }
60 |
61 | return foundDevice?.id
62 | }
63 |
64 | func setDefaultAudioDevice(type: DeviceType, deviceID: AudioDeviceID) -> String? {
65 | var propertyAddress = getPropertyAddress(type: type)
66 |
67 | var newDeviceID = deviceID
68 | let propertySize = UInt32(MemoryLayout.size)
69 |
70 | let status = AudioObjectSetPropertyData(AudioObjectID(kAudioObjectSystemObject), &propertyAddress, 0, nil, propertySize, &newDeviceID)
71 | if status != noErr {
72 | fatalError("Error: Unable to set default \(type) device")
73 | }
74 |
75 | if(type == .output) {
76 | let syncSoundEffectsOutput = getEnvironmentVariable(named: "sync_sound_effects_output") == "1" ? true : false
77 | if(syncSoundEffectsOutput) {
78 | setSoundEffectsOutput(to: deviceID)
79 | }
80 | }
81 |
82 | return getAudioDeviceNameById(deviceID: deviceID)
83 | }
84 |
85 | func setSoundEffectsOutput(to deviceID: AudioDeviceID) {
86 | var propertyAddress = createPropertyAddress(selector: kAudioHardwarePropertyDefaultSystemOutputDevice)
87 | var newDeviceID = deviceID
88 | let propertySize = UInt32(MemoryLayout.size)
89 |
90 | let status = AudioObjectSetPropertyData(AudioObjectID(kAudioObjectSystemObject), &propertyAddress, 0, nil, propertySize, &newDeviceID)
91 | if status != noErr {
92 | fatalError("Error: Unable to set default \(type) device")
93 | }
94 | }
95 |
96 | func getDeviceName(deviceID: AudioDeviceID) -> String? {
97 | var nameSize = UInt32(MemoryLayout.size)
98 | var deviceName: CFString = "" as CFString
99 | var address = createPropertyAddress(selector: kAudioDevicePropertyDeviceNameCFString)
100 |
101 | let status = withUnsafeMutablePointer(to: &deviceName) { ptr in
102 | AudioObjectGetPropertyData(deviceID, &address, 0, nil, &nameSize, ptr)
103 | }
104 |
105 | if status == noErr, let name = deviceName as String? {
106 | return name
107 | } else {
108 | return nil
109 | }
110 | }
111 |
112 | func getDefaultAudioDevice(type: DeviceType) -> (name: String, id: AudioDeviceID) {
113 | var deviceID = AudioDeviceID()
114 | var propertySize = UInt32(MemoryLayout.size)
115 | var propertyAddress = getPropertyAddress(type: type)
116 |
117 | let status = AudioObjectGetPropertyData(AudioObjectID(kAudioObjectSystemObject), &propertyAddress, 0, nil, &propertySize, &deviceID)
118 | if status != noErr {
119 | fatalError("Error: Unable to get default \(type) device")
120 | }
121 | guard let deviceName = getDeviceName(deviceID: deviceID) else {
122 | fatalError("Failed to retrieve device Name for \(deviceID)")
123 | }
124 | return (name: deviceName, id: deviceID)
125 | }
126 |
127 | func getAudioDeviceList(type: DeviceType) -> [(name: String, id: AudioDeviceID)] {
128 | var propertySize: UInt32 = 0
129 | var address = createPropertyAddress(selector: kAudioHardwarePropertyDevices)
130 |
131 | var status = AudioObjectGetPropertyDataSize(AudioObjectID(kAudioObjectSystemObject), &address, 0, nil, &propertySize)
132 | guard status == noErr else {
133 | fatalError("Error: Unable to get the size of the audio devices array")
134 | }
135 |
136 | let deviceCount = Int(propertySize) / MemoryLayout.size
137 | var deviceIDs = [AudioDeviceID](repeating: 0, count: deviceCount)
138 |
139 | status = AudioObjectGetPropertyData(AudioObjectID(kAudioObjectSystemObject), &address, 0, nil, &propertySize, &deviceIDs)
140 | guard status == noErr else {
141 | fatalError("Error: Unable to get audio devices")
142 | }
143 |
144 | var deviceList: [(name: String, id: AudioDeviceID)] = []
145 | for id in deviceIDs {
146 | let scope: AudioObjectPropertyScope = (type == .input) ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput
147 | var streamAddress = AudioObjectPropertyAddress(
148 | mSelector: kAudioDevicePropertyStreams,
149 | mScope: scope,
150 | mElement: kAudioObjectPropertyElementMain)
151 | var streamSize: UInt32 = 0
152 |
153 | status = AudioObjectGetPropertyDataSize(id, &streamAddress, 0, nil, &streamSize)
154 | if status != noErr || streamSize == 0 {
155 | continue // Skip device if it doesn't have streams for the specified type
156 | }
157 |
158 | guard let deviceName = getDeviceName(deviceID: id) else {
159 | continue
160 | }
161 |
162 | deviceList.append((name: deviceName, id: id))
163 |
164 | }
165 |
166 | return deviceList
167 | }
168 |
169 | func convertStringToDeviceID(deviceIDString: String) -> AudioDeviceID? {
170 | if let deviceIDInt = UInt32(deviceIDString) {
171 | return AudioDeviceID(deviceIDInt)
172 | } else {
173 | fatalError("Invalid Device ID String")
174 | }
175 | }
176 |
177 |
178 | func deviceToJson(device: (name: String, id: AudioDeviceID), friendlyName: String, isDefault: Bool, type: DeviceType) -> String {
179 | let iconName = isDefault ? "\(type)_selected.png" : "\(type).png"
180 | return "{\"title\": \"\(friendlyName)\", \"uid\": \"\(device.name)\", \"autocomplete\": \"\(friendlyName)\", \"arg\": \"\(device.id)\", \"icon\": {\"path\": \"./icons/\(iconName)\"}}"
181 | }
182 |
183 | func filterAudioDevices(devices: [(name: String, id: AudioDeviceID)], ignoreList: [String]) -> [(name: String, id: AudioDeviceID)] {
184 | return devices.filter { !ignoreList.contains($0.name) }
185 | }
186 |
187 | func printDeviceNames(type: DeviceType) {
188 | getAudioDeviceList(type: type).forEach { device in
189 | print(device.name)
190 | }
191 | }
192 |
193 | func convertFavoritesList(favoritesAsMultilineString: String) -> [String: String] {
194 | let favoriteList = convertMultilineArgumentToList(argument: favoritesAsMultilineString)
195 |
196 | var resultMap: [String: String] = [:]
197 |
198 | for favoriteLine in favoriteList {
199 | let components = favoriteLine.split(separator: ";", maxSplits: 1, omittingEmptySubsequences: true)
200 |
201 | if components.count == 2 {
202 | // If there are two components, we have both key and value
203 | let key = String(components[0]).trimmingCharacters(in: .whitespaces)
204 | let value = String(components[1]).trimmingCharacters(in: .whitespaces)
205 | resultMap[key] = value
206 | } else if components.count == 1 {
207 | // If there's no semicolon, we can still add the key with an empty value
208 | let key = String(components[0]).trimmingCharacters(in: .whitespaces)
209 | resultMap[key] = key
210 | }
211 | }
212 |
213 | return resultMap
214 | }
215 |
216 | func printDeviceItems(type: DeviceType) {
217 | let favoritesAsMultilineString = getAppropriateDeviceList(type: type)
218 | let ignoreList = convertMultilineArgumentToList(argument: getEnvironmentVariable(named: "ignorelist"))
219 | let favoriteList = convertFavoritesList(favoritesAsMultilineString: favoritesAsMultilineString)
220 | let defaultDevice = getDefaultAudioDevice(type: type)
221 | let devices = getAudioDeviceList(type: type)
222 | let devicesAsJson = filterAudioDevices(devices: devices, ignoreList: ignoreList).map { device in
223 | let isDefault = (defaultDevice.id == device.id)
224 | let friendlyName = favoriteList[device.name] ?? device.name
225 | return deviceToJson(device: device, friendlyName: friendlyName, isDefault: isDefault, type: type)
226 | }.joined(separator: ",")
227 |
228 | print("{\"items\": [\(devicesAsJson)]}")
229 | }
230 |
231 | func getAppropriateDeviceList(type: DeviceType) -> String {
232 | return getEnvironmentVariable(named: (type == .output ? "outputs" : "inputs"))
233 | }
234 |
235 | func switchDeviceById(type: DeviceType, deviceIDAsString: String) {
236 | guard let deviceID = convertStringToDeviceID(deviceIDString: deviceIDAsString) else {
237 | fatalError("Could not convert to AudioDeviceId: \(deviceIDAsString)")
238 | }
239 | guard let selectedDevice = setDefaultAudioDevice(type: type, deviceID: deviceID) else {
240 | fatalError("Device Not Found: \(deviceID)")
241 | }
242 |
243 | print(selectedDevice)
244 | }
245 |
246 | func getEnvironmentVariable(named name: String) -> String {
247 | return ProcessInfo.processInfo.environment[name] ?? ""
248 | }
249 |
250 | func switchDeviceByDeviceIndexAndList(type: DeviceType, deviceIndexAsString: String) {
251 | guard let deviceIndex = Int(deviceIndexAsString) else {
252 | fatalError("Invalid Device Index: \(deviceIndexAsString)")
253 | }
254 |
255 | let deviceList = convertMultilineArgumentToList(argument: getAppropriateDeviceList(type: type))
256 |
257 | guard deviceIndex < deviceList.count else {
258 | fatalError("Invalid Index Passed")
259 | }
260 |
261 | guard let deviceFromList = deviceList[deviceIndex].split(separator: ";").first else {
262 | fatalError("Invalid Device Index: \(deviceIndex)")
263 | }
264 |
265 | guard let deviceID = getAudioDeviceIdByName(deviceName: String(deviceFromList), type: type) else {
266 | fatalError("Device not found: Index: \(deviceIndex), deviceList: \(deviceList)")
267 | }
268 |
269 | guard let selectedDevice = setDefaultAudioDevice(type: type, deviceID: deviceID) else {
270 | fatalError("Device Not Found: \(deviceID)")
271 | }
272 |
273 | print(selectedDevice)
274 | }
275 |
276 | func convertMultilineArgumentToList(argument: String) -> [String] {
277 | return argument.split(separator: "\n").map(String.init)
278 | }
279 |
280 | func rotateFavorites(type: DeviceType) {
281 | let defaultDevice = getDefaultAudioDevice(type: type)
282 | let deviceList = convertMultilineArgumentToList(argument: getAppropriateDeviceList(type: type)).map { String($0.split(separator: ";").first!) }
283 | guard deviceList.count > 0 else {
284 | fatalError("No devices in list")
285 | }
286 |
287 | let defaultDeviceIndex = deviceList.firstIndex(of: defaultDevice.name) ?? -1
288 | let nextDeviceIndex = (defaultDeviceIndex + 1) % deviceList.count
289 | guard let nextDeviceName = deviceList[nextDeviceIndex].split(separator: ";").first else {
290 | fatalError("Device not found at index: \(nextDeviceIndex)")
291 | }
292 | guard let nextDeviceID = getAudioDeviceIdByName(deviceName: String(nextDeviceName), type: type) else {
293 | fatalError("Device not found: \(nextDeviceName)")
294 | }
295 |
296 | guard let selectedDevice = setDefaultAudioDevice(type: type, deviceID: nextDeviceID) else {
297 | fatalError("Device Not Found: \(nextDeviceID)")
298 | }
299 |
300 | print(selectedDevice)
301 | }
302 |
303 |
304 | func printUsageAndExit() {
305 | print("Usage: ./main.swift [| ]")
306 | print("command: (list | switch_by_id | switch_by_name | rotate_favorites | print_device_names)")
307 | print("type: (input | output)")
308 | exit(1)
309 | }
310 |
--------------------------------------------------------------------------------