Initial push for the native Mac FreeRDP client
This commit is contained in:
parent
17d5e65940
commit
1cbf3dab21
@ -111,6 +111,7 @@ endif()
|
||||
if(NOT WIN32)
|
||||
find_required_package(ZLIB)
|
||||
find_optional_package(PulseAudio)
|
||||
find_optional_package(MacAudio)
|
||||
find_optional_package(PCSC)
|
||||
find_suggested_package(Cups)
|
||||
|
||||
|
@ -37,3 +37,7 @@ if(WITH_PULSEAUDIO)
|
||||
add_subdirectory(pulse)
|
||||
endif()
|
||||
|
||||
if(WITH_MACAUDIO)
|
||||
add_subdirectory(mac_audio)
|
||||
endif()
|
||||
|
||||
|
36
channels/rdpsnd/mac_audio/CMakeLists.txt
Normal file
36
channels/rdpsnd/mac_audio/CMakeLists.txt
Normal file
@ -0,0 +1,36 @@
|
||||
# FreeRDP: A Remote Desktop Protocol Client
|
||||
# FreeRDP cmake build script
|
||||
#
|
||||
# Copyright 2012 Laxmikant Rashinkar <LK.Rashinkar@gmail.com>
|
||||
# Copyright 2011 O.S. Systems Software Ltda.
|
||||
# Copyright 2011 Otavio Salvador <otavio@ossystems.com.br>
|
||||
# Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
#
|
||||
# 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.
|
||||
|
||||
set(RDPSND_MACAUDIO_SRCS
|
||||
rdpsnd_audio_q.c
|
||||
)
|
||||
|
||||
include_directories(..)
|
||||
include_directories(${MACAUDIO_INCLUDE_DIRS})
|
||||
|
||||
add_library(rdpsnd_macaudio ${RDPSND_MACAUDIO_SRCS})
|
||||
set_target_properties(rdpsnd_macaudio PROPERTIES PREFIX "")
|
||||
|
||||
target_link_libraries(rdpsnd_macaudio freerdp-utils)
|
||||
target_link_libraries(rdpsnd_macaudio ${MAC_AUDIOTOOLBOX_LIBRARY_PATH})
|
||||
target_link_libraries(rdpsnd_macaudio ${MAC_COREFOUNDATION_LIBRARY_PATH})
|
||||
|
||||
install(TARGETS rdpsnd_macaudio DESTINATION ${FREERDP_PLUGIN_PATH})
|
||||
|
241
channels/rdpsnd/mac_audio/rdpsnd_audio_q.c
Normal file
241
channels/rdpsnd/mac_audio/rdpsnd_audio_q.c
Normal file
@ -0,0 +1,241 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol client.
|
||||
* Audio Output Virtual Channel
|
||||
*
|
||||
* Copyright 2012 Laxmikant Rashinkar <LK.Rashinkar@gmail.com>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Use AudioQueue to implement audio redirection
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <freerdp/types.h>
|
||||
#include <freerdp/utils/memory.h>
|
||||
#include <freerdp/utils/dsp.h>
|
||||
#include <freerdp/utils/svc_plugin.h>
|
||||
#include <AudioToolbox/AudioToolbox.h>
|
||||
#include <AudioToolbox/AudioQueue.h>
|
||||
|
||||
#include "rdpsnd_main.h"
|
||||
|
||||
#define GOT_HERE printf(">>>>> got here: %s %s %d\n", __FILE__, __func__, __LINE__)
|
||||
|
||||
#define AQ_NUM_BUFFERS 10
|
||||
#define AQ_BUF_SIZE (32 * 1024)
|
||||
|
||||
static void aq_playback_cb(void *user_data,
|
||||
AudioQueueRef aq_ref,
|
||||
AudioQueueBufferRef aq_buf_ref
|
||||
);
|
||||
|
||||
struct rdpsnd_audio_q_plugin
|
||||
{
|
||||
rdpsndDevicePlugin device;
|
||||
|
||||
/* audio queue player state */
|
||||
int is_open; // true when audio_q has been inited
|
||||
char * device_name;
|
||||
int is_playing;
|
||||
int buf_index;
|
||||
|
||||
AudioStreamBasicDescription data_format;
|
||||
AudioQueueRef aq_ref;
|
||||
AudioQueueBufferRef buffers[AQ_NUM_BUFFERS];
|
||||
};
|
||||
typedef struct rdpsnd_audio_q_plugin rdpsndAudioQPlugin;
|
||||
|
||||
static void rdpsnd_audio_close(rdpsndDevicePlugin* device)
|
||||
{
|
||||
rdpsndAudioQPlugin* aq_plugin_p = (rdpsndAudioQPlugin*) device;
|
||||
|
||||
GOT_HERE;
|
||||
|
||||
AudioQueueStop(aq_plugin_p->aq_ref, 0);
|
||||
aq_plugin_p->is_open = 0;
|
||||
}
|
||||
|
||||
static void rdpsnd_audio_open(rdpsndDevicePlugin* device, rdpsndFormat* format, int latency)
|
||||
{
|
||||
int rv;
|
||||
int i;
|
||||
|
||||
GOT_HERE;
|
||||
|
||||
rdpsndAudioQPlugin* aq_plugin_p = (rdpsndAudioQPlugin *) device;
|
||||
if (aq_plugin_p->is_open) {
|
||||
return;
|
||||
}
|
||||
|
||||
aq_plugin_p->buf_index = 0;
|
||||
|
||||
// setup AudioStreamBasicDescription
|
||||
aq_plugin_p->data_format.mSampleRate = 44100;
|
||||
aq_plugin_p->data_format.mFormatID = kAudioFormatLinearPCM;
|
||||
aq_plugin_p->data_format.mFormatFlags = kAudioFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked;
|
||||
|
||||
// until we know better, assume that one packet = one frame
|
||||
// one frame = bytes_per_sample x number_of_channels
|
||||
aq_plugin_p->data_format.mBytesPerPacket = 4;
|
||||
aq_plugin_p->data_format.mFramesPerPacket = 1;
|
||||
aq_plugin_p->data_format.mBytesPerFrame = 4;
|
||||
aq_plugin_p->data_format.mChannelsPerFrame = 2;
|
||||
aq_plugin_p->data_format.mBitsPerChannel = 16;
|
||||
|
||||
rv = AudioQueueNewOutput(&aq_plugin_p->data_format, // audio stream basic desc
|
||||
aq_playback_cb, // callback when more data is required
|
||||
aq_plugin_p, // data to pass to callback
|
||||
CFRunLoopGetCurrent(), // The current run loop, and the one on
|
||||
// which the audio queue playback callback
|
||||
// will be invoked
|
||||
kCFRunLoopCommonModes, // run loop modes in which callbacks can
|
||||
// be invoked
|
||||
0, // flags - reserved
|
||||
&aq_plugin_p->aq_ref
|
||||
);
|
||||
if (rv != 0) {
|
||||
printf("rdpsnd_audio_open: AudioQueueNewOutput() failed with error %d\n", rv);
|
||||
aq_plugin_p->is_open = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < AQ_NUM_BUFFERS; i++)
|
||||
{
|
||||
rv = AudioQueueAllocateBuffer(aq_plugin_p->aq_ref, AQ_BUF_SIZE, &aq_plugin_p->buffers[i]);
|
||||
}
|
||||
|
||||
aq_plugin_p->is_open = 1;
|
||||
}
|
||||
|
||||
static void rdpsnd_audio_free(rdpsndDevicePlugin* device)
|
||||
{
|
||||
GOT_HERE;
|
||||
}
|
||||
|
||||
static boolean rdpsnd_audio_format_supported(rdpsndDevicePlugin* device, rdpsndFormat* format)
|
||||
{
|
||||
GOT_HERE;
|
||||
|
||||
switch (format->wFormatTag)
|
||||
{
|
||||
case 1: /* PCM */
|
||||
if (format->cbSize == 0 &&
|
||||
(format->nSamplesPerSec <= 48000) &&
|
||||
(format->wBitsPerSample == 8 || format->wBitsPerSample == 16) &&
|
||||
(format->nChannels == 1 || format->nChannels == 2))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rdpsnd_audio_set_format(rdpsndDevicePlugin* device, rdpsndFormat* format, int latency)
|
||||
{
|
||||
GOT_HERE;
|
||||
}
|
||||
|
||||
static void rdpsnd_audio_set_volume(rdpsndDevicePlugin* device, uint32 value)
|
||||
{
|
||||
GOT_HERE;
|
||||
}
|
||||
|
||||
static void rdpsnd_audio_play(rdpsndDevicePlugin* device, uint8* data, int size)
|
||||
{
|
||||
rdpsndAudioQPlugin* aq_plugin_p = (rdpsndAudioQPlugin *) device;
|
||||
AudioQueueBufferRef aq_buf_ref;
|
||||
int len;
|
||||
|
||||
GOT_HERE;
|
||||
|
||||
if (!aq_plugin_p->is_open) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* get next empty buffer */
|
||||
aq_buf_ref = aq_plugin_p->buffers[aq_plugin_p->buf_index];
|
||||
|
||||
// fill aq_buf_ref with audio data
|
||||
len = size > AQ_BUF_SIZE ? AQ_BUF_SIZE : size;
|
||||
|
||||
memcpy(aq_buf_ref->mAudioData, (char *) data, len);
|
||||
aq_buf_ref->mAudioDataByteSize = len;
|
||||
|
||||
// add buffer to audioqueue
|
||||
AudioQueueEnqueueBuffer(aq_plugin_p->aq_ref, aq_buf_ref, 0, 0);
|
||||
|
||||
// update buf_index
|
||||
aq_plugin_p->buf_index++;
|
||||
if (aq_plugin_p->buf_index >= AQ_NUM_BUFFERS) {
|
||||
aq_plugin_p->buf_index = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void rdpsnd_audio_start(rdpsndDevicePlugin* device)
|
||||
{
|
||||
GOT_HERE;
|
||||
|
||||
rdpsndAudioQPlugin* aq_plugin_p = (rdpsndAudioQPlugin *) device;
|
||||
|
||||
AudioQueueStart(aq_plugin_p->aq_ref, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* AudioQueue Playback callback
|
||||
*
|
||||
* our job here is to fill aq_buf_ref with audio data and enqueue it
|
||||
*/
|
||||
|
||||
static void aq_playback_cb(void *user_data,
|
||||
AudioQueueRef aq_ref,
|
||||
AudioQueueBufferRef aq_buf_ref
|
||||
)
|
||||
{
|
||||
GOT_HERE;
|
||||
}
|
||||
|
||||
int FreeRDPRdpsndDeviceEntry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pEntryPoints)
|
||||
{
|
||||
rdpsndAudioQPlugin* aqPlugin;
|
||||
RDP_PLUGIN_DATA* data;
|
||||
|
||||
GOT_HERE;
|
||||
|
||||
aqPlugin = xnew(rdpsndAudioQPlugin);
|
||||
|
||||
aqPlugin->device.Open = rdpsnd_audio_open;
|
||||
aqPlugin->device.FormatSupported = rdpsnd_audio_format_supported;
|
||||
aqPlugin->device.SetFormat = rdpsnd_audio_set_format;
|
||||
aqPlugin->device.SetVolume = rdpsnd_audio_set_volume;
|
||||
aqPlugin->device.Play = rdpsnd_audio_play;
|
||||
aqPlugin->device.Start = rdpsnd_audio_start;
|
||||
aqPlugin->device.Close = rdpsnd_audio_close;
|
||||
aqPlugin->device.Free = rdpsnd_audio_free;
|
||||
|
||||
data = pEntryPoints->plugin_data;
|
||||
|
||||
if (data && strcmp((char *)data->data[0], "macaudio") == 0) {
|
||||
if(strlen((char *)data->data[1]) > 0)
|
||||
aqPlugin->device_name = strdup((char *)data->data[1]);
|
||||
else
|
||||
aqPlugin->device_name = NULL;
|
||||
}
|
||||
pEntryPoints->pRegisterRdpsndDevice(pEntryPoints->rdpsnd, (rdpsndDevicePlugin*)aqPlugin);
|
||||
return 0;
|
||||
}
|
||||
|
@ -525,7 +525,12 @@ static void rdpsnd_process_connect(rdpSvcPlugin* plugin)
|
||||
{
|
||||
default_data[0].data[0] = "alsa";
|
||||
default_data[0].data[1] = "default";
|
||||
rdpsnd_load_device_plugin(rdpsnd, "alsa", default_data);
|
||||
if (!rdpsnd_load_device_plugin(rdpsnd, "alsa", default_data))
|
||||
{
|
||||
default_data[0].data[0] = "macaudio";
|
||||
default_data[0].data[1] = "default";
|
||||
rdpsnd_load_device_plugin(rdpsnd, "macaudio", default_data);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (rdpsnd->device == NULL)
|
||||
|
25
client/Mac/MRDPCursor.h
Normal file
25
client/Mac/MRDPCursor.h
Normal file
@ -0,0 +1,25 @@
|
||||
//
|
||||
// MRDPCursor.h
|
||||
// MacFreeRDP
|
||||
//
|
||||
// Created by Laxmikant Rashinkar on 3/28/12.
|
||||
// Copyright (c) 2012 FreeRDP.org All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#define boolean int
|
||||
|
||||
#include "freerdp/graphics.h"
|
||||
|
||||
@interface MRDPCursor : NSObject
|
||||
{
|
||||
@public
|
||||
rdpPointer *pointer;
|
||||
uint8 *cursor_data; // bitmapped pixel data
|
||||
NSBitmapImageRep *bmiRep;
|
||||
NSCursor *nsCursor;
|
||||
NSImage *nsImage;
|
||||
}
|
||||
|
||||
@end
|
12
client/Mac/MRDPCursor.m
Normal file
12
client/Mac/MRDPCursor.m
Normal file
@ -0,0 +1,12 @@
|
||||
//
|
||||
// MRDPCursor.m
|
||||
// MacFreeRDP
|
||||
//
|
||||
// Created by Laxmikant Rashinkar on 3/28/12.
|
||||
// Copyright (c) 2012 FreeRDP.org All rights reserved.
|
||||
//
|
||||
|
||||
#import "MRDPCursor.h"
|
||||
|
||||
@implementation MRDPCursor
|
||||
@end
|
144
client/Mac/MRDPView.h
Normal file
144
client/Mac/MRDPView.h
Normal file
@ -0,0 +1,144 @@
|
||||
//
|
||||
// MRDPView.h
|
||||
// MacFreeRDP
|
||||
//
|
||||
// Created by Laxmikant Rashinkar on 3/28/12.
|
||||
// Copyright (c) 2012 FreeRDP.org All rights reserved.
|
||||
//
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
typedef int boolean;
|
||||
|
||||
#include "freerdp/freerdp.h"
|
||||
#include "freerdp/types.h"
|
||||
#include "freerdp/channels/channels.h"
|
||||
#include "freerdp/gdi/gdi.h"
|
||||
#include "freerdp/graphics.h"
|
||||
#include "freerdp/utils/event.h"
|
||||
#include "freerdp/plugins/cliprdr.h"
|
||||
#include "freerdp/utils/args.h"
|
||||
|
||||
@interface MRDPView : NSView
|
||||
{
|
||||
CFRunLoopSourceRef run_loop_src;
|
||||
CFRunLoopSourceRef run_loop_src_channels;
|
||||
NSBitmapImageRep *bmiRep;
|
||||
NSMutableArray *cursors;
|
||||
NSTimer *pasteboard_timer;
|
||||
NSRect rect;
|
||||
freerdp *rdp_instance;
|
||||
rdpContext *rdp_context;
|
||||
boolean mouseInClientArea;
|
||||
char *pixel_data;
|
||||
int width;
|
||||
int height;
|
||||
int argc;
|
||||
char **argv;
|
||||
|
||||
// store state info for some keys
|
||||
int kdlshift;
|
||||
int kdrshift;
|
||||
int kdlctrl;
|
||||
int kdrctrl;
|
||||
int kdlalt;
|
||||
int kdralt;
|
||||
int kdlmeta;
|
||||
int kdrmeta;
|
||||
int kdcapslock;
|
||||
|
||||
@public
|
||||
NSWindow *ourMainWindow;
|
||||
NSPasteboard *pasteboard_rd; // for reading from clipboard
|
||||
NSPasteboard *pasteboard_wr; // for writing to clipboard
|
||||
int pasteboard_changecount;
|
||||
int pasteboard_format;
|
||||
int is_connected; // true when connected to RDP server
|
||||
}
|
||||
|
||||
- (void) rdpConnectEror;
|
||||
- (void) saveStateInfo :(freerdp *) instance :(rdpContext *) context;
|
||||
- (BOOL) eventIsInClientArea :(NSEvent *) event :(int *) xptr :(int *) yptr;
|
||||
- (void) onPasteboardTimerFired :(NSTimer *) timer;
|
||||
- (void) my_draw_rect :(void *) context;
|
||||
- (void) releaseResources;
|
||||
|
||||
@property (assign) int is_connected;
|
||||
|
||||
@end
|
||||
|
||||
/* Pointer Flags */
|
||||
#define PTR_FLAGS_WHEEL 0x0200
|
||||
#define PTR_FLAGS_WHEEL_NEGATIVE 0x0100
|
||||
#define PTR_FLAGS_MOVE 0x0800
|
||||
#define PTR_FLAGS_DOWN 0x8000
|
||||
#define PTR_FLAGS_BUTTON1 0x1000
|
||||
#define PTR_FLAGS_BUTTON2 0x2000
|
||||
#define PTR_FLAGS_BUTTON3 0x4000
|
||||
#define WheelRotationMask 0x01FF
|
||||
|
||||
void pointer_new(rdpContext* context, rdpPointer* pointer);
|
||||
void pointer_free(rdpContext* context, rdpPointer* pointer);
|
||||
void pointer_set(rdpContext* context, rdpPointer* pointer);
|
||||
void pointer_setNull(rdpContext* context);
|
||||
void pointer_setDefault(rdpContext* context);
|
||||
int rdp_connect();
|
||||
boolean mac_pre_connect(freerdp *inst);
|
||||
boolean mac_post_connect(freerdp *inst);
|
||||
void mac_context_new(freerdp *inst, rdpContext *context);
|
||||
void mac_context_free(freerdp *inst, rdpContext *context);
|
||||
void mac_set_bounds(rdpContext *context, rdpBounds *bounds);
|
||||
void mac_bitmap_update(rdpContext *context, BITMAP_UPDATE *bitmap);
|
||||
void mac_begin_paint(rdpContext *context);
|
||||
void mac_end_paint(rdpContext* context);
|
||||
void mac_save_state_info(freerdp *inst, rdpContext *context);
|
||||
void skt_activity_cb(CFSocketRef s, CFSocketCallBackType callbackType, CFDataRef address, const void *data, void *info);
|
||||
void channel_activity_cb(CFSocketRef s, CFSocketCallBackType callbackType, CFDataRef address, const void *data, void *info);
|
||||
int register_fds(int *fds, int count, void *inst);
|
||||
int invoke_draw_rect(rdpContext *context);
|
||||
int process_plugin_args(rdpSettings* settings, const char* name, RDP_PLUGIN_DATA* plugin_data, void* user_data);
|
||||
int receive_channel_data(freerdp *inst, int chan_id, uint8 *data, int size, int flags, int total_size);
|
||||
void process_cliprdr_event(freerdp *inst);
|
||||
void cliprdr_process_cb_format_list_event(freerdp *inst, RDP_CB_FORMAT_LIST_EVENT* event);
|
||||
void cliprdr_send_data_request(freerdp *inst, uint32 format);
|
||||
void cliprdr_process_cb_monitor_ready_event(freerdp* inst);
|
||||
void cliprdr_process_cb_data_response_event(freerdp *inst, RDP_CB_DATA_RESPONSE_EVENT *event);
|
||||
void cliprdr_process_text(freerdp *inst, uint8 *data, int len);
|
||||
void cliprdr_send_supported_format_list(freerdp *inst);
|
||||
int register_channel_fds(int *fds, int count, void *inst);
|
||||
|
||||
/* LK_TODO
|
||||
int freerdp_parse_args(rdpSettings* settings, int argc, char** argv,
|
||||
ProcessPluginArgs plugin_callback, void* plugin_user_data,
|
||||
ProcessUIArgs ui_callback, void* ui_user_data);
|
||||
*/
|
||||
|
||||
struct mac_context
|
||||
{
|
||||
// *must* have this - do not delete
|
||||
rdpContext _p;
|
||||
};
|
||||
|
||||
struct cursor
|
||||
{
|
||||
rdpPointer *pointer;
|
||||
uint8 *cursor_data; // bitmapped pixel data
|
||||
void *bmiRep; // NSBitmapImageRep
|
||||
void *nsCursor; // NSCursor
|
||||
void *nsImage; // NSImage
|
||||
};
|
||||
|
||||
struct rgba_data
|
||||
{
|
||||
char red;
|
||||
char green;
|
||||
char blue;
|
||||
char alpha;
|
||||
};
|
||||
|
||||
struct kkey
|
||||
{
|
||||
int key_code;
|
||||
int flags;
|
||||
};
|
||||
|
1519
client/Mac/MRDPView.m
Normal file
1519
client/Mac/MRDPView.m
Normal file
File diff suppressed because it is too large
Load Diff
140
client/Mac/README.txt
Normal file
140
client/Mac/README.txt
Normal file
@ -0,0 +1,140 @@
|
||||
|
||||
-------------------------------------------------------------------------
|
||||
Building FreeRDP on Mac OS X
|
||||
-------------------------------------------------------------------------
|
||||
|
||||
Platform: Lion with Xcode 4.3.2
|
||||
|
||||
------------------
|
||||
installing cmake
|
||||
------------------
|
||||
|
||||
first install macports by googling for it, the run the following command
|
||||
sudo port install cmake
|
||||
|
||||
----------------
|
||||
installing gcc
|
||||
----------------
|
||||
Click on Xcode->Preferences->Downloads
|
||||
Click on Components
|
||||
Click on Install Command line tools
|
||||
|
||||
You will be prompted for your Apple Developer userid and password
|
||||
|
||||
----------------------------------------
|
||||
download FreeRDP source code using git
|
||||
----------------------------------------
|
||||
|
||||
mkdir ~/projects/A8
|
||||
cd ~/projects/A8
|
||||
git clone git://github.com/FreeRDP/FreeRDP.git
|
||||
|
||||
------------------
|
||||
building FreeRDP
|
||||
------------------
|
||||
|
||||
cd ~projects/A8/FreeRDP
|
||||
cmake -DWITH_MACAUDIO=ON -DCMAKE_INSTALL_PREFIX="</path/to/your/staging/dir>"
|
||||
make
|
||||
make install
|
||||
|
||||
------------------------
|
||||
creating Xcode project
|
||||
------------------------
|
||||
|
||||
Start xcode
|
||||
Select 'Create a new xcode project'
|
||||
In 'Choose a template for your new project', click on Mac OS X -> application
|
||||
Click on 'Cocoa Application'
|
||||
Click on next
|
||||
I used the following:
|
||||
Product Name: Mac
|
||||
Company Identifier: com.freerdp
|
||||
Check 'Automatic Reference Counting'
|
||||
Create the project in your directory of choice
|
||||
|
||||
-------------------------------
|
||||
Adding files to your projects
|
||||
-------------------------------
|
||||
|
||||
Add the following files to your project:
|
||||
|
||||
cd ~/projects/A8/FreeRDP/client/Mac/MRDPCursor.h
|
||||
cd ~/projects/A8/FreeRDP/client/Mac/MRDPCursor.m
|
||||
cd ~/projects/A8/FreeRDP/client/Mac/MRDPView.h
|
||||
cd ~/projects/A8/FreeRDP/client/Mac/MRDPView.m
|
||||
|
||||
This is what your AppDelegate.h file should like like
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#import "MRDPView.h"
|
||||
|
||||
@interface AppDelegate : NSObject <NSApplicationDelegate>
|
||||
|
||||
@property (assign) IBOutlet NSWindow *window;
|
||||
@property (assign) IBOutlet MRDPView *mrdpView;
|
||||
|
||||
int rdp_connect();
|
||||
|
||||
@end
|
||||
|
||||
This is what your AppDelegate.m file should like like
|
||||
|
||||
#import "AppDelegate.h"
|
||||
|
||||
@implementation AppDelegate
|
||||
|
||||
@synthesize window = _window;
|
||||
@synthesize mrdpView;
|
||||
|
||||
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
|
||||
{
|
||||
rdp_connect();
|
||||
}
|
||||
|
||||
- (void) applicationWillTerminate:(NSNotification *)notification
|
||||
{
|
||||
[mrdpView releaseResources];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
----------------------------------
|
||||
Modifying your MainMenu.xib file
|
||||
----------------------------------
|
||||
|
||||
In your project select MainMenu.xib and drag a NSView object intot the main window
|
||||
Name the class MRDPView
|
||||
In Interface Builder, select the Application Delegate and tie the mrdpview outlet to the NSView
|
||||
Set the default size of the main window to 1024x768. This is FreeRDP's default resolution
|
||||
|
||||
----------------------------
|
||||
Configuring build settings
|
||||
----------------------------
|
||||
|
||||
In Project Navigator, click on Mac
|
||||
Click on Targets -> Mac
|
||||
Click on Build Phases
|
||||
Click on 'Link Binary With Libraries' and click on the + button, then click on the 'Add Other' button to add the following dynamic libraries
|
||||
~/projects/A8/FreeRDP/libfreerdp-core/libfreerdp-core.dylib
|
||||
~/projects/A8/FreeRDP/libfreerdp-channels/libfreerdp-channels.dylilb
|
||||
~/projects/A8/FreeRDP/libfreerdp-utils/libfreerdp-utils.dylib
|
||||
~/projects/A8/FreeRDP/libfreerdp-codec/libfreerdp-codec.dylib
|
||||
~/projects/A8/FreeRDP/libfreerdp-cache/libfreerdp-cache.dylib
|
||||
~/projects/A8/FreeRDP/libfreerdp-gdi/libfreerdp-gdi.dylib
|
||||
|
||||
Click on 'Build Settings'
|
||||
In 'Search Paths -> Library Search Paths' set the following
|
||||
Header Search Path Debug: ~/projects/A8/FreeRDP/include
|
||||
Header Search Path Release: ~/projects/A8/FreeRDP/include
|
||||
|
||||
TODO: in build settings, set strip build product to yes when done debugging
|
||||
|
||||
---------------------------
|
||||
To deploy the application
|
||||
---------------------------
|
||||
|
||||
in xcode, click on Product->Archive
|
||||
Click on Distribute button
|
||||
Select Export As -> application
|
||||
|
@ -97,6 +97,7 @@ cmake \
|
||||
-DWITH_CUPS:BOOL=ON \
|
||||
-DWITH_PCSC:BOOL=ON \
|
||||
-DWITH_PULSEAUDIO:BOOL=ON \
|
||||
-DWITH_MACAUDIO:BOOL=ON \
|
||||
-DWITH_X11:BOOL=ON \
|
||||
-DWITH_XCURSOR:BOOL=ON \
|
||||
-DWITH_XEXT:BOOL=ON \
|
||||
|
Loading…
Reference in New Issue
Block a user