Ver Fonte

project: refactored CocoaSpice into package

This gives us a few main advantages:

1. It improves encapsulation and division of responsibility.
2. CocoaSpice can be used in other projects more easily.
3. It lays the foundation for better unit testing of key parts.
4. It cleans up the codebase.

Resolves #2376
osy há 3 anos atrás
pai
commit
4e275c8898
49 ficheiros alterados com 117 adições e 4675 exclusões
  1. 0 47
      CocoaSpice/CSConnection.h
  2. 0 316
      CocoaSpice/CSConnection.m
  3. 0 43
      CocoaSpice/CSConnectionDelegate.h
  4. 0 61
      CocoaSpice/CSDisplayMetal.h
  5. 0 731
      CocoaSpice/CSDisplayMetal.m
  6. 0 63
      CocoaSpice/CSInput.h
  7. 0 325
      CocoaSpice/CSInput.m
  8. 0 34
      CocoaSpice/CSMain.h
  9. 0 150
      CocoaSpice/CSMain.m
  10. 0 30
      CocoaSpice/CSSession+Sharing.h
  11. 0 54
      CocoaSpice/CSSession+Sharing.m
  12. 0 32
      CocoaSpice/CSSession.h
  13. 0 384
      CocoaSpice/CSSession.m
  14. 0 35
      CocoaSpice/CSUSBDevice.h
  15. 0 104
      CocoaSpice/CSUSBDevice.m
  16. 0 44
      CocoaSpice/CSUSBManager.h
  17. 0 240
      CocoaSpice/CSUSBManager.m
  18. 0 32
      CocoaSpice/CSUSBManagerDelegate.h
  19. 0 36
      CocoaSpice/CocoaSpice.h
  20. 2 2
      Managers/UTMInputOutput.h
  21. 34 60
      Managers/UTMPasteboard.swift
  22. 1 1
      Managers/UTMQemuVirtualMachine+SPICE.m
  23. 0 1
      Managers/UTMQemuVirtualMachine.m
  24. 0 45
      Managers/UTMScreenshot.h
  25. 0 76
      Managers/UTMScreenshot.m
  26. 1 4
      Managers/UTMSpiceIO.h
  27. 4 3
      Managers/UTMSpiceIO.m
  28. 3 24
      Managers/UTMTerminalIO.m
  29. 3 1
      Managers/UTMVirtualMachine-Protected.h
  30. 2 4
      Managers/UTMVirtualMachine.h
  31. 3 3
      Managers/UTMVirtualMachine.m
  32. 0 2
      Managers/UTMVirtualMachineDelegate.h
  33. 0 3
      Platform/Swift-Bridging-Header.h
  34. 3 3
      Platform/iOS/Display/VMDisplayMetalViewController+Gamepad.m
  35. 3 3
      Platform/iOS/Display/VMDisplayMetalViewController+Pointer.m
  36. 4 4
      Platform/iOS/Display/VMDisplayMetalViewController+Touch.m
  37. 4 5
      Platform/iOS/Display/VMDisplayMetalViewController.m
  38. 0 1
      Platform/iOS/Legacy/VMListViewController.m
  39. 2 2
      Platform/iOS/UTMDataExtension.swift
  40. 6 5
      Platform/macOS/Display/VMDisplayMetalWindowController.swift
  41. 0 41
      Renderer/UTMRenderSource.h
  42. 0 24
      Renderer/UTMRenderer.h
  43. 0 265
      Renderer/UTMRenderer.m
  44. 0 53
      Renderer/UTMShaderTypes.h
  45. 0 102
      Renderer/UTMShaders.metal
  46. 33 148
      UTM.xcodeproj/project.pbxproj
  47. 9 0
      UTM.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
  48. 0 39
      gstreamer/gst_ios_init.h
  49. 0 990
      gstreamer/gst_ios_init.m

+ 0 - 47
CocoaSpice/CSConnection.h

@@ -1,47 +0,0 @@
-//
-// Copyright © 2019 osy. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-
-#import <Foundation/Foundation.h>
-#import "CSConnectionDelegate.h"
-
-@class CSDisplayMetal;
-@class CSUSBManager;
-
-NS_ASSUME_NONNULL_BEGIN
-
-@interface CSConnection : NSObject
-
-@property (nonatomic, readonly) NSArray<CSDisplayMetal *> *monitors;
-@property (nonatomic, readonly) CSSession *session;
-@property (nonatomic, readonly) CSInput *input;
-#if !defined(WITH_QEMU_TCI)
-@property (nonatomic, readonly) CSUSBManager *usbManager;
-#endif
-@property (nonatomic, weak, nullable) id<CSConnectionDelegate> delegate;
-@property (nonatomic, nullable, copy) NSString *host;
-@property (nonatomic, nullable, copy) NSString *port;
-@property (nonatomic, nullable, copy) NSURL *unixSocketURL;
-@property (nonatomic, assign) BOOL audioEnabled;
-
-- (instancetype)init NS_UNAVAILABLE;
-- (instancetype)initWithHost:(NSString *)host port:(NSString *)port NS_DESIGNATED_INITIALIZER;
-- (instancetype)initWithUnixSocketFile:(NSURL *)socketFile NS_DESIGNATED_INITIALIZER;
-- (BOOL)connect;
-- (void)disconnect;
-
-@end
-
-NS_ASSUME_NONNULL_END

+ 0 - 316
CocoaSpice/CSConnection.m

@@ -1,316 +0,0 @@
-//
-// Copyright © 2019 osy. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-
-#import "CocoaSpice.h"
-#import "UTMLogging.h"
-#import <glib.h>
-#import <spice-client.h>
-#import <spice/vd_agent.h>
-
-@interface CSConnection ()
-
-@property (nonatomic, readwrite) CSSession *session;
-@property (nonatomic, readwrite) CSUSBManager *usbManager;
-@property (nonatomic, readwrite) CSInput *input;
-@property (nonatomic, readwrite) SpiceSession *spiceSession;
-@property (nonatomic, readwrite) SpiceMainChannel *spiceMain;
-@property (nonatomic, readwrite) SpiceAudio *spiceAudio;
-@property (nonatomic, readwrite) NSArray<CSDisplayMetal *> *monitors;
-
-@end
-
-@implementation CSConnection
-
-static void cs_main_channel_event(SpiceChannel *channel, SpiceChannelEvent event,
-                               gpointer data)
-{
-    CSConnection *self = (__bridge CSConnection *)data;
-    const GError *error = NULL;
-    NSString *genericMsg = NSLocalizedString(@"An error occurred trying to connect to SPICE.", @"CSConnection");
-    
-    switch (event) {
-        case SPICE_CHANNEL_OPENED:
-            g_message("main channel: opened");
-            [self.delegate spiceConnected:self];
-            break;
-        case SPICE_CHANNEL_SWITCHING:
-            g_message("main channel: switching host");
-            break;
-        case SPICE_CHANNEL_CLOSED:
-            /* this event is only sent if the channel was succesfully opened before */
-            g_message("main channel: closed");
-            spice_session_disconnect(self.spiceSession);
-            break;
-        case SPICE_CHANNEL_ERROR_IO:
-        case SPICE_CHANNEL_ERROR_TLS:
-        case SPICE_CHANNEL_ERROR_LINK:
-        case SPICE_CHANNEL_ERROR_CONNECT:
-        case SPICE_CHANNEL_ERROR_AUTH:
-            error = spice_channel_get_error(channel);
-            if (error) {
-                g_message("channel error: %s", error->message);
-            }
-            [self.delegate spiceError:self err:(error ? [NSString stringWithUTF8String:error->message] : genericMsg)];
-            break;
-        default:
-            /* TODO: more sophisticated error handling */
-            g_warning("unknown main channel event: %u", event);
-            /* connection_disconnect(conn); */
-            break;
-    }
-}
-
-static void cs_display_monitors(SpiceChannel *display, GParamSpec *pspec,
-                             gpointer data)
-{
-    CSConnection *self = (__bridge CSConnection *)data;
-    GArray *cfgs = NULL;
-    SpiceDisplayMonitorConfig *cfg = NULL;
-    int chid;
-    
-    g_object_get(display,
-                 "channel-id", &chid,
-                 "monitors", &cfgs,
-                 NULL);
-    g_return_if_fail(cfgs != NULL);
-    
-    NSMutableIndexSet *markedItems = [NSMutableIndexSet indexSet];
-    NSMutableArray<CSDisplayMetal *> *oldMonitors = [self.monitors mutableCopy];
-    NSMutableArray<CSDisplayMetal *> *newMonitors = [NSMutableArray array];
-    
-    // mark monitors that are in use
-    for (int i = 0; i < cfgs->len; i++) {
-        cfg = &g_array_index(cfgs, SpiceDisplayMonitorConfig, i);
-        int j;
-        for (j = 0; j < oldMonitors.count; j++) {
-            CSDisplayMetal *monitor = oldMonitors[j];
-            if (cfg->id == monitor.monitorID && chid == monitor.channelID) {
-                [markedItems addIndex:j];
-                break;
-            }
-        }
-        if (j == oldMonitors.count) { // not seen
-            CSDisplayMetal *monitor = [[CSDisplayMetal alloc] initWithSession:self.spiceSession channelID:chid monitorID:i];
-            [newMonitors addObject:monitor];
-            [self.delegate spiceDisplayCreated:self display:monitor];
-        }
-    }
-    
-    // mark monitors that are in other channels
-    for (int j = 0; j < oldMonitors.count; j++) {
-        CSDisplayMetal *monitor = oldMonitors[j];
-        if (chid != monitor.channelID) {
-            [markedItems addIndex:j];
-        }
-    }
-    
-    // set the new monitors array
-    NSMutableArray<CSDisplayMetal *> *monitors = [[oldMonitors objectsAtIndexes:markedItems] mutableCopy];
-    [oldMonitors removeObjectsAtIndexes:markedItems];
-    [monitors addObjectsFromArray:newMonitors];
-    self.monitors = monitors;
-    
-    // remove old monitors
-    for (CSDisplayMetal *monitor in oldMonitors) {
-        [self.delegate spiceDisplayDestroyed:self display:monitor];
-    }
-    
-    g_clear_pointer(&cfgs, g_array_unref);
-}
-
-static void cs_main_agent_update(SpiceChannel *main, gpointer data)
-{
-    CSConnection *self = (__bridge CSConnection *)data;
-    gboolean agent_connected = false;
-    CSConnectionAgentFeature features = kCSConnectionAgentFeatureNone;
-    
-    g_object_get(main, "agent-connected", &agent_connected, NULL);
-    UTMLog(@"SPICE agent connected: %d", agent_connected);
-    if (agent_connected) {
-        if (spice_main_channel_agent_test_capability(SPICE_MAIN_CHANNEL(main), VD_AGENT_CAP_MONITORS_CONFIG)) {
-            features |= kCSConnectionAgentFeatureMonitorsConfig;
-        }
-        [self.delegate spiceAgentConnected:self supportingFeatures:features];
-    } else {
-        [self.delegate spiceAgentDisconnected:self];
-    }
-}
-
-static void cs_channel_new(SpiceSession *s, SpiceChannel *channel, gpointer data)
-{
-    CSConnection *self = (__bridge CSConnection *)data;
-    int chid;
-    
-    g_object_get(channel, "channel-id", &chid, NULL);
-    SPICE_DEBUG("new channel (#%d)", chid);
-    
-    if (SPICE_IS_MAIN_CHANNEL(channel)) {
-        SPICE_DEBUG("new main channel");
-        g_assert(!self.spiceMain); // should only be 1 main channel
-        self.spiceMain = SPICE_MAIN_CHANNEL(channel);
-        UTMLog(@"%s:%d", __FUNCTION__, __LINE__);
-        g_signal_connect(channel, "channel-event",
-                         G_CALLBACK(cs_main_channel_event), GLIB_OBJC_RETAIN(self));
-        g_signal_connect(channel, "main_agent_update",
-                         G_CALLBACK(cs_main_agent_update), GLIB_OBJC_RETAIN(self));
-    }
-    
-    if (SPICE_IS_DISPLAY_CHANNEL(channel)) {
-        SPICE_DEBUG("new display channel (#%d)", chid);
-        UTMLog(@"%s:%d", __FUNCTION__, __LINE__);
-        g_signal_connect(channel, "notify::monitors",
-                         G_CALLBACK(cs_display_monitors), GLIB_OBJC_RETAIN(self));
-        spice_channel_connect(channel);
-    }
-    
-    if (SPICE_IS_PLAYBACK_CHANNEL(channel)) {
-        SPICE_DEBUG("new audio channel");
-        if (self.audioEnabled) {
-            self.spiceAudio = spice_audio_get(s, [CSMain sharedInstance].glibMainContext);
-            spice_channel_connect(channel);
-        } else {
-            SPICE_DEBUG("audio disabled");
-        }
-    }
-
-    if (SPICE_IS_PORT_CHANNEL(channel)) {
-        SPICE_DEBUG("new port channel");
-        spice_channel_connect(channel);
-    }
-}
-
-static void cs_channel_destroy(SpiceSession *s, SpiceChannel *channel, gpointer data)
-{
-    CSConnection *self = (__bridge CSConnection *)data;
-    int chid;
-    
-    g_object_get(channel, "channel-id", &chid, NULL);
-    if (SPICE_IS_MAIN_CHANNEL(channel)) {
-        UTMLog(@"%s:%d", __FUNCTION__, __LINE__);
-        SPICE_DEBUG("zap main channel");
-        self.spiceMain = NULL;
-        g_signal_handlers_disconnect_by_func(channel, G_CALLBACK(cs_main_channel_event), GLIB_OBJC_RELEASE(self));
-        g_signal_handlers_disconnect_by_func(channel, G_CALLBACK(cs_main_agent_update), GLIB_OBJC_RELEASE(self));
-    }
-    
-    if (SPICE_IS_DISPLAY_CHANNEL(channel)) {
-        UTMLog(@"%s:%d", __FUNCTION__, __LINE__);
-        SPICE_DEBUG("zap display channel (#%d)", chid);
-        g_signal_handlers_disconnect_by_func(channel, G_CALLBACK(cs_display_monitors), GLIB_OBJC_RELEASE(self));
-        for (CSDisplayMetal *monitor in self.monitors) {
-            [self.delegate spiceDisplayDestroyed:self display:monitor];
-        }
-        self.monitors = [NSArray<CSDisplayMetal *> array];
-    }
-    
-    if (SPICE_IS_PLAYBACK_CHANNEL(channel)) {
-        SPICE_DEBUG("zap audio channel");
-        self.spiceAudio = NULL;
-    }
-}
-
-static void cs_connection_destroy(SpiceSession *session,
-                               gpointer data)
-{
-    CSConnection *self = (__bridge CSConnection *)data;
-    [self.delegate spiceDisconnected:self];
-}
-
-- (void)setHost:(NSString *)host {
-    g_object_set(self.spiceSession, "host", [host UTF8String], NULL);
-}
-
-- (NSString *)host {
-    gchar *strhost;
-    g_object_get(self.spiceSession, "host", &strhost, NULL);
-    NSString *nshost = [NSString stringWithUTF8String:strhost];
-    g_free(strhost);
-    return nshost;
-}
-
-- (void)setPort:(NSString *)port {
-    g_object_set(self.spiceSession, "port", [port UTF8String], NULL);
-}
-
-- (NSString *)port {
-    gchar *strhost;
-    g_object_get(self.spiceSession, "port", &strhost, NULL);
-    NSString *nshost = [NSString stringWithUTF8String:strhost];
-    g_free(strhost);
-    return nshost;
-}
-
-- (void)setUnixSocketURL:(NSURL *)unixSocketURL {
-    g_object_set(self.spiceSession, "unix-path", unixSocketURL.path.UTF8String, NULL);
-    _unixSocketURL = unixSocketURL;
-}
-
-- (void)dealloc {
-    UTMLog(@"%s:%d", __FUNCTION__, __LINE__);
-    g_signal_handlers_disconnect_by_func(self.spiceSession, G_CALLBACK(cs_channel_new), GLIB_OBJC_RELEASE(self));
-    g_signal_handlers_disconnect_by_func(self.spiceSession, G_CALLBACK(cs_channel_destroy), GLIB_OBJC_RELEASE(self));
-    g_signal_handlers_disconnect_by_func(self.spiceSession, G_CALLBACK(cs_connection_destroy), GLIB_OBJC_RELEASE(self));
-    g_object_unref(self.spiceSession);
-    self.spiceSession = NULL;
-}
-
-- (void)finishInit {
-    UTMLog(@"%s:%d", __FUNCTION__, __LINE__);
-    g_signal_connect(self.spiceSession, "channel-new",
-                     G_CALLBACK(cs_channel_new), GLIB_OBJC_RETAIN(self));
-    g_signal_connect(self.spiceSession, "channel-destroy",
-                     G_CALLBACK(cs_channel_destroy), GLIB_OBJC_RETAIN(self));
-    g_signal_connect(self.spiceSession, "disconnected",
-                     G_CALLBACK(cs_connection_destroy), GLIB_OBJC_RETAIN(self));
-    
-#if !defined(WITH_QEMU_TCI)
-    SpiceUsbDeviceManager *manager = spice_usb_device_manager_get(self.spiceSession, NULL);
-    g_assert(manager != NULL);
-    self.usbManager = [[CSUSBManager alloc] initWithUsbDeviceManager:manager];
-#endif
-    self.input = [[CSInput alloc] initWithSession:self.spiceSession];
-    self.session = [[CSSession alloc] initWithSession:self.spiceSession];
-    self.monitors = [NSArray<CSDisplayMetal *> array];
-}
-
-- (instancetype)initWithHost:(NSString *)host port:(NSString *)port {
-    if (self = [super init]) {
-        self.spiceSession = spice_session_new();
-        self.host = host;
-        self.port = port;
-        [self finishInit];
-    }
-    return self;
-}
-
-- (instancetype)initWithUnixSocketFile:(NSURL *)socketFile {
-    if (self = [super init]) {
-        self.spiceSession = spice_session_new();
-        self.unixSocketURL = socketFile;
-        [self finishInit];
-    }
-    return self;
-}
-
-- (BOOL)connect {
-    return spice_session_connect(self.spiceSession);
-}
-
-- (void)disconnect {
-    spice_session_disconnect(self.spiceSession);
-}
-
-@end

+ 0 - 43
CocoaSpice/CSConnectionDelegate.h

@@ -1,43 +0,0 @@
-//
-// Copyright © 2019 osy. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-
-#import <Foundation/Foundation.h>
-
-@class CSConnection;
-@class CSDisplayMetal;
-@class CSInput;
-@class CSSession;
-
-typedef NS_OPTIONS(NSInteger, CSConnectionAgentFeature) {
-    kCSConnectionAgentFeatureNone,
-    kCSConnectionAgentFeatureMonitorsConfig
-};
-
-NS_ASSUME_NONNULL_BEGIN
-
-@protocol CSConnectionDelegate <NSObject>
-
-- (void)spiceConnected:(CSConnection *)connection;
-- (void)spiceDisconnected:(CSConnection *)connection;
-- (void)spiceError:(CSConnection *)connection err:(nullable NSString *)msg;
-- (void)spiceDisplayCreated:(CSConnection *)connection display:(CSDisplayMetal *)display;
-- (void)spiceDisplayDestroyed:(CSConnection *)connection display:(CSDisplayMetal *)display;
-- (void)spiceAgentConnected:(CSConnection *)connection supportingFeatures:(CSConnectionAgentFeature)features;
-- (void)spiceAgentDisconnected:(CSConnection *)connection;
-
-@end
-
-NS_ASSUME_NONNULL_END

+ 0 - 61
CocoaSpice/CSDisplayMetal.h

@@ -1,61 +0,0 @@
-//
-// Copyright © 2019 osy. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-
-#import <Foundation/Foundation.h>
-#import "UTMRenderSource.h"
-@import CoreGraphics;
-
-@class UTMScreenshot;
-
-typedef struct _SpiceSession SpiceSession;
-
-NS_ASSUME_NONNULL_BEGIN
-
-@interface CSDisplayMetal : NSObject <UTMRenderSource>
-
-@property (nonatomic, assign) BOOL ready;
-@property (nonatomic, readonly, nullable) SpiceSession *session;
-@property (nonatomic, readonly, assign) NSInteger channelID;
-@property (nonatomic, readonly, assign) NSInteger monitorID;
-@property (nonatomic, assign) CGSize displaySize;
-@property (nonatomic, readonly) UTMScreenshot *screenshot;
-@property (nonatomic, assign) BOOL inhibitCursor;
-@property (nonatomic) CGSize cursorSize;
-
-// properties from UTMRenderSource
-@property (nonatomic, readonly) BOOL cursorVisible;
-@property (nonatomic) CGPoint cursorOrigin;
-@property (nonatomic) CGPoint viewportOrigin;
-@property (nonatomic) CGFloat viewportScale;
-@property (nonatomic, readonly) dispatch_semaphore_t drawLock;
-@property (nonatomic, nullable) id<MTLDevice> device;
-@property (nonatomic, nullable, readonly) id<MTLTexture> displayTexture;
-@property (nonatomic, nullable, readonly) id<MTLTexture> cursorTexture;
-@property (nonatomic, readonly) NSUInteger displayNumVertices;
-@property (nonatomic, readonly) NSUInteger cursorNumVertices;
-@property (nonatomic, nullable, readonly) id<MTLBuffer> displayVertices;
-@property (nonatomic, nullable, readonly) id<MTLBuffer> cursorVertices;
-
-- (instancetype)init NS_UNAVAILABLE;
-- (instancetype)initWithSession:(nonnull SpiceSession *)session channelID:(NSInteger)channelID monitorID:(NSInteger)monitorID NS_DESIGNATED_INITIALIZER;
-- (instancetype)initWithSession:(nonnull SpiceSession *)session channelID:(NSInteger)channelID;
-- (void)updateVisibleAreaWithRect:(CGRect)rect;
-- (void)requestResolution:(CGRect)bounds;
-- (void)forceCursorPosition:(CGPoint)pos;
-
-@end
-
-NS_ASSUME_NONNULL_END

+ 0 - 731
CocoaSpice/CSDisplayMetal.m

@@ -1,731 +0,0 @@
-//
-// Copyright © 2019 osy. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-
-@import CoreImage;
-#import "TargetConditionals.h"
-#import "UTMScreenshot.h"
-#import "UTMShaderTypes.h"
-#import "CocoaSpice.h"
-#import "UTMLogging.h"
-#import <glib.h>
-#import <spice-client.h>
-#import <spice/protocol.h>
-#import <IOSurface/IOSurfaceRef.h>
-
-#ifdef DISPLAY_DEBUG
-#undef DISPLAY_DEBUG
-#endif
-#define DISPLAY_DEBUG(display, fmt, ...) \
-    SPICE_DEBUG("%d:%d " fmt, \
-                (int)display.channelID, \
-                (int)display.monitorID, \
-                ## __VA_ARGS__)
-
-@interface CSDisplayMetal ()
-
-@property (nonatomic, readwrite, nullable) SpiceSession *session;
-@property (nonatomic, readwrite, assign) NSInteger channelID;
-@property (nonatomic, readwrite, assign) NSInteger monitorID;
-@property (nonatomic, nullable) SpiceDisplayChannel *display;
-@property (nonatomic, nullable) SpiceMainChannel *main;
-@property (nonatomic, nullable) SpiceCursorChannel *cursor;
-@property (nonatomic, readwrite) CGPoint cursorHotspot;
-@property (nonatomic, readwrite) BOOL cursorHidden;
-@property (nonatomic, readwrite) BOOL hasCursor;
-@property (nonatomic, readwrite) BOOL isGLEnabled;
-@property (nonatomic, readwrite) BOOL hasGLDrawAck;
-@property (nonatomic) SpiceGlScanout scanout;
-
-// Non-GL Canvas
-@property (nonatomic) dispatch_semaphore_t canvasLock;
-@property (nonatomic) gint canvasFormat;
-@property (nonatomic) gint canvasStride;
-@property (nonatomic) const void *canvasData;
-@property (nonatomic) CGRect canvasArea;
-
-// Other Drawing
-@property (nonatomic) CGRect visibleArea;
-@property (nonatomic) CGPoint mouseGuest;
-
-// UTMRenderSource properties
-@property (nonatomic, nullable, readwrite) id<MTLTexture> canvasTexture;
-@property (nonatomic, nullable, readwrite) id<MTLTexture> glTexture;
-@property (nonatomic, nullable, readwrite) id<MTLTexture> cursorTexture;
-@property (nonatomic, readwrite) NSUInteger displayNumVertices;
-@property (nonatomic, readwrite) NSUInteger cursorNumVertices;
-@property (nonatomic, nullable, readwrite) id<MTLBuffer> displayVertices;
-@property (nonatomic, nullable, readwrite) id<MTLBuffer> cursorVertices;
-
-@end
-
-@implementation CSDisplayMetal
-
-#pragma mark - Display events
-
-static void cs_primary_create(SpiceChannel *channel, gint format,
-                           gint width, gint height, gint stride,
-                           gint shmid, gpointer imgdata, gpointer data) {
-    CSDisplayMetal *self = (__bridge CSDisplayMetal *)data;
-    
-    g_assert(format == SPICE_SURFACE_FMT_32_xRGB || format == SPICE_SURFACE_FMT_16_555);
-    dispatch_semaphore_wait(self.canvasLock, DISPATCH_TIME_FOREVER);
-    self.canvasArea = CGRectMake(0, 0, width, height);
-    self.canvasFormat = format;
-    self.canvasStride = stride;
-    self.canvasData = imgdata;
-    dispatch_semaphore_signal(self.canvasLock);
-    
-    cs_update_monitor_area(channel, NULL, data);
-}
-
-static void cs_primary_destroy(SpiceDisplayChannel *channel, gpointer data) {
-    CSDisplayMetal *self = (__bridge CSDisplayMetal *)data;
-    self.ready = NO;
-    
-    dispatch_semaphore_wait(self.canvasLock, DISPATCH_TIME_FOREVER);
-    self.canvasArea = CGRectZero;
-    self.canvasFormat = 0;
-    self.canvasStride = 0;
-    self.canvasData = NULL;
-    dispatch_semaphore_signal(self.canvasLock);
-}
-
-static void cs_invalidate(SpiceChannel *channel,
-                       gint x, gint y, gint w, gint h, gpointer data) {
-    CSDisplayMetal *self = (__bridge CSDisplayMetal *)data;
-    CGRect rect = CGRectIntersection(CGRectMake(x, y, w, h), self.visibleArea);
-    self.isGLEnabled = NO;
-    if (!CGRectIsEmpty(rect)) {
-        [self drawRegion:rect];
-    }
-}
-
-static void cs_mark(SpiceChannel *channel, gint mark, gpointer data) {
-    //CSDisplayMetal *self = (__bridge CSDisplayMetal *)data;
-    //@synchronized (self) {
-    //    self->_mark = mark; // currently this does nothing for us
-    //}
-}
-
-static gboolean cs_set_overlay(SpiceChannel *channel, void* pipeline_ptr, gpointer data) {
-    //FIXME: implement overlay
-    //CSDisplayMetal *self = (__bridge CSDisplayMetal *)data;
-    return false;
-}
-
-static void cs_update_monitor_area(SpiceChannel *channel, GParamSpec *pspec, gpointer data) {
-    CSDisplayMetal *self = (__bridge CSDisplayMetal *)data;
-    SpiceDisplayMonitorConfig *cfg, *c = NULL;
-    GArray *monitors = NULL;
-    int i;
-    
-    DISPLAY_DEBUG(self, "update monitor area");
-    if (self.monitorID < 0)
-        goto whole;
-    
-    g_object_get(self.display, "monitors", &monitors, NULL);
-    for (i = 0; monitors != NULL && i < monitors->len; i++) {
-        cfg = &g_array_index(monitors, SpiceDisplayMonitorConfig, i);
-        if (cfg->id == self.monitorID) {
-            c = cfg;
-            break;
-        }
-    }
-    if (c == NULL) {
-        DISPLAY_DEBUG(self, "update monitor: no monitor %d", (int)self.monitorID);
-        self.ready = NO;
-        if (spice_channel_test_capability(SPICE_CHANNEL(self.display),
-                                          SPICE_DISPLAY_CAP_MONITORS_CONFIG)) {
-            DISPLAY_DEBUG(self, "waiting until MonitorsConfig is received");
-            g_clear_pointer(&monitors, g_array_unref);
-            return;
-        }
-        goto whole;
-    }
-    
-    if (c->surface_id != 0) {
-        g_warning("FIXME: only support monitor config with primary surface 0, "
-                  "but given config surface %u", c->surface_id);
-        goto whole;
-    }
-    
-    /* If only one head on this monitor, update the whole area */
-    if (monitors->len == 1 && !self.isGLEnabled) {
-        [self updateVisibleAreaWithRect:CGRectMake(0, 0, c->width, c->height)];
-    } else {
-        [self updateVisibleAreaWithRect:CGRectMake(c->x, c->y, c->width, c->height)];
-    }
-    self.ready = YES;
-    g_clear_pointer(&monitors, g_array_unref);
-    return;
-    
-whole:
-    g_clear_pointer(&monitors, g_array_unref);
-    /* by display whole surface */
-    [self updateVisibleAreaWithRect:self.canvasArea];
-    self.ready = YES;
-}
-
-#pragma mark - Cursor events
-
-static void cs_update_mouse_mode(SpiceChannel *channel, gpointer data)
-{
-    CSDisplayMetal *self = (__bridge CSDisplayMetal *)data;
-    enum SpiceMouseMode mouse_mode;
-    
-    g_object_get(channel, "mouse-mode", &mouse_mode, NULL);
-    DISPLAY_DEBUG(self, "mouse mode %u", mouse_mode);
-    
-    if (mouse_mode == SPICE_MOUSE_MODE_SERVER) {
-        self.mouseGuest = CGPointMake(-1, -1);
-    }
-}
-
-static void cs_cursor_invalidate(CSDisplayMetal *self)
-{
-    // We implement two different textures so invalidate is not needed
-}
-
-static void cs_cursor_set(SpiceCursorChannel *channel,
-                          G_GNUC_UNUSED GParamSpec *pspec,
-                          gpointer data)
-{
-    CSDisplayMetal *self = (__bridge CSDisplayMetal *)data;
-    SpiceCursorShape *cursor_shape;
-    
-    g_object_get(G_OBJECT(channel), "cursor", &cursor_shape, NULL);
-    if (G_UNLIKELY(cursor_shape == NULL || cursor_shape->data == NULL)) {
-        if (cursor_shape != NULL) {
-            g_boxed_free(SPICE_TYPE_CURSOR_SHAPE, cursor_shape);
-        }
-        return;
-    }
-    
-    cs_cursor_invalidate(self);
-    
-    CGPoint hotspot = CGPointMake(cursor_shape->hot_spot_x, cursor_shape->hot_spot_y);
-    CGSize newSize = CGSizeMake(cursor_shape->width, cursor_shape->height);
-    if (!CGSizeEqualToSize(newSize, self.cursorSize) || !CGPointEqualToPoint(hotspot, self.cursorHotspot)) {
-        [self rebuildCursorWithSize:newSize center:hotspot];
-    }
-    [self drawCursor:cursor_shape->data];
-    self.cursorHidden = NO;
-    cs_cursor_invalidate(self);
-    g_boxed_free(SPICE_TYPE_CURSOR_SHAPE, cursor_shape);
-}
-
-static void cs_cursor_move(SpiceCursorChannel *channel, gint x, gint y, gpointer data)
-{
-    CSDisplayMetal *self = (__bridge CSDisplayMetal *)data;
-    
-    cs_cursor_invalidate(self); // old pointer buffer
-    
-    self.mouseGuest = CGPointMake(x, y);
-    
-    cs_cursor_invalidate(self); // new pointer buffer
-    
-    /* apparently we have to restore cursor when "cursor_move" */
-    if (self.hasCursor) {
-        self.cursorHidden = NO;
-    }
-}
-
-static void cs_cursor_hide(SpiceCursorChannel *channel, gpointer data)
-{
-    CSDisplayMetal *self = (__bridge CSDisplayMetal *)data;
-    
-    self.cursorHidden = YES;
-    cs_cursor_invalidate(self);
-}
-
-static void cs_cursor_reset(SpiceCursorChannel *channel, gpointer data)
-{
-    CSDisplayMetal *self = (__bridge CSDisplayMetal *)data;
-    
-    DISPLAY_DEBUG(self, "%s",  __FUNCTION__);
-    [self destroyCursor];
-    cs_cursor_invalidate(self);
-}
-
-#pragma mark - GL
-
-static void cs_gl_scanout(SpiceDisplayChannel *channel, GParamSpec *pspec, gpointer data)
-{
-    CSDisplayMetal *self = (__bridge CSDisplayMetal *)data;
-
-    DISPLAY_DEBUG(self, "%s: got scanout",  __FUNCTION__);
-
-    const SpiceGlScanout *scanout;
-
-    scanout = spice_display_channel_get_gl_scanout(self.display);
-    /* should only be called when the display has a scanout */
-    g_return_if_fail(scanout != NULL);
-    
-    self.isGLEnabled = YES;
-    self.hasGLDrawAck = YES;
-    self.scanout = *scanout;
-
-    [self rebuildScanoutTexture];
-}
-
-static void cs_gl_draw(SpiceDisplayChannel *channel,
-                       guint32 x, guint32 y, guint32 w, guint32 h,
-                       gpointer data)
-{
-    CSDisplayMetal *self = (__bridge CSDisplayMetal *)data;
-
-    DISPLAY_DEBUG(self, "%s",  __FUNCTION__);
-
-    self.isGLEnabled = YES;
-    self.hasGLDrawAck = NO;
-}
-
-#pragma mark - Channel events
-
-static void cs_channel_new(SpiceSession *s, SpiceChannel *channel, gpointer data) {
-    CSDisplayMetal *self = (__bridge CSDisplayMetal *)data;
-    gint channel_id;
-    
-    g_object_get(channel, "channel-id", &channel_id, NULL);
-    
-    if (SPICE_IS_DISPLAY_CHANNEL(channel)) {
-        SpiceDisplayPrimary primary;
-        if (channel_id != self.channelID) {
-            return;
-        }
-        self.display = SPICE_DISPLAY_CHANNEL(channel);
-        UTMLog(@"%s:%d", __FUNCTION__, __LINE__);
-        g_signal_connect(channel, "display-primary-create",
-                         G_CALLBACK(cs_primary_create), GLIB_OBJC_RETAIN(self));
-        g_signal_connect(channel, "display-primary-destroy",
-                         G_CALLBACK(cs_primary_destroy), GLIB_OBJC_RETAIN(self));
-        g_signal_connect(channel, "display-invalidate",
-                         G_CALLBACK(cs_invalidate), GLIB_OBJC_RETAIN(self));
-        g_signal_connect_after(channel, "display-mark",
-                               G_CALLBACK(cs_mark), GLIB_OBJC_RETAIN(self));
-        g_signal_connect_after(channel, "notify::monitors",
-                               G_CALLBACK(cs_update_monitor_area), GLIB_OBJC_RETAIN(self));
-        g_signal_connect_after(channel, "gst-video-overlay",
-                               G_CALLBACK(cs_set_overlay), GLIB_OBJC_RETAIN(self));
-        g_signal_connect(channel, "notify::gl-scanout",
-                         G_CALLBACK(cs_gl_scanout), GLIB_OBJC_RETAIN(self));
-        g_signal_connect(channel, "gl-draw",
-                         G_CALLBACK(cs_gl_draw), GLIB_OBJC_RETAIN(self));
-        if (spice_display_channel_get_primary(channel, 0, &primary)) {
-            cs_primary_create(channel, primary.format, primary.width, primary.height,
-                              primary.stride, primary.shmid, primary.data, (__bridge void *)self);
-            cs_mark(channel, primary.marked, (__bridge void *)self);
-        }
-        
-        spice_channel_connect(channel);
-        return;
-    }
-    
-    if (SPICE_IS_CURSOR_CHANNEL(channel)) {
-        gpointer cursor_shape;
-        if (channel_id != self.channelID) {
-            return;
-        }
-        self.cursor = SPICE_CURSOR_CHANNEL(channel);
-        g_signal_connect(channel, "notify::cursor",
-                         G_CALLBACK(cs_cursor_set), GLIB_OBJC_RETAIN(self));
-        g_signal_connect(channel, "cursor-move",
-                         G_CALLBACK(cs_cursor_move), GLIB_OBJC_RETAIN(self));
-        g_signal_connect(channel, "cursor-hide",
-                         G_CALLBACK(cs_cursor_hide), GLIB_OBJC_RETAIN(self));
-        g_signal_connect(channel, "cursor-reset",
-                         G_CALLBACK(cs_cursor_reset), GLIB_OBJC_RETAIN(self));
-        spice_channel_connect(channel);
-        
-        g_object_get(G_OBJECT(channel), "cursor", &cursor_shape, NULL);
-        if (cursor_shape != NULL) {
-            g_boxed_free(SPICE_TYPE_CURSOR_SHAPE, cursor_shape);
-            cs_cursor_set(self.cursor, NULL, (__bridge void *)self);
-        }
-        return;
-    }
-    
-    if (SPICE_IS_MAIN_CHANNEL(channel)) {
-        self.main = SPICE_MAIN_CHANNEL(channel);
-        g_signal_connect(channel, "main-mouse-update",
-                         G_CALLBACK(cs_update_mouse_mode), GLIB_OBJC_RETAIN(self));
-        cs_update_mouse_mode(channel, data);
-        return;
-    }
-}
-
-static void cs_channel_destroy(SpiceSession *s, SpiceChannel *channel, gpointer data) {
-    CSDisplayMetal *self = (__bridge CSDisplayMetal *)data;
-    gint channel_id;
-    
-    g_object_get(channel, "channel-id", &channel_id, NULL);
-    DISPLAY_DEBUG(self, "channel_destroy %d", channel_id);
-    
-    if (SPICE_IS_DISPLAY_CHANNEL(channel)) {
-        if (channel_id != self.channelID) {
-            return;
-        }
-        cs_primary_destroy(self.display, (__bridge void *)self);
-        self.display = NULL;
-        UTMLog(@"%s:%d", __FUNCTION__, __LINE__);
-        g_signal_handlers_disconnect_by_func(channel, G_CALLBACK(cs_primary_create), GLIB_OBJC_RELEASE(self));
-        g_signal_handlers_disconnect_by_func(channel, G_CALLBACK(cs_primary_destroy), GLIB_OBJC_RELEASE(self));
-        g_signal_handlers_disconnect_by_func(channel, G_CALLBACK(cs_invalidate), GLIB_OBJC_RELEASE(self));
-        g_signal_handlers_disconnect_by_func(channel, G_CALLBACK(cs_mark), GLIB_OBJC_RELEASE(self));
-        g_signal_handlers_disconnect_by_func(channel, G_CALLBACK(cs_update_monitor_area), GLIB_OBJC_RELEASE(self));
-        g_signal_handlers_disconnect_by_func(channel, G_CALLBACK(cs_set_overlay), GLIB_OBJC_RELEASE(self));
-        g_signal_handlers_disconnect_by_func(channel, G_CALLBACK(cs_gl_scanout), GLIB_OBJC_RELEASE(self));
-        g_signal_handlers_disconnect_by_func(channel, G_CALLBACK(cs_gl_draw), GLIB_OBJC_RELEASE(self));
-        return;
-    }
-    
-    if (SPICE_IS_CURSOR_CHANNEL(channel)) {
-        if (channel_id != self.channelID) {
-            return;
-        }
-        self.cursor = NULL;
-        g_signal_handlers_disconnect_by_func(channel, G_CALLBACK(cs_cursor_set), GLIB_OBJC_RELEASE(self));
-        g_signal_handlers_disconnect_by_func(channel, G_CALLBACK(cs_cursor_move), GLIB_OBJC_RELEASE(self));
-        g_signal_handlers_disconnect_by_func(channel, G_CALLBACK(cs_cursor_hide), GLIB_OBJC_RELEASE(self));
-        g_signal_handlers_disconnect_by_func(channel, G_CALLBACK(cs_cursor_reset), GLIB_OBJC_RELEASE(self));
-        return;
-    }
-    
-    if (SPICE_IS_MAIN_CHANNEL(channel)) {
-        self.main = NULL;
-        g_signal_handlers_disconnect_by_func(channel, G_CALLBACK(cs_update_mouse_mode), GLIB_OBJC_RELEASE(self));
-        return;
-    }
-    
-    return;
-}
-
-- (void)setDevice:(id<MTLDevice>)device {
-    _device = device;
-    [self rebuildDisplayVertices];
-    if (self.isGLEnabled) {
-        [self rebuildScanoutTexture];
-    } else {
-        [self rebuildCanvasTexture];
-    }
-}
-
-- (UTMScreenshot *)screenshot {
-    CGImageRef img;
-    CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
-    
-    dispatch_semaphore_wait(self.canvasLock, DISPATCH_TIME_FOREVER);
-    if (self.canvasData) { // may be destroyed at this point
-        CGDataProviderRef dataProviderRef = CGDataProviderCreateWithData(NULL, self.canvasData, self.canvasStride * self.canvasArea.size.height, nil);
-        img = CGImageCreate(self.canvasArea.size.width, self.canvasArea.size.height, 8, 32, self.canvasStride, colorSpaceRef, kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipFirst, dataProviderRef, NULL, NO, kCGRenderingIntentDefault);
-        CGDataProviderRelease(dataProviderRef);
-    } else if (self.glTexture) {
-        CIImage *ciimage = [[CIImage alloc] initWithMTLTexture:self.glTexture options:nil];
-        CIImage *flipped = [ciimage imageByApplyingOrientation:kCGImagePropertyOrientationDownMirrored];
-        CIContext *cictx = [CIContext context];
-        img = [cictx createCGImage:flipped fromRect:flipped.extent];
-    } else {
-        img = NULL;
-    }
-    dispatch_semaphore_signal(self.canvasLock);
-    
-    CGColorSpaceRelease(colorSpaceRef);
-    
-    if (img) {
-#if TARGET_OS_IPHONE
-        UIImage *uiimg = [UIImage imageWithCGImage:img];
-#else
-        NSImage *uiimg = [[NSImage alloc] initWithCGImage:img size:NSZeroSize];
-#endif
-        CGImageRelease(img);
-        return [[UTMScreenshot alloc] initWithImage:uiimg];
-    } else {
-        return nil;
-    }
-}
-
-- (id<MTLTexture>)displayTexture {
-    if (self.isGLEnabled) {
-        return self.glTexture;
-    } else {
-        return self.canvasTexture;
-    }
-}
-
-#pragma mark - Methods
-
-- (instancetype)initWithSession:(nonnull SpiceSession *)session channelID:(NSInteger)channelID monitorID:(NSInteger)monitorID {
-    if (self = [super init]) {
-        GList *list;
-        GList *it;
-        
-        self.canvasLock = dispatch_semaphore_create(1);
-        self.viewportScale = 1.0f;
-        self.viewportOrigin = CGPointMake(0, 0);
-        self.channelID = channelID;
-        self.monitorID = monitorID;
-        self.session = session;
-        g_object_ref(session);
-        
-        UTMLog(@"%s:%d", __FUNCTION__, __LINE__);
-        g_signal_connect(session, "channel-new",
-                         G_CALLBACK(cs_channel_new), GLIB_OBJC_RETAIN(self));
-        g_signal_connect(session, "channel-destroy",
-                         G_CALLBACK(cs_channel_destroy), GLIB_OBJC_RETAIN(self));
-        list = spice_session_get_channels(session);
-        for (it = g_list_first(list); it != NULL; it = g_list_next(it)) {
-            if (SPICE_IS_MAIN_CHANNEL(it->data)) {
-                cs_channel_new(session, it->data, (__bridge void *)self);
-                break;
-            }
-        }
-        for (it = g_list_first(list); it != NULL; it = g_list_next(it)) {
-            if (!SPICE_IS_MAIN_CHANNEL(it->data))
-                cs_channel_new(session, it->data, (__bridge void *)self);
-        }
-        g_list_free(list);
-    }
-    return self;
-}
-
-- (instancetype)initWithSession:(nonnull SpiceSession *)session channelID:(NSInteger)channelID {
-    return [self initWithSession:session channelID:channelID monitorID:0];
-}
-
-- (void)dealloc {
-    if (self.display) {
-        cs_channel_destroy(self.session, SPICE_CHANNEL(self.display), (__bridge void *)self);
-    }
-    if (_cursor) {
-        cs_channel_destroy(self.session, SPICE_CHANNEL(_cursor), (__bridge void *)self);
-    }
-    UTMLog(@"%s:%d", __FUNCTION__, __LINE__);
-    g_signal_handlers_disconnect_by_func(self.session, G_CALLBACK(cs_channel_new), GLIB_OBJC_RELEASE(self));
-    g_signal_handlers_disconnect_by_func(self.session, G_CALLBACK(cs_channel_destroy), GLIB_OBJC_RELEASE(self));
-    g_object_unref(self.session);
-    self.session = NULL;
-}
-
-- (void)updateVisibleAreaWithRect:(CGRect)rect {
-    CGRect primary;
-    if (self.isGLEnabled) {
-        primary = CGRectMake(0, 0, self.scanout.width, self.scanout.height);
-    } else {
-        primary = self.canvasArea;
-    }
-    CGRect visible = CGRectIntersection(primary, rect);
-    if (CGRectIsNull(visible)) {
-        DISPLAY_DEBUG(self, "The monitor area is not intersecting primary surface");
-        self.ready = NO;
-        self.visibleArea = CGRectZero;
-    } else {
-        self.visibleArea = visible;
-    }
-    self.displaySize = self.visibleArea.size;
-    [self rebuildDisplayVertices];
-    if (!self.isGLEnabled) {
-        [self rebuildCanvasTexture];
-    }
-}
-
-- (void)rebuildScanoutTexture {
-    if (!self.device) {
-        return; // not ready
-    }
-    IOSurfaceID iosurfaceid = 0;
-    IOSurfaceRef iosurface = NULL;
-    if (read(self.scanout.fd, &iosurfaceid, sizeof(iosurfaceid)) != sizeof(iosurfaceid)) {
-        UTMLog(@"Failed to read scanout fd: %d", self.scanout.fd);
-        perror("read");
-        return;
-    }
-    if ((iosurface = IOSurfaceLookup(iosurfaceid)) == NULL) {
-        UTMLog(@"Failed to lookup surface: %d", iosurfaceid);
-        return;
-    }
-
-    MTLTextureDescriptor *textureDescriptor = [[MTLTextureDescriptor alloc] init];
-    textureDescriptor.pixelFormat = MTLPixelFormatBGRA8Unorm;
-    textureDescriptor.width = self.scanout.width;
-    textureDescriptor.height = self.scanout.height;
-    textureDescriptor.usage = MTLTextureUsageShaderRead;
-    self.glTexture = [self.device newTextureWithDescriptor:textureDescriptor iosurface:iosurface plane:0];
-    CFRelease(iosurface);
-}
-
-- (void)rebuildCanvasTexture {
-    if (CGRectIsEmpty(self.canvasArea) || !self.device) {
-        return;
-    }
-    MTLTextureDescriptor *textureDescriptor = [[MTLTextureDescriptor alloc] init];
-    // don't worry that that components are reversed, we fix it in shaders
-    textureDescriptor.pixelFormat = (self.canvasFormat == SPICE_SURFACE_FMT_32_xRGB) ? MTLPixelFormatBGRA8Unorm : (MTLPixelFormat)43;// FIXME: MTLPixelFormatBGR5A1Unorm is supposed to be available.
-    textureDescriptor.width = self.visibleArea.size.width;
-    textureDescriptor.height = self.visibleArea.size.height;
-    self.canvasTexture = [self.device newTextureWithDescriptor:textureDescriptor];
-    [self drawRegion:self.visibleArea];
-}
-
-- (void)rebuildDisplayVertices {
-    // We flip the y-coordinates because pixman renders flipped
-    UTMVertex quadVertices[] =
-    {
-        // Pixel positions, Texture coordinates
-        { {  self.visibleArea.size.width/2,   self.visibleArea.size.height/2 },  { 1.f, 0.f } },
-        { { -self.visibleArea.size.width/2,   self.visibleArea.size.height/2 },  { 0.f, 0.f } },
-        { { -self.visibleArea.size.width/2,  -self.visibleArea.size.height/2 },  { 0.f, 1.f } },
-        
-        { {  self.visibleArea.size.width/2,   self.visibleArea.size.height/2 },  { 1.f, 0.f } },
-        { { -self.visibleArea.size.width/2,  -self.visibleArea.size.height/2 },  { 0.f, 1.f } },
-        { {  self.visibleArea.size.width/2,  -self.visibleArea.size.height/2 },  { 1.f, 1.f } },
-    };
-    
-    // Create our vertex buffer, and initialize it with our quadVertices array
-    self.displayVertices = [self.device newBufferWithBytes:quadVertices
-                                                    length:sizeof(quadVertices)
-                                                   options:MTLResourceStorageModeShared];
-
-    // Calculate the number of vertices by dividing the byte length by the size of each vertex
-    self.displayNumVertices = sizeof(quadVertices) / sizeof(UTMVertex);
-}
-
-- (void)drawRegion:(CGRect)rect {
-    NSInteger pixelSize = (self.canvasFormat == SPICE_SURFACE_FMT_32_xRGB) ? 4 : 2;
-    // create draw region
-    MTLRegion region = {
-        { rect.origin.x-self.visibleArea.origin.x, rect.origin.y-self.visibleArea.origin.y, 0 }, // MTLOrigin
-        { rect.size.width, rect.size.height, 1} // MTLSize
-    };
-    dispatch_semaphore_wait(self.canvasLock, DISPATCH_TIME_FOREVER);
-    if (self.canvasData) {
-        [self.canvasTexture  replaceRegion:region
-                               mipmapLevel:0
-                                 withBytes:(const char *)self.canvasData + (NSUInteger)(rect.origin.y*self.canvasStride + rect.origin.x*pixelSize)
-                               bytesPerRow:self.canvasStride];
-    }
-    dispatch_semaphore_signal(self.canvasLock);
-}
-
-- (BOOL)visible {
-    return self.ready;
-}
-
-- (void)requestResolution:(CGRect)bounds {
-    if (!self.main) {
-        UTMLog(@"ignoring change resolution because main channel not found");
-        return;
-    }
-    spice_main_channel_update_display_enabled(self.main, (int)self.monitorID, TRUE, FALSE);
-    spice_main_channel_update_display(self.main,
-                                      (int)self.monitorID,
-                                      bounds.origin.x,
-                                      bounds.origin.y,
-                                      bounds.size.width,
-                                      bounds.size.height,
-                                      TRUE);
-    spice_main_channel_send_monitor_config(self.main);
-}
-
-- (void)rendererFrameHasRendered {
-    if (self.isGLEnabled && !self.hasGLDrawAck) {
-        spice_display_channel_gl_draw_done(self.display);
-        self.hasGLDrawAck = YES;
-    }
-}
-
-#pragma mark - Cursor drawing
-
-- (void)rebuildCursorWithSize:(CGSize)size center:(CGPoint)hotspot {
-    // hotspot is the offset in buffer for the center of the pointer
-    if (!self.device) {
-        UTMLog(@"MTL device not ready for cursor draw");
-        return;
-    }
-    MTLTextureDescriptor *textureDescriptor = [[MTLTextureDescriptor alloc] init];
-    // don't worry that that components are reversed, we fix it in shaders
-    textureDescriptor.pixelFormat = MTLPixelFormatBGRA8Unorm;
-    textureDescriptor.width = size.width;
-    textureDescriptor.height = size.height;
-    self.cursorTexture = [self.device newTextureWithDescriptor:textureDescriptor];
-
-    // We flip the y-coordinates because pixman renders flipped
-    UTMVertex quadVertices[] =
-    {
-     // Pixel positions, Texture coordinates
-     { { -hotspot.x + size.width, hotspot.y               },  { 1.f, 0.f } },
-     { { -hotspot.x             , hotspot.y               },  { 0.f, 0.f } },
-     { { -hotspot.x             , hotspot.y - size.height },  { 0.f, 1.f } },
-     
-     { { -hotspot.x + size.width, hotspot.y               },  { 1.f, 0.f } },
-     { { -hotspot.x             , hotspot.y - size.height },  { 0.f, 1.f } },
-     { { -hotspot.x + size.width, hotspot.y - size.height },  { 1.f, 1.f } },
-    };
-
-    // Create our vertex buffer, and initialize it with our quadVertices array
-    self.cursorVertices = [self.device newBufferWithBytes:quadVertices
-                                                   length:sizeof(quadVertices)
-                                                  options:MTLResourceStorageModeShared];
-
-    // Calculate the number of vertices by dividing the byte length by the size of each vertex
-    self.cursorNumVertices = sizeof(quadVertices) / sizeof(UTMVertex);
-    self.cursorSize = size;
-    self.cursorHotspot = hotspot;
-    self.hasCursor = YES;
-}
-
-- (void)destroyCursor {
-    self.cursorNumVertices = 0;
-    self.cursorVertices = nil;
-    self.cursorTexture = nil;
-    self.cursorSize = CGSizeZero;
-    self.cursorHotspot = CGPointZero;
-    self.hasCursor = NO;
-}
-
-- (void)drawCursor:(const void *)buffer {
-    const NSInteger pixelSize = 4;
-    MTLRegion region = {
-        { 0, 0 }, // MTLOrigin
-        { self.cursorSize.width, self.cursorSize.height, 1} // MTLSize
-    };
-    [self.cursorTexture replaceRegion:region
-                          mipmapLevel:0
-                            withBytes:buffer
-                          bytesPerRow:self.cursorSize.width*pixelSize];
-}
-
-- (BOOL)cursorVisible {
-    return !self.inhibitCursor && self.hasCursor && !self.cursorHidden;
-}
-
-- (CGPoint)cursorOrigin {
-    CGPoint point = self.mouseGuest;
-    point.x -= self.displaySize.width/2;
-    point.y -= self.displaySize.height/2;
-    point.x *= self.viewportScale;
-    point.y *= self.viewportScale;
-    return point;
-}
-
-- (BOOL)cursorInverted {
-    return !self.isGLEnabled;
-}
-
-- (void)forceCursorPosition:(CGPoint)pos {
-    self.mouseGuest = pos;
-}
-
-@end

+ 0 - 63
CocoaSpice/CSInput.h

@@ -1,63 +0,0 @@
-//
-// Copyright © 2019 osy. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-
-#import <Foundation/Foundation.h>
-#import "UTMRenderSource.h"
-@import CoreGraphics;
-
-typedef struct _SpiceSession SpiceSession;
-
-typedef NS_ENUM(NSInteger, CSInputKey) {
-    kCSInputKeyPress,
-    kCSInputKeyRelease
-};
-
-typedef NS_OPTIONS(NSUInteger, CSInputButton) {
-    kCSInputButtonNone = 0,
-    kCSInputButtonLeft = (1 << 0),
-    kCSInputButtonMiddle = (1 << 1),
-    kCSInputButtonRight = (1 << 2)
-};
-
-typedef NS_ENUM(NSInteger, CSInputScroll) {
-    kCSInputScrollUp,
-    kCSInputScrollDown,
-    kCSInputScrollSmooth
-};
-
-NS_ASSUME_NONNULL_BEGIN
-
-@interface CSInput : NSObject
-
-@property (nonatomic, readonly, assign) BOOL serverModeCursor;
-@property (nonatomic, assign) BOOL disableInputs;
-
-- (void)sendKey:(CSInputKey)type code:(int)scancode;
-- (void)sendPause:(CSInputKey)type;
-- (void)releaseKeys;
-
-- (void)sendMouseMotion:(CSInputButton)button point:(CGPoint)point;
-- (void)sendMouseMotion:(CSInputButton)button point:(CGPoint)point forMonitorID:(NSInteger)monitorID;
-- (void)sendMouseScroll:(CSInputScroll)type button:(CSInputButton)button dy:(CGFloat)dy;
-- (void)sendMouseButton:(CSInputButton)button pressed:(BOOL)pressed point:(CGPoint)point;
-- (void)requestMouseMode:(BOOL)server;
-
-- (instancetype)init NS_UNAVAILABLE;
-- (instancetype)initWithSession:(SpiceSession *)session NS_DESIGNATED_INITIALIZER;
-
-@end
-
-NS_ASSUME_NONNULL_END

+ 0 - 325
CocoaSpice/CSInput.m

@@ -1,325 +0,0 @@
-//
-// Copyright © 2019 osy. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-
-#import "CSInput.h"
-#import "CocoaSpice.h"
-#import "UTMLogging.h"
-#import <glib.h>
-#import <spice-client.h>
-#import <spice/protocol.h>
-#import "UTMShaderTypes.h"
-
-@interface CSInput ()
-
-@property (nonatomic, nullable) SpiceSession *session;
-@property (nonatomic, nullable) SpiceMainChannel *main;
-@property (nonatomic, nullable) SpiceInputsChannel *inputs;
-
-@end
-
-@implementation CSInput {
-    CGFloat                 _scroll_delta_y;
-    
-    uint32_t                _key_state[512 / 32];
-}
-
-#pragma mark - Channel events
-
-static void cs_channel_new(SpiceSession *s, SpiceChannel *channel, gpointer data)
-{
-    CSInput *self = (__bridge CSInput *)data;
-    int chid;
-    
-    g_object_get(channel, "channel-id", &chid, NULL);
-    if (SPICE_IS_MAIN_CHANNEL(channel)) {
-        self.main = SPICE_MAIN_CHANNEL(channel);
-        return;
-    }
-    
-    if (SPICE_IS_INPUTS_CHANNEL(channel)) {
-        self.inputs = SPICE_INPUTS_CHANNEL(channel);
-        spice_channel_connect(channel);
-        return;
-    }
-}
-
-static void cs_channel_destroy(SpiceSession *s, SpiceChannel *channel, gpointer data)
-{
-    CSInput *self = (__bridge CSInput *)data;
-    int chid;
-    
-    g_object_get(channel, "channel-id", &chid, NULL);
-    DISPLAY_DEBUG(self, "channel_destroy %d", chid);
-    
-    if (SPICE_IS_MAIN_CHANNEL(channel)) {
-        self.main = NULL;
-        return;
-    }
-    
-    if (SPICE_IS_INPUTS_CHANNEL(channel)) {
-        self.inputs = NULL;
-        return;
-    }
-    
-    return;
-}
-
-#pragma mark - Properties
-
-- (BOOL)serverModeCursor {
-    enum SpiceMouseMode mouse_mode;
-    g_object_get(self.main, "mouse-mode", &mouse_mode, NULL);
-    return (mouse_mode == SPICE_MOUSE_MODE_SERVER);
-}
-
-#pragma mark - Key handling
-
-- (void)sendPause:(CSInputKey)type {
-    /* Send proper scancodes. This will send same scancodes
-     * as hardware.
-     * The 0x21d is a sort of Third-Ctrl while
-     * 0x45 is the NumLock.
-     */
-    if (type == kCSInputKeyPress) {
-        spice_inputs_channel_key_press(self.inputs, 0x21d);
-        spice_inputs_channel_key_press(self.inputs, 0x45);
-    } else {
-        spice_inputs_channel_key_release(self.inputs, 0x21d);
-        spice_inputs_channel_key_release(self.inputs, 0x45);
-    }
-}
-
-- (void)sendKey:(CSInputKey)type code:(int)scancode {
-    uint32_t i, b, m;
-    
-    g_return_if_fail(scancode != 0);
-    
-    if (!self.inputs)
-        return;
-    
-    if (self.disableInputs)
-        return;
-    
-    i = scancode / 32;
-    b = scancode % 32;
-    m = (1u << b);
-    g_return_if_fail(i < SPICE_N_ELEMENTS(self->_key_state));
-    
-    switch (type) {
-        case kCSInputKeyPress:
-            spice_inputs_channel_key_press(self.inputs, scancode);
-            
-            self->_key_state[i] |= m;
-            break;
-            
-        case kCSInputKeyRelease:
-            if (!(self->_key_state[i] & m))
-                break;
-            
-            
-            spice_inputs_channel_key_release(self.inputs, scancode);
-            
-            self->_key_state[i] &= ~m;
-            break;
-            
-        default:
-            g_warn_if_reached();
-    }
-}
-
-- (void)releaseKeys {
-    uint32_t i, b;
-    
-    DISPLAY_DEBUG(self, "%s", __FUNCTION__);
-    for (i = 0; i < SPICE_N_ELEMENTS(self->_key_state); i++) {
-        if (!self->_key_state[i]) {
-            continue;
-        }
-        for (b = 0; b < 32; b++) {
-            unsigned int scancode = i * 32 + b;
-            if (scancode != 0) {
-                [self sendKey:kCSInputKeyRelease code:scancode];
-            }
-        }
-    }
-}
-
-#pragma mark - Mouse handling
-
-static int cs_button_mask_to_spice(CSInputButton button)
-{
-    int spice = 0;
-    
-    if (button & kCSInputButtonLeft)
-        spice |= SPICE_MOUSE_BUTTON_MASK_LEFT;
-    if (button & kCSInputButtonMiddle)
-        spice |= SPICE_MOUSE_BUTTON_MASK_MIDDLE;
-    if (button & kCSInputButtonRight)
-        spice |= SPICE_MOUSE_BUTTON_MASK_RIGHT;
-    return spice;
-}
-
-static int cs_button_to_spice(CSInputButton button)
-{
-    int spice = 0;
-    
-    if (button & kCSInputButtonLeft)
-        spice |= SPICE_MOUSE_BUTTON_LEFT;
-    if (button & kCSInputButtonMiddle)
-        spice |= SPICE_MOUSE_BUTTON_MIDDLE;
-    if (button & kCSInputButtonRight)
-        spice |= SPICE_MOUSE_BUTTON_RIGHT;
-    return spice;
-}
-
-- (void)sendMouseMotion:(CSInputButton)button point:(CGPoint)point forMonitorID:(NSInteger)monitorID {
-    if (!self.inputs)
-        return;
-    if (self.disableInputs)
-        return;
-    
-    if (self.serverModeCursor) {
-        spice_inputs_channel_motion(self.inputs, point.x, point.y,
-                                    cs_button_mask_to_spice(button));
-    } else {
-        spice_inputs_channel_position(self.inputs, point.x, point.y, (int)monitorID,
-                                      cs_button_mask_to_spice(button));
-    }
-}
-
-// FIXME: remove this when multiple displays are implemented properly
-- (void)sendMouseMotion:(CSInputButton)button point:(CGPoint)point {
-    [self sendMouseMotion:button point:point forMonitorID:0];
-}
-
-- (void)sendMouseScroll:(CSInputScroll)type button:(CSInputButton)button dy:(CGFloat)dy {
-    gint button_state = cs_button_mask_to_spice(button);
-    
-    DISPLAY_DEBUG(self, "%s", __FUNCTION__);
-    
-    if (!self.inputs)
-        return;
-    if (self.disableInputs)
-        return;
-    
-    switch (type) {
-        case kCSInputScrollUp:
-            spice_inputs_channel_button_press(self.inputs, SPICE_MOUSE_BUTTON_UP, button_state);
-            spice_inputs_channel_button_release(self.inputs, SPICE_MOUSE_BUTTON_UP, button_state);
-            break;
-        case kCSInputScrollDown:
-            spice_inputs_channel_button_press(self.inputs, SPICE_MOUSE_BUTTON_DOWN, button_state);
-            spice_inputs_channel_button_release(self.inputs, SPICE_MOUSE_BUTTON_DOWN, button_state);
-            break;
-        case kCSInputScrollSmooth:
-            self->_scroll_delta_y += dy;
-            while (ABS(self->_scroll_delta_y) >= 1) {
-                if (self->_scroll_delta_y < 0) {
-                    spice_inputs_channel_button_press(self.inputs, SPICE_MOUSE_BUTTON_UP, button_state);
-                    spice_inputs_channel_button_release(self.inputs, SPICE_MOUSE_BUTTON_UP, button_state);
-                    self->_scroll_delta_y += 1;
-                } else {
-                    spice_inputs_channel_button_press(self.inputs, SPICE_MOUSE_BUTTON_DOWN, button_state);
-                    spice_inputs_channel_button_release(self.inputs, SPICE_MOUSE_BUTTON_DOWN, button_state);
-                    self->_scroll_delta_y -= 1;
-                }
-            }
-            break;
-        default:
-            DISPLAY_DEBUG(self, "unsupported scroll direction");
-    }
-}
-
-- (void)sendMouseButton:(CSInputButton)button pressed:(BOOL)pressed point:(CGPoint)point {
-    DISPLAY_DEBUG(self, "%s %s: button %u", __FUNCTION__,
-                  pressed ? "press" : "release",
-                  (unsigned int)button);
-    
-    if (self.disableInputs)
-        return;
-    
-    if ((point.x < 0 || point.y < 0) &&
-        !self.serverModeCursor) {
-        /* rule out clicks in outside region */
-        return;
-    }
-    
-    if (!self.inputs)
-        return;
-    
-    if (pressed) {
-        spice_inputs_channel_button_press(self.inputs,
-                                          cs_button_to_spice(button),
-                                          cs_button_mask_to_spice(button));
-    } else {
-        spice_inputs_channel_button_release(self.inputs,
-                                            cs_button_to_spice(button),
-                                            cs_button_mask_to_spice(button));
-    }
-}
-
-- (void)requestMouseMode:(BOOL)server {
-    if (server) {
-        spice_main_channel_request_mouse_mode(self.main, SPICE_MOUSE_MODE_SERVER);
-    } else {
-        spice_main_channel_request_mouse_mode(self.main, SPICE_MOUSE_MODE_CLIENT);
-    }
-}
-
-#pragma mark - Initializers
-
-- (instancetype)initWithSession:(SpiceSession *)session {
-    self = [super init];
-    if (self) {
-        GList *list;
-        GList *it;
-        
-        self.session = session;
-        g_object_ref(session);
-        
-        UTMLog(@"%s:%d", __FUNCTION__, __LINE__);
-        g_signal_connect(session, "channel-new",
-                         G_CALLBACK(cs_channel_new), GLIB_OBJC_RETAIN(self));
-        g_signal_connect(session, "channel-destroy",
-                         G_CALLBACK(cs_channel_destroy), GLIB_OBJC_RETAIN(self));
-        list = spice_session_get_channels(session);
-        for (it = g_list_first(list); it != NULL; it = g_list_next(it)) {
-            if (SPICE_IS_MAIN_CHANNEL(it->data)) {
-                cs_channel_new(session, it->data, (__bridge void *)self);
-                break;
-            }
-        }
-        for (it = g_list_first(list); it != NULL; it = g_list_next(it)) {
-            if (!SPICE_IS_MAIN_CHANNEL(it->data))
-                cs_channel_new(session, it->data, (__bridge void *)self);
-        }
-        g_list_free(list);
-    }
-    return self;
-}
-
-- (void)dealloc {
-    if (self.main) {
-        cs_channel_destroy(self.session, SPICE_CHANNEL(self.main), (__bridge void *)self);
-    }
-    UTMLog(@"%s:%d", __FUNCTION__, __LINE__);
-    g_signal_handlers_disconnect_by_func(self.session, G_CALLBACK(cs_channel_new), GLIB_OBJC_RELEASE(self));
-    g_signal_handlers_disconnect_by_func(self.session, G_CALLBACK(cs_channel_destroy), GLIB_OBJC_RELEASE(self));
-    g_object_unref(self.session);
-    self.session = NULL;
-}
-
-@end

+ 0 - 34
CocoaSpice/CSMain.h

@@ -1,34 +0,0 @@
-//
-// Copyright © 2019 osy. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-
-#import <Foundation/Foundation.h>
-
-NS_ASSUME_NONNULL_BEGIN
-
-@interface CSMain : NSObject
-
-@property (nonatomic, readonly) BOOL running;
-@property (nonatomic, readonly) void *glibMainContext;
-
-+ (CSMain *)sharedInstance;
-- (instancetype)init NS_UNAVAILABLE;
-- (void)spiceSetDebug:(BOOL)enabled;
-- (BOOL)spiceStart;
-- (void)spiceStop;
-
-@end
-
-NS_ASSUME_NONNULL_END

+ 0 - 150
CocoaSpice/CSMain.m

@@ -1,150 +0,0 @@
-//
-// Copyright © 2019 osy. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-
-#import "CSMain.h"
-#import "UTMLogging.h"
-#import <glib.h>
-#import <spice-client.h>
-#import <pthread.h>
-#import "gst_ios_init.h"
-
-@interface CSMain ()
-
-@property (nonatomic, readwrite) BOOL running;
-@property (nonatomic) pthread_t spiceThread;
-
-@end
-
-@implementation CSMain {
-    GMainContext *_main_context;
-    GMainLoop *_main_loop;
-}
-
-static void logHandler(const gchar *log_domain, GLogLevelFlags log_level,
-                       const gchar *message, gpointer user_data)
-{
-    GDateTime *now;
-    gchar *dateTimeStr;
-    
-    char* levelStr = "UNKNOWN";
-    if (log_level & G_LOG_LEVEL_ERROR) {
-        levelStr = "ERROR";
-    } else if (log_level & G_LOG_LEVEL_CRITICAL) {
-        levelStr = "CRITICAL";
-    } else if (log_level & G_LOG_LEVEL_WARNING) {
-        levelStr = "WARNING";
-    } else if (log_level & G_LOG_LEVEL_MESSAGE) {
-        levelStr = "MESSAGE";
-    } else if (log_level & G_LOG_LEVEL_INFO) {
-        levelStr = "INFO";
-    } else if (log_level & G_LOG_LEVEL_DEBUG) {
-        levelStr = "DEBUG";
-    }
-    
-    now = g_date_time_new_now_local();
-    dateTimeStr = g_date_time_format(now, "%Y-%m-%d %T");
-    
-    fprintf(stdout, "%s,%03d %s %s-%s\n", dateTimeStr,
-            g_date_time_get_microsecond(now) / 1000, levelStr,
-            log_domain, message);
-    
-    g_date_time_unref(now);
-    g_free(dateTimeStr);
-}
-
-void *spice_main_loop(void *args) {
-    CSMain *self = (__bridge_transfer CSMain *)args;
-    
-    gst_ios_init();
-    
-    g_main_context_ref(self->_main_context);
-    g_main_context_push_thread_default(self->_main_context);
-    g_main_loop_run(self->_main_loop);
-    g_main_context_pop_thread_default(self->_main_context);
-    g_main_context_unref(self->_main_context);
-    
-    return NULL;
-}
-
-+ (CSMain *)sharedInstance {
-    static CSMain *sharedInstance = nil;
-    static dispatch_once_t onceToken;
-    dispatch_once(&onceToken, ^{
-        sharedInstance = [[self alloc] init];
-    });
-    return sharedInstance;
-}
-
-- (void *)glibMainContext {
-    return _main_context;
-}
-
-- (id)init {
-    self = [super init];
-    if (self) {
-        if ((_main_context = g_main_context_new()) == NULL) {
-            return nil;
-        }
-        if ((_main_loop = g_main_loop_new(_main_context, FALSE)) == NULL) {
-            g_main_context_unref(_main_context);
-            return nil;
-        }
-    }
-    return self;
-}
-
-- (void)dealloc {
-    [self spiceStop];
-    g_main_loop_unref(_main_loop);
-    g_main_context_unref(_main_context);
-}
-
-- (void)spiceSetDebug:(BOOL)enabled {
-    spice_util_set_debug(enabled);
-    if (enabled) {
-        g_log_set_handler(NULL, G_LOG_LEVEL_MASK, logHandler, NULL);
-    }
-}
-
-- (BOOL)spiceStart {
-    @synchronized (self) {
-        if (!self.running) {
-            pthread_t spiceThread;
-            spice_util_set_main_context(_main_context);
-            if (pthread_create(&spiceThread, NULL, &spice_main_loop, (__bridge_retained void *)self) != 0) {
-                return NO;
-            }
-            self.running = YES;
-            self.spiceThread = spiceThread;
-        }
-    }
-    return YES;
-}
-
-- (void)spiceStop {
-    @synchronized (self) {
-        if (self.running) {
-            void *status;
-            spice_util_set_main_context(NULL);
-            g_main_loop_quit(_main_loop);
-            pthread_join(self.spiceThread, &status);
-            self.running = NO;
-            self.spiceThread = NULL;
-        }
-    }
-}
-
-@end

+ 0 - 30
CocoaSpice/CSSession+Sharing.h

@@ -1,30 +0,0 @@
-//
-// Copyright © 2020 osy. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-
-#import "CSSession.h"
-
-NS_ASSUME_NONNULL_BEGIN
-
-@interface CSSession (Sharing)
-
-@property (nonatomic, readonly) NSURL *defaultPublicShare;
-
-- (void)createDefaultShareReadme;
-- (void)setSharedDirectory:(NSString *)path readOnly:(BOOL)readOnly;
-
-@end
-
-NS_ASSUME_NONNULL_END

+ 0 - 54
CocoaSpice/CSSession+Sharing.m

@@ -1,54 +0,0 @@
-//
-// Copyright © 2020 osy. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-
-#import "CSSession+Sharing.h"
-#import <spice-client.h>
-
-static const NSString *const kDefaultShareReadme =
-    @"You have not selected a shared directory. This is a temporary directory "
-     "that can be deleted at any time. You can access these files on the host "
-     "at ~/Documents/Public relative to UTM's sandbox (if enabled). To select a "
-     "permanent shared directory, shut down the VM and select a shared "
-     "directory from the VM details screen.";
-
-@implementation CSSession (Sharing)
-
-- (void)setSharedDirectory:(NSString *)path readOnly:(BOOL)readOnly {
-    g_object_set(self.session, "shared-dir", [path cStringUsingEncoding:NSUTF8StringEncoding], NULL);
-    g_object_set(self.session, "share-dir-ro", readOnly, NULL);
-}
-
-- (NSURL *)defaultPublicShare {
-    NSFileManager *fileManager = [NSFileManager defaultManager];
-    NSURL *documentsDir = [[fileManager URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] firstObject];
-    NSURL *publicShare = [documentsDir URLByAppendingPathComponent:@"Public" isDirectory:YES];
-    BOOL isDir = NO;
-    if (![fileManager fileExistsAtPath:publicShare.path isDirectory:&isDir] || !isDir) {
-        [fileManager removeItemAtURL:publicShare error:nil]; // remove file if exists
-        [fileManager createDirectoryAtURL:publicShare withIntermediateDirectories:NO attributes:nil error:nil];
-    }
-    return publicShare;
-}
-
-- (void)createDefaultShareReadme {
-    NSFileManager *fileManager = [NSFileManager defaultManager];
-    NSURL *readme = [self.defaultPublicShare URLByAppendingPathComponent:@"README.txt"];
-    if (![fileManager fileExistsAtPath:readme.path]) {
-        [kDefaultShareReadme writeToURL:readme atomically:YES encoding:NSASCIIStringEncoding error:nil];
-    }
-}
-
-@end

+ 0 - 32
CocoaSpice/CSSession.h

@@ -1,32 +0,0 @@
-//
-// Copyright © 2020 osy. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-
-#import <Foundation/Foundation.h>
-
-typedef struct _SpiceSession SpiceSession;
-
-NS_ASSUME_NONNULL_BEGIN
-
-@interface CSSession : NSObject
-
-@property (nonatomic, readonly, nullable) SpiceSession *session;
-@property (nonatomic) BOOL shareClipboard;
-
-- (id)initWithSession:(nonnull SpiceSession *)session;
-
-@end
-
-NS_ASSUME_NONNULL_END

+ 0 - 384
CocoaSpice/CSSession.m

@@ -1,384 +0,0 @@
-//
-// Copyright © 2020 osy. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-
-#import "CSSession.h"
-#import "CSSession+Sharing.h"
-#import "CocoaSpice.h"
-#import "UTMLogging.h"
-#import "UTM-Swift.h"
-#import <glib.h>
-#import <spice-client.h>
-#import <spice/vd_agent.h>
-
-@interface CSSession ()
-
-@property (nonatomic, readwrite, nullable) SpiceSession *session;
-@property (nonatomic, readonly) BOOL sessionReadOnly;
-
-@end
-
-@implementation CSSession {
-    SpiceMainChannel        *_main;
-}
-
-static UTMPasteboardType utmTypeForClipboardType(guint type)
-{
-    switch (type) {
-        case VD_AGENT_CLIPBOARD_UTF8_TEXT: {
-            return UTMPasteboardTypeString;
-        }
-        case VD_AGENT_CLIPBOARD_IMAGE_PNG: {
-            return UTMPasteboardTypePng;
-        }
-        case VD_AGENT_CLIPBOARD_IMAGE_BMP: {
-            return UTMPasteboardTypeBmp;
-        }
-        case VD_AGENT_CLIPBOARD_IMAGE_TIFF: {
-            return UTMPasteboardTypeTiff;
-        }
-        case VD_AGENT_CLIPBOARD_IMAGE_JPG: {
-            return UTMPasteboardTypeJpg;
-        }
-        default: {
-            break;
-        }
-    }
-    return UTMPasteboardTypeString;
-}
-
-// helper from spice-util.c
-
-typedef enum {
-    NEWLINE_TYPE_LF,
-    NEWLINE_TYPE_CR_LF
-} NewlineType;
-
-static gssize get_line(const gchar *str, gsize len,
-                       NewlineType type, gsize *nl_len)
-{
-    const gchar *p, *endl;
-    gsize nl = 0;
-
-    endl = (type == NEWLINE_TYPE_CR_LF) ? "\r\n" : "\n";
-    p = g_strstr_len(str, len, endl);
-    if (p) {
-        len = p - str;
-        nl = strlen(endl);
-    }
-
-    *nl_len = nl;
-    return len;
-}
-
-static gchar* spice_convert_newlines(const gchar *str, gssize len,
-                                     NewlineType from,
-                                     NewlineType to)
-{
-    gssize length;
-    gsize nl;
-    GString *output;
-    gint i;
-
-    g_return_val_if_fail(str != NULL, NULL);
-    g_return_val_if_fail(len >= -1, NULL);
-    /* only 2 supported combinations */
-    g_return_val_if_fail((from == NEWLINE_TYPE_LF &&
-                          to == NEWLINE_TYPE_CR_LF) ||
-                         (from == NEWLINE_TYPE_CR_LF &&
-                          to == NEWLINE_TYPE_LF), NULL);
-
-    if (len == -1)
-        len = strlen(str);
-    /* sometime we get \0 terminated strings, skip that, or it fails
-       to utf8 validate line with \0 end */
-    else if (len > 0 && str[len-1] == 0)
-        len -= 1;
-
-    /* allocate worst case, if it's small enough, we don't care much,
-     * if it's big, malloc will put us in mmap'd region, and we can
-     * over allocate.
-     */
-    output = g_string_sized_new(len * 2 + 1);
-
-    for (i = 0; i < len; i += length + nl) {
-        length = get_line(str + i, len - i, from, &nl);
-        if (length < 0)
-            break;
-
-        g_string_append_len(output, str + i, length);
-
-        if (nl) {
-            /* let's not double \r if it's already in the line */
-            if (to == NEWLINE_TYPE_CR_LF &&
-                (output->len == 0 || output->str[output->len - 1] != '\r'))
-                g_string_append_c(output, '\r');
-
-            g_string_append_c(output, '\n');
-        }
-    }
-
-    return g_string_free(output, FALSE);
-}
-
-G_GNUC_INTERNAL
-gchar* spice_dos2unix(const gchar *str, gssize len)
-{
-    return spice_convert_newlines(str, len,
-                                  NEWLINE_TYPE_CR_LF,
-                                  NEWLINE_TYPE_LF);
-}
-
-G_GNUC_INTERNAL
-gchar* spice_unix2dos(const gchar *str, gssize len)
-{
-    return spice_convert_newlines(str, len,
-                                  NEWLINE_TYPE_LF,
-                                  NEWLINE_TYPE_CR_LF);
-}
-
-static void cs_clipboard_got_from_guest(SpiceMainChannel *main, guint selection,
-                                        guint type, const guchar *data, guint size,
-                                        gpointer user_data)
-{
-    CSSession *self = (__bridge CSSession *)user_data;
-
-    SPICE_DEBUG("clipboard got data");
-    
-    if (type == VD_AGENT_CLIPBOARD_UTF8_TEXT) {
-        gchar *conv = NULL;
-        /* on windows, gtk+ would already convert to LF endings, but
-           not on unix */
-        if (spice_main_channel_agent_test_capability(self->_main, VD_AGENT_CAP_GUEST_LINEEND_CRLF)) {
-            conv = spice_dos2unix((gchar*)data, size);
-            size = (guint)strlen(conv);
-        }
-        NSString *string = [NSString stringWithUTF8String:(conv ? conv : (const char *)data)];
-        [[UTMPasteboard generalPasteboard] setString:string];
-        g_free(conv);
-    } else {
-        UTMPasteboardType utmType = utmTypeForClipboardType(type);
-        NSData *pasteData = [NSData dataWithBytes:data length:size];
-        [[UTMPasteboard generalPasteboard] setData:pasteData forType:utmType];
-    }
-}
-
-static gboolean cs_clipboard_grab(SpiceMainChannel *main, guint selection,
-                                  guint32* types, guint32 ntypes,
-                                  gpointer user_data)
-{
-    CSSession *self = (__bridge CSSession *)user_data;
-    
-    if (selection != VD_AGENT_CLIPBOARD_SELECTION_CLIPBOARD) {
-        SPICE_DEBUG("skipping grab unimplemented selection: %d", selection);
-        return FALSE;
-    }
-
-    if (self.sessionReadOnly || !self.shareClipboard) {
-        SPICE_DEBUG("ignoring clipboard_grab");
-        return TRUE;
-    }
-
-    for (int n = 0; n < ntypes; ++n) {
-        spice_main_channel_clipboard_selection_request(self->_main, selection,
-                                                       types[n]);
-    }
-
-    return TRUE;
-}
-
-static gboolean cs_clipboard_request(SpiceMainChannel *main, guint selection,
-                                     guint type, gpointer user_data)
-{
-    CSSession *self = (__bridge CSSession *)user_data;
-    
-    if (selection != VD_AGENT_CLIPBOARD_SELECTION_CLIPBOARD) {
-        SPICE_DEBUG("skipping request unimplemented selection: %d", selection);
-        return FALSE;
-    }
-
-    if (self.sessionReadOnly || !self.shareClipboard) {
-        SPICE_DEBUG("ignoring clipboard_request");
-        return FALSE;
-    }
-
-    UTMPasteboardType utmType = utmTypeForClipboardType(type);
-    NSData *data = [[UTMPasteboard generalPasteboard] dataForType:utmType];
-    spice_main_channel_clipboard_selection_notify(self->_main, selection, type, data.bytes, data.length);
-
-    return TRUE;
-}
-
-static void cs_clipboard_release(SpiceMainChannel *main, guint selection,
-                                 gpointer user_data)
-{
-    //CSSession *self = (__bridge CSSession *)user_data;
-    [[UTMPasteboard generalPasteboard] clearContents];
-}
-
-static void cs_channel_new(SpiceSession *session, SpiceChannel *channel,
-                           gpointer user_data)
-{
-    CSSession *self = (__bridge CSSession *)user_data;
-
-    if (SPICE_IS_MAIN_CHANNEL(channel)) {
-        SPICE_DEBUG("Changing main channel from %p to %p", self->_main, channel);
-        self->_main = SPICE_MAIN_CHANNEL(channel);
-        g_signal_connect(channel, "main-clipboard-selection-grab",
-                         G_CALLBACK(cs_clipboard_grab), GLIB_OBJC_RETAIN(self));
-        g_signal_connect(channel, "main-clipboard-selection-request",
-                         G_CALLBACK(cs_clipboard_request), GLIB_OBJC_RETAIN(self));
-        g_signal_connect(channel, "main-clipboard-selection-release",
-                         G_CALLBACK(cs_clipboard_release), GLIB_OBJC_RETAIN(self));
-        g_signal_connect(channel, "main-clipboard-selection",
-                         G_CALLBACK(cs_clipboard_got_from_guest), GLIB_OBJC_RETAIN(self));
-    }
-}
-
-static void cs_channel_destroy(SpiceSession *session, SpiceChannel *channel,
-                               gpointer user_data)
-{
-    CSSession *self = (__bridge CSSession *)user_data;
-
-    if (SPICE_IS_MAIN_CHANNEL(channel) && SPICE_MAIN_CHANNEL(channel) == self->_main) {
-        self->_main = NULL;
-        g_signal_handlers_disconnect_by_func(channel, G_CALLBACK(cs_clipboard_grab), GLIB_OBJC_RELEASE(self));
-        g_signal_handlers_disconnect_by_func(channel, G_CALLBACK(cs_clipboard_request), GLIB_OBJC_RELEASE(self));
-        g_signal_handlers_disconnect_by_func(channel, G_CALLBACK(cs_clipboard_release), GLIB_OBJC_RELEASE(self));
-        g_signal_handlers_disconnect_by_func(channel, G_CALLBACK(cs_clipboard_got_from_guest), GLIB_OBJC_RELEASE(self));
-    }
-}
-
-#pragma mark - Initializers
-
-- (id)init {
-    if (self = [super init]) {
-        [[NSNotificationCenter defaultCenter] addObserver:self
-                                                 selector:@selector(pasteboardDidChange:)
-                                                     name:UTMPasteboard.changedNotification
-                                                   object:nil];
-        
-        [[NSNotificationCenter defaultCenter] addObserver:self
-                                                 selector:@selector(pasteboardDidRemove:)
-                                                     name:UTMPasteboard.removedNotification
-                                                   object:nil];
-    }
-    return self;
-}
-
-- (id)initWithSession:(nonnull SpiceSession *)session {
-    self = [self init];
-    if (self) {
-        GList *list;
-        GList *it;
-        
-        self.session = session;
-        g_object_ref(session);
-        
-        // g_get_user_special_dir(G_USER_DIRECTORY_PUBLIC_SHARE) returns NULL so we replace it with a valid value here
-        [self createDefaultShareReadme];
-        [self setSharedDirectory:self.defaultPublicShare.path readOnly:NO];
-        
-        UTMLog(@"%s:%d", __FUNCTION__, __LINE__);
-        g_signal_connect(session, "channel-new",
-                         G_CALLBACK(cs_channel_new), GLIB_OBJC_RETAIN(self));
-        g_signal_connect(session, "channel-destroy",
-                         G_CALLBACK(cs_channel_destroy), GLIB_OBJC_RETAIN(self));
-        list = spice_session_get_channels(session);
-        for (it = g_list_first(list); it != NULL; it = g_list_next(it)) {
-            cs_channel_new(session, it->data, (__bridge void *)self);
-        }
-        g_list_free(list);
-    }
-    return self;
-}
-
-- (void)dealloc {
-    UTMLog(@"%s:%d", __FUNCTION__, __LINE__);
-    g_signal_handlers_disconnect_by_func(self.session, G_CALLBACK(cs_channel_new), GLIB_OBJC_RELEASE(self));
-    g_signal_handlers_disconnect_by_func(self.session, G_CALLBACK(cs_channel_destroy), GLIB_OBJC_RELEASE(self));
-    g_object_unref(self.session);
-    self.session = NULL;
-    [[NSNotificationCenter defaultCenter] removeObserver:self
-                                                    name:UTMPasteboard.changedNotification
-                                                  object:nil];
-    
-    [[NSNotificationCenter defaultCenter] removeObserver:self
-                                                    name:UTMPasteboard.removedNotification
-                                                  object:nil];
-}
-
-#pragma mark - Notification handler
-
-- (void)pasteboardDidChange:(NSNotification *)notification {
-    UTMLog(@"seen UIPasteboardChangedNotification");
-    if (!self.shareClipboard || self.sessionReadOnly) {
-        return;
-    }
-    guint32 type = VD_AGENT_CLIPBOARD_NONE;
-    UTMPasteboard *pb = [UTMPasteboard generalPasteboard];
-    if ([pb canReadItemForType:UTMPasteboardTypePng]) {
-        type = VD_AGENT_CLIPBOARD_IMAGE_PNG;
-    } else if ([pb canReadItemForType:UTMPasteboardTypeBmp]) {
-        type = VD_AGENT_CLIPBOARD_IMAGE_BMP;
-    } else if ([pb canReadItemForType:UTMPasteboardTypeTiff]) {
-        type = VD_AGENT_CLIPBOARD_IMAGE_TIFF;
-    } else if ([pb canReadItemForType:UTMPasteboardTypeJpg]) {
-        type = VD_AGENT_CLIPBOARD_IMAGE_JPG;
-    } else if ([pb canReadItemForType:UTMPasteboardTypeString]) {
-        type = VD_AGENT_CLIPBOARD_UTF8_TEXT;
-    } else {
-        UTMLog(@"pasteboard with unrecognized type");
-    }
-    if (spice_main_channel_agent_test_capability(self->_main, VD_AGENT_CAP_CLIPBOARD_BY_DEMAND)) {
-        spice_main_channel_clipboard_selection_grab(self->_main, VD_AGENT_CLIPBOARD_SELECTION_CLIPBOARD, &type, 1);
-    }
-}
-
-- (void)pasteboardDidRemove:(NSNotification *)notification {
-    UTMLog(@"seen UIPasteboardRemovedNotification");
-    if (!self.shareClipboard || self.sessionReadOnly) {
-        return;
-    }
-    guint32 type = VD_AGENT_CLIPBOARD_UTF8_TEXT;
-    if (spice_main_channel_agent_test_capability(self->_main, VD_AGENT_CAP_CLIPBOARD_BY_DEMAND)) {
-        spice_main_channel_clipboard_selection_grab(self->_main, VD_AGENT_CLIPBOARD_SELECTION_CLIPBOARD, &type, 1);
-    }
-}
-
-#pragma mark - Instance methods
-
-- (BOOL)sessionReadOnly {
-    return spice_session_get_read_only(_session);
-}
-        
-/* This will convert line endings if needed (between Windows/Unix conventions),
- * and will make sure 'len' does not take into account any trailing \0 as this could
- * cause some confusion guest side.
- * The 'len' argument will be modified by this function to the length of the modified
- * string
- */
-- (NSString *)fixupClipboardText:(NSString *)text {
-    if (spice_main_channel_agent_test_capability(self->_main,
-                                                 VD_AGENT_CAP_GUEST_LINEEND_CRLF)) {
-        char *conv = NULL;
-        conv = spice_unix2dos([text cStringUsingEncoding:NSUTF8StringEncoding], text.length);
-        text = [NSString stringWithUTF8String:conv];
-        g_free(conv);
-    }
-    return text;
-}
-
-@end

+ 0 - 35
CocoaSpice/CSUSBDevice.h

@@ -1,35 +0,0 @@
-//
-// Copyright © 2021 osy. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-
-#import <Foundation/Foundation.h>
-
-typedef struct _SpiceUsbDevice SpiceUsbDevice;
-
-NS_ASSUME_NONNULL_BEGIN
-
-@interface CSUSBDevice : NSObject
-
-@property (nonatomic, readonly) SpiceUsbDevice *device;
-@property (nonatomic, nullable, readonly) NSString *name;
-
-+ (instancetype)usbDeviceWithDevice:(SpiceUsbDevice *)device;
-- (instancetype)init NS_UNAVAILABLE;
-- (instancetype)initWithDevice:(SpiceUsbDevice *)device;
-- (BOOL)isEqualToUSBDevice:(CSUSBDevice *)usbDevice;
-
-@end
-
-NS_ASSUME_NONNULL_END

+ 0 - 104
CocoaSpice/CSUSBDevice.m

@@ -1,104 +0,0 @@
-//
-// Copyright © 2021 osy. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-
-#import "CSUSBDevice.h"
-#import <glib.h>
-#import <spice-client.h>
-#import <libusb.h>
-
-@interface CSUSBDevice ()
-
-@property (nonatomic, readwrite, nonnull) SpiceUsbDevice *device;
-
-@end
-
-@implementation CSUSBDevice
-
-+ (instancetype)usbDeviceWithDevice:(SpiceUsbDevice *)device {
-    return [[CSUSBDevice alloc] initWithDevice:device];
-}
-
-- (instancetype)initWithDevice:(SpiceUsbDevice *)device {
-    if (self = [super init]) {
-        self.device = g_boxed_copy(spice_usb_device_get_type(), device);
-    }
-    return self;
-}
-
-- (void)dealloc {
-    g_boxed_free(spice_usb_device_get_type(), self.device);
-}
-
-- (NSString *)name {
-    libusb_device *dev = (libusb_device *)spice_usb_device_get_libusb_device(self.device);
-    struct libusb_device_descriptor ddesc;
-    libusb_device_handle *handle;
-    if (dev == NULL) {
-        return nil;
-    }
-    if (libusb_get_device_descriptor(dev, &ddesc) != 0) {
-        return nil;
-    }
-    if (libusb_open(dev, &handle) == 0) {
-        unsigned char name[64] = { 0 };
-        int bus = libusb_get_bus_number(dev);
-        int port = libusb_get_port_number(dev);
-        libusb_get_string_descriptor_ascii(handle,
-                                           ddesc.iProduct,
-                                           name, sizeof(name));
-        libusb_close(handle);
-        if (name[0] == '\0') {
-            return nil;
-        } else {
-            return [NSString stringWithFormat:@"%s (%d:%d)", (const char *)name, bus, port];
-        }
-    } else {
-        return nil;
-    }
-}
-
-- (NSString *)description {
-    gchar *description = spice_usb_device_get_description(self.device, NULL);
-    if (!description) {
-        return @"";
-    }
-    NSString *nsdescription = [NSString stringWithUTF8String:description];
-    g_free(description);
-    return nsdescription;
-}
-
-- (BOOL)isEqualToUSBDevice:(CSUSBDevice *)usbDevice {
-    NSString *description = self.description;
-    return description.length > 0 && [description isEqualToString:usbDevice.description];
-}
-
-- (BOOL)isEqual:(id)object {
-    if (self == object) {
-        return YES;
-    }
-    
-    if (![object isKindOfClass:[CSUSBDevice class]]) {
-        return NO;
-    }
-    
-    return [self isEqualToUSBDevice:object];
-}
-
-- (NSUInteger)hash {
-    return self.description.hash;
-}
-
-@end

+ 0 - 44
CocoaSpice/CSUSBManager.h

@@ -1,44 +0,0 @@
-//
-// Copyright © 2021 osy. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-
-#import <Foundation/Foundation.h>
-#import "CSUSBManagerDelegate.h"
-
-typedef struct _SpiceUsbDeviceManager SpiceUsbDeviceManager;
-typedef void (^CSUSBManagerConnectionCallback)(BOOL, NSString * _Nullable);
-
-NS_ASSUME_NONNULL_BEGIN
-
-@interface CSUSBManager : NSObject
-
-@property (nonatomic, weak, nullable) id<CSUSBManagerDelegate> delegate;
-@property (nonatomic) BOOL isAutoConnect;
-@property (nonatomic) NSString *autoConnectFilter;
-@property (nonatomic) BOOL isRedirectOnConnect;
-@property (nonatomic, readonly) NSInteger numberFreeChannels;
-@property (nonatomic, readonly) NSArray<CSUSBDevice *> *usbDevices;
-@property (nonatomic, readonly) BOOL isBusy;
-
-- (instancetype)init NS_UNAVAILABLE;
-- (instancetype)initWithUsbDeviceManager:(SpiceUsbDeviceManager *)usbDeviceManager NS_DESIGNATED_INITIALIZER;
-- (BOOL)canRedirectUsbDevice:(CSUSBDevice *)usbDevice errorMessage:(NSString * _Nullable * _Nullable)errorMessage;
-- (BOOL)isUsbDeviceConnected:(CSUSBDevice *)usbDevice;
-- (void)connectUsbDevice:(CSUSBDevice *)usbDevice withCompletion:(CSUSBManagerConnectionCallback)completion;
-- (void)disconnectUsbDevice:(CSUSBDevice *)usbDevice withCompletion:(CSUSBManagerConnectionCallback)completion;
-
-@end
-
-NS_ASSUME_NONNULL_END

+ 0 - 240
CocoaSpice/CSUSBManager.m

@@ -1,240 +0,0 @@
-//
-// Copyright © 2021 osy. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-
-#import "CocoaSpice.h"
-#import <glib.h>
-#import <spice-client.h>
-
-typedef enum {
-    kUsbManagerCallConnect,
-    kUsbManagerCallDisconnect
-} usbManagerCall;
-
-typedef struct {
-    usbManagerCall call;
-    SpiceUsbDeviceManager *manager;
-    SpiceUsbDevice *device;
-    gpointer callback;
-} usbManagerData;
-
-@interface CSUSBManager ()
-
-@property (nonatomic, readwrite, nonnull) SpiceUsbDeviceManager *usbDeviceManager;
-
-@end
-
-@implementation CSUSBManager
-
-#pragma mark - Signal callbacks
-
-static void cs_device_error(SpiceUsbDeviceManager *manager,
-                            SpiceUsbDevice        *device,
-                            GError                *error,
-                            gpointer               data)
-{
-    CSUSBManager *self = (__bridge CSUSBManager *)data;
-    CSUSBDevice *usbdevice = [CSUSBDevice usbDeviceWithDevice:device];
-
-    if (error->domain == G_IO_ERROR && error->code == G_IO_ERROR_CANCELLED)
-        return;
-    
-    [self.delegate spiceUsbManager:self deviceError:[NSString stringWithUTF8String:error->message] forDevice:usbdevice];
-}
-
-static void cs_device_added(SpiceUsbDeviceManager *manager,
-    SpiceUsbDevice *device, gpointer data)
-{
-    CSUSBManager *self = (__bridge CSUSBManager *)data;
-    CSUSBDevice *usbdevice = [CSUSBDevice usbDeviceWithDevice:device];
-    
-    [self.delegate spiceUsbManager:self deviceAttached:usbdevice];
-}
-
-static void cs_device_removed(SpiceUsbDeviceManager *manager,
-    SpiceUsbDevice *device, gpointer data)
-{
-    CSUSBManager *self = (__bridge CSUSBManager *)data;
-    CSUSBDevice *usbdevice = [CSUSBDevice usbDeviceWithDevice:device];
-    
-    [self.delegate spiceUsbManager:self deviceRemoved:usbdevice];
-}
-
-static void cs_connect_cb(GObject *gobject, GAsyncResult *res, gpointer data)
-{
-    SpiceUsbDeviceManager *manager = SPICE_USB_DEVICE_MANAGER(gobject);
-    CSUSBManagerConnectionCallback callback = (__bridge_transfer CSUSBManagerConnectionCallback)(data);
-    GError *err = NULL;
-
-    spice_usb_device_manager_connect_device_finish(manager, res, &err);
-    if (err) {
-        callback(NO, [NSString stringWithUTF8String:err->message]);
-        g_error_free(err);
-    } else {
-        callback(YES, nil);
-    }
-}
-
-static void cs_disconnect_cb(GObject *gobject, GAsyncResult *res, gpointer data)
-{
-    SpiceUsbDeviceManager *manager = SPICE_USB_DEVICE_MANAGER(gobject);
-    CSUSBManagerConnectionCallback callback = (__bridge_transfer CSUSBManagerConnectionCallback)(data);
-    GError *err = NULL;
-
-    spice_usb_device_manager_disconnect_device_finish(manager, res, &err);
-    if (err) {
-        callback(NO, [NSString stringWithUTF8String:err->message]);
-        g_error_free(err);
-    } else {
-        callback(YES, nil);
-    }
-}
-
-static gboolean cs_call_manager(gpointer user_data)
-{
-    usbManagerData *data = (usbManagerData *)user_data;
-    switch (data->call) {
-        case kUsbManagerCallConnect:
-            spice_usb_device_manager_connect_device_async(data->manager, data->device, NULL, cs_connect_cb, data->callback);
-            break;
-        case kUsbManagerCallDisconnect:
-            spice_usb_device_manager_disconnect_device_async(data->manager, data->device, NULL, cs_disconnect_cb, data->callback);
-            break;
-        default:
-            g_assert(0);
-    }
-    return G_SOURCE_REMOVE;
-}
-
-#pragma mark - Properties
-
-- (BOOL)isAutoConnect {
-    gboolean value;
-    g_object_get(self.usbDeviceManager, "auto-connect", &value, NULL);
-    return value;
-}
-
-- (void)setIsAutoConnect:(BOOL)isAutoConnect {
-    g_object_set(self.usbDeviceManager, "auto-connect", isAutoConnect, NULL);
-}
-
-- (NSString *)autoConnectFilter {
-    gchar *string;
-    g_object_get(self.usbDeviceManager, "auto-connect-filter", &string, NULL);
-    NSString *nsstring = [NSString stringWithUTF8String:string];
-    g_free(string);
-    return nsstring;
-}
-
-- (void)setAutoConnectFilter:(NSString *)autoConnectFilter {
-    const gchar *string = [autoConnectFilter UTF8String];
-    g_object_set(self.usbDeviceManager, "auto-connect-filter", string, NULL);
-}
-
-- (BOOL)isRedirectOnConnect {
-    gboolean value;
-    g_object_get(self.usbDeviceManager, "redirect-on-connect", &value, NULL);
-    return value;
-}
-
-- (void)setIsRedirectOnConnect:(BOOL)isRedirectOnConnect {
-    g_object_set(self.usbDeviceManager, "redirect-on-connect", isRedirectOnConnect, NULL);
-}
-
-- (NSInteger)numberFreeChannels {
-    gint value;
-    g_object_get(self.usbDeviceManager, "free-channels", &value, NULL);
-    return value;
-}
-
-- (NSArray<CSUSBDevice *> *)usbDevices {
-    NSMutableArray<CSUSBDevice *> *usbDevices = [NSMutableArray new];
-    GPtrArray *arr = spice_usb_device_manager_get_devices(self.usbDeviceManager);
-    if (arr != NULL) {
-        for (int i = 0; i < arr->len; i++) {
-            SpiceUsbDevice *device = g_ptr_array_index(arr, i);
-            [usbDevices addObject:[CSUSBDevice usbDeviceWithDevice:device]];
-        }
-        g_ptr_array_unref(arr);
-    }
-    return usbDevices;
-}
-
-- (BOOL)isBusy {
-    return spice_usb_device_manager_is_redirecting(self.usbDeviceManager);
-}
-
-#pragma mark - Construction
-
-- (instancetype)initWithUsbDeviceManager:(SpiceUsbDeviceManager *)usbDeviceManager {
-    if (self = [super init]) {
-        self.usbDeviceManager = usbDeviceManager;
-        g_signal_connect(usbDeviceManager, "auto-connect-failed",
-                         G_CALLBACK(cs_device_error), GLIB_OBJC_RETAIN(self));
-        g_signal_connect(usbDeviceManager, "device-error",
-                         G_CALLBACK(cs_device_error), GLIB_OBJC_RETAIN(self));
-        g_signal_connect(usbDeviceManager, "device-added",
-                         G_CALLBACK(cs_device_added), GLIB_OBJC_RETAIN(self));
-        g_signal_connect(usbDeviceManager, "device-removed",
-                         G_CALLBACK(cs_device_removed), GLIB_OBJC_RETAIN(self));
-    }
-    return self;
-}
-
-- (void)dealloc {
-    g_signal_handlers_disconnect_by_func(self.usbDeviceManager, G_CALLBACK(cs_device_error), GLIB_OBJC_RELEASE(self));
-    g_signal_handlers_disconnect_by_func(self.usbDeviceManager, G_CALLBACK(cs_device_error), GLIB_OBJC_RELEASE(self));
-    g_signal_handlers_disconnect_by_func(self.usbDeviceManager, G_CALLBACK(cs_device_added), GLIB_OBJC_RELEASE(self));
-    g_signal_handlers_disconnect_by_func(self.usbDeviceManager, G_CALLBACK(cs_device_removed), GLIB_OBJC_RELEASE(self));
-}
-
-#pragma mark - Methods
-
-- (BOOL)canRedirectUsbDevice:(CSUSBDevice *)usbDevice errorMessage:(NSString * _Nullable __autoreleasing *)errorMessage {
-    GError *err = NULL;
-    gboolean res = spice_usb_device_manager_can_redirect_device(self.usbDeviceManager, usbDevice.device, &err);
-    if (errorMessage && err) {
-        *errorMessage = [NSString stringWithUTF8String:err->message];
-    }
-    g_clear_error(&err);
-    return res;
-}
-
-- (BOOL)isUsbDeviceConnected:(CSUSBDevice *)usbDevice {
-    return spice_usb_device_manager_is_device_connected(self.usbDeviceManager, usbDevice.device);
-}
-
-- (void)spiceUsbManagerCall:(usbManagerCall)call forUsbDevice:(CSUSBDevice *)usbDevice withCompletion:(CSUSBManagerConnectionCallback)completion {
-    usbManagerData *data = g_new0(usbManagerData, 1);
-    data->call = call;
-    data->manager = self.usbDeviceManager;
-    data->device = usbDevice.device;
-    data->callback = (__bridge_retained gpointer)completion;
-    g_main_context_invoke_full([CSMain sharedInstance].glibMainContext,
-                               G_PRIORITY_HIGH,
-                               cs_call_manager,
-                               data,
-                               g_free);
-}
-
-- (void)connectUsbDevice:(CSUSBDevice *)usbDevice withCompletion:(CSUSBManagerConnectionCallback)completion {
-    [self spiceUsbManagerCall:kUsbManagerCallConnect forUsbDevice:usbDevice withCompletion:completion];
-}
-
-- (void)disconnectUsbDevice:(CSUSBDevice *)usbDevice withCompletion:(CSUSBManagerConnectionCallback)completion {
-    [self spiceUsbManagerCall:kUsbManagerCallDisconnect forUsbDevice:usbDevice withCompletion:completion];
-}
-
-@end

+ 0 - 32
CocoaSpice/CSUSBManagerDelegate.h

@@ -1,32 +0,0 @@
-//
-// Copyright © 2021 osy. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-
-#import <Foundation/Foundation.h>
-
-@class CSUSBDevice;
-@class CSUSBManager;
-
-NS_ASSUME_NONNULL_BEGIN
-
-@protocol CSUSBManagerDelegate <NSObject>
-
-- (void)spiceUsbManager:(CSUSBManager *)usbManager deviceError:(NSString *)error forDevice:(CSUSBDevice *)device;
-- (void)spiceUsbManager:(CSUSBManager *)usbManager deviceAttached:(CSUSBDevice *)device;
-- (void)spiceUsbManager:(CSUSBManager *)usbManager deviceRemoved:(CSUSBDevice *)device;
-
-@end
-
-NS_ASSUME_NONNULL_END

+ 0 - 36
CocoaSpice/CocoaSpice.h

@@ -1,36 +0,0 @@
-//
-// Copyright © 2019 osy. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-
-#ifndef CocoaSpice_h
-#define CocoaSpice_h
-
-#include "CSConnection.h"
-#include "CSDisplayMetal.h"
-#include "CSInput.h"
-#include "CSMain.h"
-#include "CSSession.h"
-#include "CSSession+Sharing.h"
-#include "CSUSBDevice.h"
-#include "CSUSBManager.h"
-
-#define GLIB_OBJC_RETAIN(x) (__bridge_retained void *)(x)
-#define GLIB_OBJC_RELEASE(x) (__bridge void *)(__bridge_transfer NSObject *)(__bridge void *)(x)
-
-#define DISPLAY_DEBUG(display, fmt, ...) \
-    SPICE_DEBUG(fmt, \
-        ## __VA_ARGS__)
-
-#endif /* CocoaSpice_h */

+ 2 - 2
Managers/UTMInputOutput.h

@@ -16,7 +16,7 @@
 
 #import <Foundation/Foundation.h>
 
-@class UTMScreenshot;
+@class CSScreenshot;
 @class UTMViewState;
 
 typedef void(^ioConnectCompletionHandler_t)(BOOL, NSError * _Nullable);
@@ -30,7 +30,7 @@ NS_ASSUME_NONNULL_BEGIN
 - (BOOL)startWithError:(NSError **)err;
 - (void)connectWithCompletion:(ioConnectCompletionHandler_t)block;
 - (void)disconnect;
-- (UTMScreenshot* _Nullable)screenshot;
+- (CSScreenshot* _Nullable)screenshot;
 - (void)syncViewState:(UTMViewState *)viewState;
 - (void)restoreViewState:(UTMViewState *)viewState;
 

+ 34 - 60
Managers/UTMPasteboard.swift

@@ -14,6 +14,7 @@
 // limitations under the License.
 //
 
+import CocoaSpice
 #if canImport(UIKit)
 import UIKit
 import MobileCoreServices
@@ -27,24 +28,7 @@ typealias SystemPasteboardType = NSPasteboard.PasteboardType
 #error("Neither UIKit nor AppKit found!")
 #endif
 
-@objc class UTMPasteboard: NSObject {
-    @objc(UTMPasteboardType) enum PasteboardType: Int {
-        case URL
-        case bmp
-        case fileURL
-        case font
-        case html
-        case jpg
-        case pdf
-        case png
-        case rtf
-        case rtfd
-        case sound
-        case string
-        case tabularText
-        case tiff
-    }
-    
+@objc class UTMPasteboard: NSObject, CSPasteboardDelegate {
     @objc(generalPasteboard)
     static let general = UTMPasteboard(for: SystemPasteboard.general)
     
@@ -87,9 +71,9 @@ typealias SystemPasteboardType = NSPasteboard.PasteboardType
         let newCount = systemPasteboard.changeCount
         if newCount > changeCount {
             if hasContents() {
-                NotificationCenter.default.post(name: .pasteboardChangedNotification, object: self)
+                NotificationCenter.default.post(name: .csPasteboardChanged, object: self)
             } else {
-                NotificationCenter.default.post(name: .pasteboardRemovedNotification, object: self)
+                NotificationCenter.default.post(name: .csPasteboardRemoved, object: self)
             }
         }
         changeCount = newCount
@@ -97,9 +81,7 @@ typealias SystemPasteboardType = NSPasteboard.PasteboardType
 }
 
 #if canImport(UIKit)
-extension UTMPasteboard.PasteboardType: RawRepresentable {
-    typealias RawValue = String
-    
+extension CSPasteboardType {
     init?(rawValue: String) {
         let cfValue = rawValue as CFString
         switch cfValue {
@@ -141,6 +123,8 @@ extension UTMPasteboard.PasteboardType: RawRepresentable {
         case .string: return kUTTypeUTF8PlainText as String
         case .tabularText: return kUTTypeUTF8TabSeparatedText as String
         case .tiff: return kUTTypeTIFF as String
+        @unknown default:
+            return kUTTypeUTF8PlainText as String
         }
     }
 }
@@ -155,43 +139,41 @@ extension UTMPasteboard.PasteboardType: RawRepresentable {
         systemPasteboard.items = []
     }
     
-    func setData(_ data: Data, forType dataType: PasteboardType) {
+    func setData(_ data: Data, for type: CSPasteboardType) {
         clearContents()
         changeCount += 1
-        systemPasteboard.setData(data, forPasteboardType: dataType.rawValue)
+        systemPasteboard.setData(data, forPasteboardType: type.rawValue)
     }
     
-    func data(forType dataType: PasteboardType) -> Data? {
-        return systemPasteboard.data(forPasteboardType: dataType.rawValue)
+    func data(for type: CSPasteboardType) -> Data? {
+        return systemPasteboard.data(forPasteboardType: type.rawValue)
     }
     
-    func setString(_ string: String, forType dataType: PasteboardType) {
+    func setString(_ string: String, for type: CSPasteboardType) {
         clearContents()
         changeCount += 1
-        systemPasteboard.setValue(string, forPasteboardType: dataType.rawValue)
+        systemPasteboard.setValue(string, forPasteboardType: type.rawValue)
     }
     
     func setString(_ string: String) {
-        setString(string, forType: .string)
+        setString(string, for: .string)
     }
     
-    func string(forType dataType: PasteboardType) -> String? {
-        return systemPasteboard.value(forPasteboardType: dataType.rawValue) as? String
+    func string(for type: CSPasteboardType) -> String? {
+        return systemPasteboard.value(forPasteboardType: type.rawValue) as? String
     }
     
     func string() -> String? {
-        return string(forType: .string)
+        return string(for: .string)
     }
     
-    func canReadItem(forType dataType: PasteboardType) -> Bool {
+    func canReadItem(for type: CSPasteboardType) -> Bool {
         let types = systemPasteboard.types
-        return types.contains(dataType.rawValue)
+        return types.contains(type.rawValue)
     }
 }
 #elseif canImport(AppKit)
-extension UTMPasteboard.PasteboardType: RawRepresentable {
-    typealias RawValue = NSPasteboard.PasteboardType
-    
+extension CSPasteboardType {
     init?(rawValue: NSPasteboard.PasteboardType) {
         switch rawValue {
         case .URL: self = .URL
@@ -226,6 +208,8 @@ extension UTMPasteboard.PasteboardType: RawRepresentable {
         case .string: return .string
         case .tabularText: return .tabularText
         case .tiff: return .tiff
+        @unknown default:
+            return .string
         }
     }
 }
@@ -244,49 +228,39 @@ extension UTMPasteboard.PasteboardType: RawRepresentable {
         _ = systemPasteboard.clearContents()
     }
     
-    func setData(_ data: Data, forType dataType: PasteboardType) {
+    func setData(_ data: Data, for type: CSPasteboardType) {
         clearContents()
         changeCount += 1
-        _ = systemPasteboard.setData(data, forType: dataType.rawValue)
+        _ = systemPasteboard.setData(data, forType: type.rawValue)
     }
     
-    func data(forType dataType: PasteboardType) -> Data? {
-        return systemPasteboard.data(forType: dataType.rawValue)
+    func data(for type: CSPasteboardType) -> Data? {
+        return systemPasteboard.data(forType: type.rawValue)
     }
     
-    func setString(_ string: String, forType dataType: PasteboardType) {
+    func setString(_ string: String, for type: CSPasteboardType) {
         clearContents()
         changeCount += 1
-        _ = systemPasteboard.setString(string, forType: dataType.rawValue)
+        _ = systemPasteboard.setString(string, forType: type.rawValue)
     }
     
     func setString(_ string: String) {
-        setString(string, forType: .string)
+        setString(string, for: .string)
     }
     
-    func string(forType dataType: PasteboardType) -> String? {
-        return systemPasteboard.string(forType: dataType.rawValue)
+    func string(for type: CSPasteboardType) -> String? {
+        return systemPasteboard.string(forType: type.rawValue)
     }
     
     func string() -> String? {
-        return string(forType: .string)
+        return string(for: .string)
     }
     
-    func canReadItem(forType dataType: PasteboardType) -> Bool {
+    func canReadItem(for type: CSPasteboardType) -> Bool {
         guard let types = systemPasteboard.types else {
             return false
         }
-        return types.contains(dataType.rawValue)
+        return types.contains(type.rawValue)
     }
 }
 #endif
-
-extension NSNotification.Name {
-    public static let pasteboardChangedNotification: NSNotification.Name = .init(rawValue: "utmPasteboardChangedNotification")
-    public static let pasteboardRemovedNotification: NSNotification.Name = .init(rawValue: "utmPasteboardRemovedNotification")
-}
-
-@objc extension UTMPasteboard {
-    public static let changedNotification = NSNotification.Name.pasteboardChangedNotification
-    public static let removedNotification = NSNotification.Name.pasteboardRemovedNotification
-}

+ 1 - 1
Managers/UTMQemuVirtualMachine+SPICE.m

@@ -14,9 +14,9 @@
 // limitations under the License.
 //
 
+@import CocoaSpice;
 #import <TargetConditionals.h>
 #import "UTMQemuVirtualMachine+SPICE.h"
-#import "CocoaSpice.h"
 #import "UTMQemuConfiguration+Display.h"
 #import "UTMQemuConfiguration+Sharing.h"
 #import "UTMLogging.h"

+ 0 - 1
Managers/UTMQemuVirtualMachine.m

@@ -31,7 +31,6 @@
 #import "UTMTerminalIO.h"
 #import "UTMSpiceIO.h"
 #import "UTMLogging.h"
-#import "UTMScreenshot.h"
 #import "UTMPortAllocator.h"
 #import "qapi-events.h"
 

+ 0 - 45
Managers/UTMScreenshot.h

@@ -1,45 +0,0 @@
-//
-// Copyright © 2020 osy. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-
-#import "TargetConditionals.h"
-#if TARGET_OS_IPHONE
-#include <UIKit/UIKit.h>
-#else
-#include <AppKit/AppKit.h>
-#endif
-
-NS_ASSUME_NONNULL_BEGIN
-
-@interface UTMScreenshot : NSObject
-
-#if TARGET_OS_IPHONE
-@property (nonatomic, readonly) UIImage *image;
-#else
-@property (nonatomic, readonly) NSImage *image;
-#endif
-
-- (instancetype)init NS_DESIGNATED_INITIALIZER;
-#if TARGET_OS_IPHONE
-- (instancetype)initWithImage:(UIImage *)image;
-#else
-- (instancetype)initWithImage:(NSImage *)image;
-#endif
-- (instancetype)initWithContentsOfURL:(NSURL *)url;
-- (void)writeToURL:(NSURL *)url atomically:(BOOL)atomically;
-
-@end
-
-NS_ASSUME_NONNULL_END

+ 0 - 76
Managers/UTMScreenshot.m

@@ -1,76 +0,0 @@
-//
-// Copyright © 2020 osy. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-
-#import "TargetConditionals.h"
-#import "UTMScreenshot.h"
-
-@implementation UTMScreenshot
-
-- (instancetype)init {
-    return [super init];
-}
-
-#if TARGET_OS_IPHONE
-- (instancetype)initWithImage:(UIImage *)image {
-    if (self = [self init]) {
-        _image = image;
-    }
-    return self;
-}
-
-- (instancetype)initWithContentsOfURL:(NSURL *)url {
-    if (self = [self init]) {
-        _image = [[UIImage alloc] initWithContentsOfFile:url.path];
-        if (_image == nil) {
-            self = nil;
-        }
-    }
-    return self;
-}
-
-- (void)writeToURL:(NSURL *)url atomically:(BOOL)atomically {
-    [UIImagePNGRepresentation(_image) writeToURL:url atomically:atomically];
-}
-#else
-- (instancetype)initWithImage:(NSImage *)image {
-    if (self = [self init]) {
-        _image = image;
-    }
-    return self;
-}
-
-- (instancetype)initWithContentsOfURL:(NSURL *)url {
-    if (self = [self init]) {
-        _image = [[NSImage alloc] initWithContentsOfURL:url];
-        if (_image == nil) {
-            self = nil;
-        }
-    }
-    return self;
-}
-
-- (void)writeToURL:(NSURL *)url atomically:(BOOL)atomically {
-    CGImageRef cgRef = [self.image CGImageForProposedRect:NULL
-                                                  context:nil
-                                                    hints:nil];
-    NSBitmapImageRep *newRep = [[NSBitmapImageRep alloc] initWithCGImage:cgRef];
-    [newRep setSize:[self.image size]];   // if you want the same resolution
-    NSData *pngData = [newRep representationUsingType:NSBitmapImageFileTypePNG properties:@{}];
-    [pngData writeToURL:url atomically:atomically];
-}
-#endif
-
-@end

+ 1 - 4
Managers/UTMSpiceIO.h

@@ -15,14 +15,11 @@
 //
 
 #import <Foundation/Foundation.h>
+@import CocoaSpice;
 #import "UTMInputOutput.h"
-#import "CSConnectionDelegate.h"
 #import "UTMSpiceIODelegate.h"
 
 @class UTMQemuConfiguration;
-@class CSDisplayMetal;
-@class CSInput;
-@class CSUSBManager;
 
 NS_ASSUME_NONNULL_BEGIN
 

+ 4 - 3
Managers/UTMSpiceIO.m

@@ -20,7 +20,7 @@
 #import "UTMQemuConfiguration+Sharing.h"
 #import "UTMLogging.h"
 #import "UTMViewState.h"
-#import "CocoaSpice.h"
+#import "UTM-Swift.h"
 
 extern BOOL isPortAvailable(NSInteger port); // from UTMPortAllocator
 extern NSString *const kUTMErrorDomain;
@@ -63,6 +63,7 @@ extern NSString *const kUTMErrorDomain;
             self.spiceConnection.delegate = self;
             self.spiceConnection.audioEnabled = _configuration.soundEnabled;
             self.spiceConnection.session.shareClipboard = _configuration.shareClipboardEnabled;
+            self.spiceConnection.session.pasteboardDelegate = [UTMPasteboard generalPasteboard];
         }
     }
 }
@@ -119,7 +120,7 @@ extern NSString *const kUTMErrorDomain;
 #endif
 }
 
-- (UTMScreenshot *)screenshot {
+- (CSScreenshot *)screenshot {
     return [self.primaryDisplay screenshot];
 }
 
@@ -176,7 +177,7 @@ extern NSString *const kUTMErrorDomain;
 - (void)spiceDisplayCreated:(CSConnection *)connection display:(CSDisplayMetal *)display {
     NSAssert(connection == self.spiceConnection, @"Unknown connection");
     [self.delegate spiceDidCreateDisplay:display];
-    if (display.channelID == 0 && display.monitorID == 0) {
+    if (display.isPrimaryDisplay) {
         self.primaryDisplay = display;
     }
 }

+ 3 - 24
Managers/UTMTerminalIO.m

@@ -18,6 +18,8 @@
 #import "UTMTerminalIO.h"
 #import "UTMQemuConfiguration.h"
 
+@class CSScreenshot;
+
 @interface UTMTerminalIO ()
 
 @property (nonatomic, readwrite) BOOL isConnected;
@@ -57,30 +59,7 @@
     [_terminal disconnect];
 }
 
-- (UTMScreenshot *)screenshot {
-    // MAIN THREAD ONLY
-//    NSMutableParagraphStyle* paragraphStyle = [[NSMutableParagraphStyle defaultParagraphStyle] mutableCopy];
-//    paragraphStyle.alignment = NSTextAlignmentCenter;
-//    UIFont* font = [UIFont systemFontOfSize: 18.0];
-//    NSDictionary* strAttributes = @{
-//        NSFontAttributeName: font,
-//        NSForegroundColorAttributeName: [UIColor whiteColor],
-//        NSParagraphStyleAttributeName: paragraphStyle
-//    };
-//
-//    CGSize size = CGSizeMake(150.0f, 100.0f);
-//    UIGraphicsBeginImageContextWithOptions(size, NO, 0);
-//    CGContextRef context = UIGraphicsGetCurrentContext();
-//    CGFloat color[] = {0, 0, 0};
-//    CGContextSetFillColor(context, color);
-//    CGContextFillRect(context, CGRectMake(0.0f, 0.0f, size.width, size.height));
-//    NSString* text = @"Serial console";
-//    CGFloat yOffset = (size.height - font.pointSize) / 2.0f;
-//    [text drawInRect:CGRectMake(0.0, yOffset, size.width, [font pointSize]) withAttributes:strAttributes];
-//    UIImage* result = UIGraphicsGetImageFromCurrentImageContext();
-//    UIGraphicsEndImageContext();
-//
-//    return result;
+- (CSScreenshot *)screenshot {
     return nil;
 }
 

+ 3 - 1
Managers/UTMVirtualMachine-Protected.h

@@ -16,6 +16,8 @@
 
 #import "UTMVirtualMachine.h"
 
+@class CSScreenshot;
+
 NS_ASSUME_NONNULL_BEGIN
 
 extern NSString *const kUTMBundleConfigFilename;
@@ -34,7 +36,7 @@ extern NSString *const kUTMBundleConfigFilename;
 
 @property (nonatomic, readwrite, nullable) NSURL *path;
 @property (nonatomic, readwrite, copy) id<UTMConfigurable> config;
-@property (nonatomic, readwrite, nullable) UTMScreenshot *screenshot;
+@property (nonatomic, readwrite, nullable) CSScreenshot *screenshot;
 
 + (BOOL)isAppleVMForPath:(NSURL *)path;
 - (NSURL *)packageURLForName:(NSString *)name;

+ 2 - 4
Managers/UTMVirtualMachine.h

@@ -16,13 +16,11 @@
 
 #import <Foundation/Foundation.h>
 #import "UTMVirtualMachineDelegate.h"
-#import "CSConnectionDelegate.h"
-#import "UTMRenderSource.h"
 #import "UTMInputOutput.h"
 
 @protocol UTMConfigurable;
 @class UTMLogging;
-@class UTMScreenshot;
+@class CSScreenshot;
 
 NS_ASSUME_NONNULL_BEGIN
 
@@ -33,7 +31,7 @@ NS_ASSUME_NONNULL_BEGIN
 @property (nonatomic, readonly, copy) id<UTMConfigurable> config;
 @property (nonatomic, readonly) UTMViewState *viewState;
 @property (nonatomic, assign, readonly) UTMVMState state;
-@property (nonatomic, readonly, nullable) UTMScreenshot *screenshot;
+@property (nonatomic, readonly, nullable) CSScreenshot *screenshot;
 
 + (BOOL)URLisVirtualMachine:(NSURL *)url NS_SWIFT_NAME(isVirtualMachine(url:));
 + (NSString *)virtualMachineName:(NSURL *)url;

+ 3 - 3
Managers/UTMVirtualMachine.m

@@ -20,9 +20,9 @@
 #import "UTMConfigurable.h"
 #import "UTMQemuConfiguration+Constants.h"
 #import "UTMLogging.h"
-#import "UTMScreenshot.h"
 #import "UTMViewState.h"
 #import "UTM-Swift.h"
+@import CocoaSpice;
 
 NSString *const kUTMErrorDomain = @"com.utmapp.utm";
 NSString *const kUTMBundleConfigFilename = @"config.plist";
@@ -49,7 +49,7 @@ NSString *const kUTMBundleScreenshotFilename = @"screenshot.png";
     _state = state;
 }
 
-- (void)setScreenshot:(UTMScreenshot *)screenshot {
+- (void)setScreenshot:(CSScreenshot *)screenshot {
     [self propertyWillChange];
     _screenshot = screenshot;
 }
@@ -301,7 +301,7 @@ NSString *const kUTMBundleScreenshotFilename = @"screenshot.png";
 
 - (void)loadScreenshot {
     NSURL *url = [self.path URLByAppendingPathComponent:kUTMBundleScreenshotFilename];
-    self.screenshot = [[UTMScreenshot alloc] initWithContentsOfURL:url];
+    self.screenshot = [[CSScreenshot alloc] initWithContentsOfURL:url];
 }
 
 - (void)saveScreenshot {

+ 0 - 2
Managers/UTMVirtualMachineDelegate.h

@@ -14,8 +14,6 @@
 // limitations under the License.
 //
 
-#import "UTMRenderSource.h"
-
 @protocol UTMConfigurable;
 @class UTMVirtualMachine;
 @class CSDisplayMetal;

+ 0 - 3
Platform/Swift-Bridging-Header.h

@@ -40,12 +40,9 @@
 #include "UTMQemuVirtualMachine+Drives.h"
 #include "UTMQemuVirtualMachine+SPICE.h"
 #include "UTMQemuVirtualMachine+Terminal.h"
-#include "UTMRenderer.h"
-#include "UTMScreenshot.h"
 #include "UTMSpiceIO.h"
 #include "UTMTerminal.h"
 #include "UTMTerminalDelegate.h"
-#include "CocoaSpice.h"
 #if TARGET_OS_IPHONE
 #include "AppDelegate.h"
 #include "UIViewController+Extensions.h"

+ 3 - 3
Platform/iOS/Display/VMDisplayMetalViewController+Gamepad.m

@@ -139,15 +139,15 @@ const CGFloat kThumbstickSpeedMultiplier = 1000; // in points per second
         case 0:
             break;
         case -1:
-            [self.vmInput sendMouseButton:kCSInputButtonLeft pressed:isPressed point:CGPointZero];
+            [self.vmInput sendMouseButton:kCSInputButtonLeft pressed:isPressed];
             _mouseLeftDown = isPressed;
             break;
         case -3:
-            [self.vmInput sendMouseButton:kCSInputButtonRight pressed:isPressed point:CGPointZero];
+            [self.vmInput sendMouseButton:kCSInputButtonRight pressed:isPressed];
             _mouseRightDown = isPressed;
             break;
         case -2:
-            [self.vmInput sendMouseButton:kCSInputButtonMiddle pressed:isPressed point:CGPointZero];
+            [self.vmInput sendMouseButton:kCSInputButtonMiddle pressed:isPressed];
             _mouseMiddleDown = isPressed;
             break;
         default:

+ 3 - 3
Platform/iOS/Display/VMDisplayMetalViewController+Pointer.m

@@ -66,16 +66,16 @@ NS_AVAILABLE_IOS(13.4)
     };
     mouse.mouseInput.leftButton.pressedChangedHandler = ^(GCControllerButtonInput * _Nonnull button, float value, BOOL pressed) {
         self->_mouseLeftDown = pressed;
-        [self.vmInput sendMouseButton:kCSInputButtonLeft pressed:pressed point:CGPointZero];
+        [self.vmInput sendMouseButton:kCSInputButtonLeft pressed:pressed];
     };
     mouse.mouseInput.rightButton.pressedChangedHandler = ^(GCControllerButtonInput * _Nonnull button, float value, BOOL pressed) {
         self->_mouseRightDown = pressed;
-        [self.vmInput sendMouseButton:kCSInputButtonRight pressed:pressed point:CGPointZero];
+        [self.vmInput sendMouseButton:kCSInputButtonRight pressed:pressed];
 
     };
     mouse.mouseInput.middleButton.pressedChangedHandler = ^(GCControllerButtonInput * _Nonnull button, float value, BOOL pressed) {
         self->_mouseMiddleDown = pressed;
-        [self.vmInput sendMouseButton:kCSInputButtonMiddle pressed:pressed point:CGPointZero];
+        [self.vmInput sendMouseButton:kCSInputButtonMiddle pressed:pressed];
     };
     // no handler to the gcmouse scroll event, gestureScroll works fine.
     _mouseCaptured = YES;

+ 4 - 4
Platform/iOS/Display/VMDisplayMetalViewController+Touch.m

@@ -369,12 +369,12 @@ static CGFloat CGPointToPixel(CGFloat point) {
     if (!self.serverModeCursor) {
         _cursor.center = location;
     }
-    [self.vmInput sendMouseButton:button pressed:YES point:CGPointZero];
+    [self.vmInput sendMouseButton:button pressed:YES];
     [self onDelay:0.05f action:^{
         self->_mouseLeftDown = NO;
         self->_mouseRightDown = NO;
         self->_mouseMiddleDown = NO;
-        [self.vmInput sendMouseButton:button pressed:NO point:CGPointZero];
+        [self.vmInput sendMouseButton:button pressed:NO];
     }];
     [_clickFeedbackGenerator selectionChanged];
 }
@@ -391,12 +391,12 @@ static CGFloat CGPointToPixel(CGFloat point) {
         if (middle) {
             _mouseMiddleDown = YES;
         }
-        [self.vmInput sendMouseButton:self.mouseButtonDown pressed:YES point:CGPointZero];
+        [self.vmInput sendMouseButton:self.mouseButtonDown pressed:YES];
     } else if (state == UIGestureRecognizerStateEnded) {
         _mouseLeftDown = NO;
         _mouseRightDown = NO;
         _mouseMiddleDown = NO;
-        [self.vmInput sendMouseButton:self.mouseButtonDown pressed:NO point:CGPointZero];
+        [self.vmInput sendMouseButton:self.mouseButtonDown pressed:NO];
     }
 }
 

+ 4 - 5
Platform/iOS/Display/VMDisplayMetalViewController.m

@@ -22,18 +22,17 @@
 #import "VMDisplayMetalViewController+Gamepad.h"
 #import "VMDisplayMetalViewController+USB.h"
 #import "VMKeyboardView.h"
-#import "UTMRenderer.h"
 #import "UTMVirtualMachine.h"
 #import "UTMQemuManager.h"
 #import "UTMQemuConfiguration.h"
 #import "UTMQemuConfiguration+Display.h"
 #import "UTMLogging.h"
 #import "CSDisplayMetal.h"
-#import "UTMScreenshot.h"
 #import "UTM-Swift.h"
+@import CocoaSpiceRenderer;
 
 @implementation VMDisplayMetalViewController {
-    UTMRenderer *_renderer;
+    CSRenderer *_renderer;
 }
 
 - (void)setupSubviews {
@@ -66,7 +65,7 @@
         return;
     }
     
-    _renderer = [[UTMRenderer alloc] initWithMetalKitView:self.mtkView];
+    _renderer = [[CSRenderer alloc] initWithMetalKitView:self.mtkView];
     if (!_renderer) {
         UTMLog(@"Renderer failed initialization");
         return;
@@ -203,7 +202,7 @@
 }
 
 - (void)spiceDidCreateDisplay:(CSDisplayMetal *)display {
-    if (display.channelID == 0 && display.monitorID == 0) {
+    if (display.isPrimaryDisplay) {
         self.vmDisplay = display;
         _renderer.source = display;
     }

+ 0 - 1
Platform/iOS/Legacy/VMListViewController.m

@@ -23,7 +23,6 @@
 #import "UIViewController+Extensions.h"
 #import "VMDisplayMetalViewController.h"
 #import "VMDisplayTerminalViewController.h"
-#import "UTMScreenshot.h"
 #import "UTMJailbreak.h"
 
 @import SafariServices;

+ 2 - 2
Platform/iOS/UTMDataExtension.swift

@@ -63,9 +63,9 @@ extension UTMData {
     
     func tryClickAtPoint(point: CGPoint, button: CSInputButton) {
         if let vc = vmVC as? VMDisplayMetalViewController, let input = vc.vmInput {
-            input.sendMouseButton(button, pressed: true, point: point)
+            input.sendMouseButton(button, pressed: true)
             DispatchQueue.main.asyncAfter(deadline: .now() + 0.02) {
-                input.sendMouseButton(button, pressed: false, point: point)
+                input.sendMouseButton(button, pressed: false)
             }
         }
     }

+ 6 - 5
Platform/macOS/Display/VMDisplayMetalWindowController.swift

@@ -15,10 +15,11 @@
 //
 
 import Carbon.HIToolbox
+import CocoaSpiceRenderer
 
 class VMDisplayMetalWindowController: VMDisplayQemuWindowController {
     var metalView: VMMetalView!
-    var renderer: UTMRenderer?
+    var renderer: CSRenderer?
     
     @objc fileprivate dynamic weak var vmDisplay: CSDisplayMetal?
     @objc fileprivate weak var vmInput: CSInput?
@@ -59,7 +60,7 @@ class VMDisplayMetalWindowController: VMDisplayQemuWindowController {
             return
         }
         displayView.addSubview(metalView)
-        renderer = UTMRenderer.init(metalKitView: metalView)
+        renderer = CSRenderer.init(metalKitView: metalView)
         guard let renderer = self.renderer else {
             showErrorAlert(NSLocalizedString("Internal error.", comment: "VMDisplayMetalWindowController"))
             logger.critical("Failed to create renderer.")
@@ -134,7 +135,7 @@ extension VMDisplayMetalWindowController: UTMSpiceIODelegate {
     }
     
     func spiceDidCreateDisplay(_ display: CSDisplayMetal) {
-        if display.channelID == 0 && display.monitorID == 0 {
+        if display.isPrimaryDisplay {
             vmDisplay = display
             renderer!.source = vmDisplay
         }
@@ -360,11 +361,11 @@ extension VMDisplayMetalWindowController: VMMetalViewInputDelegate {
     }
     
     func mouseDown(button: CSInputButton) {
-        vmInput?.sendMouseButton(modifyMouseButton(button), pressed: true, point: .zero)
+        vmInput?.sendMouseButton(modifyMouseButton(button), pressed: true)
     }
     
     func mouseUp(button: CSInputButton) {
-        vmInput?.sendMouseButton(modifyMouseButton(button), pressed: false, point: .zero)
+        vmInput?.sendMouseButton(modifyMouseButton(button), pressed: false)
     }
     
     func mouseScroll(dy: CGFloat, button: CSInputButton) {

+ 0 - 41
Renderer/UTMRenderSource.h

@@ -1,41 +0,0 @@
-//
-// Copyright © 2019 osy. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-
-#import <Foundation/Foundation.h>
-@import MetalKit;
-
-NS_ASSUME_NONNULL_BEGIN
-
-@protocol UTMRenderSource <NSObject>
-
-@property (nonatomic, readonly) BOOL cursorVisible;
-@property (nonatomic) CGPoint cursorOrigin;
-@property (nonatomic) CGPoint viewportOrigin;
-@property (nonatomic) CGFloat viewportScale;
-@property (nonatomic, nullable) id<MTLDevice> device;
-@property (nonatomic, nullable, readonly) id<MTLTexture> displayTexture;
-@property (nonatomic, nullable, readonly) id<MTLTexture> cursorTexture;
-@property (nonatomic, readonly) NSUInteger displayNumVertices;
-@property (nonatomic, readonly) NSUInteger cursorNumVertices;
-@property (nonatomic, nullable, readonly) id<MTLBuffer> displayVertices;
-@property (nonatomic, nullable, readonly) id<MTLBuffer> cursorVertices;
-@property (nonatomic, readonly) BOOL cursorInverted;
-
-- (void)rendererFrameHasRendered;
-
-@end
-
-NS_ASSUME_NONNULL_END

+ 0 - 24
Renderer/UTMRenderer.h

@@ -1,24 +0,0 @@
-/*
-See LICENSE folder for this sample’s licensing information.
-
-Abstract:
-Header for renderer class which performs Metal setup and per frame rendering
-*/
-
-#import "UTMRenderSource.h"
-@import MetalKit;
-@import CoreGraphics;
-
-NS_ASSUME_NONNULL_BEGIN
-
-// Our platform independent renderer class
-@interface UTMRenderer : NSObject<MTKViewDelegate>
-
-@property (nonatomic, weak, nullable) id<UTMRenderSource> source;
-
-- (nonnull instancetype)initWithMetalKitView:(nonnull MTKView *)mtkView;
-- (void)changeUpscaler:(MTLSamplerMinMagFilter)upscaler downscaler:(MTLSamplerMinMagFilter)downscaler;
-
-@end
-
-NS_ASSUME_NONNULL_END

+ 0 - 265
Renderer/UTMRenderer.m

@@ -1,265 +0,0 @@
-/*
-See LICENSE folder for this sample’s licensing information.
-
-Abstract:
-Implementation of renderer class which performs Metal setup and per frame rendering
-*/
-
-@import simd;
-@import MetalKit;
-
-#import "UTMRenderer.h"
-#import "UTMLogging.h"
-
-// Header shared between C code here, which executes Metal API commands, and .metal files, which
-//   uses these types as inputs to the shaders
-#import "UTMShaderTypes.h"
-
-// Main class performing the rendering
-@implementation UTMRenderer
-{
-    // The device (aka GPU) we're using to render
-    id<MTLDevice> _device;
-
-    // Our render pipeline composed of our vertex and fragment shaders in the .metal shader file
-    id<MTLRenderPipelineState> _pipelineState;
-
-    // The command Queue from which we'll obtain command buffers
-    id<MTLCommandQueue> _commandQueue;
-
-    // The current size of our view so we can use this in our render pipeline
-    vector_uint2 _viewportSize;
-    
-    // Sampler object
-    id<MTLSamplerState> _sampler;
-}
-
-- (void)setSource:(id<UTMRenderSource>)source {
-    source.device = _device;
-    _source = source;
-}
-
-/// Initialize with the MetalKit view from which we'll obtain our Metal device
-- (nonnull instancetype)initWithMetalKitView:(nonnull MTKView *)mtkView
-{
-    self = [super init];
-    if(self)
-    {
-        _device = mtkView.device;
-
-        /// Create our render pipeline
-
-        // Load all the shader files with a .metal file extension in the project
-        id<MTLLibrary> defaultLibrary = [_device newDefaultLibrary];
-
-        // Load the vertex function from the library
-        id<MTLFunction> vertexFunction = [defaultLibrary newFunctionWithName:@"vertexShader"];
-
-        // Load the fragment function from the library
-        id<MTLFunction> fragmentFunction = [defaultLibrary newFunctionWithName:@"samplingShader"];
-
-        // Set up a descriptor for creating a pipeline state object
-        MTLRenderPipelineDescriptor *pipelineStateDescriptor = [[MTLRenderPipelineDescriptor alloc] init];
-        pipelineStateDescriptor.label = @"Texturing Pipeline";
-        pipelineStateDescriptor.vertexFunction = vertexFunction;
-        pipelineStateDescriptor.fragmentFunction = fragmentFunction;
-        pipelineStateDescriptor.colorAttachments[0].pixelFormat = mtkView.colorPixelFormat;
-        pipelineStateDescriptor.colorAttachments[0].blendingEnabled = YES;
-        pipelineStateDescriptor.colorAttachments[0].rgbBlendOperation = MTLBlendOperationAdd;
-        pipelineStateDescriptor.colorAttachments[0].alphaBlendOperation = MTLBlendOperationAdd;
-        pipelineStateDescriptor.colorAttachments[0].sourceRGBBlendFactor = MTLBlendFactorSourceAlpha;
-        pipelineStateDescriptor.colorAttachments[0].destinationRGBBlendFactor = MTLBlendFactorOneMinusSourceAlpha;
-        pipelineStateDescriptor.colorAttachments[0].sourceAlphaBlendFactor = MTLBlendFactorOne;
-        pipelineStateDescriptor.colorAttachments[0].destinationAlphaBlendFactor = MTLBlendFactorOne;
-        pipelineStateDescriptor.depthAttachmentPixelFormat = mtkView.depthStencilPixelFormat;
-
-        NSError *error = NULL;
-        _pipelineState = [_device newRenderPipelineStateWithDescriptor:pipelineStateDescriptor
-                                                                 error:&error];
-        if (!_pipelineState)
-        {
-            // Pipeline State creation could fail if we haven't properly set up our pipeline descriptor.
-            //  If the Metal API validation is enabled, we can find out more information about what
-            //  went wrong.  (Metal API validation is enabled by default when a debug build is run
-            //  from Xcode)
-            UTMLog(@"Failed to created pipeline state, error %@", error);
-        }
-
-        // Create the command queue
-        _commandQueue = [_device newCommandQueue];
-        
-        // Sampler
-        [self changeUpscaler:MTLSamplerMinMagFilterLinear downscaler:MTLSamplerMinMagFilterLinear];
-    }
-
-    return self;
-}
-
-/// Scalers from VM settings
-- (void)changeUpscaler:(MTLSamplerMinMagFilter)upscaler downscaler:(MTLSamplerMinMagFilter)downscaler {
-    MTLSamplerDescriptor *samplerDescriptor = [MTLSamplerDescriptor new];
-    samplerDescriptor.minFilter = downscaler;
-    samplerDescriptor.magFilter = upscaler;
-     
-    _sampler = [_device newSamplerStateWithDescriptor:samplerDescriptor];
-}
-
-/// Called whenever view changes orientation or is resized
-- (void)mtkView:(nonnull MTKView *)view drawableSizeWillChange:(CGSize)size
-{
-    // Save the size of the drawable as we'll pass these
-    //   values to our vertex shader when we draw
-    _viewportSize.x = size.width;
-    _viewportSize.y = size.height;
-}
-
-/// Create a translation+scale matrix
-static matrix_float4x4 matrix_scale_translate(CGFloat scale, CGPoint translate)
-{
-    matrix_float4x4 m = {
-        .columns[0] = {
-            scale,
-            0,
-            0,
-            0
-        },
-        .columns[1] = {
-            0,
-            scale,
-            0,
-            0
-        },
-        .columns[2] = {
-            0,
-            0,
-            1,
-            0
-        },
-        .columns[3] = {
-            translate.x,
-            -translate.y, // y flipped
-            0,
-            1
-        }
-        
-    };
-    return m;
-}
-
-/// Called whenever the view needs to render a frame
-- (void)drawInMTKView:(nonnull MTKView *)view
-{
-    id<UTMRenderSource> source = self.source;
-    if (view.hidden || !source) {
-        return;
-    }
-
-    // Create a new command buffer for each render pass to the current drawable
-    id<MTLCommandBuffer> commandBuffer = [_commandQueue commandBuffer];
-    commandBuffer.label = @"MyCommand";
-
-    // Obtain a renderPassDescriptor generated from the view's drawable textures
-    MTLRenderPassDescriptor *renderPassDescriptor = view.currentRenderPassDescriptor;
-
-    if(renderPassDescriptor != nil)
-    {
-        // Create a render command encoder so we can render into something
-        id<MTLRenderCommandEncoder> renderEncoder =
-        [commandBuffer renderCommandEncoderWithDescriptor:renderPassDescriptor];
-        renderEncoder.label = @"MyRenderEncoder";
-        
-        // Render the screen first
-        
-        bool hasAlpha = NO;
-        bool isInverted = NO;
-        matrix_float4x4 transform = matrix_scale_translate(source.viewportScale,
-                                                           source.viewportOrigin);
-
-        [renderEncoder setRenderPipelineState:_pipelineState];
-
-        [renderEncoder setVertexBuffer:source.displayVertices
-                                offset:0
-                              atIndex:UTMVertexInputIndexVertices];
-
-        [renderEncoder setVertexBytes:&_viewportSize
-                               length:sizeof(_viewportSize)
-                              atIndex:UTMVertexInputIndexViewportSize];
-
-        [renderEncoder setVertexBytes:&transform
-                               length:sizeof(transform)
-                              atIndex:UTMVertexInputIndexTransform];
-
-        [renderEncoder setVertexBytes:&hasAlpha
-                               length:sizeof(hasAlpha)
-                              atIndex:UTMVertexInputIndexHasAlpha];
-
-        // Set the texture object.  The UTMTextureIndexBaseColor enum value corresponds
-        ///  to the 'colorMap' argument in our 'samplingShader' function because its
-        //   texture attribute qualifier also uses UTMTextureIndexBaseColor for its index
-        [renderEncoder setFragmentTexture:source.displayTexture
-                                  atIndex:UTMTextureIndexBaseColor];
-        
-        [renderEncoder setFragmentSamplerState:_sampler
-                                       atIndex:UTMSamplerIndexTexture];
-        
-        [renderEncoder setFragmentBytes:&isInverted
-                                 length:sizeof(isInverted)
-                                atIndex:UTMFragmentBufferIndexIsInverted];
-
-        // Draw the vertices of our triangles
-        [renderEncoder drawPrimitives:MTLPrimitiveTypeTriangle
-                          vertexStart:0
-                          vertexCount:source.displayNumVertices];
-        
-        // Draw cursor
-        if (source.cursorVisible) {
-            // Next render the cursor
-            bool hasAlpha = YES;
-            bool isInverted = source.cursorInverted;
-            matrix_float4x4 transform = matrix_scale_translate(source.viewportScale,
-                                                               CGPointMake(source.viewportOrigin.x +
-                                                                           source.cursorOrigin.x,
-                                                                           source.viewportOrigin.y +
-                                                                           source.cursorOrigin.y));
-            [renderEncoder setVertexBuffer:source.cursorVertices
-                                    offset:0
-                                  atIndex:UTMVertexInputIndexVertices];
-            [renderEncoder setVertexBytes:&_viewportSize
-                                   length:sizeof(_viewportSize)
-                                  atIndex:UTMVertexInputIndexViewportSize];
-            [renderEncoder setVertexBytes:&transform
-                                 length:sizeof(transform)
-                                atIndex:UTMVertexInputIndexTransform];
-            [renderEncoder setVertexBytes:&hasAlpha
-                                 length:sizeof(hasAlpha)
-                                atIndex:UTMVertexInputIndexHasAlpha];
-            [renderEncoder setFragmentTexture:source.cursorTexture
-                                      atIndex:UTMTextureIndexBaseColor];
-            [renderEncoder setFragmentSamplerState:_sampler
-                                           atIndex:UTMSamplerIndexTexture];
-            [renderEncoder setFragmentBytes:&isInverted
-                                     length:sizeof(isInverted)
-                                    atIndex:UTMFragmentBufferIndexIsInverted];
-            [renderEncoder drawPrimitives:MTLPrimitiveTypeTriangle
-                              vertexStart:0
-                              vertexCount:source.cursorNumVertices];
-        }
-
-        [renderEncoder endEncoding];
-        
-        // Schedule a present once the framebuffer is complete using the current drawable
-        [commandBuffer presentDrawable:view.currentDrawable];
-        
-        // Release lock after GPU is done
-        [commandBuffer addCompletedHandler:^(id<MTLCommandBuffer> commandBuffer) {
-            // GPU work is complete
-            [source rendererFrameHasRendered];
-        }];
-    }
-
-
-    // Finalize rendering here & push the command buffer to the GPU
-    [commandBuffer commit];
-}
-
-@end

+ 0 - 53
Renderer/UTMShaderTypes.h

@@ -1,53 +0,0 @@
-/*
-See LICENSE folder for this sample’s licensing information.
-
-Abstract:
-Header containing types and enum constants shared between Metal shaders and C/ObjC source
-*/
-
-#ifndef UTMShaderTypes_h
-#define UTMShaderTypes_h
-
-#include <simd/simd.h>
-
-// Buffer index values shared between shader and C code to ensure Metal shader buffer inputs match
-//   Metal API buffer set calls
-typedef enum UTMVertexInputIndex
-{
-    UTMVertexInputIndexVertices     = 0,
-    UTMVertexInputIndexViewportSize = 1,
-    UTMVertexInputIndexTransform    = 2,
-    UTMVertexInputIndexHasAlpha     = 3,
-} UTMVertexInputIndex;
-
-// Texture index values shared between shader and C code to ensure Metal shader buffer inputs match
-//   Metal API texture set calls
-typedef enum UTMTextureIndex
-{
-    UTMTextureIndexBaseColor = 0,
-} UTMTextureIndex;
-
-typedef enum UTMSamplerIndex
-{
-    UTMSamplerIndexTexture = 0,
-} UTMSamplerIndex;
-
-typedef enum UTMFragmentBufferIndex
-{
-    UTMFragmentBufferIndexIsInverted = 0,
-} UTMFragmentBufferIndex;
-
-//  This structure defines the layout of each vertex in the array of vertices set as an input to our
-//    Metal vertex shader.  Since this header is shared between our .metal shader and C code,
-//    we can be sure that the layout of the vertex array in the code matches the layout that
-//    our vertex shader expects
-typedef struct
-{
-    // Positions in pixel space (i.e. a value of 100 indicates 100 pixels from the origin/center)
-    vector_float2 position;
-
-    // 2D texture coordinate
-    vector_float2 textureCoordinate;
-} UTMVertex;
-
-#endif /* UTMShaderTypes_h */

+ 0 - 102
Renderer/UTMShaders.metal

@@ -1,102 +0,0 @@
-/*
-See LICENSE folder for this sample’s licensing information.
-
-Abstract:
-Metal shaders used for this sample
-*/
-
-#include <metal_stdlib>
-#include <simd/simd.h>
-
-using namespace metal;
-
-// Include header shared between this Metal shader code and C code executing Metal API commands
-#import "UTMShaderTypes.h"
-
-// Vertex shader outputs and per-fragment inputs. Includes clip-space position and vertex outputs
-//  interpolated by rasterizer and fed to each fragment generated by clip-space primitives.
-typedef struct
-{
-    // The [[position]] attribute qualifier of this member indicates this value is the clip space
-    //   position of the vertex wen this structure is returned from the vertex shader
-    float4 clipSpacePosition [[position]];
-
-    // Since this member does not have a special attribute qualifier, the rasterizer will
-    //   interpolate its value with values of other vertices making up the triangle and
-    //   pass that interpolated value to the fragment shader for each fragment in that triangle;
-    float2 textureCoordinate;
-
-    // If no, then we fake an alpha value
-    bool hasAlpha;
-} RasterizerData;
-
-// Vertex Function
-vertex RasterizerData
-vertexShader(uint vertexID [[ vertex_id ]],
-             constant UTMVertex *vertexArray [[ buffer(UTMVertexInputIndexVertices) ]],
-             constant vector_uint2 *viewportSizePointer  [[ buffer(UTMVertexInputIndexViewportSize) ]],
-             constant matrix_float4x4 &transformation [[ buffer(UTMVertexInputIndexTransform) ]],
-             constant bool *hasAlpha [[ buffer(UTMVertexInputIndexHasAlpha) ]])
-
-{
-
-    RasterizerData out;
-    
-    // Transform the vertex
-    vector_float4 position = transformation * float4(vertexArray[vertexID].position,0,1);
-
-    // Index into our array of positions to get the current vertex
-    //   Our positions are specified in pixel dimensions (i.e. a value of 100 is 100 pixels from
-    //   the origin)
-    float2 pixelSpacePosition = position.xy;
-
-    // Get the size of the drawable so that we can convert to normalized device coordinates,
-    float2 viewportSize = float2(*viewportSizePointer);
-
-    // The output position of every vertex shader is in clip space (also known as normalized device
-    //   coordinate space, or NDC). A value of (-1.0, -1.0) in clip-space represents the
-    //   lower-left corner of the viewport whereas (1.0, 1.0) represents the upper-right corner of
-    //   the viewport.
-
-    // In order to convert from positions in pixel space to positions in clip space we divide the
-    //   pixel coordinates by half the size of the viewport.
-    out.clipSpacePosition.xy = pixelSpacePosition / (viewportSize / 2.0);
-
-    // Set the z component of our clip space position 0 (since we're only rendering in
-    //   2-Dimensions for this sample)
-    out.clipSpacePosition.z = 0.0;
-
-    // Set the w component to 1.0 since we don't need a perspective divide, which is also not
-    //   necessary when rendering in 2-Dimensions
-    out.clipSpacePosition.w = 1.0;
-
-    // Pass our input textureCoordinate straight to our output RasterizerData. This value will be
-    //   interpolated with the other textureCoordinate values in the vertices that make up the
-    //   triangle.
-    out.textureCoordinate = vertexArray[vertexID].textureCoordinate;
-    
-    // All fragments have alpha or not
-    out.hasAlpha = *hasAlpha;
-
-    return out;
-}
-
-// Fragment function
-fragment float4
-samplingShader(RasterizerData in [[stage_in]],
-               texture2d<half> colorTexture [[ texture(UTMTextureIndexBaseColor) ]],
-               sampler textureSampler [[ sampler(UTMSamplerIndexTexture) ]],
-               constant bool *isInverted [[ buffer(UTMFragmentBufferIndexIsInverted) ]])
-{
-    // Sample the texture to obtain a color
-    half4 colorSample = colorTexture.sample(textureSampler, in.textureCoordinate);
-
-    // fake alpha
-    if (!in.hasAlpha) {
-        colorSample.a = 0xff;
-    }
-
-    // We return the color of the texture inverted when requested
-    return float4(*isInverted ? colorSample.bgra : colorSample);
-}
-

+ 33 - 148
UTM.xcodeproj/project.pbxproj

@@ -82,6 +82,9 @@
 		848F71ED277A2F47006A0240 /* UTMSerialPortDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 848F71EB277A2F47006A0240 /* UTMSerialPortDelegate.swift */; };
 		848F71EE277A2F47006A0240 /* UTMSerialPortDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 848F71EB277A2F47006A0240 /* UTMSerialPortDelegate.swift */; };
 		84A381AA268CB30C0048EE4D /* VMConfigDrivesButtons.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84A381A9268CB30C0048EE4D /* VMConfigDrivesButtons.swift */; };
+		84B36D1E27B3264600C22685 /* CocoaSpice in Frameworks */ = {isa = PBXBuildFile; productRef = 84B36D1D27B3264600C22685 /* CocoaSpice */; };
+		84B36D2027B3264E00C22685 /* CocoaSpiceNoUsb in Frameworks */ = {isa = PBXBuildFile; productRef = 84B36D1F27B3264E00C22685 /* CocoaSpiceNoUsb */; };
+		84B36D2227B3265400C22685 /* CocoaSpice in Frameworks */ = {isa = PBXBuildFile; productRef = 84B36D2127B3265400C22685 /* CocoaSpice */; };
 		84C584E1268E95B3000FCABF /* UTMAppleConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84C584DE268E95B3000FCABF /* UTMAppleConfiguration.swift */; };
 		84C584E3268F8AE7000FCABF /* VMQEMUSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84C584E2268F8AE7000FCABF /* VMQEMUSettingsView.swift */; };
 		84C584E5268F8C65000FCABF /* VMAppleSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84C584E4268F8C65000FCABF /* VMAppleSettingsView.swift */; };
@@ -140,10 +143,6 @@
 		CE03D0D424DCF6DD00F76B84 /* VMMetalViewInputDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE03D0D324DCF6DD00F76B84 /* VMMetalViewInputDelegate.swift */; };
 		CE0B6CEC24AD532500FE012D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = CE550BD52259479D0063E575 /* Assets.xcassets */; };
 		CE0B6CED24AD532A00FE012D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = CE550BD52259479D0063E575 /* Assets.xcassets */; };
-		CE0B6CEE24AD566A00FE012D /* CSConnection.m in Sources */ = {isa = PBXBuildFile; fileRef = CE4AA14B2264004F002E4A54 /* CSConnection.m */; };
-		CE0B6CEF24AD566D00FE012D /* CSDisplayMetal.m in Sources */ = {isa = PBXBuildFile; fileRef = CE4AA1482263B24F002E4A54 /* CSDisplayMetal.m */; };
-		CE0B6CF024AD567100FE012D /* CSInput.m in Sources */ = {isa = PBXBuildFile; fileRef = CE664510226935F000B0849A /* CSInput.m */; };
-		CE0B6CF124AD567300FE012D /* CSMain.m in Sources */ = {isa = PBXBuildFile; fileRef = CE26FC24226EBC5A0090BE9B /* CSMain.m */; };
 		CE0B6CF324AD568400FE012D /* UTMQemuConfiguration.m in Sources */ = {isa = PBXBuildFile; fileRef = CE31C244225E555600A965DD /* UTMQemuConfiguration.m */; };
 		CE0B6CF424AD568400FE012D /* UTMQemuConfiguration+Constants.m in Sources */ = {isa = PBXBuildFile; fileRef = CE5425362437DDE900E520F7 /* UTMQemuConfiguration+Constants.m */; };
 		CE0B6CF524AD568400FE012D /* UTMQemuConfiguration+Miscellaneous.m in Sources */ = {isa = PBXBuildFile; fileRef = CEE0421124418F2E0001680F /* UTMQemuConfiguration+Miscellaneous.m */; };
@@ -154,7 +153,6 @@
 		CE0B6CFA24AD568400FE012D /* UTMQemuConfiguration+System.m in Sources */ = {isa = PBXBuildFile; fileRef = CE5425332437C22A00E520F7 /* UTMQemuConfiguration+System.m */; };
 		CE0B6CFB24AD568400FE012D /* UTMQemuConfiguration+Networking.m in Sources */ = {isa = PBXBuildFile; fileRef = CEA02A982436C7A30087E45F /* UTMQemuConfiguration+Networking.m */; };
 		CE0B6CFC24AD568400FE012D /* UTMQemuConfigurationPortForward.m in Sources */ = {isa = PBXBuildFile; fileRef = CE54252D2436E48D00E520F7 /* UTMQemuConfigurationPortForward.m */; };
-		CE0B6CFD24AD569A00FE012D /* gst_ios_init.m in Sources */ = {isa = PBXBuildFile; fileRef = CEFE75D9228933DE0050ABCC /* gst_ios_init.m */; };
 		CE0B6CFE24AD56AE00FE012D /* UTMLogging.m in Sources */ = {isa = PBXBuildFile; fileRef = CE6EDCE1241DA0E900A719DC /* UTMLogging.m */; };
 		CE0B6D0024AD56AE00FE012D /* UTMVirtualMachine.m in Sources */ = {isa = PBXBuildFile; fileRef = CE5F165B2261395000F3D56B /* UTMVirtualMachine.m */; };
 		CE0B6D0124AD56AE00FE012D /* UTMJSONStream.m in Sources */ = {isa = PBXBuildFile; fileRef = CE36B26922763F28004A1435 /* UTMJSONStream.m */; };
@@ -169,8 +167,6 @@
 		CE0B6D0B24AD56C300FE012D /* qapi-dealloc-visitor.c in Sources */ = {isa = PBXBuildFile; fileRef = CECC764D2273A7D50059B955 /* qapi-dealloc-visitor.c */; };
 		CE0B6D0C24AD56C300FE012D /* error.c in Sources */ = {isa = PBXBuildFile; fileRef = CE36B1542275061B004A1435 /* error.c */; };
 		CE0B6D0D24AD56C300FE012D /* qapi-util.c in Sources */ = {isa = PBXBuildFile; fileRef = CECC764E2273A7D50059B955 /* qapi-util.c */; };
-		CE0B6D0E24AD56E500FE012D /* UTMShaders.metal in Sources */ = {isa = PBXBuildFile; fileRef = CE2D63D02265154700FC7E63 /* UTMShaders.metal */; };
-		CE0B6D0F24AD56E500FE012D /* UTMRenderer.m in Sources */ = {isa = PBXBuildFile; fileRef = CE2D63CF2265154700FC7E63 /* UTMRenderer.m */; };
 		CE0B6D1024AD57C400FE012D /* qapi-builtin-types.c in Sources */ = {isa = PBXBuildFile; fileRef = CE23C0D523FCEC03001177D6 /* qapi-builtin-types.c */; };
 		CE0B6D1124AD57C700FE012D /* qapi-builtin-visit.c in Sources */ = {isa = PBXBuildFile; fileRef = CE23C09623FCEC00001177D6 /* qapi-builtin-visit.c */; };
 		CE0B6D1224AD57CB00FE012D /* qapi-commands-audio.c in Sources */ = {isa = PBXBuildFile; fileRef = CE23C09D23FCEC00001177D6 /* qapi-commands-audio.c */; };
@@ -286,8 +282,6 @@
 		CE0B6D8024AD584D00FE012D /* qapi-events-sockets.c in Sources */ = {isa = PBXBuildFile; fileRef = CE23C0AF23FCEC01001177D6 /* qapi-events-sockets.c */; };
 		CE0B6D8124AD584D00FE012D /* qapi-events.c in Sources */ = {isa = PBXBuildFile; fileRef = CE23C14023FCEC09001177D6 /* qapi-events.c */; };
 		CE0B6D8224AD584D00FE012D /* qapi-types-block-core.c in Sources */ = {isa = PBXBuildFile; fileRef = CE23C09923FCEC00001177D6 /* qapi-types-block-core.c */; };
-		CE0B6D8624AD5ADE00FE012D /* UTMScreenshot.m in Sources */ = {isa = PBXBuildFile; fileRef = CE0B6D8424AD5ADE00FE012D /* UTMScreenshot.m */; };
-		CE0B6D8724AD5ADE00FE012D /* UTMScreenshot.m in Sources */ = {isa = PBXBuildFile; fileRef = CE0B6D8424AD5ADE00FE012D /* UTMScreenshot.m */; };
 		CE0B6EBB24AD677200FE012D /* libgstgio.a in Frameworks */ = {isa = PBXBuildFile; fileRef = CE9D19622265425A00355E14 /* libgstgio.a */; };
 		CE0B6EBC24AD677200FE012D /* gstpbutils-1.0.0.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CE2D640E22653C7500FC7E63 /* gstpbutils-1.0.0.framework */; };
 		CE0B6EC224AD677200FE012D /* libgstvideorate.a in Frameworks */ = {isa = PBXBuildFile; fileRef = CE9D19592265425900355E14 /* libgstvideorate.a */; };
@@ -396,7 +390,6 @@
 		CE2D927B24AD46670059923A /* qapi-types-job.c in Sources */ = {isa = PBXBuildFile; fileRef = CE23C13123FCEC08001177D6 /* qapi-types-job.c */; };
 		CE2D927C24AD46670059923A /* UTMQemu.m in Sources */ = {isa = PBXBuildFile; fileRef = CE9D197B226542FE00355E14 /* UTMQemu.m */; };
 		CE2D927D24AD46670059923A /* qapi-visit-machine.c in Sources */ = {isa = PBXBuildFile; fileRef = CE23C10D23FCEC06001177D6 /* qapi-visit-machine.c */; };
-		CE2D927E24AD46670059923A /* CSSession.m in Sources */ = {isa = PBXBuildFile; fileRef = CE5425392439334400E520F7 /* CSSession.m */; };
 		CE2D927F24AD46670059923A /* qapi-commands-machine-target.c in Sources */ = {isa = PBXBuildFile; fileRef = CE23C0DB23FCEC03001177D6 /* qapi-commands-machine-target.c */; };
 		CE2D928024AD46670059923A /* UTMQemuConfigurationPortForward.m in Sources */ = {isa = PBXBuildFile; fileRef = CE54252D2436E48D00E520F7 /* UTMQemuConfigurationPortForward.m */; };
 		CE2D928124AD46670059923A /* qapi-events.c in Sources */ = {isa = PBXBuildFile; fileRef = CE23C14023FCEC09001177D6 /* qapi-events.c */; };
@@ -415,7 +408,6 @@
 		CE2D929024AD46670059923A /* qapi-types-net.c in Sources */ = {isa = PBXBuildFile; fileRef = CE23C0B523FCEC02001177D6 /* qapi-types-net.c */; };
 		CE2D929124AD46670059923A /* qapi-types-rdma.c in Sources */ = {isa = PBXBuildFile; fileRef = CE23C13023FCEC08001177D6 /* qapi-types-rdma.c */; };
 		CE2D929224AD46670059923A /* qapi-commands-rocker.c in Sources */ = {isa = PBXBuildFile; fileRef = CE23C08123FCEBFF001177D6 /* qapi-commands-rocker.c */; };
-		CE2D929324AD46670059923A /* gst_ios_init.m in Sources */ = {isa = PBXBuildFile; fileRef = CEFE75D9228933DE0050ABCC /* gst_ios_init.m */; };
 		CE2D929424AD46670059923A /* cf-input-visitor.c in Sources */ = {isa = PBXBuildFile; fileRef = CECC764C2273A7D50059B955 /* cf-input-visitor.c */; };
 		CE2D929524AD46670059923A /* qapi-commands-char.c in Sources */ = {isa = PBXBuildFile; fileRef = CE23C08623FCEBFF001177D6 /* qapi-commands-char.c */; };
 		CE2D929624AD46670059923A /* qapi-visit-migration.c in Sources */ = {isa = PBXBuildFile; fileRef = CE23C0CE23FCEC03001177D6 /* qapi-visit-migration.c */; };
@@ -423,7 +415,6 @@
 		CE2D929924AD46670059923A /* UTMJSONStream.m in Sources */ = {isa = PBXBuildFile; fileRef = CE36B26922763F28004A1435 /* UTMJSONStream.m */; };
 		CE2D929A24AD46670059923A /* qapi-commands-sockets.c in Sources */ = {isa = PBXBuildFile; fileRef = CE23C0BD23FCEC02001177D6 /* qapi-commands-sockets.c */; };
 		CE2D929C24AD46670059923A /* UTMViewState.m in Sources */ = {isa = PBXBuildFile; fileRef = CE6EDCDE241C4A6800A719DC /* UTMViewState.m */; };
-		CE2D929E24AD46670059923A /* CSMain.m in Sources */ = {isa = PBXBuildFile; fileRef = CE26FC24226EBC5A0090BE9B /* CSMain.m */; };
 		CE2D929F24AD46670059923A /* UTMQemuConfiguration+Constants.m in Sources */ = {isa = PBXBuildFile; fileRef = CE5425362437DDE900E520F7 /* UTMQemuConfiguration+Constants.m */; };
 		CE2D92A024AD46670059923A /* VMDisplayMetalViewController+Touch.m in Sources */ = {isa = PBXBuildFile; fileRef = CE056CA5242454100004B68A /* VMDisplayMetalViewController+Touch.m */; };
 		CE2D92A124AD46670059923A /* UTMQemuConfiguration+Display.m in Sources */ = {isa = PBXBuildFile; fileRef = CEE0420B244117040001680F /* UTMQemuConfiguration+Display.m */; };
@@ -477,13 +468,11 @@
 		CE2D92D824AD46670059923A /* qapi-commands-trace.c in Sources */ = {isa = PBXBuildFile; fileRef = CE23C11023FCEC06001177D6 /* qapi-commands-trace.c */; };
 		CE2D92D924AD46670059923A /* qapi-visit.c in Sources */ = {isa = PBXBuildFile; fileRef = CE23C13523FCEC08001177D6 /* qapi-visit.c */; };
 		CE2D92DA24AD46670059923A /* VMCursor.m in Sources */ = {isa = PBXBuildFile; fileRef = CE3ADD692411C661002D6A5F /* VMCursor.m */; };
-		CE2D92DB24AD46670059923A /* CSDisplayMetal.m in Sources */ = {isa = PBXBuildFile; fileRef = CE4AA1482263B24F002E4A54 /* CSDisplayMetal.m */; };
 		CE2D92DD24AD46670059923A /* qapi-events-tpm.c in Sources */ = {isa = PBXBuildFile; fileRef = CE23C13923FCEC08001177D6 /* qapi-events-tpm.c */; };
 		CE2D92DE24AD46670059923A /* qapi-events-job.c in Sources */ = {isa = PBXBuildFile; fileRef = CE23C14523FCEC09001177D6 /* qapi-events-job.c */; };
 		CE2D92DF24AD46670059923A /* qapi-dealloc-visitor.c in Sources */ = {isa = PBXBuildFile; fileRef = CECC764D2273A7D50059B955 /* qapi-dealloc-visitor.c */; };
 		CE2D92E024AD46670059923A /* qapi-visit-job.c in Sources */ = {isa = PBXBuildFile; fileRef = CE23C09523FCEC00001177D6 /* qapi-visit-job.c */; };
 		CE2D92E124AD46670059923A /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = CE550BCD225947990063E575 /* AppDelegate.m */; };
-		CE2D92E224AD46670059923A /* CSInput.m in Sources */ = {isa = PBXBuildFile; fileRef = CE664510226935F000B0849A /* CSInput.m */; };
 		CE2D92E424AD46670059923A /* qapi-types-block.c in Sources */ = {isa = PBXBuildFile; fileRef = CE23C08723FCEBFF001177D6 /* qapi-types-block.c */; };
 		CE2D92E524AD46670059923A /* qapi-events-machine.c in Sources */ = {isa = PBXBuildFile; fileRef = CE23C0B923FCEC02001177D6 /* qapi-events-machine.c */; };
 		CE2D92E624AD46670059923A /* UTMQemuConfiguration+Networking.m in Sources */ = {isa = PBXBuildFile; fileRef = CEA02A982436C7A30087E45F /* UTMQemuConfiguration+Networking.m */; };
@@ -530,7 +519,6 @@
 		CE2D931624AD46670059923A /* qapi-commands-run-state.c in Sources */ = {isa = PBXBuildFile; fileRef = CE23C07E23FCEBFF001177D6 /* qapi-commands-run-state.c */; };
 		CE2D931924AD46670059923A /* qapi-types-misc-target.c in Sources */ = {isa = PBXBuildFile; fileRef = CE23C16023FCEC0A001177D6 /* qapi-types-misc-target.c */; };
 		CE2D931A24AD46670059923A /* qapi-events-rdma.c in Sources */ = {isa = PBXBuildFile; fileRef = CE23C12923FCEC07001177D6 /* qapi-events-rdma.c */; };
-		CE2D931B24AD46670059923A /* UTMShaders.metal in Sources */ = {isa = PBXBuildFile; fileRef = CE2D63D02265154700FC7E63 /* UTMShaders.metal */; };
 		CE2D931D24AD46670059923A /* qapi-visit-dump.c in Sources */ = {isa = PBXBuildFile; fileRef = CE23C0B323FCEC01001177D6 /* qapi-visit-dump.c */; };
 		CE2D931E24AD46670059923A /* qapi-visit-error.c in Sources */ = {isa = PBXBuildFile; fileRef = CE23C15D23FCEC0A001177D6 /* qapi-visit-error.c */; };
 		CE2D931F24AD46670059923A /* error.c in Sources */ = {isa = PBXBuildFile; fileRef = CE36B1542275061B004A1435 /* error.c */; };
@@ -539,10 +527,8 @@
 		CE2D932224AD46670059923A /* VMScroll.m in Sources */ = {isa = PBXBuildFile; fileRef = CE20FAE72448D2BE0059AE11 /* VMScroll.m */; };
 		CE2D932324AD46670059923A /* UTMTerminal.m in Sources */ = {isa = PBXBuildFile; fileRef = E28394B3240C20E0006742E2 /* UTMTerminal.m */; };
 		CE2D932524AD46670059923A /* qapi-types-char.c in Sources */ = {isa = PBXBuildFile; fileRef = CE23C12023FCEC07001177D6 /* qapi-types-char.c */; };
-		CE2D932724AD46670059923A /* CSConnection.m in Sources */ = {isa = PBXBuildFile; fileRef = CE4AA14B2264004F002E4A54 /* CSConnection.m */; };
 		CE2D932824AD46670059923A /* qapi-visit-audio.c in Sources */ = {isa = PBXBuildFile; fileRef = CE23C0BE23FCEC02001177D6 /* qapi-visit-audio.c */; };
 		CE2D932924AD46670059923A /* qapi-builtin-visit.c in Sources */ = {isa = PBXBuildFile; fileRef = CE23C09623FCEC00001177D6 /* qapi-builtin-visit.c */; };
-		CE2D932A24AD46670059923A /* UTMRenderer.m in Sources */ = {isa = PBXBuildFile; fileRef = CE2D63CF2265154700FC7E63 /* UTMRenderer.m */; };
 		CE2D932C24AD46670059923A /* libgstautodetect.a in Frameworks */ = {isa = PBXBuildFile; fileRef = CE9D19522265425900355E14 /* libgstautodetect.a */; };
 		CE2D932D24AD46670059923A /* libgstaudiotestsrc.a in Frameworks */ = {isa = PBXBuildFile; fileRef = CE9D19532265425900355E14 /* libgstaudiotestsrc.a */; };
 		CE2D932E24AD46670059923A /* libgstvideoconvert.a in Frameworks */ = {isa = PBXBuildFile; fileRef = CE9D19542265425900355E14 /* libgstvideoconvert.a */; };
@@ -733,10 +719,6 @@
 		CE8813D624CD265700532628 /* VMShareFileModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE8813D424CD265700532628 /* VMShareFileModifier.swift */; };
 		CE8813DB24D1290600532628 /* UTMQemuConfiguration+ConstantsGenerated.m in Sources */ = {isa = PBXBuildFile; fileRef = CE8813D924D1290600532628 /* UTMQemuConfiguration+ConstantsGenerated.m */; };
 		CE8813DC24D1290600532628 /* UTMQemuConfiguration+ConstantsGenerated.m in Sources */ = {isa = PBXBuildFile; fileRef = CE8813D924D1290600532628 /* UTMQemuConfiguration+ConstantsGenerated.m */; };
-		CE900B9E25FC2869007533FD /* CSUSBManager.m in Sources */ = {isa = PBXBuildFile; fileRef = CE900B9D25FC2869007533FD /* CSUSBManager.m */; };
-		CE900B9F25FC2869007533FD /* CSUSBManager.m in Sources */ = {isa = PBXBuildFile; fileRef = CE900B9D25FC2869007533FD /* CSUSBManager.m */; };
-		CE900BAF25FC3E65007533FD /* CSUSBDevice.m in Sources */ = {isa = PBXBuildFile; fileRef = CE900BAE25FC3E65007533FD /* CSUSBDevice.m */; };
-		CE900BB025FC3E65007533FD /* CSUSBDevice.m in Sources */ = {isa = PBXBuildFile; fileRef = CE900BAE25FC3E65007533FD /* CSUSBDevice.m */; };
 		CE928C2A26ABE6690099F293 /* UTMAppleVirtualMachine.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE928C2926ABE6690099F293 /* UTMAppleVirtualMachine.swift */; };
 		CE928C3126ACCDEA0099F293 /* VMAppleRemovableDrivesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE928C3026ACCDEA0099F293 /* VMAppleRemovableDrivesView.swift */; };
 		CE93758924B930270074066F /* BusyOverlay.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE7D972B24B2B17D0080CB69 /* BusyOverlay.swift */; };
@@ -773,7 +755,6 @@
 		CEA45E3E263519B5002FA97D /* UTMPortAllocator.m in Sources */ = {isa = PBXBuildFile; fileRef = CEF83ED224FDEA9400557D15 /* UTMPortAllocator.m */; };
 		CEA45E3F263519B5002FA97D /* UTMQemu.m in Sources */ = {isa = PBXBuildFile; fileRef = CE9D197B226542FE00355E14 /* UTMQemu.m */; };
 		CEA45E40263519B5002FA97D /* qapi-visit-machine.c in Sources */ = {isa = PBXBuildFile; fileRef = CE23C10D23FCEC06001177D6 /* qapi-visit-machine.c */; };
-		CEA45E41263519B5002FA97D /* CSSession.m in Sources */ = {isa = PBXBuildFile; fileRef = CE5425392439334400E520F7 /* CSSession.m */; };
 		CEA45E42263519B5002FA97D /* qapi-commands-machine-target.c in Sources */ = {isa = PBXBuildFile; fileRef = CE23C0DB23FCEC03001177D6 /* qapi-commands-machine-target.c */; };
 		CEA45E43263519B5002FA97D /* UTMQemuConfigurationPortForward.m in Sources */ = {isa = PBXBuildFile; fileRef = CE54252D2436E48D00E520F7 /* UTMQemuConfigurationPortForward.m */; };
 		CEA45E44263519B5002FA97D /* qapi-events.c in Sources */ = {isa = PBXBuildFile; fileRef = CE23C14023FCEC09001177D6 /* qapi-events.c */; };
@@ -797,7 +778,6 @@
 		CEA45E56263519B5002FA97D /* qapi-types-rdma.c in Sources */ = {isa = PBXBuildFile; fileRef = CE23C13023FCEC08001177D6 /* qapi-types-rdma.c */; };
 		CEA45E57263519B5002FA97D /* ImagePicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = CED814EE24C7EB760042F0F1 /* ImagePicker.swift */; };
 		CEA45E58263519B5002FA97D /* qapi-commands-rocker.c in Sources */ = {isa = PBXBuildFile; fileRef = CE23C08123FCEBFF001177D6 /* qapi-commands-rocker.c */; };
-		CEA45E59263519B5002FA97D /* gst_ios_init.m in Sources */ = {isa = PBXBuildFile; fileRef = CEFE75D9228933DE0050ABCC /* gst_ios_init.m */; };
 		CEA45E5A263519B5002FA97D /* VMConfigSystemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE2D955324AD4F980059923A /* VMConfigSystemView.swift */; };
 		CEA45E5B263519B5002FA97D /* VMShareFileModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE8813D424CD265700532628 /* VMShareFileModifier.swift */; };
 		CEA45E5C263519B5002FA97D /* cf-input-visitor.c in Sources */ = {isa = PBXBuildFile; fileRef = CECC764C2273A7D50059B955 /* cf-input-visitor.c */; };
@@ -811,7 +791,6 @@
 		CEA45E64263519B5002FA97D /* UTMLoggingSwift.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE020BAA24AEE00000B44AB6 /* UTMLoggingSwift.swift */; };
 		CEA45E65263519B5002FA97D /* UTMApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE2D955524AD4F980059923A /* UTMApp.swift */; };
 		CEA45E66263519B5002FA97D /* qapi-visit-acpi.c in Sources */ = {isa = PBXBuildFile; fileRef = 2CE8EB032572E166000E2EBB /* qapi-visit-acpi.c */; };
-		CEA45E67263519B5002FA97D /* CSMain.m in Sources */ = {isa = PBXBuildFile; fileRef = CE26FC24226EBC5A0090BE9B /* CSMain.m */; };
 		CEA45E68263519B5002FA97D /* UTMQemuConfiguration+Constants.m in Sources */ = {isa = PBXBuildFile; fileRef = CE5425362437DDE900E520F7 /* UTMQemuConfiguration+Constants.m */; };
 		CEA45E69263519B5002FA97D /* VMConfigQEMUView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE2D953924AD4F980059923A /* VMConfigQEMUView.swift */; };
 		CEA45E6A263519B5002FA97D /* VMDisplayMetalViewController+Touch.m in Sources */ = {isa = PBXBuildFile; fileRef = CE056CA5242454100004B68A /* VMDisplayMetalViewController+Touch.m */; };
@@ -850,7 +829,6 @@
 		CEA45E8B263519B5002FA97D /* UTMQcow2.c in Sources */ = {isa = PBXBuildFile; fileRef = 2C6D9E132571AFE5003298E6 /* UTMQcow2.c */; };
 		CEA45E8C263519B5002FA97D /* qapi-types-block-export.c in Sources */ = {isa = PBXBuildFile; fileRef = 2CE8EAFC2572E14C000E2EBB /* qapi-types-block-export.c */; };
 		CEA45E8D263519B5002FA97D /* qapi-events-qdev.c in Sources */ = {isa = PBXBuildFile; fileRef = CE23C09E23FCEC00001177D6 /* qapi-events-qdev.c */; };
-		CEA45E8E263519B5002FA97D /* CSSession+Sharing.m in Sources */ = {isa = PBXBuildFile; fileRef = CEBE02632588494100B9BCA8 /* CSSession+Sharing.m */; };
 		CEA45E8F263519B5002FA97D /* VMContextMenuModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C33B3A82566C9B100A954A6 /* VMContextMenuModifier.swift */; };
 		CEA45E90263519B5002FA97D /* VMListViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = CE550BD0225947990063E575 /* VMListViewController.m */; };
 		CEA45E91263519B5002FA97D /* VMDisplayMetalViewController+Pencil.m in Sources */ = {isa = PBXBuildFile; fileRef = CE5076DA250AB55D00C26C19 /* VMDisplayMetalViewController+Pencil.m */; };
@@ -895,7 +873,6 @@
 		CEA45EB8263519B5002FA97D /* qapi-visit.c in Sources */ = {isa = PBXBuildFile; fileRef = CE23C13523FCEC08001177D6 /* qapi-visit.c */; };
 		CEA45EB9263519B5002FA97D /* VMCursor.m in Sources */ = {isa = PBXBuildFile; fileRef = CE3ADD692411C661002D6A5F /* VMCursor.m */; };
 		CEA45EBA263519B5002FA97D /* VMConfigDriveDetailsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE9375A024BBDDD10074066F /* VMConfigDriveDetailsView.swift */; };
-		CEA45EBB263519B5002FA97D /* CSDisplayMetal.m in Sources */ = {isa = PBXBuildFile; fileRef = CE4AA1482263B24F002E4A54 /* CSDisplayMetal.m */; };
 		CEA45EBC263519B5002FA97D /* qapi-events-tpm.c in Sources */ = {isa = PBXBuildFile; fileRef = CE23C13923FCEC08001177D6 /* qapi-events-tpm.c */; };
 		CEA45EBD263519B5002FA97D /* UTMQemuSystem.m in Sources */ = {isa = PBXBuildFile; fileRef = CE03D05024D90B4E00F76B84 /* UTMQemuSystem.m */; };
 		CEA45EBE263519B5002FA97D /* NumberTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = CED234EC254796E500ED0A57 /* NumberTextField.swift */; };
@@ -906,7 +883,6 @@
 		CEA45EC3263519B5002FA97D /* VMCommands.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE772AB225C8B7B500E4E379 /* VMCommands.swift */; };
 		CEA45EC4263519B5002FA97D /* qapi-visit-job.c in Sources */ = {isa = PBXBuildFile; fileRef = CE23C09523FCEC00001177D6 /* qapi-visit-job.c */; };
 		CEA45EC5263519B5002FA97D /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = CE550BCD225947990063E575 /* AppDelegate.m */; };
-		CEA45EC6263519B5002FA97D /* CSInput.m in Sources */ = {isa = PBXBuildFile; fileRef = CE664510226935F000B0849A /* CSInput.m */; };
 		CEA45EC7263519B5002FA97D /* qapi-types-block.c in Sources */ = {isa = PBXBuildFile; fileRef = CE23C08723FCEBFF001177D6 /* qapi-types-block.c */; };
 		CEA45EC8263519B5002FA97D /* qapi-events-machine.c in Sources */ = {isa = PBXBuildFile; fileRef = CE23C0B923FCEC02001177D6 /* qapi-events-machine.c */; };
 		CEA45EC9263519B5002FA97D /* VMConfigDriveCreateViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = CE2C67DA227F769300AEF1D0 /* VMConfigDriveCreateViewController.m */; };
@@ -928,7 +904,6 @@
 		CEA45ED9263519B5002FA97D /* qapi-commands-introspect.c in Sources */ = {isa = PBXBuildFile; fileRef = CE23C10523FCEC05001177D6 /* qapi-commands-introspect.c */; };
 		CEA45EDA263519B5002FA97D /* qapi-types-sockets.c in Sources */ = {isa = PBXBuildFile; fileRef = CE23C10E23FCEC06001177D6 /* qapi-types-sockets.c */; };
 		CEA45EDB263519B5002FA97D /* VMDisplayTerminalViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = E28394C0240C268A006742E2 /* VMDisplayTerminalViewController.m */; };
-		CEA45EDC263519B5002FA97D /* UTMScreenshot.m in Sources */ = {isa = PBXBuildFile; fileRef = CE0B6D8424AD5ADE00FE012D /* UTMScreenshot.m */; };
 		CEA45EDD263519B5002FA97D /* qapi-events-block-core.c in Sources */ = {isa = PBXBuildFile; fileRef = CE23C0EF23FCEC04001177D6 /* qapi-events-block-core.c */; };
 		CEA45EDF263519B5002FA97D /* UTMJailbreak.m in Sources */ = {isa = PBXBuildFile; fileRef = CEB63A7924F469E300CAF323 /* UTMJailbreak.m */; };
 		CEA45EE0263519B5002FA97D /* UTMQemuManager.m in Sources */ = {isa = PBXBuildFile; fileRef = CE36B280227668D1004A1435 /* UTMQemuManager.m */; };
@@ -979,7 +954,6 @@
 		CEA45F0E263519B5002FA97D /* qapi-commands-run-state.c in Sources */ = {isa = PBXBuildFile; fileRef = CE23C07E23FCEBFF001177D6 /* qapi-commands-run-state.c */; };
 		CEA45F0F263519B5002FA97D /* qapi-types-misc-target.c in Sources */ = {isa = PBXBuildFile; fileRef = CE23C16023FCEC0A001177D6 /* qapi-types-misc-target.c */; };
 		CEA45F10263519B5002FA97D /* qapi-events-rdma.c in Sources */ = {isa = PBXBuildFile; fileRef = CE23C12923FCEC07001177D6 /* qapi-events-rdma.c */; };
-		CEA45F11263519B5002FA97D /* UTMShaders.metal in Sources */ = {isa = PBXBuildFile; fileRef = CE2D63D02265154700FC7E63 /* UTMShaders.metal */; };
 		CEA45F12263519B5002FA97D /* qapi-visit-dump.c in Sources */ = {isa = PBXBuildFile; fileRef = CE23C0B323FCEC01001177D6 /* qapi-visit-dump.c */; };
 		CEA45F13263519B5002FA97D /* qapi-visit-error.c in Sources */ = {isa = PBXBuildFile; fileRef = CE23C15D23FCEC0A001177D6 /* qapi-visit-error.c */; };
 		CEA45F14263519B5002FA97D /* error.c in Sources */ = {isa = PBXBuildFile; fileRef = CE36B1542275061B004A1435 /* error.c */; };
@@ -992,10 +966,8 @@
 		CEA45F1B263519B5002FA97D /* UTMTerminal.m in Sources */ = {isa = PBXBuildFile; fileRef = E28394B3240C20E0006742E2 /* UTMTerminal.m */; };
 		CEA45F1D263519B5002FA97D /* VMConfigSwitch.m in Sources */ = {isa = PBXBuildFile; fileRef = CEBCAF5324353B3700C2B423 /* VMConfigSwitch.m */; };
 		CEA45F1E263519B5002FA97D /* qapi-types-char.c in Sources */ = {isa = PBXBuildFile; fileRef = CE23C12023FCEC07001177D6 /* qapi-types-char.c */; };
-		CEA45F1F263519B5002FA97D /* CSConnection.m in Sources */ = {isa = PBXBuildFile; fileRef = CE4AA14B2264004F002E4A54 /* CSConnection.m */; };
 		CEA45F20263519B5002FA97D /* qapi-visit-audio.c in Sources */ = {isa = PBXBuildFile; fileRef = CE23C0BE23FCEC02001177D6 /* qapi-visit-audio.c */; };
 		CEA45F21263519B5002FA97D /* qapi-builtin-visit.c in Sources */ = {isa = PBXBuildFile; fileRef = CE23C09623FCEC00001177D6 /* qapi-builtin-visit.c */; };
-		CEA45F22263519B5002FA97D /* UTMRenderer.m in Sources */ = {isa = PBXBuildFile; fileRef = CE2D63CF2265154700FC7E63 /* UTMRenderer.m */; };
 		CEA45F24263519B5002FA97D /* libgstautodetect.a in Frameworks */ = {isa = PBXBuildFile; fileRef = CE9D19522265425900355E14 /* libgstautodetect.a */; };
 		CEA45F25263519B5002FA97D /* libgstaudiotestsrc.a in Frameworks */ = {isa = PBXBuildFile; fileRef = CE9D19532265425900355E14 /* libgstaudiotestsrc.a */; };
 		CEA45F26263519B5002FA97D /* libgstvideoconvert.a in Frameworks */ = {isa = PBXBuildFile; fileRef = CE9D19542265425900355E14 /* libgstvideoconvert.a */; };
@@ -1163,8 +1135,6 @@
 		CEBDA1DF24D8BDDB0010B5EC /* QEMUHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = CEBDA1DE24D8BDDB0010B5EC /* QEMUHelper.m */; };
 		CEBDA1E124D8BDDB0010B5EC /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = CEBDA1E024D8BDDB0010B5EC /* main.m */; };
 		CEBDA1E524D8BDDB0010B5EC /* QEMUHelper.xpc in Embed XPC Services */ = {isa = PBXBuildFile; fileRef = CEBDA1DA24D8BDDA0010B5EC /* QEMUHelper.xpc */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
-		CEBE02642588494100B9BCA8 /* CSSession+Sharing.m in Sources */ = {isa = PBXBuildFile; fileRef = CEBE02632588494100B9BCA8 /* CSSession+Sharing.m */; };
-		CEBE02652588494100B9BCA8 /* CSSession+Sharing.m in Sources */ = {isa = PBXBuildFile; fileRef = CEBE02632588494100B9BCA8 /* CSSession+Sharing.m */; };
 		CEBE820326A4C1B5007AAB12 /* VMWizardDrivesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEBE820226A4C1B5007AAB12 /* VMWizardDrivesView.swift */; };
 		CEBE820426A4C1B5007AAB12 /* VMWizardDrivesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEBE820226A4C1B5007AAB12 /* VMWizardDrivesView.swift */; };
 		CEBE820526A4C1B5007AAB12 /* VMWizardDrivesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEBE820226A4C1B5007AAB12 /* VMWizardDrivesView.swift */; };
@@ -1181,7 +1151,6 @@
 		CED814EC24C7C2850042F0F1 /* VMConfigInfoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CED814EB24C7C2850042F0F1 /* VMConfigInfoView.swift */; };
 		CED814ED24C7C2850042F0F1 /* VMConfigInfoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CED814EB24C7C2850042F0F1 /* VMConfigInfoView.swift */; };
 		CED814EF24C7EB760042F0F1 /* ImagePicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = CED814EE24C7EB760042F0F1 /* ImagePicker.swift */; };
-		CEDF83F6258ADE130030E4AC /* CSSession.m in Sources */ = {isa = PBXBuildFile; fileRef = CE5425392439334400E520F7 /* CSSession.m */; };
 		CEDF83F9258AE24E0030E4AC /* UTMPasteboard.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEDF83F8258AE24E0030E4AC /* UTMPasteboard.swift */; };
 		CEDF83FA258AE24E0030E4AC /* UTMPasteboard.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEDF83F8258AE24E0030E4AC /* UTMPasteboard.swift */; };
 		CEEC811B24E48EC700ACB0B3 /* SettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEEC811A24E48EC600ACB0B3 /* SettingsView.swift */; };
@@ -1627,8 +1596,6 @@
 		CE059DC7243E9E3400338317 /* UTMLocationManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = UTMLocationManager.m; sourceTree = "<group>"; };
 		CE059DC9243FBA3C00338317 /* VMConfigCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = VMConfigCell.h; sourceTree = "<group>"; };
 		CE059DCA243FBA3C00338317 /* VMConfigCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = VMConfigCell.m; sourceTree = "<group>"; };
-		CE0B6D8324AD5ADE00FE012D /* UTMScreenshot.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = UTMScreenshot.h; sourceTree = "<group>"; };
-		CE0B6D8424AD5ADE00FE012D /* UTMScreenshot.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = UTMScreenshot.m; sourceTree = "<group>"; };
 		CE0DF17025A80B6300A51894 /* Bootstrap.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Bootstrap.h; sourceTree = "<group>"; };
 		CE0DF17125A80B6300A51894 /* Bootstrap.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = Bootstrap.c; sourceTree = "<group>"; };
 		CE0E828D24E4D4CE003EA9FE /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Base; path = Base.lproj/Localizable.strings; sourceTree = "<group>"; };
@@ -1871,19 +1838,12 @@
 		CE23C15F23FCEC0A001177D6 /* qapi-types-transaction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "qapi-types-transaction.h"; path = "$(SYSROOT_DIR)/qapi/qapi-types-transaction.h"; sourceTree = SOURCE_ROOT; };
 		CE23C16023FCEC0A001177D6 /* qapi-types-misc-target.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "qapi-types-misc-target.c"; path = "$(SYSROOT_DIR)/qapi/qapi-types-misc-target.c"; sourceTree = SOURCE_ROOT; };
 		CE258ACC22715F8300E5A333 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
-		CE26FC23226EBC5A0090BE9B /* CSMain.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CSMain.h; sourceTree = "<group>"; };
-		CE26FC24226EBC5A0090BE9B /* CSMain.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CSMain.m; sourceTree = "<group>"; };
 		CE2B89332262A21E00C6D9D8 /* UTMVirtualMachine.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = UTMVirtualMachine.h; sourceTree = "<group>"; };
 		CE2B89352262B2F600C6D9D8 /* UTMVirtualMachineDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = UTMVirtualMachineDelegate.h; sourceTree = "<group>"; };
 		CE2C67D6227F6F1200AEF1D0 /* VMConfigDrivePickerViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = VMConfigDrivePickerViewController.h; sourceTree = "<group>"; };
 		CE2C67D7227F6F1200AEF1D0 /* VMConfigDrivePickerViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = VMConfigDrivePickerViewController.m; sourceTree = "<group>"; };
 		CE2C67D9227F769300AEF1D0 /* VMConfigDriveCreateViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = VMConfigDriveCreateViewController.h; sourceTree = "<group>"; };
 		CE2C67DA227F769300AEF1D0 /* VMConfigDriveCreateViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = VMConfigDriveCreateViewController.m; sourceTree = "<group>"; };
-		CE2D63CF2265154700FC7E63 /* UTMRenderer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UTMRenderer.m; sourceTree = "<group>"; };
-		CE2D63D02265154700FC7E63 /* UTMShaders.metal */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.metal; path = UTMShaders.metal; sourceTree = "<group>"; };
-		CE2D63D12265154700FC7E63 /* UTMShaderTypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UTMShaderTypes.h; sourceTree = "<group>"; };
-		CE2D63D22265154700FC7E63 /* UTMRenderer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UTMRenderer.h; sourceTree = "<group>"; };
-		CE2D63D5226517D600FC7E63 /* UTMRenderSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UTMRenderSource.h; sourceTree = "<group>"; };
 		CE2D63D722653C7300FC7E63 /* qemu-i386-softmmu.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = "qemu-i386-softmmu.framework"; path = "$(SYSROOT_DIR)/Frameworks/qemu-i386-softmmu.framework"; sourceTree = "<group>"; };
 		CE2D63D822653C7300FC7E63 /* gmodule-2.0.0.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = "gmodule-2.0.0.framework"; path = "$(SYSROOT_DIR)/Frameworks/gmodule-2.0.0.framework"; sourceTree = "<group>"; };
 		CE2D63D922653C7300FC7E63 /* jpeg.62.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = jpeg.62.framework; path = "$(SYSROOT_DIR)/Frameworks/jpeg.62.framework"; sourceTree = "<group>"; };
@@ -2004,11 +1964,6 @@
 		CE4507D1226A5BE200A28D22 /* VMKeyboardView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = VMKeyboardView.m; sourceTree = "<group>"; };
 		CE4507D3226A5C9900A28D22 /* VMKeyboardViewDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = VMKeyboardViewDelegate.h; sourceTree = "<group>"; };
 		CE4698F824C8FBD9008C1BD6 /* Icons */ = {isa = PBXFileReference; lastKnownFileType = folder; path = Icons; sourceTree = "<group>"; };
-		CE4AA1472263B24F002E4A54 /* CSDisplayMetal.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CSDisplayMetal.h; sourceTree = "<group>"; };
-		CE4AA1482263B24F002E4A54 /* CSDisplayMetal.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CSDisplayMetal.m; sourceTree = "<group>"; };
-		CE4AA14A2264004F002E4A54 /* CSConnection.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CSConnection.h; sourceTree = "<group>"; };
-		CE4AA14B2264004F002E4A54 /* CSConnection.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CSConnection.m; sourceTree = "<group>"; };
-		CE4AA14D22642EB4002E4A54 /* CSConnectionDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CSConnectionDelegate.h; sourceTree = "<group>"; };
 		CE4EF26F2506DBFD00E9D33B /* VMRemovableDrivesViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VMRemovableDrivesViewController.swift; sourceTree = "<group>"; };
 		CE4EF2712506DD7900E9D33B /* VMRemovableDrivesView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = VMRemovableDrivesView.xib; sourceTree = "<group>"; };
 		CE5076D9250AB55D00C26C19 /* VMDisplayMetalViewController+Pencil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "VMDisplayMetalViewController+Pencil.h"; sourceTree = "<group>"; };
@@ -2022,8 +1977,6 @@
 		CE5425332437C22A00E520F7 /* UTMQemuConfiguration+System.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "UTMQemuConfiguration+System.m"; sourceTree = "<group>"; };
 		CE5425352437DDE900E520F7 /* UTMQemuConfiguration+Constants.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "UTMQemuConfiguration+Constants.h"; sourceTree = "<group>"; };
 		CE5425362437DDE900E520F7 /* UTMQemuConfiguration+Constants.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "UTMQemuConfiguration+Constants.m"; sourceTree = "<group>"; };
-		CE5425382439334400E520F7 /* CSSession.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CSSession.h; sourceTree = "<group>"; };
-		CE5425392439334400E520F7 /* CSSession.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CSSession.m; sourceTree = "<group>"; };
 		CE5451A126AF5F0F008594E5 /* virglrenderer.1.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = virglrenderer.1.framework; path = "$(SYSROOT_DIR)/Frameworks/virglrenderer.1.framework"; sourceTree = "<group>"; };
 		CE5451A226AF5F0F008594E5 /* epoxy.0.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = epoxy.0.framework; path = "$(SYSROOT_DIR)/Frameworks/epoxy.0.framework"; sourceTree = "<group>"; };
 		CE5451A326AF5F0F008594E5 /* GLESv2.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GLESv2.framework; path = "$(SYSROOT_DIR)/Frameworks/GLESv2.framework"; sourceTree = "<group>"; };
@@ -2042,9 +1995,6 @@
 		CE5F165B2261395000F3D56B /* UTMVirtualMachine.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = UTMVirtualMachine.m; sourceTree = "<group>"; };
 		CE612AC524D3B50700FA6300 /* VMDisplayWindowController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VMDisplayWindowController.swift; sourceTree = "<group>"; };
 		CE66450C2269313200B0849A /* MetalKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MetalKit.framework; path = System/Library/Frameworks/MetalKit.framework; sourceTree = SDKROOT; };
-		CE66450E2269355F00B0849A /* CocoaSpice.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CocoaSpice.h; sourceTree = "<group>"; };
-		CE66450F226935F000B0849A /* CSInput.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CSInput.h; sourceTree = "<group>"; };
-		CE664510226935F000B0849A /* CSInput.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CSInput.m; sourceTree = "<group>"; };
 		CE6B240A25F1F3CE0020D43E /* main.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = main.c; sourceTree = "<group>"; };
 		CE6B240F25F1F43A0020D43E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
 		CE6B241025F1F4B30020D43E /* QEMULauncher.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = QEMULauncher.entitlements; sourceTree = "<group>"; };
@@ -2080,11 +2030,6 @@
 		CE8813D424CD265700532628 /* VMShareFileModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VMShareFileModifier.swift; sourceTree = "<group>"; };
 		CE8813D924D1290600532628 /* UTMQemuConfiguration+ConstantsGenerated.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UTMQemuConfiguration+ConstantsGenerated.m"; sourceTree = "<group>"; };
 		CE8E6620227E5DF2003B9903 /* UTMQemuManagerDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = UTMQemuManagerDelegate.h; sourceTree = "<group>"; };
-		CE900B9C25FC2869007533FD /* CSUSBManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CSUSBManager.h; sourceTree = "<group>"; };
-		CE900B9D25FC2869007533FD /* CSUSBManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CSUSBManager.m; sourceTree = "<group>"; };
-		CE900BA225FC31E4007533FD /* CSUSBManagerDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CSUSBManagerDelegate.h; sourceTree = "<group>"; };
-		CE900BAD25FC3E65007533FD /* CSUSBDevice.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CSUSBDevice.h; sourceTree = "<group>"; };
-		CE900BAE25FC3E65007533FD /* CSUSBDevice.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CSUSBDevice.m; sourceTree = "<group>"; };
 		CE928C2926ABE6690099F293 /* UTMAppleVirtualMachine.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UTMAppleVirtualMachine.swift; sourceTree = "<group>"; };
 		CE928C3026ACCDEA0099F293 /* VMAppleRemovableDrivesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VMAppleRemovableDrivesView.swift; sourceTree = "<group>"; };
 		CE93759524BB7E9F0074066F /* UTMTabViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UTMTabViewController.swift; sourceTree = "<group>"; };
@@ -2148,8 +2093,6 @@
 		CEBDA1DE24D8BDDB0010B5EC /* QEMUHelper.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = QEMUHelper.m; sourceTree = "<group>"; };
 		CEBDA1E024D8BDDB0010B5EC /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
 		CEBDA1E224D8BDDB0010B5EC /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
-		CEBE02622588494100B9BCA8 /* CSSession+Sharing.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "CSSession+Sharing.h"; sourceTree = "<group>"; };
-		CEBE02632588494100B9BCA8 /* CSSession+Sharing.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "CSSession+Sharing.m"; sourceTree = "<group>"; };
 		CEBE820226A4C1B5007AAB12 /* VMWizardDrivesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VMWizardDrivesView.swift; sourceTree = "<group>"; };
 		CEBE820626A4C74E007AAB12 /* VMWizardSharingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VMWizardSharingView.swift; sourceTree = "<group>"; };
 		CEBE820A26A4C8E0007AAB12 /* VMWizardSummaryView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VMWizardSummaryView.swift; sourceTree = "<group>"; };
@@ -2208,8 +2151,6 @@
 		CEF83ED124FDEA9400557D15 /* UTMPortAllocator.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = UTMPortAllocator.h; sourceTree = "<group>"; };
 		CEF83ED224FDEA9400557D15 /* UTMPortAllocator.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = UTMPortAllocator.m; sourceTree = "<group>"; };
 		CEFC6CDC24C25697003F6962 /* VMDriveImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VMDriveImage.swift; sourceTree = "<group>"; };
-		CEFE75D9228933DE0050ABCC /* gst_ios_init.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = gst_ios_init.m; sourceTree = "<group>"; };
-		CEFE75DA228933DE0050ABCC /* gst_ios_init.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = gst_ios_init.h; sourceTree = "<group>"; };
 		E2151A57241451120008E6AC /* UIViewController+Extensions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "UIViewController+Extensions.h"; sourceTree = "<group>"; };
 		E2151A58241451120008E6AC /* UIViewController+Extensions.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "UIViewController+Extensions.m"; sourceTree = "<group>"; };
 		E28394B3240C20E0006742E2 /* UTMTerminal.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UTMTerminal.m; sourceTree = "<group>"; };
@@ -2309,6 +2250,7 @@
 				CE2D936224AD46670059923A /* gstcheck-1.0.0.framework in Frameworks */,
 				CE2D936324AD46670059923A /* iconv.2.framework in Frameworks */,
 				CE2D936424AD46670059923A /* gstsdp-1.0.0.framework in Frameworks */,
+				84B36D1E27B3264600C22685 /* CocoaSpice in Frameworks */,
 				CE2D936524AD46670059923A /* ssl.1.1.framework in Frameworks */,
 				CE2D936624AD46670059923A /* spice-server.1.framework in Frameworks */,
 				CE2D936724AD46670059923A /* pixman-1.0.framework in Frameworks */,
@@ -2340,6 +2282,7 @@
 				CE0B6EEC24AD677200FE012D /* libgstautodetect.a in Frameworks */,
 				CE03D0C424D913AA00F76B84 /* ffi.7.framework in Frameworks */,
 				CE03D0CC24D9144100F76B84 /* crypto.1.1.framework in Frameworks */,
+				84B36D2227B3265400C22685 /* CocoaSpice in Frameworks */,
 				CE0B6ED724AD677200FE012D /* gstaudio-1.0.0.framework in Frameworks */,
 				CE0B6EFA24AD677200FE012D /* gstapp-1.0.0.framework in Frameworks */,
 				CE03D0CE24D9A30100F76B84 /* iconv.2.framework in Frameworks */,
@@ -2443,6 +2386,7 @@
 				CEA45F52263519B5002FA97D /* spice-client-glib-2.0.8.framework in Frameworks */,
 				CEA45F53263519B5002FA97D /* gstrtsp-1.0.0.framework in Frameworks */,
 				CEA45F54263519B5002FA97D /* opus.0.framework in Frameworks */,
+				84B36D2027B3264E00C22685 /* CocoaSpiceNoUsb in Frameworks */,
 				CEA45F55263519B5002FA97D /* glib-2.0.0.framework in Frameworks */,
 				CEA45F56263519B5002FA97D /* png16.16.framework in Frameworks */,
 				CEA45F57263519B5002FA97D /* gstfft-1.0.0.framework in Frameworks */,
@@ -2484,18 +2428,6 @@
 			path = Display;
 			sourceTree = "<group>";
 		};
-		CE2D63CE2265150F00FC7E63 /* Renderer */ = {
-			isa = PBXGroup;
-			children = (
-				CE2D63D22265154700FC7E63 /* UTMRenderer.h */,
-				CE2D63CF2265154700FC7E63 /* UTMRenderer.m */,
-				CE2D63D5226517D600FC7E63 /* UTMRenderSource.h */,
-				CE2D63D02265154700FC7E63 /* UTMShaders.metal */,
-				CE2D63D12265154700FC7E63 /* UTMShaderTypes.h */,
-			);
-			path = Renderer;
-			sourceTree = "<group>";
-		};
 		CE2D63D622653C7300FC7E63 /* Frameworks */ = {
 			isa = PBXGroup;
 			children = (
@@ -2959,44 +2891,15 @@
 			name = Generated;
 			sourceTree = "<group>";
 		};
-		CE4AA1462262FB58002E4A54 /* CocoaSpice */ = {
-			isa = PBXGroup;
-			children = (
-				CE66450E2269355F00B0849A /* CocoaSpice.h */,
-				CE4AA14A2264004F002E4A54 /* CSConnection.h */,
-				CE4AA14B2264004F002E4A54 /* CSConnection.m */,
-				CE4AA14D22642EB4002E4A54 /* CSConnectionDelegate.h */,
-				CE4AA1472263B24F002E4A54 /* CSDisplayMetal.h */,
-				CE4AA1482263B24F002E4A54 /* CSDisplayMetal.m */,
-				CE66450F226935F000B0849A /* CSInput.h */,
-				CE664510226935F000B0849A /* CSInput.m */,
-				CE26FC23226EBC5A0090BE9B /* CSMain.h */,
-				CE26FC24226EBC5A0090BE9B /* CSMain.m */,
-				CE5425382439334400E520F7 /* CSSession.h */,
-				CE5425392439334400E520F7 /* CSSession.m */,
-				CEBE02622588494100B9BCA8 /* CSSession+Sharing.h */,
-				CEBE02632588494100B9BCA8 /* CSSession+Sharing.m */,
-				CE900BAD25FC3E65007533FD /* CSUSBDevice.h */,
-				CE900BAE25FC3E65007533FD /* CSUSBDevice.m */,
-				CE900B9C25FC2869007533FD /* CSUSBManager.h */,
-				CE900B9D25FC2869007533FD /* CSUSBManager.m */,
-				CE900BA225FC31E4007533FD /* CSUSBManagerDelegate.h */,
-			);
-			path = CocoaSpice;
-			sourceTree = "<group>";
-		};
 		CE550BC0225947990063E575 = {
 			isa = PBXGroup;
 			children = (
 				CE50A41F2637BB200050430F /* Build.xcconfig */,
 				CE258ACC22715F8300E5A333 /* README.md */,
-				CE4AA1462262FB58002E4A54 /* CocoaSpice */,
 				CE31C242225E543A00A965DD /* Configuration */,
-				CEFE75D8228933870050ABCC /* gstreamer */,
 				CE5F1659226138AB00F3D56B /* Managers */,
 				CE2D953624AD4F980059923A /* Platform */,
 				CECC76492273A7AE0059B955 /* qapi */,
-				CE2D63CE2265150F00FC7E63 /* Renderer */,
 				CEBDA1DB24D8BDDA0010B5EC /* QEMUHelper */,
 				CE9D18F72265410E00355E14 /* qemu */,
 				CE6B240925F1F3CE0020D43E /* QEMULauncher */,
@@ -3120,8 +3023,6 @@
 				E2D64BCB241DB62A0034E0C6 /* UTMTerminalIO.m */,
 				CE059DC6243E9E3400338317 /* UTMLocationManager.h */,
 				CE059DC7243E9E3400338317 /* UTMLocationManager.m */,
-				CE0B6D8324AD5ADE00FE012D /* UTMScreenshot.h */,
-				CE0B6D8424AD5ADE00FE012D /* UTMScreenshot.m */,
 				CE020BB524B14F8400B44AB6 /* UTMVirtualMachineExtension.swift */,
 				835AA7B026AB7C85007A0411 /* UTMPendingVirtualMachine.swift */,
 			);
@@ -3324,15 +3225,6 @@
 			path = StaticDataTableViewController;
 			sourceTree = "<group>";
 		};
-		CEFE75D8228933870050ABCC /* gstreamer */ = {
-			isa = PBXGroup;
-			children = (
-				CEFE75DA228933DE0050ABCC /* gst_ios_init.h */,
-				CEFE75D9228933DE0050ABCC /* gst_ios_init.m */,
-			);
-			path = gstreamer;
-			sourceTree = "<group>";
-		};
 		E28394B7240C2191006742E2 /* HTerm */ = {
 			isa = PBXGroup;
 			children = (
@@ -3394,6 +3286,7 @@
 				CE93759824BB821F0074066F /* IQKeyboardManagerSwift */,
 				83993291272F68550059355F /* ZIPFoundation */,
 				B329049B270FE136002707AC /* AltKit */,
+				84B36D1D27B3264600C22685 /* CocoaSpice */,
 			);
 			productName = UTM;
 			productReference = CE2D93BE24AD46670059923A /* UTM.app */;
@@ -3420,6 +3313,7 @@
 				CE020BA824AEDF3000B44AB6 /* Logging */,
 				8399328F272F4A400059355F /* ZIPFoundation */,
 				848F71E5277A2466006A0240 /* SwiftTerm */,
+				84B36D2127B3265400C22685 /* CocoaSpice */,
 			);
 			productName = UTM;
 			productReference = CE2D951C24AD48BE0059923A /* UTM.app */;
@@ -3462,6 +3356,7 @@
 				CEA45E20263519B5002FA97D /* Logging */,
 				CEA45E22263519B5002FA97D /* IQKeyboardManagerSwift */,
 				83993293272F685F0059355F /* ZIPFoundation */,
+				84B36D1F27B3264E00C22685 /* CocoaSpiceNoUsb */,
 			);
 			productName = UTM;
 			productReference = CEA45FB9263519B5002FA97D /* UTM SE.app */;
@@ -3532,6 +3427,7 @@
 				8399328E272F4A400059355F /* XCRemoteSwiftPackageReference "ZIPFoundation" */,
 				B329049A270FE136002707AC /* XCRemoteSwiftPackageReference "AltKit" */,
 				848F71E4277A2466006A0240 /* XCRemoteSwiftPackageReference "SwiftTerm" */,
+				84B36D1C27B3261E00C22685 /* XCRemoteSwiftPackageReference "CocoaSpice" */,
 			);
 			productRefGroup = CE550BCA225947990063E575 /* Products */;
 			projectDirPath = "";
@@ -3719,7 +3615,6 @@
 				CE2D927424AD46670059923A /* WKWebView+Workarounds.m in Sources */,
 				CE2D927524AD46670059923A /* qapi-visit-crypto.c in Sources */,
 				CE2D927624AD46670059923A /* qapi-visit-tpm.c in Sources */,
-				CE900B9E25FC2869007533FD /* CSUSBManager.m in Sources */,
 				2CE8EB41257811E8000E2EBB /* UTMQemuConfiguration+Defaults.m in Sources */,
 				CE2D927724AD46670059923A /* qapi-visit-trace.c in Sources */,
 				CE2D927824AD46670059923A /* qapi-events-rocker.c in Sources */,
@@ -3733,7 +3628,6 @@
 				CEF83ED324FDEA9400557D15 /* UTMPortAllocator.m in Sources */,
 				CE2D927C24AD46670059923A /* UTMQemu.m in Sources */,
 				CE2D927D24AD46670059923A /* qapi-visit-machine.c in Sources */,
-				CE2D927E24AD46670059923A /* CSSession.m in Sources */,
 				CEBE820326A4C1B5007AAB12 /* VMWizardDrivesView.swift in Sources */,
 				CE2D927F24AD46670059923A /* qapi-commands-machine-target.c in Sources */,
 				CE2D928024AD46670059923A /* UTMQemuConfigurationPortForward.m in Sources */,
@@ -3761,7 +3655,6 @@
 				CE2D929124AD46670059923A /* qapi-types-rdma.c in Sources */,
 				CED814EF24C7EB760042F0F1 /* ImagePicker.swift in Sources */,
 				CE2D929224AD46670059923A /* qapi-commands-rocker.c in Sources */,
-				CE2D929324AD46670059923A /* gst_ios_init.m in Sources */,
 				CE2D958924AD4F990059923A /* VMConfigSystemView.swift in Sources */,
 				CE8813D524CD265700532628 /* VMShareFileModifier.swift in Sources */,
 				CEF0305126A2AFBF00667B63 /* BigWhiteSpinner.swift in Sources */,
@@ -3780,7 +3673,6 @@
 				CE2D958D24AD4F990059923A /* UTMApp.swift in Sources */,
 				2CE8EB042572E166000E2EBB /* qapi-visit-acpi.c in Sources */,
 				8469CACF277D345700BA5601 /* qapi-visit-compat.c in Sources */,
-				CE2D929E24AD46670059923A /* CSMain.m in Sources */,
 				CE2D929F24AD46670059923A /* UTMQemuConfiguration+Constants.m in Sources */,
 				CE2D955B24AD4F980059923A /* VMConfigQEMUView.swift in Sources */,
 				CE2D92A024AD46670059923A /* VMDisplayMetalViewController+Touch.m in Sources */,
@@ -3825,7 +3717,6 @@
 				2CE8EAFE2572E14D000E2EBB /* qapi-types-block-export.c in Sources */,
 				4B224B9D279D4D8100B63CFF /* InListButtonStyle.swift in Sources */,
 				CE2D92B924AD46670059923A /* qapi-events-qdev.c in Sources */,
-				CEBE02642588494100B9BCA8 /* CSSession+Sharing.m in Sources */,
 				2C33B3A92566C9B100A954A6 /* VMContextMenuModifier.swift in Sources */,
 				CEB63A9424F4747900CAF323 /* VMListViewController.m in Sources */,
 				CE5076DB250AB55D00C26C19 /* VMDisplayMetalViewController+Pencil.m in Sources */,
@@ -3876,7 +3767,6 @@
 				CE2D92D924AD46670059923A /* qapi-visit.c in Sources */,
 				CE2D92DA24AD46670059923A /* VMCursor.m in Sources */,
 				CE9375A124BBDDD10074066F /* VMConfigDriveDetailsView.swift in Sources */,
-				CE2D92DB24AD46670059923A /* CSDisplayMetal.m in Sources */,
 				CE2D92DD24AD46670059923A /* qapi-events-tpm.c in Sources */,
 				CE03D05224D90B4E00F76B84 /* UTMQemuSystem.m in Sources */,
 				8469CACA277D301300BA5601 /* qapi-types-compat.c in Sources */,
@@ -3888,7 +3778,6 @@
 				CE772AB325C8B7B500E4E379 /* VMCommands.swift in Sources */,
 				CE2D92E024AD46670059923A /* qapi-visit-job.c in Sources */,
 				CE2D92E124AD46670059923A /* AppDelegate.m in Sources */,
-				CE2D92E224AD46670059923A /* CSInput.m in Sources */,
 				CE2D92E424AD46670059923A /* qapi-types-block.c in Sources */,
 				CE2D92E524AD46670059923A /* qapi-events-machine.c in Sources */,
 				CEB63A8C24F46E6E00CAF323 /* VMConfigDriveCreateViewController.m in Sources */,
@@ -3912,10 +3801,8 @@
 				CE2D92F324AD46670059923A /* qapi-commands-introspect.c in Sources */,
 				CE2D92F424AD46670059923A /* qapi-types-sockets.c in Sources */,
 				CE2D92F524AD46670059923A /* VMDisplayTerminalViewController.m in Sources */,
-				CE0B6D8624AD5ADE00FE012D /* UTMScreenshot.m in Sources */,
 				CE2D92F624AD46670059923A /* qapi-events-block-core.c in Sources */,
 				84FCABBA268CE05E0036196C /* UTMQemuVirtualMachine.m in Sources */,
-				CE900BAF25FC3E65007533FD /* CSUSBDevice.m in Sources */,
 				CEB63A7A24F469E300CAF323 /* UTMJailbreak.m in Sources */,
 				CE2D92F724AD46670059923A /* UTMQemuManager.m in Sources */,
 				CEB63A8024F46E5700CAF323 /* VMConfigPickerView.m in Sources */,
@@ -3970,7 +3857,6 @@
 				CE2D931924AD46670059923A /* qapi-types-misc-target.c in Sources */,
 				84C60FBD268289EF00B58C00 /* VMDisplayViewController.m in Sources */,
 				CE2D931A24AD46670059923A /* qapi-events-rdma.c in Sources */,
-				CE2D931B24AD46670059923A /* UTMShaders.metal in Sources */,
 				844EC0FD2773EED5003C104A /* UTMDownloadable.swift in Sources */,
 				CE2D931D24AD46670059923A /* qapi-visit-dump.c in Sources */,
 				CE2D931E24AD46670059923A /* qapi-visit-error.c in Sources */,
@@ -3985,10 +3871,8 @@
 				CEA905C92603DA0D00801E7C /* VMDisplayMetalViewController+USB.m in Sources */,
 				CEB63A7D24F46E5700CAF323 /* VMConfigSwitch.m in Sources */,
 				CE2D932524AD46670059923A /* qapi-types-char.c in Sources */,
-				CE2D932724AD46670059923A /* CSConnection.m in Sources */,
 				CE2D932824AD46670059923A /* qapi-visit-audio.c in Sources */,
 				CE2D932924AD46670059923A /* qapi-builtin-visit.c in Sources */,
-				CE2D932A24AD46670059923A /* UTMRenderer.m in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -3999,7 +3883,6 @@
 				CEB63A7724F4654400CAF323 /* Main.swift in Sources */,
 				CE0B6D0024AD56AE00FE012D /* UTMVirtualMachine.m in Sources */,
 				CEB63A7B24F469E300CAF323 /* UTMJailbreak.m in Sources */,
-				CE0B6D0E24AD56E500FE012D /* UTMShaders.metal in Sources */,
 				83A004BB26A8CC95001AC09E /* UTMImportFromWebTask.swift in Sources */,
 				CE0B6D3924AD57FD00FE012D /* qapi-commands-job.c in Sources */,
 				CE0B6D3724AD57FD00FE012D /* qapi-events-block-core.c in Sources */,
@@ -4033,9 +3916,6 @@
 				8469CACC277D301300BA5601 /* qapi-types-compat.c in Sources */,
 				CE0B6D4D24AD584C00FE012D /* qapi-types-block.c in Sources */,
 				CE03D0D224DCF4B600F76B84 /* VMMetalView.swift in Sources */,
-				CE0B6CF124AD567300FE012D /* CSMain.m in Sources */,
-				CE0B6CEE24AD566A00FE012D /* CSConnection.m in Sources */,
-				CEDF83F6258ADE130030E4AC /* CSSession.m in Sources */,
 				CE0B6D8024AD584D00FE012D /* qapi-events-sockets.c in Sources */,
 				8401FDB0269E1F7F00265F0D /* VMConfigAppleDriveCreateView.swift in Sources */,
 				CE0B6D6224AD584D00FE012D /* qapi-types-misc-target.c in Sources */,
@@ -4044,7 +3924,6 @@
 				CE0B6D2324AD57FC00FE012D /* qapi-commands-crypto.c in Sources */,
 				CEF0305326A2AFBF00667B63 /* BigWhiteSpinner.swift in Sources */,
 				CE0B6CFA24AD568400FE012D /* UTMQemuConfiguration+System.m in Sources */,
-				CE900BB025FC3E65007533FD /* CSUSBDevice.m in Sources */,
 				CEBBF1A824B921F000C15049 /* VMDetailsView.swift in Sources */,
 				CE0B6D7E24AD584D00FE012D /* qapi-events-misc.c in Sources */,
 				CE0B6D4124AD584C00FE012D /* qapi-visit-transaction.c in Sources */,
@@ -4057,7 +3936,6 @@
 				CE0B6D7C24AD584D00FE012D /* qapi-visit-char.c in Sources */,
 				844EC0FF2773EED5003C104A /* UTMDownloadable.swift in Sources */,
 				CEF83ECD24FB382B00557D15 /* UTMQemuVirtualMachine+Terminal.m in Sources */,
-				CE0B6CF024AD567100FE012D /* CSInput.m in Sources */,
 				CE9375A224BBDDD10074066F /* VMConfigDriveDetailsView.swift in Sources */,
 				CE2D955824AD4F980059923A /* VMConfigDisplayView.swift in Sources */,
 				CEF83EC324F9C9E100557D15 /* UTMDrive.m in Sources */,
@@ -4083,7 +3961,6 @@
 				CE0B6D4F24AD584C00FE012D /* qapi-visit-qdev.c in Sources */,
 				CE0B6D4024AD584C00FE012D /* qapi-types-rocker.c in Sources */,
 				CE928C3126ACCDEA0099F293 /* VMAppleRemovableDrivesView.swift in Sources */,
-				CE0B6CEF24AD566D00FE012D /* CSDisplayMetal.m in Sources */,
 				CE0B6D6724AD584D00FE012D /* qapi-types-ui.c in Sources */,
 				83C15C5F26CC441500ADFD45 /* KeyCodeMap.swift in Sources */,
 				CE0B6D6824AD584D00FE012D /* qapi-visit-machine.c in Sources */,
@@ -4117,7 +3994,6 @@
 				CE0B6D3D24AD584C00FE012D /* qapi-visit-block-core.c in Sources */,
 				CE0B6D5C24AD584D00FE012D /* qapi-events-net.c in Sources */,
 				8401FDA8269D4A4100265F0D /* VMConfigAppleSharingView.swift in Sources */,
-				CE900B9F25FC2869007533FD /* CSUSBManager.m in Sources */,
 				CE0B6D0324AD56AE00FE012D /* UTMTerminal.m in Sources */,
 				CE0B6CFC24AD568400FE012D /* UTMQemuConfigurationPortForward.m in Sources */,
 				8469CAD1277D345700BA5601 /* qapi-visit-compat.c in Sources */,
@@ -4135,7 +4011,6 @@
 				CEF83ED424FDEA9400557D15 /* UTMPortAllocator.m in Sources */,
 				CE0B6D7D24AD584D00FE012D /* qapi-events-ui.c in Sources */,
 				8401FDA0269D266E00265F0D /* VMConfigAppleBootView.swift in Sources */,
-				CEBE02652588494100B9BCA8 /* CSSession+Sharing.m in Sources */,
 				CE0B6D5624AD584C00FE012D /* qapi-types-machine-target.c in Sources */,
 				CE93759624BB7EA00074066F /* UTMTabViewController.swift in Sources */,
 				CE0B6D0424AD56AE00FE012D /* UTMSpiceIO.m in Sources */,
@@ -4179,13 +4054,11 @@
 				CE0B6D1C24AD57FC00FE012D /* qapi-commands-char.c in Sources */,
 				CE0B6D6424AD584D00FE012D /* qapi-visit-error.c in Sources */,
 				CE0B6D5A24AD584C00FE012D /* qapi-events-trace.c in Sources */,
-				CE0B6CFD24AD569A00FE012D /* gst_ios_init.m in Sources */,
 				4B224B9F279D4D8100B63CFF /* InListButtonStyle.swift in Sources */,
 				CEF83EBB24F9ABEA00557D15 /* UTMQemuManager+BlockDevices.m in Sources */,
 				CEECE13C25E47D9500A2AAB8 /* AppDelegate.swift in Sources */,
 				CE0B6CF724AD568400FE012D /* UTMQemuConfiguration+Display.m in Sources */,
 				CE0B6D6F24AD584D00FE012D /* qapi-events-transaction.c in Sources */,
-				CE0B6D0F24AD56E500FE012D /* UTMRenderer.m in Sources */,
 				CE0B6D2524AD57FC00FE012D /* qapi-commands-sockets.c in Sources */,
 				CE0B6D1624AD57FC00FE012D /* qapi-commands-block.c in Sources */,
 				CE0B6D4724AD584C00FE012D /* qapi-visit-net.c in Sources */,
@@ -4221,7 +4094,6 @@
 				CE0B6D8224AD584D00FE012D /* qapi-types-block-core.c in Sources */,
 				2CE8EAFF2572E14D000E2EBB /* qapi-types-block-export.c in Sources */,
 				8453DCB6278CE5410037A0DA /* UTMQemuImage.swift in Sources */,
-				CE0B6D8724AD5ADE00FE012D /* UTMScreenshot.m in Sources */,
 				CEDF83FA258AE24E0030E4AC /* UTMPasteboard.swift in Sources */,
 				848F71EE277A2F47006A0240 /* UTMSerialPortDelegate.swift in Sources */,
 				CE0B6D1124AD57C700FE012D /* qapi-builtin-visit.c in Sources */,
@@ -4302,7 +4174,6 @@
 				CEA45E3E263519B5002FA97D /* UTMPortAllocator.m in Sources */,
 				CEA45E3F263519B5002FA97D /* UTMQemu.m in Sources */,
 				CEA45E40263519B5002FA97D /* qapi-visit-machine.c in Sources */,
-				CEA45E41263519B5002FA97D /* CSSession.m in Sources */,
 				CEA45E42263519B5002FA97D /* qapi-commands-machine-target.c in Sources */,
 				CEA45E43263519B5002FA97D /* UTMQemuConfigurationPortForward.m in Sources */,
 				CEA45E44263519B5002FA97D /* qapi-events.c in Sources */,
@@ -4326,7 +4197,6 @@
 				CEA45E56263519B5002FA97D /* qapi-types-rdma.c in Sources */,
 				CEA45E57263519B5002FA97D /* ImagePicker.swift in Sources */,
 				CEA45E58263519B5002FA97D /* qapi-commands-rocker.c in Sources */,
-				CEA45E59263519B5002FA97D /* gst_ios_init.m in Sources */,
 				CEA45E5A263519B5002FA97D /* VMConfigSystemView.swift in Sources */,
 				CEA45E5B263519B5002FA97D /* VMShareFileModifier.swift in Sources */,
 				CEA45E5C263519B5002FA97D /* cf-input-visitor.c in Sources */,
@@ -4340,7 +4210,6 @@
 				CEA45E64263519B5002FA97D /* UTMLoggingSwift.swift in Sources */,
 				CEA45E65263519B5002FA97D /* UTMApp.swift in Sources */,
 				CEA45E66263519B5002FA97D /* qapi-visit-acpi.c in Sources */,
-				CEA45E67263519B5002FA97D /* CSMain.m in Sources */,
 				CEF0305F26A2AFDF00667B63 /* VMWizardState.swift in Sources */,
 				CEA45E68263519B5002FA97D /* UTMQemuConfiguration+Constants.m in Sources */,
 				CEA45E69263519B5002FA97D /* VMConfigQEMUView.swift in Sources */,
@@ -4384,7 +4253,6 @@
 				CEA45E8B263519B5002FA97D /* UTMQcow2.c in Sources */,
 				CEA45E8C263519B5002FA97D /* qapi-types-block-export.c in Sources */,
 				CEA45E8D263519B5002FA97D /* qapi-events-qdev.c in Sources */,
-				CEA45E8E263519B5002FA97D /* CSSession+Sharing.m in Sources */,
 				CEA45E8F263519B5002FA97D /* VMContextMenuModifier.swift in Sources */,
 				CEA45E90263519B5002FA97D /* VMListViewController.m in Sources */,
 				CEA45E91263519B5002FA97D /* VMDisplayMetalViewController+Pencil.m in Sources */,
@@ -4431,7 +4299,6 @@
 				CEA45EB8263519B5002FA97D /* qapi-visit.c in Sources */,
 				CEA45EB9263519B5002FA97D /* VMCursor.m in Sources */,
 				CEA45EBA263519B5002FA97D /* VMConfigDriveDetailsView.swift in Sources */,
-				CEA45EBB263519B5002FA97D /* CSDisplayMetal.m in Sources */,
 				CEF0305226A2AFBF00667B63 /* BigWhiteSpinner.swift in Sources */,
 				CEA45EBC263519B5002FA97D /* qapi-events-tpm.c in Sources */,
 				CEA45EBD263519B5002FA97D /* UTMQemuSystem.m in Sources */,
@@ -4445,7 +4312,6 @@
 				CEA45EC3263519B5002FA97D /* VMCommands.swift in Sources */,
 				CEA45EC4263519B5002FA97D /* qapi-visit-job.c in Sources */,
 				CEA45EC5263519B5002FA97D /* AppDelegate.m in Sources */,
-				CEA45EC6263519B5002FA97D /* CSInput.m in Sources */,
 				CEA45EC7263519B5002FA97D /* qapi-types-block.c in Sources */,
 				CEA45EC8263519B5002FA97D /* qapi-events-machine.c in Sources */,
 				CEA45EC9263519B5002FA97D /* VMConfigDriveCreateViewController.m in Sources */,
@@ -4472,7 +4338,6 @@
 				CEA45ED9263519B5002FA97D /* qapi-commands-introspect.c in Sources */,
 				CEA45EDA263519B5002FA97D /* qapi-types-sockets.c in Sources */,
 				CEA45EDB263519B5002FA97D /* VMDisplayTerminalViewController.m in Sources */,
-				CEA45EDC263519B5002FA97D /* UTMScreenshot.m in Sources */,
 				CEF0307526A2B40B00667B63 /* VMWizardHardwareView.swift in Sources */,
 				CEA45EDD263519B5002FA97D /* qapi-events-block-core.c in Sources */,
 				83F02322278A4EDE00B157AE /* UTMPendingVMDetailsView.swift in Sources */,
@@ -4532,7 +4397,6 @@
 				CEA45F0E263519B5002FA97D /* qapi-commands-run-state.c in Sources */,
 				CEA45F0F263519B5002FA97D /* qapi-types-misc-target.c in Sources */,
 				CEA45F10263519B5002FA97D /* qapi-events-rdma.c in Sources */,
-				CEA45F11263519B5002FA97D /* UTMShaders.metal in Sources */,
 				CEA45F12263519B5002FA97D /* qapi-visit-dump.c in Sources */,
 				CEA45F13263519B5002FA97D /* qapi-visit-error.c in Sources */,
 				CEA45F14263519B5002FA97D /* error.c in Sources */,
@@ -4545,10 +4409,8 @@
 				CEA45F1B263519B5002FA97D /* UTMTerminal.m in Sources */,
 				CEA45F1D263519B5002FA97D /* VMConfigSwitch.m in Sources */,
 				CEA45F1E263519B5002FA97D /* qapi-types-char.c in Sources */,
-				CEA45F1F263519B5002FA97D /* CSConnection.m in Sources */,
 				CEA45F20263519B5002FA97D /* qapi-visit-audio.c in Sources */,
 				CEA45F21263519B5002FA97D /* qapi-builtin-visit.c in Sources */,
-				CEA45F22263519B5002FA97D /* UTMRenderer.m in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -5227,6 +5089,14 @@
 				minimumVersion = 1.0.0;
 			};
 		};
+		84B36D1C27B3261E00C22685 /* XCRemoteSwiftPackageReference "CocoaSpice" */ = {
+			isa = XCRemoteSwiftPackageReference;
+			repositoryURL = "https://github.com/utmapp/CocoaSpice.git";
+			requirement = {
+				branch = main;
+				kind = branch;
+			};
+		};
 		B329049A270FE136002707AC /* XCRemoteSwiftPackageReference "AltKit" */ = {
 			isa = XCRemoteSwiftPackageReference;
 			repositoryURL = "https://github.com/rileytestut/AltKit.git";
@@ -5290,6 +5160,21 @@
 			package = 848F71E4277A2466006A0240 /* XCRemoteSwiftPackageReference "SwiftTerm" */;
 			productName = SwiftTerm;
 		};
+		84B36D1D27B3264600C22685 /* CocoaSpice */ = {
+			isa = XCSwiftPackageProductDependency;
+			package = 84B36D1C27B3261E00C22685 /* XCRemoteSwiftPackageReference "CocoaSpice" */;
+			productName = CocoaSpice;
+		};
+		84B36D1F27B3264E00C22685 /* CocoaSpiceNoUsb */ = {
+			isa = XCSwiftPackageProductDependency;
+			package = 84B36D1C27B3261E00C22685 /* XCRemoteSwiftPackageReference "CocoaSpice" */;
+			productName = CocoaSpiceNoUsb;
+		};
+		84B36D2127B3265400C22685 /* CocoaSpice */ = {
+			isa = XCSwiftPackageProductDependency;
+			package = 84B36D1C27B3261E00C22685 /* XCRemoteSwiftPackageReference "CocoaSpice" */;
+			productName = CocoaSpice;
+		};
 		B329049B270FE136002707AC /* AltKit */ = {
 			isa = XCSwiftPackageProductDependency;
 			package = B329049A270FE136002707AC /* XCRemoteSwiftPackageReference "AltKit" */;

+ 9 - 0
UTM.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved

@@ -10,6 +10,15 @@
           "version": "0.0.2"
         }
       },
+      {
+        "package": "CocoaSpice",
+        "repositoryURL": "https://github.com/utmapp/CocoaSpice.git",
+        "state": {
+          "branch": "main",
+          "revision": "ece15eb5ac2458136b1a1bb11b1364a30f378b7d",
+          "version": null
+        }
+      },
       {
         "package": "IQKeyboardManagerSwift",
         "repositoryURL": "https://github.com/hackiftekhar/IQKeyboardManager.git",

+ 0 - 39
gstreamer/gst_ios_init.h

@@ -1,39 +0,0 @@
-#ifndef __GST_IOS_INIT_H__
-#define __GST_IOS_INIT_H__
-
-#include <gst/gst.h>
-
-G_BEGIN_DECLS
-
-#define GST_G_IO_MODULE_DECLARE(name) \
-extern void G_PASTE(g_io_module_, G_PASTE(name, _load_static)) (void)
-
-#define GST_G_IO_MODULE_LOAD(name) \
-G_PASTE(g_io_module_, G_PASTE(name, _load_static)) ()
-
-/* Uncomment each line to enable the plugin categories that your application needs.
- * You can also enable individual plugins. See gst_ios_init.c to see their names
- */
-
-#define GST_IOS_PLUGINS_CORE
-#define GST_IOS_PLUGINS_CAPTURE
-//#define GST_IOS_PLUGINS_CODECS_RESTRICTED
-//#define GST_IOS_PLUGINS_ENCODING
-//#define GST_IOS_PLUGINS_CODECS_GPL
-//#define GST_IOS_PLUGINS_NET_RESTRICTED
-#define GST_IOS_PLUGINS_SYS
-//#define GST_IOS_PLUGINS_VIS
-#define GST_IOS_PLUGINS_PLAYBACK
-//#define GST_IOS_PLUGINS_EFFECTS
-//#define GST_IOS_PLUGINS_CODECS
-//#define GST_IOS_PLUGINS_NET
-//#define GST_IOS_PLUGINS_EDITING
-#define GST_IOS_PLUGIN_JPEG
-
-//#define GST_IOS_GIO_MODULE_GNUTLS
-
-void gst_ios_init (void);
-
-G_END_DECLS
-
-#endif

+ 0 - 990
gstreamer/gst_ios_init.m

@@ -1,990 +0,0 @@
-#include "gst_ios_init.h"
-#include <Foundation/Foundation.h>
-@import AudioToolbox;
-
-#if defined(GST_IOS_PLUGIN_COREELEMENTS) || defined(GST_IOS_PLUGINS_CORE)
-GST_PLUGIN_STATIC_DECLARE(coreelements);
-#endif
-#if defined(GST_IOS_PLUGIN_ADDER) || defined(GST_IOS_PLUGINS_CORE)
-GST_PLUGIN_STATIC_DECLARE(adder);
-#endif
-#if defined(GST_IOS_PLUGIN_APP) || defined(GST_IOS_PLUGINS_CORE)
-GST_PLUGIN_STATIC_DECLARE(app);
-#endif
-#if defined(GST_IOS_PLUGIN_AUDIOCONVERT) || defined(GST_IOS_PLUGINS_CORE)
-GST_PLUGIN_STATIC_DECLARE(audioconvert);
-#endif
-#if defined(GST_IOS_PLUGIN_AUDIORATE) || defined(GST_IOS_PLUGINS_CORE)
-GST_PLUGIN_STATIC_DECLARE(audiorate);
-#endif
-#if defined(GST_IOS_PLUGIN_AUDIORESAMPLE) || defined(GST_IOS_PLUGINS_CORE)
-GST_PLUGIN_STATIC_DECLARE(audioresample);
-#endif
-#if defined(GST_IOS_PLUGIN_AUDIOTESTSRC) || defined(GST_IOS_PLUGINS_CORE)
-GST_PLUGIN_STATIC_DECLARE(audiotestsrc);
-#endif
-#if defined(GST_IOS_PLUGIN_GIO) || defined(GST_IOS_PLUGINS_CORE)
-GST_PLUGIN_STATIC_DECLARE(gio);
-#endif
-#if defined(GST_IOS_PLUGIN_PANGO) || defined(GST_IOS_PLUGINS_CORE)
-//GST_PLUGIN_STATIC_DECLARE(pango);
-#endif
-#if defined(GST_IOS_PLUGIN_TYPEFINDFUNCTIONS) || defined(GST_IOS_PLUGINS_CORE)
-GST_PLUGIN_STATIC_DECLARE(typefindfunctions);
-#endif
-#if defined(GST_IOS_PLUGIN_VIDEOCONVERT) || defined(GST_IOS_PLUGINS_CORE)
-GST_PLUGIN_STATIC_DECLARE(videoconvert);
-#endif
-#if defined(GST_IOS_PLUGIN_VIDEORATE) || defined(GST_IOS_PLUGINS_CORE)
-GST_PLUGIN_STATIC_DECLARE(videorate);
-#endif
-#if defined(GST_IOS_PLUGIN_VIDEOSCALE) || defined(GST_IOS_PLUGINS_CORE)
-GST_PLUGIN_STATIC_DECLARE(videoscale);
-#endif
-#if defined(GST_IOS_PLUGIN_VIDEOTESTSRC) || defined(GST_IOS_PLUGINS_CORE)
-GST_PLUGIN_STATIC_DECLARE(videotestsrc);
-#endif
-#if defined(GST_IOS_PLUGIN_VOLUME) || defined(GST_IOS_PLUGINS_CORE)
-GST_PLUGIN_STATIC_DECLARE(volume);
-#endif
-#if defined(GST_IOS_PLUGIN_AUTODETECT) || defined(GST_IOS_PLUGINS_CORE)
-GST_PLUGIN_STATIC_DECLARE(autodetect);
-#endif
-#if defined(GST_IOS_PLUGIN_VIDEOFILTER) || defined(GST_IOS_PLUGINS_CORE)
-GST_PLUGIN_STATIC_DECLARE(videofilter);
-#endif
-#if defined(GST_IOS_PLUGIN_CAMERABIN) || defined(GST_IOS_PLUGINS_CAPTURE)
-//GST_PLUGIN_STATIC_DECLARE(camerabin);
-#endif
-#if defined(GST_IOS_PLUGIN_ASFMUX) || defined(GST_IOS_PLUGINS_CODECS_RESTRICTED)
-GST_PLUGIN_STATIC_DECLARE(asfmux);
-#endif
-#if defined(GST_IOS_PLUGIN_DTSDEC) || defined(GST_IOS_PLUGINS_CODECS_RESTRICTED)
-GST_PLUGIN_STATIC_DECLARE(dtsdec);
-#endif
-#if defined(GST_IOS_PLUGIN_FAAD) || defined(GST_IOS_PLUGINS_CODECS_RESTRICTED)
-GST_PLUGIN_STATIC_DECLARE(faad);
-#endif
-#if defined(GST_IOS_PLUGIN_MPEGPSDEMUX) || defined(GST_IOS_PLUGINS_CODECS_RESTRICTED)
-GST_PLUGIN_STATIC_DECLARE(mpegpsdemux);
-#endif
-#if defined(GST_IOS_PLUGIN_MPEGPSMUX) || defined(GST_IOS_PLUGINS_CODECS_RESTRICTED)
-GST_PLUGIN_STATIC_DECLARE(mpegpsmux);
-#endif
-#if defined(GST_IOS_PLUGIN_MPEGTSDEMUX) || defined(GST_IOS_PLUGINS_CODECS_RESTRICTED)
-GST_PLUGIN_STATIC_DECLARE(mpegtsdemux);
-#endif
-#if defined(GST_IOS_PLUGIN_MPEGTSMUX) || defined(GST_IOS_PLUGINS_CODECS_RESTRICTED)
-GST_PLUGIN_STATIC_DECLARE(mpegtsmux);
-#endif
-#if defined(GST_IOS_PLUGIN_VOAACENC) || defined(GST_IOS_PLUGINS_CODECS_RESTRICTED)
-GST_PLUGIN_STATIC_DECLARE(voaacenc);
-#endif
-#if defined(GST_IOS_PLUGIN_A52DEC) || defined(GST_IOS_PLUGINS_CODECS_RESTRICTED)
-GST_PLUGIN_STATIC_DECLARE(a52dec);
-#endif
-#if defined(GST_IOS_PLUGIN_AMRNB) || defined(GST_IOS_PLUGINS_CODECS_RESTRICTED)
-GST_PLUGIN_STATIC_DECLARE(amrnb);
-#endif
-#if defined(GST_IOS_PLUGIN_AMRWBDEC) || defined(GST_IOS_PLUGINS_CODECS_RESTRICTED)
-GST_PLUGIN_STATIC_DECLARE(amrwbdec);
-#endif
-#if defined(GST_IOS_PLUGIN_ASF) || defined(GST_IOS_PLUGINS_CODECS_RESTRICTED)
-GST_PLUGIN_STATIC_DECLARE(asf);
-#endif
-#if defined(GST_IOS_PLUGIN_DVDSUB) || defined(GST_IOS_PLUGINS_CODECS_RESTRICTED)
-GST_PLUGIN_STATIC_DECLARE(dvdsub);
-#endif
-#if defined(GST_IOS_PLUGIN_DVDLPCMDEC) || defined(GST_IOS_PLUGINS_CODECS_RESTRICTED)
-GST_PLUGIN_STATIC_DECLARE(dvdlpcmdec);
-#endif
-#if defined(GST_IOS_PLUGIN_MAD) || defined(GST_IOS_PLUGINS_CODECS_RESTRICTED)
-GST_PLUGIN_STATIC_DECLARE(mad);
-#endif
-#if defined(GST_IOS_PLUGIN_MPEG2DEC) || defined(GST_IOS_PLUGINS_CODECS_RESTRICTED)
-GST_PLUGIN_STATIC_DECLARE(mpeg2dec);
-#endif
-#if defined(GST_IOS_PLUGIN_XINGMUX) || defined(GST_IOS_PLUGINS_CODECS_RESTRICTED)
-GST_PLUGIN_STATIC_DECLARE(xingmux);
-#endif
-#if defined(GST_IOS_PLUGIN_REALMEDIA) || defined(GST_IOS_PLUGINS_CODECS_RESTRICTED)
-GST_PLUGIN_STATIC_DECLARE(realmedia);
-#endif
-#if defined(GST_IOS_PLUGIN_X264) || defined(GST_IOS_PLUGINS_CODECS_RESTRICTED)
-GST_PLUGIN_STATIC_DECLARE(x264);
-#endif
-#if defined(GST_IOS_PLUGIN_LIBAV) || defined(GST_IOS_PLUGINS_CODECS_RESTRICTED)
-GST_PLUGIN_STATIC_DECLARE(libav);
-#endif
-#if defined(GST_IOS_PLUGIN_ENCODING) || defined(GST_IOS_PLUGINS_ENCODING)
-GST_PLUGIN_STATIC_DECLARE(encoding);
-#endif
-#if defined(GST_IOS_PLUGIN_ASSRENDER) || defined(GST_IOS_PLUGINS_CODECS_GPL)
-GST_PLUGIN_STATIC_DECLARE(assrender);
-#endif
-#if defined(GST_IOS_PLUGIN_MMS) || defined(GST_IOS_PLUGINS_NET_RESTRICTED)
-GST_PLUGIN_STATIC_DECLARE(mms);
-#endif
-#if defined(GST_IOS_PLUGIN_RTMP) || defined(GST_IOS_PLUGINS_NET_RESTRICTED)
-GST_PLUGIN_STATIC_DECLARE(rtmp);
-#endif
-#if defined(GST_IOS_PLUGIN_OSXAUDIO) || defined(GST_IOS_PLUGINS_SYS)
-GST_PLUGIN_STATIC_DECLARE(osxaudio);
-#endif
-#if defined(GST_IOS_PLUGIN_APPLEMEDIA) || defined(GST_IOS_PLUGINS_SYS)
-//GST_PLUGIN_STATIC_DECLARE(applemedia);
-#endif
-#if defined(GST_IOS_PLUGIN_SHM) || defined(GST_IOS_PLUGINS_SYS)
-//GST_PLUGIN_STATIC_DECLARE(shm);
-#endif
-#if defined(GST_IOS_PLUGIN_OPENGL) || defined(GST_IOS_PLUGINS_SYS)
-//GST_PLUGIN_STATIC_DECLARE(opengl);
-#endif
-#if defined(GST_IOS_PLUGIN_LIBVISUAL) || defined(GST_IOS_PLUGINS_VIS)
-GST_PLUGIN_STATIC_DECLARE(libvisual);
-#endif
-#if defined(GST_IOS_PLUGIN_GOOM) || defined(GST_IOS_PLUGINS_VIS)
-GST_PLUGIN_STATIC_DECLARE(goom);
-#endif
-#if defined(GST_IOS_PLUGIN_GOOM2K1) || defined(GST_IOS_PLUGINS_VIS)
-GST_PLUGIN_STATIC_DECLARE(goom2k1);
-#endif
-#if defined(GST_IOS_PLUGIN_AUDIOVISUALIZERS) || defined(GST_IOS_PLUGINS_VIS)
-GST_PLUGIN_STATIC_DECLARE(audiovisualizers);
-#endif
-#if defined(GST_IOS_PLUGIN_PLAYBACK) || defined(GST_IOS_PLUGINS_PLAYBACK)
-GST_PLUGIN_STATIC_DECLARE(playback);
-#endif
-#if defined(GST_IOS_PLUGIN_ALPHA) || defined(GST_IOS_PLUGINS_EFFECTS)
-GST_PLUGIN_STATIC_DECLARE(alpha);
-#endif
-#if defined(GST_IOS_PLUGIN_ALPHACOLOR) || defined(GST_IOS_PLUGINS_EFFECTS)
-GST_PLUGIN_STATIC_DECLARE(alphacolor);
-#endif
-#if defined(GST_IOS_PLUGIN_AUDIOFX) || defined(GST_IOS_PLUGINS_EFFECTS)
-GST_PLUGIN_STATIC_DECLARE(audiofx);
-#endif
-#if defined(GST_IOS_PLUGIN_CAIRO) || defined(GST_IOS_PLUGINS_EFFECTS)
-GST_PLUGIN_STATIC_DECLARE(cairo);
-#endif
-#if defined(GST_IOS_PLUGIN_CUTTER) || defined(GST_IOS_PLUGINS_EFFECTS)
-GST_PLUGIN_STATIC_DECLARE(cutter);
-#endif
-#if defined(GST_IOS_PLUGIN_DEBUG) || defined(GST_IOS_PLUGINS_EFFECTS)
-GST_PLUGIN_STATIC_DECLARE(debug);
-#endif
-#if defined(GST_IOS_PLUGIN_DEINTERLACE) || defined(GST_IOS_PLUGINS_EFFECTS)
-GST_PLUGIN_STATIC_DECLARE(deinterlace);
-#endif
-#if defined(GST_IOS_PLUGIN_DTMF) || defined(GST_IOS_PLUGINS_EFFECTS)
-GST_PLUGIN_STATIC_DECLARE(dtmf);
-#endif
-#if defined(GST_IOS_PLUGIN_EFFECTV) || defined(GST_IOS_PLUGINS_EFFECTS)
-GST_PLUGIN_STATIC_DECLARE(effectv);
-#endif
-#if defined(GST_IOS_PLUGIN_EQUALIZER) || defined(GST_IOS_PLUGINS_EFFECTS)
-GST_PLUGIN_STATIC_DECLARE(equalizer);
-#endif
-#if defined(GST_IOS_PLUGIN_GDKPIXBUF) || defined(GST_IOS_PLUGINS_EFFECTS)
-GST_PLUGIN_STATIC_DECLARE(gdkpixbuf);
-#endif
-#if defined(GST_IOS_PLUGIN_IMAGEFREEZE) || defined(GST_IOS_PLUGINS_EFFECTS)
-GST_PLUGIN_STATIC_DECLARE(imagefreeze);
-#endif
-#if defined(GST_IOS_PLUGIN_INTERLEAVE) || defined(GST_IOS_PLUGINS_EFFECTS)
-GST_PLUGIN_STATIC_DECLARE(interleave);
-#endif
-#if defined(GST_IOS_PLUGIN_LEVEL) || defined(GST_IOS_PLUGINS_EFFECTS)
-GST_PLUGIN_STATIC_DECLARE(level);
-#endif
-#if defined(GST_IOS_PLUGIN_MULTIFILE) || defined(GST_IOS_PLUGINS_EFFECTS)
-GST_PLUGIN_STATIC_DECLARE(multifile);
-#endif
-#if defined(GST_IOS_PLUGIN_REPLAYGAIN) || defined(GST_IOS_PLUGINS_EFFECTS)
-GST_PLUGIN_STATIC_DECLARE(replaygain);
-#endif
-#if defined(GST_IOS_PLUGIN_SHAPEWIPE) || defined(GST_IOS_PLUGINS_EFFECTS)
-GST_PLUGIN_STATIC_DECLARE(shapewipe);
-#endif
-#if defined(GST_IOS_PLUGIN_SMPTE) || defined(GST_IOS_PLUGINS_EFFECTS)
-GST_PLUGIN_STATIC_DECLARE(smpte);
-#endif
-#if defined(GST_IOS_PLUGIN_SPECTRUM) || defined(GST_IOS_PLUGINS_EFFECTS)
-GST_PLUGIN_STATIC_DECLARE(spectrum);
-#endif
-#if defined(GST_IOS_PLUGIN_VIDEOBOX) || defined(GST_IOS_PLUGINS_EFFECTS)
-GST_PLUGIN_STATIC_DECLARE(videobox);
-#endif
-#if defined(GST_IOS_PLUGIN_VIDEOCROP) || defined(GST_IOS_PLUGINS_EFFECTS)
-GST_PLUGIN_STATIC_DECLARE(videocrop);
-#endif
-#if defined(GST_IOS_PLUGIN_VIDEOMIXER) || defined(GST_IOS_PLUGINS_EFFECTS)
-GST_PLUGIN_STATIC_DECLARE(videomixer);
-#endif
-#if defined(GST_IOS_PLUGIN_ACCURIP) || defined(GST_IOS_PLUGINS_EFFECTS)
-GST_PLUGIN_STATIC_DECLARE(accurip);
-#endif
-#if defined(GST_IOS_PLUGIN_AIFF) || defined(GST_IOS_PLUGINS_EFFECTS)
-GST_PLUGIN_STATIC_DECLARE(aiff);
-#endif
-#if defined(GST_IOS_PLUGIN_AUDIOFXBAD) || defined(GST_IOS_PLUGINS_EFFECTS)
-GST_PLUGIN_STATIC_DECLARE(audiofxbad);
-#endif
-#if defined(GST_IOS_PLUGIN_AUTOCONVERT) || defined(GST_IOS_PLUGINS_EFFECTS)
-GST_PLUGIN_STATIC_DECLARE(autoconvert);
-#endif
-#if defined(GST_IOS_PLUGIN_BAYER) || defined(GST_IOS_PLUGINS_EFFECTS)
-GST_PLUGIN_STATIC_DECLARE(bayer);
-#endif
-#if defined(GST_IOS_PLUGIN_COLOREFFECTS) || defined(GST_IOS_PLUGINS_EFFECTS)
-GST_PLUGIN_STATIC_DECLARE(coloreffects);
-#endif
-#if defined(GST_IOS_PLUGIN_DEBUGUTILSBAD) || defined(GST_IOS_PLUGINS_EFFECTS)
-GST_PLUGIN_STATIC_DECLARE(debugutilsbad);
-#endif
-#if defined(GST_IOS_PLUGIN_FIELDANALYSIS) || defined(GST_IOS_PLUGINS_EFFECTS)
-GST_PLUGIN_STATIC_DECLARE(fieldanalysis);
-#endif
-#if defined(GST_IOS_PLUGIN_FREEVERB) || defined(GST_IOS_PLUGINS_EFFECTS)
-GST_PLUGIN_STATIC_DECLARE(freeverb);
-#endif
-#if defined(GST_IOS_PLUGIN_FREI0R) || defined(GST_IOS_PLUGINS_EFFECTS)
-GST_PLUGIN_STATIC_DECLARE(frei0r);
-#endif
-#if defined(GST_IOS_PLUGIN_GAUDIEFFECTS) || defined(GST_IOS_PLUGINS_EFFECTS)
-GST_PLUGIN_STATIC_DECLARE(gaudieffects);
-#endif
-#if defined(GST_IOS_PLUGIN_GEOMETRICTRANSFORM) || defined(GST_IOS_PLUGINS_EFFECTS)
-GST_PLUGIN_STATIC_DECLARE(geometrictransform);
-#endif
-#if defined(GST_IOS_PLUGIN_INTERLACE) || defined(GST_IOS_PLUGINS_EFFECTS)
-GST_PLUGIN_STATIC_DECLARE(interlace);
-#endif
-#if defined(GST_IOS_PLUGIN_IVTC) || defined(GST_IOS_PLUGINS_EFFECTS)
-GST_PLUGIN_STATIC_DECLARE(ivtc);
-#endif
-#if defined(GST_IOS_PLUGIN_LIVEADDER) || defined(GST_IOS_PLUGINS_EFFECTS)
-GST_PLUGIN_STATIC_DECLARE(liveadder);
-#endif
-#if defined(GST_IOS_PLUGIN_RAWPARSE) || defined(GST_IOS_PLUGINS_EFFECTS)
-GST_PLUGIN_STATIC_DECLARE(rawparse);
-#endif
-#if defined(GST_IOS_PLUGIN_REMOVESILENCE) || defined(GST_IOS_PLUGINS_EFFECTS)
-GST_PLUGIN_STATIC_DECLARE(removesilence);
-#endif
-#if defined(GST_IOS_PLUGIN_SEGMENTCLIP) || defined(GST_IOS_PLUGINS_EFFECTS)
-GST_PLUGIN_STATIC_DECLARE(segmentclip);
-#endif
-#if defined(GST_IOS_PLUGIN_SMOOTH) || defined(GST_IOS_PLUGINS_EFFECTS)
-GST_PLUGIN_STATIC_DECLARE(smooth);
-#endif
-#if defined(GST_IOS_PLUGIN_SPEED) || defined(GST_IOS_PLUGINS_EFFECTS)
-GST_PLUGIN_STATIC_DECLARE(speed);
-#endif
-#if defined(GST_IOS_PLUGIN_VIDEOFILTERSBAD) || defined(GST_IOS_PLUGINS_EFFECTS)
-GST_PLUGIN_STATIC_DECLARE(videofiltersbad);
-#endif
-#if defined(GST_IOS_PLUGIN_SUBPARSE) || defined(GST_IOS_PLUGINS_CODECS)
-GST_PLUGIN_STATIC_DECLARE(subparse);
-#endif
-#if defined(GST_IOS_PLUGIN_OGG) || defined(GST_IOS_PLUGINS_CODECS)
-GST_PLUGIN_STATIC_DECLARE(ogg);
-#endif
-#if defined(GST_IOS_PLUGIN_THEORA) || defined(GST_IOS_PLUGINS_CODECS)
-GST_PLUGIN_STATIC_DECLARE(theora);
-#endif
-#if defined(GST_IOS_PLUGIN_VORBIS) || defined(GST_IOS_PLUGINS_CODECS)
-GST_PLUGIN_STATIC_DECLARE(vorbis);
-#endif
-#if defined(GST_IOS_PLUGIN_IVORBISDEC) || defined(GST_IOS_PLUGINS_CODECS)
-GST_PLUGIN_STATIC_DECLARE(ivorbisdec);
-#endif
-#if defined(GST_IOS_PLUGIN_ALAW) || defined(GST_IOS_PLUGINS_CODECS)
-GST_PLUGIN_STATIC_DECLARE(alaw);
-#endif
-#if defined(GST_IOS_PLUGIN_APETAG) || defined(GST_IOS_PLUGINS_CODECS)
-GST_PLUGIN_STATIC_DECLARE(apetag);
-#endif
-#if defined(GST_IOS_PLUGIN_AUDIOPARSERS) || defined(GST_IOS_PLUGINS_CODECS)
-GST_PLUGIN_STATIC_DECLARE(audioparsers);
-#endif
-#if defined(GST_IOS_PLUGIN_AUPARSE) || defined(GST_IOS_PLUGINS_CODECS)
-GST_PLUGIN_STATIC_DECLARE(auparse);
-#endif
-#if defined(GST_IOS_PLUGIN_AVI) || defined(GST_IOS_PLUGINS_CODECS)
-GST_PLUGIN_STATIC_DECLARE(avi);
-#endif
-#if defined(GST_IOS_PLUGIN_DV) || defined(GST_IOS_PLUGINS_CODECS)
-GST_PLUGIN_STATIC_DECLARE(dv);
-#endif
-#if defined(GST_IOS_PLUGIN_FLAC) || defined(GST_IOS_PLUGINS_CODECS)
-GST_PLUGIN_STATIC_DECLARE(flac);
-#endif
-#if defined(GST_IOS_PLUGIN_FLV) || defined(GST_IOS_PLUGINS_CODECS)
-GST_PLUGIN_STATIC_DECLARE(flv);
-#endif
-#if defined(GST_IOS_PLUGIN_FLXDEC) || defined(GST_IOS_PLUGINS_CODECS)
-GST_PLUGIN_STATIC_DECLARE(flxdec);
-#endif
-#if defined(GST_IOS_PLUGIN_ICYDEMUX) || defined(GST_IOS_PLUGINS_CODECS)
-GST_PLUGIN_STATIC_DECLARE(icydemux);
-#endif
-#if defined(GST_IOS_PLUGIN_ID3DEMUX) || defined(GST_IOS_PLUGINS_CODECS)
-GST_PLUGIN_STATIC_DECLARE(id3demux);
-#endif
-#if defined(GST_IOS_PLUGIN_ISOMP4) || defined(GST_IOS_PLUGINS_CODECS)
-GST_PLUGIN_STATIC_DECLARE(isomp4);
-#endif
-#if defined(GST_IOS_PLUGIN_JPEG) || defined(GST_IOS_PLUGINS_CODECS)
-GST_PLUGIN_STATIC_DECLARE(jpeg);
-#endif
-#if defined(GST_IOS_PLUGIN_MATROSKA) || defined(GST_IOS_PLUGINS_CODECS)
-GST_PLUGIN_STATIC_DECLARE(matroska);
-#endif
-#if defined(GST_IOS_PLUGIN_MULAW) || defined(GST_IOS_PLUGINS_CODECS)
-GST_PLUGIN_STATIC_DECLARE(mulaw);
-#endif
-#if defined(GST_IOS_PLUGIN_MULTIPART) || defined(GST_IOS_PLUGINS_CODECS)
-GST_PLUGIN_STATIC_DECLARE(multipart);
-#endif
-#if defined(GST_IOS_PLUGIN_PNG) || defined(GST_IOS_PLUGINS_CODECS)
-GST_PLUGIN_STATIC_DECLARE(png);
-#endif
-#if defined(GST_IOS_PLUGIN_SPEEX) || defined(GST_IOS_PLUGINS_CODECS)
-GST_PLUGIN_STATIC_DECLARE(speex);
-#endif
-#if defined(GST_IOS_PLUGIN_TAGLIB) || defined(GST_IOS_PLUGINS_CODECS)
-GST_PLUGIN_STATIC_DECLARE(taglib);
-#endif
-#if defined(GST_IOS_PLUGIN_VPX) || defined(GST_IOS_PLUGINS_CODECS)
-GST_PLUGIN_STATIC_DECLARE(vpx);
-#endif
-#if defined(GST_IOS_PLUGIN_WAVENC) || defined(GST_IOS_PLUGINS_CODECS)
-GST_PLUGIN_STATIC_DECLARE(wavenc);
-#endif
-#if defined(GST_IOS_PLUGIN_WAVPACK) || defined(GST_IOS_PLUGINS_CODECS)
-GST_PLUGIN_STATIC_DECLARE(wavpack);
-#endif
-#if defined(GST_IOS_PLUGIN_WAVPARSE) || defined(GST_IOS_PLUGINS_CODECS)
-GST_PLUGIN_STATIC_DECLARE(wavparse);
-#endif
-#if defined(GST_IOS_PLUGIN_Y4MENC) || defined(GST_IOS_PLUGINS_CODECS)
-GST_PLUGIN_STATIC_DECLARE(y4menc);
-#endif
-#if defined(GST_IOS_PLUGIN_ADPCMDEC) || defined(GST_IOS_PLUGINS_CODECS)
-GST_PLUGIN_STATIC_DECLARE(adpcmdec);
-#endif
-#if defined(GST_IOS_PLUGIN_ADPCMENC) || defined(GST_IOS_PLUGINS_CODECS)
-GST_PLUGIN_STATIC_DECLARE(adpcmenc);
-#endif
-#if defined(GST_IOS_PLUGIN_DASHDEMUX) || defined(GST_IOS_PLUGINS_CODECS)
-GST_PLUGIN_STATIC_DECLARE(dashdemux);
-#endif
-#if defined(GST_IOS_PLUGIN_DVBSUBOVERLAY) || defined(GST_IOS_PLUGINS_CODECS)
-GST_PLUGIN_STATIC_DECLARE(dvbsuboverlay);
-#endif
-#if defined(GST_IOS_PLUGIN_DVDSPU) || defined(GST_IOS_PLUGINS_CODECS)
-GST_PLUGIN_STATIC_DECLARE(dvdspu);
-#endif
-#if defined(GST_IOS_PLUGIN_FRAGMENTED) || defined(GST_IOS_PLUGINS_CODECS)
-GST_PLUGIN_STATIC_DECLARE(fragmented);
-#endif
-#if defined(GST_IOS_PLUGIN_ID3TAG) || defined(GST_IOS_PLUGINS_CODECS)
-GST_PLUGIN_STATIC_DECLARE(id3tag);
-#endif
-#if defined(GST_IOS_PLUGIN_KATE) || defined(GST_IOS_PLUGINS_CODECS)
-GST_PLUGIN_STATIC_DECLARE(kate);
-#endif
-#if defined(GST_IOS_PLUGIN_MIDI) || defined(GST_IOS_PLUGINS_CODECS)
-GST_PLUGIN_STATIC_DECLARE(midi);
-#endif
-#if defined(GST_IOS_PLUGIN_MXF) || defined(GST_IOS_PLUGINS_CODECS)
-GST_PLUGIN_STATIC_DECLARE(mxf);
-#endif
-#if defined(GST_IOS_PLUGIN_OPUS) || defined(GST_IOS_PLUGINS_CODECS)
-GST_PLUGIN_STATIC_DECLARE(opus);
-#endif
-#if defined(GST_IOS_PLUGIN_PCAPPARSE) || defined(GST_IOS_PLUGINS_CODECS)
-GST_PLUGIN_STATIC_DECLARE(pcapparse);
-#endif
-#if defined(GST_IOS_PLUGIN_PNM) || defined(GST_IOS_PLUGINS_CODECS)
-GST_PLUGIN_STATIC_DECLARE(pnm);
-#endif
-#if defined(GST_IOS_PLUGIN_RFBSRC) || defined(GST_IOS_PLUGINS_CODECS)
-GST_PLUGIN_STATIC_DECLARE(rfbsrc);
-#endif
-#if defined(GST_IOS_PLUGIN_SCHRO) || defined(GST_IOS_PLUGINS_CODECS)
-GST_PLUGIN_STATIC_DECLARE(schro);
-#endif
-#if defined(GST_IOS_PLUGIN_GSTSIREN) || defined(GST_IOS_PLUGINS_CODECS)
-GST_PLUGIN_STATIC_DECLARE(gstsiren);
-#endif
-#if defined(GST_IOS_PLUGIN_SMOOTHSTREAMING) || defined(GST_IOS_PLUGINS_CODECS)
-GST_PLUGIN_STATIC_DECLARE(smoothstreaming);
-#endif
-#if defined(GST_IOS_PLUGIN_SUBENC) || defined(GST_IOS_PLUGINS_CODECS)
-GST_PLUGIN_STATIC_DECLARE(subenc);
-#endif
-#if defined(GST_IOS_PLUGIN_VIDEOPARSERSBAD) || defined(GST_IOS_PLUGINS_CODECS)
-GST_PLUGIN_STATIC_DECLARE(videoparsersbad);
-#endif
-#if defined(GST_IOS_PLUGIN_Y4MDEC) || defined(GST_IOS_PLUGINS_CODECS)
-GST_PLUGIN_STATIC_DECLARE(y4mdec);
-#endif
-#if defined(GST_IOS_PLUGIN_JPEGFORMAT) || defined(GST_IOS_PLUGINS_CODECS)
-GST_PLUGIN_STATIC_DECLARE(jpegformat);
-#endif
-#if defined(GST_IOS_PLUGIN_GDP) || defined(GST_IOS_PLUGINS_CODECS)
-GST_PLUGIN_STATIC_DECLARE(gdp);
-#endif
-#if defined(GST_IOS_PLUGIN_RSVG) || defined(GST_IOS_PLUGINS_CODECS)
-GST_PLUGIN_STATIC_DECLARE(rsvg);
-#endif
-#if defined(GST_IOS_PLUGIN_TCP) || defined(GST_IOS_PLUGINS_NET)
-GST_PLUGIN_STATIC_DECLARE(tcp);
-#endif
-#if defined(GST_IOS_PLUGIN_RTSP) || defined(GST_IOS_PLUGINS_NET)
-GST_PLUGIN_STATIC_DECLARE(rtsp);
-#endif
-#if defined(GST_IOS_PLUGIN_RTP) || defined(GST_IOS_PLUGINS_NET)
-GST_PLUGIN_STATIC_DECLARE(rtp);
-#endif
-#if defined(GST_IOS_PLUGIN_RTPMANAGER) || defined(GST_IOS_PLUGINS_NET)
-GST_PLUGIN_STATIC_DECLARE(rtpmanager);
-#endif
-#if defined(GST_IOS_PLUGIN_SOUP) || defined(GST_IOS_PLUGINS_NET)
-GST_PLUGIN_STATIC_DECLARE(soup);
-#endif
-#if defined(GST_IOS_PLUGIN_UDP) || defined(GST_IOS_PLUGINS_NET)
-GST_PLUGIN_STATIC_DECLARE(udp);
-#endif
-#if defined(GST_IOS_PLUGIN_DATAURISRC) || defined(GST_IOS_PLUGINS_NET)
-GST_PLUGIN_STATIC_DECLARE(dataurisrc);
-#endif
-#if defined(GST_IOS_PLUGIN_SDP) || defined(GST_IOS_PLUGINS_NET)
-GST_PLUGIN_STATIC_DECLARE(sdp);
-#endif
-#if defined(GST_IOS_PLUGIN_GNONLIN) || defined(GST_IOS_PLUGINS_EDITING)
-GST_PLUGIN_STATIC_DECLARE(gnonlin);
-#endif
-
-#if defined(GST_IOS_GIO_MODULE_GNUTLS)
-#include <gio/gio.h>
-GST_G_IO_MODULE_DECLARE(gnutls);
-#endif
-
-void
-gst_ios_init (void)
-{
-    GstPluginFeature *plugin;
-    GstRegistry *reg;
-    NSString *resources = [[NSBundle mainBundle] resourcePath];
-    NSString *tmp = NSTemporaryDirectory();
-    NSString *cache = [NSHomeDirectory() stringByAppendingPathComponent:@"Library/Caches"];
-    NSString *docs = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents"];
-    
-    const gchar *resources_dir = [resources UTF8String];
-    const gchar *tmp_dir = [tmp UTF8String];
-    const gchar *cache_dir = [cache UTF8String];
-    const gchar *docs_dir = [docs UTF8String];
-    gchar *ca_certificates;
-    
-    g_setenv ("TMP", tmp_dir, true);
-    g_setenv ("TEMP", tmp_dir, true);
-    g_setenv ("TMPDIR", tmp_dir, true);
-    g_setenv ("XDG_RUNTIME_DIR", resources_dir, true);
-    g_setenv ("XDG_CACHE_HOME", cache_dir, true);
-    
-    g_setenv ("HOME", docs_dir, true);
-    g_setenv ("XDG_DATA_DIRS", resources_dir, true);
-    g_setenv ("XDG_CONFIG_DIRS", resources_dir, true);
-    g_setenv ("XDG_CONFIG_HOME", cache_dir, true);
-    g_setenv ("XDG_DATA_HOME", resources_dir, true);
-    g_setenv ("FONTCONFIG_PATH", resources_dir, true);
-    
-    ca_certificates = g_build_filename (resources_dir, "ssl", "certs", "ca-certifcates.crt", NULL);
-    g_setenv ("CA_CERTIFICATES", ca_certificates, true);
-    g_free (ca_certificates);
-    
-    gst_init (NULL, NULL);
-    
-#if defined(GST_IOS_PLUGIN_COREELEMENTS) || defined(GST_IOS_PLUGINS_CORE)
-    GST_PLUGIN_STATIC_REGISTER(coreelements);
-#endif
-#if defined(GST_IOS_PLUGIN_ADDER) || defined(GST_IOS_PLUGINS_CORE)
-    GST_PLUGIN_STATIC_REGISTER(adder);
-#endif
-#if defined(GST_IOS_PLUGIN_APP) || defined(GST_IOS_PLUGINS_CORE)
-    GST_PLUGIN_STATIC_REGISTER(app);
-#endif
-#if defined(GST_IOS_PLUGIN_AUDIOCONVERT) || defined(GST_IOS_PLUGINS_CORE)
-    GST_PLUGIN_STATIC_REGISTER(audioconvert);
-#endif
-#if defined(GST_IOS_PLUGIN_AUDIORATE) || defined(GST_IOS_PLUGINS_CORE)
-    GST_PLUGIN_STATIC_REGISTER(audiorate);
-#endif
-#if defined(GST_IOS_PLUGIN_AUDIORESAMPLE) || defined(GST_IOS_PLUGINS_CORE)
-    GST_PLUGIN_STATIC_REGISTER(audioresample);
-#endif
-#if defined(GST_IOS_PLUGIN_AUDIOTESTSRC) || defined(GST_IOS_PLUGINS_CORE)
-    GST_PLUGIN_STATIC_REGISTER(audiotestsrc);
-#endif
-#if defined(GST_IOS_PLUGIN_GIO) || defined(GST_IOS_PLUGINS_CORE)
-    GST_PLUGIN_STATIC_REGISTER(gio);
-#endif
-#if defined(GST_IOS_PLUGIN_PANGO) || defined(GST_IOS_PLUGINS_CORE)
-//    GST_PLUGIN_STATIC_REGISTER(pango);
-#endif
-#if defined(GST_IOS_PLUGIN_TYPEFINDFUNCTIONS) || defined(GST_IOS_PLUGINS_CORE)
-    GST_PLUGIN_STATIC_REGISTER(typefindfunctions);
-#endif
-#if defined(GST_IOS_PLUGIN_VIDEOCONVERT) || defined(GST_IOS_PLUGINS_CORE)
-    GST_PLUGIN_STATIC_REGISTER(videoconvert);
-#endif
-#if defined(GST_IOS_PLUGIN_VIDEORATE) || defined(GST_IOS_PLUGINS_CORE)
-    GST_PLUGIN_STATIC_REGISTER(videorate);
-#endif
-#if defined(GST_IOS_PLUGIN_VIDEOSCALE) || defined(GST_IOS_PLUGINS_CORE)
-    GST_PLUGIN_STATIC_REGISTER(videoscale);
-#endif
-#if defined(GST_IOS_PLUGIN_VIDEOTESTSRC) || defined(GST_IOS_PLUGINS_CORE)
-    GST_PLUGIN_STATIC_REGISTER(videotestsrc);
-#endif
-#if defined(GST_IOS_PLUGIN_VOLUME) || defined(GST_IOS_PLUGINS_CORE)
-    GST_PLUGIN_STATIC_REGISTER(volume);
-#endif
-#if defined(GST_IOS_PLUGIN_AUTODETECT) || defined(GST_IOS_PLUGINS_CORE)
-    GST_PLUGIN_STATIC_REGISTER(autodetect);
-#endif
-#if defined(GST_IOS_PLUGIN_VIDEOFILTER) || defined(GST_IOS_PLUGINS_CORE)
-    GST_PLUGIN_STATIC_REGISTER(videofilter);
-#endif
-#if defined(GST_IOS_PLUGIN_CAMERABIN) || defined(GST_IOS_PLUGINS_CAPTURE)
-//    GST_PLUGIN_STATIC_REGISTER(camerabin);
-#endif
-#if defined(GST_IOS_PLUGIN_ASFMUX) || defined(GST_IOS_PLUGINS_CODECS_RESTRICTED)
-    GST_PLUGIN_STATIC_REGISTER(asfmux);
-#endif
-#if defined(GST_IOS_PLUGIN_DTSDEC) || defined(GST_IOS_PLUGINS_CODECS_RESTRICTED)
-    GST_PLUGIN_STATIC_REGISTER(dtsdec);
-#endif
-#if defined(GST_IOS_PLUGIN_FAAD) || defined(GST_IOS_PLUGINS_CODECS_RESTRICTED)
-    GST_PLUGIN_STATIC_REGISTER(faad);
-#endif
-#if defined(GST_IOS_PLUGIN_MPEGPSDEMUX) || defined(GST_IOS_PLUGINS_CODECS_RESTRICTED)
-    GST_PLUGIN_STATIC_REGISTER(mpegpsdemux);
-#endif
-#if defined(GST_IOS_PLUGIN_MPEGPSMUX) || defined(GST_IOS_PLUGINS_CODECS_RESTRICTED)
-    GST_PLUGIN_STATIC_REGISTER(mpegpsmux);
-#endif
-#if defined(GST_IOS_PLUGIN_MPEGTSDEMUX) || defined(GST_IOS_PLUGINS_CODECS_RESTRICTED)
-    GST_PLUGIN_STATIC_REGISTER(mpegtsdemux);
-#endif
-#if defined(GST_IOS_PLUGIN_MPEGTSMUX) || defined(GST_IOS_PLUGINS_CODECS_RESTRICTED)
-    GST_PLUGIN_STATIC_REGISTER(mpegtsmux);
-#endif
-#if defined(GST_IOS_PLUGIN_VOAACENC) || defined(GST_IOS_PLUGINS_CODECS_RESTRICTED)
-    GST_PLUGIN_STATIC_REGISTER(voaacenc);
-#endif
-#if defined(GST_IOS_PLUGIN_A52DEC) || defined(GST_IOS_PLUGINS_CODECS_RESTRICTED)
-    GST_PLUGIN_STATIC_REGISTER(a52dec);
-#endif
-#if defined(GST_IOS_PLUGIN_AMRNB) || defined(GST_IOS_PLUGINS_CODECS_RESTRICTED)
-    GST_PLUGIN_STATIC_REGISTER(amrnb);
-#endif
-#if defined(GST_IOS_PLUGIN_AMRWBDEC) || defined(GST_IOS_PLUGINS_CODECS_RESTRICTED)
-    GST_PLUGIN_STATIC_REGISTER(amrwbdec);
-#endif
-#if defined(GST_IOS_PLUGIN_ASF) || defined(GST_IOS_PLUGINS_CODECS_RESTRICTED)
-    GST_PLUGIN_STATIC_REGISTER(asf);
-#endif
-#if defined(GST_IOS_PLUGIN_DVDSUB) || defined(GST_IOS_PLUGINS_CODECS_RESTRICTED)
-    GST_PLUGIN_STATIC_REGISTER(dvdsub);
-#endif
-#if defined(GST_IOS_PLUGIN_DVDLPCMDEC) || defined(GST_IOS_PLUGINS_CODECS_RESTRICTED)
-    GST_PLUGIN_STATIC_REGISTER(dvdlpcmdec);
-#endif
-#if defined(GST_IOS_PLUGIN_MAD) || defined(GST_IOS_PLUGINS_CODECS_RESTRICTED)
-    GST_PLUGIN_STATIC_REGISTER(mad);
-#endif
-#if defined(GST_IOS_PLUGIN_MPEG2DEC) || defined(GST_IOS_PLUGINS_CODECS_RESTRICTED)
-    GST_PLUGIN_STATIC_REGISTER(mpeg2dec);
-#endif
-#if defined(GST_IOS_PLUGIN_XINGMUX) || defined(GST_IOS_PLUGINS_CODECS_RESTRICTED)
-    GST_PLUGIN_STATIC_REGISTER(xingmux);
-#endif
-#if defined(GST_IOS_PLUGIN_REALMEDIA) || defined(GST_IOS_PLUGINS_CODECS_RESTRICTED)
-    GST_PLUGIN_STATIC_REGISTER(realmedia);
-#endif
-#if defined(GST_IOS_PLUGIN_X264) || defined(GST_IOS_PLUGINS_CODECS_RESTRICTED)
-    GST_PLUGIN_STATIC_REGISTER(x264);
-#endif
-#if defined(GST_IOS_PLUGIN_LIBAV) || defined(GST_IOS_PLUGINS_CODECS_RESTRICTED)
-    GST_PLUGIN_STATIC_REGISTER(libav);
-#endif
-#if defined(GST_IOS_PLUGIN_ENCODING) || defined(GST_IOS_PLUGINS_ENCODING)
-    GST_PLUGIN_STATIC_REGISTER(encoding);
-#endif
-#if defined(GST_IOS_PLUGIN_ASSRENDER) || defined(GST_IOS_PLUGINS_CODECS_GPL)
-    GST_PLUGIN_STATIC_REGISTER(assrender);
-#endif
-#if defined(GST_IOS_PLUGIN_MMS) || defined(GST_IOS_PLUGINS_NET_RESTRICTED)
-    GST_PLUGIN_STATIC_REGISTER(mms);
-#endif
-#if defined(GST_IOS_PLUGIN_RTMP) || defined(GST_IOS_PLUGINS_NET_RESTRICTED)
-    GST_PLUGIN_STATIC_REGISTER(rtmp);
-#endif
-#if defined(GST_IOS_PLUGIN_OSXAUDIO) || defined(GST_IOS_PLUGINS_SYS)
-    GST_PLUGIN_STATIC_REGISTER(osxaudio);
-#endif
-#if defined(GST_IOS_PLUGIN_APPLEMEDIA) || defined(GST_IOS_PLUGINS_SYS)
-//    GST_PLUGIN_STATIC_REGISTER(applemedia);
-#endif
-#if defined(GST_IOS_PLUGIN_SHM) || defined(GST_IOS_PLUGINS_SYS)
-//    GST_PLUGIN_STATIC_REGISTER(shm);
-#endif
-#if defined(GST_IOS_PLUGIN_OPENGL) || defined(GST_IOS_PLUGINS_SYS)
-//    GST_PLUGIN_STATIC_REGISTER(opengl);
-#endif
-#if defined(GST_IOS_PLUGIN_LIBVISUAL) || defined(GST_IOS_PLUGINS_VIS)
-    GST_PLUGIN_STATIC_REGISTER(libvisual);
-#endif
-#if defined(GST_IOS_PLUGIN_GOOM) || defined(GST_IOS_PLUGINS_VIS)
-    GST_PLUGIN_STATIC_REGISTER(goom);
-#endif
-#if defined(GST_IOS_PLUGIN_GOOM2K1) || defined(GST_IOS_PLUGINS_VIS)
-    GST_PLUGIN_STATIC_REGISTER(goom2k1);
-#endif
-#if defined(GST_IOS_PLUGIN_AUDIOVISUALIZERS) || defined(GST_IOS_PLUGINS_VIS)
-    GST_PLUGIN_STATIC_REGISTER(audiovisualizers);
-#endif
-#if defined(GST_IOS_PLUGIN_PLAYBACK) || defined(GST_IOS_PLUGINS_PLAYBACK)
-    GST_PLUGIN_STATIC_REGISTER(playback);
-#endif
-#if defined(GST_IOS_PLUGIN_ALPHA) || defined(GST_IOS_PLUGINS_EFFECTS)
-    GST_PLUGIN_STATIC_REGISTER(alpha);
-#endif
-#if defined(GST_IOS_PLUGIN_ALPHACOLOR) || defined(GST_IOS_PLUGINS_EFFECTS)
-    GST_PLUGIN_STATIC_REGISTER(alphacolor);
-#endif
-#if defined(GST_IOS_PLUGIN_AUDIOFX) || defined(GST_IOS_PLUGINS_EFFECTS)
-    GST_PLUGIN_STATIC_REGISTER(audiofx);
-#endif
-#if defined(GST_IOS_PLUGIN_CAIRO) || defined(GST_IOS_PLUGINS_EFFECTS)
-    GST_PLUGIN_STATIC_REGISTER(cairo);
-#endif
-#if defined(GST_IOS_PLUGIN_CUTTER) || defined(GST_IOS_PLUGINS_EFFECTS)
-    GST_PLUGIN_STATIC_REGISTER(cutter);
-#endif
-#if defined(GST_IOS_PLUGIN_DEBUG) || defined(GST_IOS_PLUGINS_EFFECTS)
-    GST_PLUGIN_STATIC_REGISTER(debug);
-#endif
-#if defined(GST_IOS_PLUGIN_DEINTERLACE) || defined(GST_IOS_PLUGINS_EFFECTS)
-    GST_PLUGIN_STATIC_REGISTER(deinterlace);
-#endif
-#if defined(GST_IOS_PLUGIN_DTMF) || defined(GST_IOS_PLUGINS_EFFECTS)
-    GST_PLUGIN_STATIC_REGISTER(dtmf);
-#endif
-#if defined(GST_IOS_PLUGIN_EFFECTV) || defined(GST_IOS_PLUGINS_EFFECTS)
-    GST_PLUGIN_STATIC_REGISTER(effectv);
-#endif
-#if defined(GST_IOS_PLUGIN_EQUALIZER) || defined(GST_IOS_PLUGINS_EFFECTS)
-    GST_PLUGIN_STATIC_REGISTER(equalizer);
-#endif
-#if defined(GST_IOS_PLUGIN_GDKPIXBUF) || defined(GST_IOS_PLUGINS_EFFECTS)
-    GST_PLUGIN_STATIC_REGISTER(gdkpixbuf);
-#endif
-#if defined(GST_IOS_PLUGIN_IMAGEFREEZE) || defined(GST_IOS_PLUGINS_EFFECTS)
-    GST_PLUGIN_STATIC_REGISTER(imagefreeze);
-#endif
-#if defined(GST_IOS_PLUGIN_INTERLEAVE) || defined(GST_IOS_PLUGINS_EFFECTS)
-    GST_PLUGIN_STATIC_REGISTER(interleave);
-#endif
-#if defined(GST_IOS_PLUGIN_LEVEL) || defined(GST_IOS_PLUGINS_EFFECTS)
-    GST_PLUGIN_STATIC_REGISTER(level);
-#endif
-#if defined(GST_IOS_PLUGIN_MULTIFILE) || defined(GST_IOS_PLUGINS_EFFECTS)
-    GST_PLUGIN_STATIC_REGISTER(multifile);
-#endif
-#if defined(GST_IOS_PLUGIN_REPLAYGAIN) || defined(GST_IOS_PLUGINS_EFFECTS)
-    GST_PLUGIN_STATIC_REGISTER(replaygain);
-#endif
-#if defined(GST_IOS_PLUGIN_SHAPEWIPE) || defined(GST_IOS_PLUGINS_EFFECTS)
-    GST_PLUGIN_STATIC_REGISTER(shapewipe);
-#endif
-#if defined(GST_IOS_PLUGIN_SMPTE) || defined(GST_IOS_PLUGINS_EFFECTS)
-    GST_PLUGIN_STATIC_REGISTER(smpte);
-#endif
-#if defined(GST_IOS_PLUGIN_SPECTRUM) || defined(GST_IOS_PLUGINS_EFFECTS)
-    GST_PLUGIN_STATIC_REGISTER(spectrum);
-#endif
-#if defined(GST_IOS_PLUGIN_VIDEOBOX) || defined(GST_IOS_PLUGINS_EFFECTS)
-    GST_PLUGIN_STATIC_REGISTER(videobox);
-#endif
-#if defined(GST_IOS_PLUGIN_VIDEOCROP) || defined(GST_IOS_PLUGINS_EFFECTS)
-    GST_PLUGIN_STATIC_REGISTER(videocrop);
-#endif
-#if defined(GST_IOS_PLUGIN_VIDEOMIXER) || defined(GST_IOS_PLUGINS_EFFECTS)
-    GST_PLUGIN_STATIC_REGISTER(videomixer);
-#endif
-#if defined(GST_IOS_PLUGIN_ACCURIP) || defined(GST_IOS_PLUGINS_EFFECTS)
-    GST_PLUGIN_STATIC_REGISTER(accurip);
-#endif
-#if defined(GST_IOS_PLUGIN_AIFF) || defined(GST_IOS_PLUGINS_EFFECTS)
-    GST_PLUGIN_STATIC_REGISTER(aiff);
-#endif
-#if defined(GST_IOS_PLUGIN_AUDIOFXBAD) || defined(GST_IOS_PLUGINS_EFFECTS)
-    GST_PLUGIN_STATIC_REGISTER(audiofxbad);
-#endif
-#if defined(GST_IOS_PLUGIN_AUTOCONVERT) || defined(GST_IOS_PLUGINS_EFFECTS)
-    GST_PLUGIN_STATIC_REGISTER(autoconvert);
-#endif
-#if defined(GST_IOS_PLUGIN_BAYER) || defined(GST_IOS_PLUGINS_EFFECTS)
-    GST_PLUGIN_STATIC_REGISTER(bayer);
-#endif
-#if defined(GST_IOS_PLUGIN_COLOREFFECTS) || defined(GST_IOS_PLUGINS_EFFECTS)
-    GST_PLUGIN_STATIC_REGISTER(coloreffects);
-#endif
-#if defined(GST_IOS_PLUGIN_DEBUGUTILSBAD) || defined(GST_IOS_PLUGINS_EFFECTS)
-    GST_PLUGIN_STATIC_REGISTER(debugutilsbad);
-#endif
-#if defined(GST_IOS_PLUGIN_FIELDANALYSIS) || defined(GST_IOS_PLUGINS_EFFECTS)
-    GST_PLUGIN_STATIC_REGISTER(fieldanalysis);
-#endif
-#if defined(GST_IOS_PLUGIN_FREEVERB) || defined(GST_IOS_PLUGINS_EFFECTS)
-    GST_PLUGIN_STATIC_REGISTER(freeverb);
-#endif
-#if defined(GST_IOS_PLUGIN_FREI0R) || defined(GST_IOS_PLUGINS_EFFECTS)
-    GST_PLUGIN_STATIC_REGISTER(frei0r);
-#endif
-#if defined(GST_IOS_PLUGIN_GAUDIEFFECTS) || defined(GST_IOS_PLUGINS_EFFECTS)
-    GST_PLUGIN_STATIC_REGISTER(gaudieffects);
-#endif
-#if defined(GST_IOS_PLUGIN_GEOMETRICTRANSFORM) || defined(GST_IOS_PLUGINS_EFFECTS)
-    GST_PLUGIN_STATIC_REGISTER(geometrictransform);
-#endif
-#if defined(GST_IOS_PLUGIN_INTERLACE) || defined(GST_IOS_PLUGINS_EFFECTS)
-    GST_PLUGIN_STATIC_REGISTER(interlace);
-#endif
-#if defined(GST_IOS_PLUGIN_IVTC) || defined(GST_IOS_PLUGINS_EFFECTS)
-    GST_PLUGIN_STATIC_REGISTER(ivtc);
-#endif
-#if defined(GST_IOS_PLUGIN_LIVEADDER) || defined(GST_IOS_PLUGINS_EFFECTS)
-    GST_PLUGIN_STATIC_REGISTER(liveadder);
-#endif
-#if defined(GST_IOS_PLUGIN_RAWPARSE) || defined(GST_IOS_PLUGINS_EFFECTS)
-    GST_PLUGIN_STATIC_REGISTER(rawparse);
-#endif
-#if defined(GST_IOS_PLUGIN_REMOVESILENCE) || defined(GST_IOS_PLUGINS_EFFECTS)
-    GST_PLUGIN_STATIC_REGISTER(removesilence);
-#endif
-#if defined(GST_IOS_PLUGIN_SEGMENTCLIP) || defined(GST_IOS_PLUGINS_EFFECTS)
-    GST_PLUGIN_STATIC_REGISTER(segmentclip);
-#endif
-#if defined(GST_IOS_PLUGIN_SMOOTH) || defined(GST_IOS_PLUGINS_EFFECTS)
-    GST_PLUGIN_STATIC_REGISTER(smooth);
-#endif
-#if defined(GST_IOS_PLUGIN_SPEED) || defined(GST_IOS_PLUGINS_EFFECTS)
-    GST_PLUGIN_STATIC_REGISTER(speed);
-#endif
-#if defined(GST_IOS_PLUGIN_VIDEOFILTERSBAD) || defined(GST_IOS_PLUGINS_EFFECTS)
-    GST_PLUGIN_STATIC_REGISTER(videofiltersbad);
-#endif
-#if defined(GST_IOS_PLUGIN_SUBPARSE) || defined(GST_IOS_PLUGINS_CODECS)
-    GST_PLUGIN_STATIC_REGISTER(subparse);
-#endif
-#if defined(GST_IOS_PLUGIN_OGG) || defined(GST_IOS_PLUGINS_CODECS)
-    GST_PLUGIN_STATIC_REGISTER(ogg);
-#endif
-#if defined(GST_IOS_PLUGIN_THEORA) || defined(GST_IOS_PLUGINS_CODECS)
-    GST_PLUGIN_STATIC_REGISTER(theora);
-#endif
-#if defined(GST_IOS_PLUGIN_VORBIS) || defined(GST_IOS_PLUGINS_CODECS)
-    GST_PLUGIN_STATIC_REGISTER(vorbis);
-#endif
-#if defined(GST_IOS_PLUGIN_IVORBISDEC) || defined(GST_IOS_PLUGINS_CODECS)
-    GST_PLUGIN_STATIC_REGISTER(ivorbisdec);
-#endif
-#if defined(GST_IOS_PLUGIN_ALAW) || defined(GST_IOS_PLUGINS_CODECS)
-    GST_PLUGIN_STATIC_REGISTER(alaw);
-#endif
-#if defined(GST_IOS_PLUGIN_APETAG) || defined(GST_IOS_PLUGINS_CODECS)
-    GST_PLUGIN_STATIC_REGISTER(apetag);
-#endif
-#if defined(GST_IOS_PLUGIN_AUDIOPARSERS) || defined(GST_IOS_PLUGINS_CODECS)
-    GST_PLUGIN_STATIC_REGISTER(audioparsers);
-#endif
-#if defined(GST_IOS_PLUGIN_AUPARSE) || defined(GST_IOS_PLUGINS_CODECS)
-    GST_PLUGIN_STATIC_REGISTER(auparse);
-#endif
-#if defined(GST_IOS_PLUGIN_AVI) || defined(GST_IOS_PLUGINS_CODECS)
-    GST_PLUGIN_STATIC_REGISTER(avi);
-#endif
-#if defined(GST_IOS_PLUGIN_DV) || defined(GST_IOS_PLUGINS_CODECS)
-    GST_PLUGIN_STATIC_REGISTER(dv);
-#endif
-#if defined(GST_IOS_PLUGIN_FLAC) || defined(GST_IOS_PLUGINS_CODECS)
-    GST_PLUGIN_STATIC_REGISTER(flac);
-#endif
-#if defined(GST_IOS_PLUGIN_FLV) || defined(GST_IOS_PLUGINS_CODECS)
-    GST_PLUGIN_STATIC_REGISTER(flv);
-#endif
-#if defined(GST_IOS_PLUGIN_FLXDEC) || defined(GST_IOS_PLUGINS_CODECS)
-    GST_PLUGIN_STATIC_REGISTER(flxdec);
-#endif
-#if defined(GST_IOS_PLUGIN_ICYDEMUX) || defined(GST_IOS_PLUGINS_CODECS)
-    GST_PLUGIN_STATIC_REGISTER(icydemux);
-#endif
-#if defined(GST_IOS_PLUGIN_ID3DEMUX) || defined(GST_IOS_PLUGINS_CODECS)
-    GST_PLUGIN_STATIC_REGISTER(id3demux);
-#endif
-#if defined(GST_IOS_PLUGIN_ISOMP4) || defined(GST_IOS_PLUGINS_CODECS)
-    GST_PLUGIN_STATIC_REGISTER(isomp4);
-#endif
-#if defined(GST_IOS_PLUGIN_JPEG) || defined(GST_IOS_PLUGINS_CODECS)
-    GST_PLUGIN_STATIC_REGISTER(jpeg);
-#endif
-#if defined(GST_IOS_PLUGIN_MATROSKA) || defined(GST_IOS_PLUGINS_CODECS)
-    GST_PLUGIN_STATIC_REGISTER(matroska);
-#endif
-#if defined(GST_IOS_PLUGIN_MULAW) || defined(GST_IOS_PLUGINS_CODECS)
-    GST_PLUGIN_STATIC_REGISTER(mulaw);
-#endif
-#if defined(GST_IOS_PLUGIN_MULTIPART) || defined(GST_IOS_PLUGINS_CODECS)
-    GST_PLUGIN_STATIC_REGISTER(multipart);
-#endif
-#if defined(GST_IOS_PLUGIN_PNG) || defined(GST_IOS_PLUGINS_CODECS)
-    GST_PLUGIN_STATIC_REGISTER(png);
-#endif
-#if defined(GST_IOS_PLUGIN_SPEEX) || defined(GST_IOS_PLUGINS_CODECS)
-    GST_PLUGIN_STATIC_REGISTER(speex);
-#endif
-#if defined(GST_IOS_PLUGIN_TAGLIB) || defined(GST_IOS_PLUGINS_CODECS)
-    GST_PLUGIN_STATIC_REGISTER(taglib);
-#endif
-#if defined(GST_IOS_PLUGIN_VPX) || defined(GST_IOS_PLUGINS_CODECS)
-    GST_PLUGIN_STATIC_REGISTER(vpx);
-#endif
-#if defined(GST_IOS_PLUGIN_WAVENC) || defined(GST_IOS_PLUGINS_CODECS)
-    GST_PLUGIN_STATIC_REGISTER(wavenc);
-#endif
-#if defined(GST_IOS_PLUGIN_WAVPACK) || defined(GST_IOS_PLUGINS_CODECS)
-    GST_PLUGIN_STATIC_REGISTER(wavpack);
-#endif
-#if defined(GST_IOS_PLUGIN_WAVPARSE) || defined(GST_IOS_PLUGINS_CODECS)
-    GST_PLUGIN_STATIC_REGISTER(wavparse);
-#endif
-#if defined(GST_IOS_PLUGIN_Y4MENC) || defined(GST_IOS_PLUGINS_CODECS)
-    GST_PLUGIN_STATIC_REGISTER(y4menc);
-#endif
-#if defined(GST_IOS_PLUGIN_ADPCMDEC) || defined(GST_IOS_PLUGINS_CODECS)
-    GST_PLUGIN_STATIC_REGISTER(adpcmdec);
-#endif
-#if defined(GST_IOS_PLUGIN_ADPCMENC) || defined(GST_IOS_PLUGINS_CODECS)
-    GST_PLUGIN_STATIC_REGISTER(adpcmenc);
-#endif
-#if defined(GST_IOS_PLUGIN_DASHDEMUX) || defined(GST_IOS_PLUGINS_CODECS)
-    GST_PLUGIN_STATIC_REGISTER(dashdemux);
-#endif
-#if defined(GST_IOS_PLUGIN_DVBSUBOVERLAY) || defined(GST_IOS_PLUGINS_CODECS)
-    GST_PLUGIN_STATIC_REGISTER(dvbsuboverlay);
-#endif
-#if defined(GST_IOS_PLUGIN_DVDSPU) || defined(GST_IOS_PLUGINS_CODECS)
-    GST_PLUGIN_STATIC_REGISTER(dvdspu);
-#endif
-#if defined(GST_IOS_PLUGIN_FRAGMENTED) || defined(GST_IOS_PLUGINS_CODECS)
-    GST_PLUGIN_STATIC_REGISTER(fragmented);
-#endif
-#if defined(GST_IOS_PLUGIN_ID3TAG) || defined(GST_IOS_PLUGINS_CODECS)
-    GST_PLUGIN_STATIC_REGISTER(id3tag);
-#endif
-#if defined(GST_IOS_PLUGIN_KATE) || defined(GST_IOS_PLUGINS_CODECS)
-    GST_PLUGIN_STATIC_REGISTER(kate);
-#endif
-#if defined(GST_IOS_PLUGIN_MIDI) || defined(GST_IOS_PLUGINS_CODECS)
-    GST_PLUGIN_STATIC_REGISTER(midi);
-#endif
-#if defined(GST_IOS_PLUGIN_MXF) || defined(GST_IOS_PLUGINS_CODECS)
-    GST_PLUGIN_STATIC_REGISTER(mxf);
-#endif
-#if defined(GST_IOS_PLUGIN_OPUS) || defined(GST_IOS_PLUGINS_CODECS)
-    GST_PLUGIN_STATIC_REGISTER(opus);
-#endif
-#if defined(GST_IOS_PLUGIN_PCAPPARSE) || defined(GST_IOS_PLUGINS_CODECS)
-    GST_PLUGIN_STATIC_REGISTER(pcapparse);
-#endif
-#if defined(GST_IOS_PLUGIN_PNM) || defined(GST_IOS_PLUGINS_CODECS)
-    GST_PLUGIN_STATIC_REGISTER(pnm);
-#endif
-#if defined(GST_IOS_PLUGIN_RFBSRC) || defined(GST_IOS_PLUGINS_CODECS)
-    GST_PLUGIN_STATIC_REGISTER(rfbsrc);
-#endif
-#if defined(GST_IOS_PLUGIN_SCHRO) || defined(GST_IOS_PLUGINS_CODECS)
-    GST_PLUGIN_STATIC_REGISTER(schro);
-#endif
-#if defined(GST_IOS_PLUGIN_GSTSIREN) || defined(GST_IOS_PLUGINS_CODECS)
-    GST_PLUGIN_STATIC_REGISTER(gstsiren);
-#endif
-#if defined(GST_IOS_PLUGIN_SMOOTHSTREAMING) || defined(GST_IOS_PLUGINS_CODECS)
-    GST_PLUGIN_STATIC_REGISTER(smoothstreaming);
-#endif
-#if defined(GST_IOS_PLUGIN_SUBENC) || defined(GST_IOS_PLUGINS_CODECS)
-    GST_PLUGIN_STATIC_REGISTER(subenc);
-#endif
-#if defined(GST_IOS_PLUGIN_VIDEOPARSERSBAD) || defined(GST_IOS_PLUGINS_CODECS)
-    GST_PLUGIN_STATIC_REGISTER(videoparsersbad);
-#endif
-#if defined(GST_IOS_PLUGIN_Y4MDEC) || defined(GST_IOS_PLUGINS_CODECS)
-    GST_PLUGIN_STATIC_REGISTER(y4mdec);
-#endif
-#if defined(GST_IOS_PLUGIN_JPEGFORMAT) || defined(GST_IOS_PLUGINS_CODECS)
-    GST_PLUGIN_STATIC_REGISTER(jpegformat);
-#endif
-#if defined(GST_IOS_PLUGIN_GDP) || defined(GST_IOS_PLUGINS_CODECS)
-    GST_PLUGIN_STATIC_REGISTER(gdp);
-#endif
-#if defined(GST_IOS_PLUGIN_RSVG) || defined(GST_IOS_PLUGINS_CODECS)
-    GST_PLUGIN_STATIC_REGISTER(rsvg);
-#endif
-#if defined(GST_IOS_PLUGIN_TCP) || defined(GST_IOS_PLUGINS_NET)
-    GST_PLUGIN_STATIC_REGISTER(tcp);
-#endif
-#if defined(GST_IOS_PLUGIN_RTSP) || defined(GST_IOS_PLUGINS_NET)
-    GST_PLUGIN_STATIC_REGISTER(rtsp);
-#endif
-#if defined(GST_IOS_PLUGIN_RTP) || defined(GST_IOS_PLUGINS_NET)
-    GST_PLUGIN_STATIC_REGISTER(rtp);
-#endif
-#if defined(GST_IOS_PLUGIN_RTPMANAGER) || defined(GST_IOS_PLUGINS_NET)
-    GST_PLUGIN_STATIC_REGISTER(rtpmanager);
-#endif
-#if defined(GST_IOS_PLUGIN_SOUP) || defined(GST_IOS_PLUGINS_NET)
-    GST_PLUGIN_STATIC_REGISTER(soup);
-#endif
-#if defined(GST_IOS_PLUGIN_UDP) || defined(GST_IOS_PLUGINS_NET)
-    GST_PLUGIN_STATIC_REGISTER(udp);
-#endif
-#if defined(GST_IOS_PLUGIN_DATAURISRC) || defined(GST_IOS_PLUGINS_NET)
-    GST_PLUGIN_STATIC_REGISTER(dataurisrc);
-#endif
-#if defined(GST_IOS_PLUGIN_SDP) || defined(GST_IOS_PLUGINS_NET)
-    GST_PLUGIN_STATIC_REGISTER(sdp);
-#endif
-#if defined(GST_IOS_PLUGIN_GNONLIN) || defined(GST_IOS_PLUGINS_EDITING)
-    GST_PLUGIN_STATIC_REGISTER(gnonlin);
-#endif
-    
-#if defined(GST_IOS_GIO_MODULE_GNUTLS)
-    GST_G_IO_MODULE_LOAD(gnutls);
-#endif
-    
-    /* Lower the ranks of filesrc and giosrc so iosavassetsrc is
-     * tried first in gst_element_make_from_uri() for file:// */
-    reg = gst_registry_get();
-    plugin = gst_registry_lookup_feature(reg, "filesrc");
-    if (plugin)
-        gst_plugin_feature_set_rank(plugin, GST_RANK_SECONDARY);
-    plugin = gst_registry_lookup_feature(reg, "giosrc");
-    if (plugin)
-        gst_plugin_feature_set_rank(plugin, GST_RANK_SECONDARY-1);
-}