I'm trying to write my little midi sequencer with blackjack and etc but stuck on writing sysex data into MusicTrack. I use following code to insert sysex events
// ---- Some code here --- //
PatternData pattern = { sizeof(PatternData), i, signature.numerator, signature.denominator };
CABarBeatTime beattime = CABarBeatTime((i * signature.numerator * signature.denominator) + 1, 1, 0, SUBBEAT_DIVISOR_DEFAULT);
// Convert beattime to timestamp
if ((MusicSequenceBarBeatTimeToBeats(sequence, &beattime, ×tamp)) != noErr)
{
return status;
}
// Add event
if ((status = MusicTrackNewMIDIRawDataEvent(track, timestamp, (MIDIRawData*)&pattern)) != noErr)
{
return status;
}
// ---- Some code here --- //
PatternData is
typedef struct PatternData
{
UInt32 length; // Struct length
UInt8 index; // Pattern index
UInt8 bars; // Number of bars in patten
UInt8 beats; // Number of beats in pattern
} PatternData;
I did something wrong because after call MusicSequenceFileCreate i get corrupted file.
Does somebody have an example of how to add sysex data to a music track?
Ok. I found a right way, here is it:
UInt8 data[] = { 0xF0, manufacturerId, databyte1, databyte2, databyte3, 0xF7 };
MIDIRawData raw;
memcpy(raw.data, data, 0, sizeof(data));
raw.length = sizeof(data);
if ((status = MusicTrackNewMIDIRawDataEvent(track, timestamp, &raw)) != noErr)
{
return status;
}
Here is an example, how to record normal MIDI and SYSEX messages in a MIDI track and save them in a MIDI file in the shared iTunes folder (set "Application supports iTunes file sharing" to "YES" in .plist):
See specially "calloc" in the code!!
#import "ViewController.h"
#import <CoreMIDI/MIDIServices.h>
#import <CoreMIDI/CoreMIDI.h>
#import "AppDelegate.h"
#include <sys/time.h>
#import <UIKit/UIKit.h>
#import <QuartzCore/QuartzCore.h>
#import <AVFoundation/AVFoundation.h>
#interface ViewController ()
#end
#implementation ViewController
#synthesize SYSEX_8;
long secTempA = 0;
float secTempB = 0;
long secStartA = 0;
float secStartB = 0;
MusicTimeStamp timeStamp = 0;
MusicSequence recordSequence;
MusicTrack recordTrack;
MusicTimeStamp lenRec = 0;
MIDINoteMessage noteMessage;
MusicTrack track;
NSString *fileNameForSave = #"";
NSString *midiFileWritePath = #"";
NSString *documentsDirectoryPath = #"";
UIAlertView *infoStore;
UIAlertView *infoStoreError;
MIDIRawData *sysexData;
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
// Get documents Directory
// (don't forget the ".plist" entry "Application supports iTunes file sharing YES"
NSArray *pathDocDir = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
documentsDirectoryPath = [pathDocDir objectAtIndex:0];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)SYSEX_8_touchdown:(id)sender {
NewMusicSequence(&recordSequence);
MusicSequenceNewTrack(recordSequence, &recordTrack);
MusicSequenceSetSequenceType(recordSequence, kMusicSequenceType_Beats);
timeStamp = 0;
struct timeval time;
gettimeofday(&time, NULL);
secStartA = time.tv_sec;
secStartB = time.tv_usec * 0.000001;
noteMessage.channel = 0x90; // Note ON
noteMessage.note = 0x3C;
noteMessage.velocity = 0x7F;
MusicTrackNewMIDINoteEvent(recordTrack, timeStamp, ¬eMessage);
NSLog(#"%02x %02x %02x", 0x90, 0x3C, 0x7F);
usleep(10000);
gettimeofday(&time, NULL);
secTempA = time.tv_sec;
secTempB = time.tv_usec * 0.000001;
secTempA = secTempA - secStartA;
secTempB = secTempB - secStartB;
timeStamp = (secTempA + secTempB) * 2;
noteMessage.channel = 0x90; // Note OFF
noteMessage.note = 0x3C;
noteMessage.velocity = 0x00;
MusicTrackNewMIDINoteEvent(recordTrack, timeStamp, ¬eMessage);
NSLog(#"%02x %02x %02x", 0x90, 0x3C, 0x00);
usleep(100000);
gettimeofday(&time, NULL);
secTempA = time.tv_sec;
secTempB = time.tv_usec * 0.000001;
secTempA = secTempA - secStartA;
secTempB = secTempB - secStartB;
timeStamp = (secTempA + secTempB) * 2;
Byte datatest[8];
UInt32 theSize = offsetof(MIDIRawData, data[0]) + (sizeof(UInt8) * sizeof(datatest));
sysexData = (MIDIRawData *)calloc(1, theSize);
sysexData->length = sizeof(datatest);
datatest[0] = 0xF0; // Start SYSEX
datatest[1] = 0x26;
datatest[2] = 0x79;
datatest[3] = 0x0E;
datatest[4] = 0x00;
datatest[5] = 0x00;
datatest[6] = 0x00;
datatest[7] = 0xF7; // End SYSEX
for (int j = 0; j < sizeof(datatest); j++) {
sysexData->data[j] = datatest[j];
NSLog(#"%02x", sysexData->data[j]);
}
int status;
if ((status = MusicTrackNewMIDIRawDataEvent(recordTrack, timeStamp, sysexData) != noErr)) {
NSLog(#"error %i", status);
}
else {
[self stopRecording];
}
}
- (void) stopRecording {
CAShow(recordSequence); // To show all MIDI events !!!
UInt32 sz = sizeof(MusicTimeStamp);
lenRec = 0;
MusicSequenceGetIndTrack(recordSequence, 0, &track);
MusicTrackGetProperty(track, kSequenceTrackProperty_TrackLength, &lenRec, &sz);
if (lenRec > 0.1){
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"yyyy-MM-dd HH:mm:ss +zzzz"];
NSDate *startDate = [NSDate date];
NSTimeZone *zone = [NSTimeZone systemTimeZone];
NSInteger interval = [zone secondsFromGMTForDate:startDate];
startDate = [startDate dateByAddingTimeInterval:interval];
// NSLog(#"Date: %#", startDate);
NSString *strDate = [[NSString alloc] initWithFormat:#"%#", startDate];
NSArray *arr = [strDate componentsSeparatedByString:#" "];
NSString *str;
str = [arr objectAtIndex:0];
NSArray *arr_date = [str componentsSeparatedByString:#"-"];
int year = [[arr_date objectAtIndex:0] intValue];
int month = [[arr_date objectAtIndex:1] intValue];
int day = [[arr_date objectAtIndex:2] intValue];
str = [arr objectAtIndex:1];
NSArray *arr_time = [str componentsSeparatedByString:#":"];
int hours = [[arr_time objectAtIndex:0] intValue];
int minutes = [[arr_time objectAtIndex:1] intValue];
int seconds = [[arr_time objectAtIndex:2] intValue];
fileNameForSave = [NSString stringWithFormat:#"%#_%04d%02d%02d_%02d%02d%02d%#", #"$Record", year, month, day, hours, minutes, seconds, #".mid"];
midiFileWritePath = [documentsDirectoryPath stringByAppendingPathComponent:fileNameForSave];
infoStore = [[UIAlertView alloc]initWithTitle: #"Save as MIDI file ?"
message: [NSString stringWithFormat:#"\n%#", fileNameForSave]
delegate: self
cancelButtonTitle: #"YES"
otherButtonTitles: #"NO",nil];
[infoStore show]; // rest siehe unten !!!!!
}
else {
MusicSequenceDisposeTrack(recordSequence, track);
DisposeMusicSequence(recordSequence);
}
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(int)buttonIndex {
// deletion code here
if (alertView == infoStore) {
if (buttonIndex == 0) {
NSURL *midiURL = [NSURL fileURLWithPath:midiFileWritePath];
OSStatus status = 0;
status = MusicSequenceFileCreate(recordSequence, (__bridge CFURLRef)(midiURL), kMusicSequenceFile_MIDIType, kMusicSequenceFileFlags_EraseFile, 0);
if (status != noErr) {
infoStoreError = [[UIAlertView alloc]initWithTitle: #"Information"
message: [NSString stringWithFormat:#"\nError storing MIDI file in: %#", documentsDirectoryPath]
delegate: self
cancelButtonTitle: nil
otherButtonTitles:#"OK",nil];
[infoStoreError show];
}
}
MusicSequenceDisposeTrack(recordSequence, track);
DisposeMusicSequence(recordSequence);
}
}
#end
Related
We can use instruments for various kinds of analysis. But many programmers find this tool to be too complicated and too heavy to bring real value.
Is there a simple way to track all objects of a specific class, and for each to know who exactly was allocating them and to verify that they are being freed correctly?
The answer is yes! there is a way, and I'll demo it in my answer below
Tracking allocations easily:
How to use: you can put the 150 lines of code below into a file named AllocTracker.m and drag it into your project files.
Use the check box at the right pane of Xcode to enable/disable it in your compilation target.
What you'll get?
when enabled, this module will track all allocations and deallocations of UIImage objects and log them. (It can easily be modified for tracking other classes.)
In addition to logging every allocation and deallocation, it will periodically (currently every 15 seconds) dump all objects which are currently allocated, with some added info and the call stack which allocated them.
What is the added value?
This code was used in big projects to get rid of orphan objects which were left allocated without notice, allowing to significantly reduce the memory footprint of the app and fix memory leaks.
So here is the code for AllocTracker.m:
#define TRACK_ALLOCATIONS
#ifdef TRACK_ALLOCATIONS
#import <UIKit/UIKit.h>
#define TIMER_INTERVAL 15
#implementation UIApplication(utils)
+(NSString *)dateToTimestamp:(NSDate *)date
{
if (date == nil) {
date = [NSDate date];
}
static NSDateFormatter *dateFormatter = nil;
if (!dateFormatter) {
dateFormatter = [[NSDateFormatter alloc] init];
dateFormatter.locale = [[NSLocale alloc] initWithLocaleIdentifier:#"en_US_POSIX"];
[dateFormatter setDateFormat:#"HH:mm:ss.S"];
}
NSString *ts = [dateFormatter stringFromDate:date];
return ts;
}
+(NSString*) getCaller:(int)stackDepth
{
#ifndef DEBUG
return #"NON DBG";
#else
NSArray *symbols = [NSThread callStackSymbols];
int lastIndex = (int)(symbols.count - 1);
if (lastIndex < 3) {
return #"NO DATA";
}
NSMutableString *result = [NSMutableString string];
int foundCount = 0;
for (int ix=3; ix <= lastIndex; ix++) {
NSString *line = symbols[ix];
NSRange rng1 = [line rangeOfString:#"["];
if (rng1.location == NSNotFound) {
continue;
}
NSRange rng2 = [line rangeOfString:#"]"];
NSString *caller = [line substringWithRange:NSMakeRange(rng1.location+1, rng2.location-rng1.location-1)];
if (foundCount > 0) { //not first
[result appendString:#"<--"];
}
[result appendString:caller];
if (++foundCount == stackDepth) {
break;
}
}
return (foundCount > 0) ? result : #"NO SYMBOL";
#endif
}
#end
#implementation UIImage(memoryTrack)
static NSMapTable *g_allocsMap;
static NSTimer *g_tmr;
static NSDate *g_lastDump = nil;
+(void)gotTimer:(NSTimer *)timer
{
[self dumpAllocs];
}
+(void)startTimer
{
static int count = 0;
g_tmr = [NSTimer scheduledTimerWithTimeInterval:15 target:self selector:#selector(gotTimer:) userInfo:#(count++) repeats:YES];
NSLog(#"starting timer %i", count);
}
+(void)cancelTimer
{
[g_tmr invalidate];
g_tmr = nil;
}
+(void)dumpAllocs
{
dispatch_async(dispatch_get_global_queue(QOS_CLASS_BACKGROUND, 0), ^{
NSMutableString *str = [NSMutableString string];
[str appendString:#"\n#$# ========== Non-freed UIImages =========\n"];
NSMutableArray *sorted = [NSMutableArray array];
//make sure map is not changed while enumerating
static int s_ts_start = -1;
#synchronized (g_allocsMap) {
NSEnumerator *keysEnum = [g_allocsMap keyEnumerator];
UIImage *img;
while (img = [keysEnum nextObject]) {
NSString *value = [g_allocsMap objectForKey:img];
if (value) { //might be nulled because declared as weak
NSUInteger memUsed = CGImageGetHeight(img.CGImage) * CGImageGetBytesPerRow(img.CGImage);
NSString *objData = [NSString stringWithFormat:#"mem=%5ikb, size=%4ix%-4i", (int)(memUsed/1024), (int)img.size.width, (int)img.size.height];
NSString *line = [NSString stringWithFormat:#"%p - %# [%#]\n", img, objData, value];
if (s_ts_start<0) {
s_ts_start = (int)[line rangeOfString:#"["].location + 1;
}
if (line.length > (s_ts_start+10)) {
[sorted addObject:line];
}
}
}
}
if (sorted.count > 0) {
[sorted sortUsingComparator: ^NSComparisonResult(NSString *s1, NSString *s2)
{
//we expect '0x15a973700 - mem=3600kb, size=640x360 [16:14:27.5: UIIma...'
NSString *ts1 = [s1 substringWithRange:NSMakeRange(s_ts_start, 10)];
NSString *ts2 = [s2 substringWithRange:NSMakeRange(s_ts_start, 10)];
return [ts1 compare:ts2];
}];
int ix = 0;
for (NSString *line in sorted) {
[str appendFormat:#"#$# %3i) %#", ix++, line];
}
}
[str appendString:#"#$# ======================================================\n"];
NSLog(#"%#", str);
});
}
+(instancetype)alloc
{
NSString *caller = [UIApplication getCaller:4];
#synchronized (self) {
id obj = [super alloc];
NSLog(#"#$# UIImage alloc: [%p], caller=[%#]", obj, caller);
NSDate *now = [NSDate date];
NSString *value = [NSString stringWithFormat:#"%#: %#", [UIApplication dateToTimestamp:now], caller];
if (!g_allocsMap) {
g_allocsMap = [NSMapTable mapTableWithKeyOptions:NSMapTableWeakMemory valueOptions:NSMapTableStrongMemory];
}
[g_allocsMap setObject:value forKey:obj];
if (!g_lastDump) {
[self startTimer];
g_lastDump = now;
}
return obj;
}
}
-(void)dealloc
{
NSLog(#"#$# UIImage dealloc: [%#]", self);
}
#end
#endif //TRACK_ALLOCATIONS
How it works?
We create a category of UIImage and set our own version for alloc and dealloc. Every allocated object is saved into an NSMapTable object which works like a dictionary but allow storing object with weak pointers.
For convenience we were adding two methods under UIApplication which can be used by other modules if an appropriate header file is created. One method is for formatting the timestamp, and the other is for reading the call stack (only works in debug builds).
Tip for use:
if you use a real device and install idevicesyslog (brew install libimobiledevice), you can use the terminal to see all allocation debug, like this:
idevicesyslog | grep "#\$#"
I am integrating a weight scale device in our iOS Application. The Device name nutriscale weight scale. I am using apple provided API -CBCentralManager for connecting and getting data from weight scale. I am able to detect services and characteristics of bluetooth device and getting some data from weight scale device after connecting but not able to interpret that data. I am able to get weight if it's below 255 gram. If it goes beyond 255. it gives me weight-255 answer.
Kindly correct me for this.
Here it's my code:
When i call [aPeripheral readValueForCharacteristic:aChar]; A delegate method below is being called.
- (void) peripheral:(CBPeripheral *)aPeripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error {// NSLog(#"Descriptor %#",[characteristic properties]);if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:HELLOBLUETOOTH_CHARACTERISTICS_NAME_UUID]])
{
pName = [[NSString alloc] initWithUTF8String:[[characteristic value]bytes]];
NSError *errorVa;
NSLog(#"KeyfobViewController didUpdateValueForCharacteristic %#", characteristic);
[aPeripheral setNotifyValue:YES forCharacteristic:characteristic];
[self getWeightData:characteristic error:errorVa];
}}
To interpret bytes i wrote this method
(void) getWeightData:(CBCharacteristic *)characteristic error:(NSError *)error{
// Get the Heart Rate Monitor BPM
NSData *data = [characteristic value];// 1
const uint8_t *reportData = [data bytes];
const uint16_t *reportData1 = [data bytes];
uint16_t weightValue = 0;
uint16_t weightValue1 = 0;
if(reportData)
{
if ((reportData[0] & 0x01) == 0) { // 2
// Retrieve the weight from the scale
weightValue = reportData[1];
int result= CFSwapInt16LittleToHost(*(uint16_t *)(&reportData[1]));
}
else
{
weightValue = CFSwapInt32LittleToHost(*(uint32_t *)(&reportData[1])); // 3
int result= CFSwapInt32LittleToHost(*(uint32_t *)(&reportData[1]));
NSLog(#"weightValue1 - %hhu",weightValue);
}
NSMutableArray *arrr = [NSMutableArray new];
uint8_t byte1 = reportData[0];
for (int i = 0; i < 8; i++) {int mask = 1 << i;if ((byte1 & mask) == 0) {[arrr addObject:#"0"];} else {[arrr addObject:#"1"];}}
NSLog(#"values1 - %#%#%#%#%#%#%#%#",arrr[7],arrr[6],arrr[5],arrr[4],arrr[3],arrr[2],arrr[1],arrr[0]);
[arrr removeAllObjects];
for (int i = 0; i < 16; i++) {int mask = 1 << i;if ((weightValue1 & mask) == 0) {[arrr addObject:#"0"];} else {[arrr addObject:#"1"];}}
NSLog(#"values2 - %#%#%#%#%#%#%#%#%#%#%#%#%#%#%#%#",arrr[15],arrr[14],arrr[13],arrr[12],arrr[11],arrr[10],arrr[9],arrr[8],arrr[7],arrr[6],arrr[5],arrr[4],arrr[3],arrr[2],arrr[1],arrr[0]);
// NSLog(#"values0 - %#%#%#%#%#%#%#%#",arrr[0],arrr[1],arrr[2],arrr[3],arrr[4],arrr[5],arrr[6],arrr[7]);
// NSLog(#"values2 - %#%#%#%#%#%#%#%#%#%#%#%#%#%#%#%#",arrr[0],arrr[1],arrr[2],arrr[3],arrr[4],arrr[5],arrr[6],arrr[7],arrr[8],arrr[9],arrr[10],arrr[11],arrr[12],arrr[13],arrr[14],arrr[15]);
}
// Display the weight value to the UI if no error occurred
if( (characteristic.value) || !error )
{ //
NSString *weight = [NSString stringWithFormat:#"%i", weightValue];
if([weight floatValue])
{
NSUserDefaults *defaultObject = [NSUserDefaults standardUserDefaults];
[defaultObject setObject:data forKey:#"data"];
[defaultObject synchronize];
NSString *strWeight=#"";
strWeight = [NSString stringWithFormat:#"%#",weight];
strWeight = [NSString stringWithFormat:#"%.1f",[strWeight floatValue]*0.035274];//
//[self bluetoothResponseToClass];
}
}
return;}
Kindly help me in this code. What am i doing wrong ?
Replace your function with below function
-(void) getWeightData:(CBCharacteristic *)characteristic error:(NSError *)error
{
// Get the Heart Rate Monitor BPM
NSData *data = [characteristic value];// 1
const uint8_t *reportData = [data bytes];
uint16_t weightValue = 0;
uint16_t chkValue = 0;
if(reportData)
{
chkValue = reportData[0];
weightValue = CFSwapInt32LittleToHost(*(uint32_t *)(&reportData[1]));
int var = (chkValue % 160);
weightValue = weightValue + var * 256;
NSMutableArray *arrr = [NSMutableArray new];
uint8_t byte1 = reportData[0];
for (int i = 0; i < 8; i++) {int mask = 1 << i;if ((byte1 & mask) == 0) {[arrr addObject:#"0"];} else {[arrr addObject:#"1"];}}
NSLog(#"values1 - %#%#%#%#%#%#%#%#",arrr[7],arrr[6],arrr[5],arrr[4],arrr[3],arrr[2],arrr[1],arrr[0]);
[arrr removeAllObjects];
for (int i = 0; i < 16; i++) {int mask = 1 << i;if ((chkValue & mask) == 0) {[arrr addObject:#"0"];} else {[arrr addObject:#"1"];}}
NSLog(#"values2 - %#%#%#%#%#%#%#%#%#%#%#%#%#%#%#%#",arrr[15],arrr[14],arrr[13],arrr[12],arrr[11],arrr[10],arrr[9],arrr[8],arrr[7],arrr[6],arrr[5],arrr[4],arrr[3],arrr[2],arrr[1],arrr[0]);
}
// Display the weight value to the UI if no error occurred
if( (characteristic.value) || !error )
{ //
NSString *weight = [NSString stringWithFormat:#"%i", weightValue];
lbl_Weight.text = [NSString stringWithFormat:#"%hu", weightValue];
if([weight floatValue])
{
NSUserDefaults *defaultObject = [NSUserDefaults standardUserDefaults];
[defaultObject setObject:data forKey:#"data"];
[defaultObject synchronize];
NSString *strWeight=#"";
strWeight = [NSString stringWithFormat:#"%#",weight];
strWeight = [NSString stringWithFormat:#"%.1f",[strWeight floatValue]*0.035274];//
//[self bluetoothResponseToClass];
}
}
return;
}
I am Integrating Apple Pay Integration using cyberSource in my Application .
what i have done so for .
1- I have created merchant ID
2- I have created test account on http://www.cybersource.com/
3- I have downloaded cybersource SDK for iOS.
4- I have managed to run Demo Application downloaded with SDK.
5- When i run demo App i am getting this error.
"Transaction Details .Accepted: No .Auth Amount: (null) Error: Unknown error"
I have provided my merchant account correctly . There are other fields as well which i am not sure how to get those values
static NSString* kMetadataEncodedValue = #"RklEPUNPTU1PTi5MRy5JTkFQUC5QQVlNRU5U";
static NSString* const kPaymentSolutionDefaultValue = #"001";
static NSString* const kEnvTest = #"test";
static NSString* const kEnvLive = #"live";
static NSString* const kKeyMerchantID = #"merchant_otm_eyebuy_acct";
static NSString* const kKeyMerchantExternalID = #"merchant_otm_eyebuy_acct";
static NSString* const kKeyTransactionKey = #"transactionKey";
static NSString* const kKeyEncryptedBlob = #"encryptedBlob";
static NSString* const kKeyEnv = #"env";
- (IBAction)payButtonTouchDown:(id)sender {
[self.amountTextField resignFirstResponder];
NSString* requestType = [self.requestTypeSelection titleForSegmentAtIndex:self.requestTypeSelection.selectedSegmentIndex];
[self updateStatusMessage:[NSString stringWithFormat:#"Submitting %# request...", requestType]];
self.payButton.enabled = NO;
NSString *amountText = self.amountTextField.text;
NSDecimalNumber *amountValue = [NSDecimalNumber decimalNumberWithString:amountText];
BOOL isDecimal = amountValue!= nil;
if (isDecimal) {
// TODO: Pass in encrypted payment data from PassKit
[self performRequestWithEncryptedPaymentData:self.selectedAccountData[kKeyEncryptedBlob] withPaymentAmount:amountValue];
}
else {
self.payButton.enabled = YES;
self.statusText.text = #"Enter valid Amount";
}
}
- (IBAction)requestTypeSelectionValueChanged:(UISegmentedControl *)sender {
[self updateRequestSelection];
}
-(void) updateRequestSelection {
NSString* requestType = [self.requestTypeSelection titleForSegmentAtIndex:self.requestTypeSelection.selectedSegmentIndex];
[self updateStatusMessage:[NSString stringWithFormat:#"Tap '%#' to %# request.", self.payButton.currentTitle, requestType]];
}
- (void) updateStatusMessage: (NSString*) message
{
self.statusText.text = message;
self.payButton.enabled = YES;
}
- (void)performRequestWithEncryptedPaymentData: (NSString*) encryptedPaymentData withPaymentAmount: (NSDecimalNumber*) paymentAmount
{
VMposItem *item = [[VMposItem alloc] init];
item.name = NSLocalizedString(#"Item no 1", nil);
item.price = paymentAmount;
VMposTransactionObject *transactionObject = [VMposTransactionObject createTransaction:VMPOS_TRANSACTION_PAYMENT];
[transactionObject addItem:item];
[transactionObject calculateTotals];
// TODO: Encrypted Payment is created by client application based
// on specification from SOAP API. The following values are just place holders
VMposEncryptedPayment* payment = [VMposEncryptedPayment new];
payment.encodedData = encryptedPaymentData;
payment.encodedMetadata = kMetadataEncodedValue;
payment.paymentSolution = kPaymentSolutionDefaultValue;
// Purchase details
VMposPurchaseDetails* purchaseDetails = [VMposPurchaseDetails new];
purchaseDetails.partialIndicator = NO;
// Sample Billing information
VMposAddress* billTo = [VMposAddress new];
billTo.firstName = #"John";
billTo.lastName = #"Doe";
billTo.email = #"john.doe#yahoo.com";
billTo.street1 = #"1234 Pine St.";
billTo.city = #"Redmond";
billTo.state = #"WA";
billTo.postalCode = #"98052";
billTo.country = #"US";
// Save transaction information
transactionObject.encryptedPayment = payment;
transactionObject.purchaseDetails = purchaseDetails;
transactionObject.purchaseDetails.commerceIndicator = #"internet";
transactionObject.transactionCode = #"ref_code_12345678";
transactionObject.billTo = billTo;
// Build fingerprint
//--WARNING!----------------
// Finger print generation requires the transaction key. This should
// be done at the server. It is shown here only for Demo purposes.
NSString* merchantID = self.selectedAccountData[kKeyMerchantID];
NSString* fingerprint = [self buildFingerprintWithTransaction:transactionObject withMerchantId:merchantID];
NSLog(#"Fingerprint: %#", fingerprint);
VMposGateway* gateway = [VMposGateway sharedInstance];
[gateway initSessionWithUserName:merchantID withMerchantId:merchantID withFingerprint: fingerprint withDelegate:self];
if (self.selectedAccountData[kKeyEnv] == kEnvLive) {
[VMposSettings sharedInstance].cybsEnvironment = ENV_LIVE;
}
else
{
[VMposSettings sharedInstance].cybsEnvironment = ENV_TEST;
}
if (self.requestTypeSelection.selectedSegmentIndex == 0)
{
[gateway performAuthorizationWithTransaction:transactionObject withDelegate:self];
}
else
{
[gateway performSaleWithTransaction:transactionObject withDelegate:self];
}
}
- (void)viewDidLoad
{
[super viewDidLoad];
[self configureAccounts];
[self updateStatusMessage:[NSString stringWithFormat:#"Tap '%#' to submit a test request.", self.payButton.currentTitle]];
self.amountTextField.keyboardType = UIKeyboardTypeDecimalPad;
self.amountTextField.text = #"1.09";
[self.requestTypeSelection setSelectedSegmentIndex:0];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
// returns the number of 'columns' to display.
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {
return 1;
}
// returns the # of rows in each component..
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {
return self.configuredAccounts.count;
}
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
{
NSDictionary* rowData = self.configuredAccounts[row];
return [NSString stringWithFormat:#"%# (%#)", rowData[kKeyMerchantID], rowData[kKeyEnv]];
}
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {
self.selectedAccountData = self.configuredAccounts[row];
}
//! Callback for user session initialization
- (void) didInitUserSession: (VMposUserSession*) paramUserSession withError:(VMposError*)paramError {
}
//! provides feedback from finished authorization transaction request
/*!
\param paramResponseData gateway data retrieved from server (contains information about transaction status)
\param paramError an error if request failed
*/
- (void) authorizationFinishedWithGatewayResponse:(VMposGatewayResponse *)paramResponseData
withError:(VMposError *)paramError {
self.authorized = YES;
[self updateStatusMessageWithResponse: (VMposGatewayResponse *)paramResponseData withError: paramError];
}
//! provides feedback from finished sale request
/*!
\param paramResponseData gateway data retrieved from server (contains information about transaction status)
\param paramError an error if request failed
*/
- (void) saleFinishedWithGatewayResponse:(VMposGatewayResponse *)paramResponseData
withError:(VMposError *)paramError
{
self.authorized = YES;
[self updateStatusMessageWithResponse: (VMposGatewayResponse *)paramResponseData withError: paramError];
}
- (void) updateStatusMessageWithResponse: (VMposGatewayResponse *)paramResponseData withError: (NSError*) paramError
{
NSMutableString* s = [NSMutableString new];
if (paramResponseData)
{
[s appendString: #"\nTransaction Details:"];
[s appendFormat: #"\n * Accepted: %#", paramResponseData.isAccepted ? #"Yes" : #"No"];
[s appendFormat: #"\n * Auth Amount: %#", paramResponseData.authorizedAmount.stringValue];
}
if (paramError)
{
[s appendFormat:#"\nError: %#", paramError.localizedDescription];
}
[self updateStatusMessage:s];
}
/*
----------WARNING!----------------
Finger print generation requires the transaction key. This should
be done at the server. It is shown here only for Demo purposes.
*/
-(NSString*) buildFingerprintWithTransaction: (VMposTransactionObject*) transactionObject withMerchantId: (NSString*) merchantId {
NSDate* dateNow = [NSDate date];
NSString* fingerprintDateString = [MPDemoViewController formatFingerprintDate:dateNow];
NSString* merchantTransKey = self.selectedAccountData[kKeyTransactionKey];
NSString* fgComponents = [NSString stringWithFormat:#"%#%#%#%#%#", [MPDemoViewController stringSha1:merchantTransKey], merchantId, transactionObject.transactionCode, [transactionObject.totalAmount gatewayPriceString], fingerprintDateString];
NSString* hashedFgComponents = [MPDemoViewController stringHmacSha256:fgComponents];
return [NSString stringWithFormat:#"%##%#", hashedFgComponents, fingerprintDateString];
}
+(NSString*) formatFingerprintDate: (NSDate*) date {
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
NSTimeZone* tz = [NSTimeZone timeZoneWithName:#"UTC"];
[dateFormatter setDateFormat:#"yyyy-MM-dd'T'HH:mm:ss'Z'"];
[dateFormatter setTimeZone:tz];
return [dateFormatter stringFromDate:date];
}
+ (NSString *)stringSha1:(NSString *)value
{
const char *cstr = [value cStringUsingEncoding:NSUTF8StringEncoding];
NSData *data = [NSData dataWithBytes:cstr length:value.length];
uint8_t digest[CC_SHA1_DIGEST_LENGTH];
// This is an iOS5-specific method.
// It takes in the data, how much data, and then output format, which in this case is an int array.
CC_SHA1(data.bytes, (uint)data.length, digest);
return [self stringHexEncode:digest withLength:CC_SHA1_DIGEST_LENGTH];
}
+ (NSString *)stringSha256:(NSString *)value
{
const char *cstr = [value cStringUsingEncoding:NSUTF8StringEncoding];
NSData *data = [NSData dataWithBytes:cstr length:value.length];
uint8_t digest[CC_SHA256_DIGEST_LENGTH];
// This is an iOS5-specific method.
// It takes in the data, how much data, and then output format, which in this case is an int array.
CC_SHA256(data.bytes, (uint)data.length, digest);
return [self stringHexEncode:digest withLength:CC_SHA256_DIGEST_LENGTH];
}
+ (NSString *)stringHmacSha256:(NSString *)value
{
CCHmacContext ctx;
const char* utf8ValueString = [value UTF8String];
uint8_t hmacData[CC_SHA256_DIGEST_LENGTH];
CCHmacInit(&ctx, kCCHmacAlgSHA256, utf8ValueString, strlen(utf8ValueString));
CCHmacUpdate(&ctx, utf8ValueString, strlen(utf8ValueString));
CCHmacFinal(&ctx, hmacData);
return [self stringHexEncode:hmacData withLength:CC_SHA256_DIGEST_LENGTH];
}
+(NSString*) stringHexEncode: (uint8_t*) data withLength: (NSInteger) dataLength {
NSMutableString* output = [NSMutableString stringWithCapacity:dataLength * 2];
// Parse through the CC_SHA256 results (stored inside of digest[]).
for(int i = 0; i < dataLength; i++) {
[output appendFormat:#"%02x", data[i]];
}
return output;
}
+ (NSString*)base64forData:(NSData*)theData {
const uint8_t* input = (const uint8_t*)[theData bytes];
NSInteger length = [theData length];
static char table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
NSMutableData* data = [NSMutableData dataWithLength:((length + 2) / 3) * 4];
uint8_t* output = (uint8_t*)data.mutableBytes;
NSInteger i;
for (i=0; i < length; i += 3) {
NSInteger value = 0;
NSInteger j;
for (j = i; j < (i + 3); j++) {
value <<= 8;
if (j < length) {
value |= (0xFF & input[j]);
}
}
NSInteger theIndex = (i / 3) * 4;
output[theIndex + 0] = table[(value >> 18) & 0x3F];
output[theIndex + 1] = table[(value >> 12) & 0x3F];
output[theIndex + 2] = (i + 1) < length ? table[(value >> 6) & 0x3F] : '=';
output[theIndex + 3] = (i + 2) < length ? table[(value >> 0) & 0x3F] : '=';
}
return [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding] ;
}
From where i can get all these values . it will be highly appreciated if some one in list all steps involved in Apple pay integration through CyberSource.
Also Please do not refer me to apple developer as i have read out details about Apple Pay on Apple Developer.
I do small iPhone app and I need to get IP range and iterate through it with objective C. I can get local IP, netmask. Also I have found on SO solution how to get Broadcast address. But how can I get also Network address? By knowing Network address what is first in the local network and Broadcast address what is last in the local network I would like to iterate all IP from that range. Simply call it and see response. How can I do that?
Solution to get Broadcast from https://stackoverflow.com/a/21077257
#include <net/ethernet.h>
#include <arpa/inet.h>
NSString *localIPAddress = #"192.168.1.10";
NSString *netmaskAddress = #"255.255.192.0";
// Strings to in_addr:
struct in_addr localAddr;
struct in_addr netmaskAddr;
inet_aton([localIPAddress UTF8String], &localAddr);
inet_aton([netmaskAddress UTF8String], &netmaskAddr);
// The broadcast address calculation:
localAddr.s_addr |= ~(netmaskAddr.s_addr);
// in_addr to string:
NSString *broadCastAddress = [NSString stringWithUTF8String:inet_ntoa(localAddr)];
Update: from netmaskAddress I can get number of hosts in the network. I only need to work with IPs. The question now is how can I get next IP from the given? For example I have
NSString *ip = "192.168.1.5"
How can I get "192.168.1.6" with objective C?
I do not recommend do bit operations on this kind of IP's (in_addr) because if you will take a look inside the bytes are reverse ordered.
The code below is printing the device ip, network ip, netmask and broadcast address and all ip's in network range. It might be helpful. Enjoy!
NetworkInformation *network = [[NetworkInformation alloc] init];
NSLog(#"%#", network);
for(NSString *ip in network.ipsInRange){
NSLog(#"ip: %#", ip);
}
NetworkInformation.h
#import <Foundation/Foundation.h>
#interface NetworkInformation : NSObject
#property (nonatomic, retain) NSString *deviceIP;
#property (nonatomic, retain) NSString *netmask;
#property (nonatomic, retain) NSString *address;
#property (nonatomic, retain) NSString *broadcast;
#property (nonatomic, retain) NSArray *ipsInRange;
- (void)updateData;
- (NSString *)description;
#end
NetworkInformation.m
#import "NetworkInformation.h"
#import <arpa/inet.h>
#import <ifaddrs.h>
#implementation NetworkInformation
- (id)init {
self = [super init];
if (self) {
[self updateData];
}
return self;
}
-(void)updateData {
[self updateDataFromWifiNetwork];
self.address = [self getNetworkAddress];
self.ipsInRange = [self getIPsInRange];
}
- (void)updateDataFromWifiNetwork {
self.deviceIP = nil;
self.netmask = nil;
self.broadcast = nil;
struct ifaddrs *interfaces = NULL;
struct ifaddrs *temp_addr = NULL;
int success = 0;
success = getifaddrs(&interfaces);
if (success == 0){
temp_addr = interfaces;
while(temp_addr != NULL){
if(temp_addr->ifa_addr->sa_family == AF_INET){
if([[NSString stringWithUTF8String:temp_addr->ifa_name] isEqualToString:#"en0"]){
self.deviceIP = [NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_addr)->sin_addr)];
self.netmask = [NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_netmask)->sin_addr)];
self.broadcast = [NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_dstaddr)->sin_addr)];
}
}
temp_addr = temp_addr->ifa_next;
}
}
freeifaddrs(interfaces);
if(!self.deviceIP || !self.netmask){
NSLog(#"error in updateDataFromWifiNetwork, device ip: %# netmask: %#", self.deviceIP, self.netmask);
}
}
-(NSString*)getNetworkAddress {
if(!self.deviceIP || !self.netmask){
return nil;
}
unsigned int address = [self convertSymbolicIpToNumeric:self.deviceIP];
address &= [self convertSymbolicIpToNumeric:self.netmask];
return [self convertNumericIpToSymbolic:address];
}
-(NSArray*)getIPsInRange {
unsigned int address = [self convertSymbolicIpToNumeric:self.address];
unsigned int netmask = [self convertSymbolicIpToNumeric:self.netmask];
NSMutableArray *result = [[NSMutableArray alloc] init];
int numberOfBits;
for (numberOfBits = 0; numberOfBits < 32; numberOfBits++) {
if ((netmask << numberOfBits) == 0){
break;
}
}
int numberOfIPs = 0;
for (int n = 0; n < (32 - numberOfBits); n++) {
numberOfIPs = numberOfIPs << 1;
numberOfIPs = numberOfIPs | 0x01;
}
for (int i = 1; i < (numberOfIPs) && i < numberOfIPs; i++) {
unsigned int ourIP = address + i;
NSString *ip = [self convertNumericIpToSymbolic:ourIP];
[result addObject:ip];
}
return result;
}
-(NSString*)convertNumericIpToSymbolic:(unsigned int)numericIP {
NSMutableString *sb = [NSMutableString string];
for (int shift = 24; shift > 0; shift -= 8) {
[sb appendString:[NSString stringWithFormat:#"%d", (numericIP >> shift) & 0xff]];
[sb appendString:#"."];
}
[sb appendString:[NSString stringWithFormat:#"%d", (numericIP & 0xff)]];
return sb;
}
-(unsigned int)convertSymbolicIpToNumeric:(NSString*)symbolicIP {
NSArray *st = [symbolicIP componentsSeparatedByString: #"."];
if (st.count != 4){
NSLog(#"error in convertSymbolicIpToNumeric, splited string count: %lu", st.count);
return 0;
}
int i = 24;
int ipNumeric = 0;
for (int n = 0; n < st.count; n++) {
int value = [(NSString*)st[n] intValue];
if (value != (value & 0xff)) {
NSLog(#"error in convertSymbolicIpToNumeric, invalid IP address: %#", symbolicIP);
return 0;
}
ipNumeric += value << i;
i -= 8;
}
return ipNumeric;
}
-(NSString*)description {
return [NSString stringWithFormat: #"\nip:%#\nnetmask:%#\nnetwork:%#\nbroadcast:%#", self.deviceIP, self.netmask, self.address, self.broadcast];
}
#end
I have a project needs to use the sqlite in it.
And I also create a singleton object to manage my sql
But I just found out that when I read data in sql,the memory just keep growing,and it seems never release.
the following code is how I read data in my singleton object
- (NSArray*)loadRecordPathData{
#synchronized(self)
{
if(sqlite3_open([FILEPATH UTF8String], &database) == SQLITE_OK)
{
NSMutableArray *pathNames = [[NSMutableArray alloc] init];
NSString *query = #"SELECT * FROM pathData";
sqlite3_stmt *statement;
if (sqlite3_prepare_v2(database, [query UTF8String], -1, &statement, nil)
== SQLITE_OK) {
while (sqlite3_step(statement) == SQLITE_ROW) {
BBRecordPathData *recordPathData = [BBRecordPathData new];
int readed = (int) sqlite3_column_int(statement, 0);
int isFavorite = (int) sqlite3_column_int(statement, 1);
char *pathDescroption = (char *) sqlite3_column_text(statement, 2);
char *pathStopTime = (char *) sqlite3_column_text(statement, 3);
char *pathStartTime = (char *) sqlite3_column_text(statement, 4);
int pathChallange = (int) sqlite3_column_int(statement, 5);
char *pathName = (char *) sqlite3_column_text(statement, 6);
NSString *path_StartTime = (pathStartTime) ?[[NSString alloc] initWithUTF8String:pathStartTime] : nil;
NSString *path_StopTime = (pathStopTime) ? [[NSString alloc] initWithUTF8String:pathStopTime] : nil;
NSString *path_Name = (pathName) ? [[NSString alloc] initWithUTF8String:pathName]:nil;
NSString *path_description = (pathDescroption) ? [[NSString alloc] initWithUTF8String:pathDescroption]: nil;
recordPathData.recordPathName = path_Name;
recordPathData.recordPathStartTime = path_StartTime;
recordPathData.recordPathStopTime = path_StopTime;
recordPathData.recordPathDescription = path_description;
recordPathData.challange = pathChallange;
recordPathData.isFavorite = isFavorite;
recordPathData.readed = readed;
//get contain locations
recordPathData.cotainLocations = [self getLocationsPointFromStartTimeTag:recordPathData.recordPathStartTime]; //<----from another table
if (recordPathData.cotainLocations.count == 0 || recordPathData.cotainLocations.count < 4) {
recordPathData.distance = #"0.000KM";
}else{
NSString *unite = #"M";
float distanceInMeter = 0.0;
for (int i = 3; i < recordPathData.cotainLocations.count; i++) {
if (i <= recordPathData.cotainLocations.count - 2){
CLLocation *startPoint = recordPathData.cotainLocations[i];
CLLocation *endPoint = recordPathData.cotainLocations[i + 1];
distanceInMeter += [startPoint distanceFromLocation:endPoint];
}else{
recordPathData.distance = #"0.000KM";
}
}
if (distanceInMeter > 1000.0) {
unite = #"KM";
distanceInMeter /= 1000.0;
recordPathData.distance = [NSString stringWithFormat:#"%.2f%#",distanceInMeter,unite];
}else{
recordPathData.distance = [NSString stringWithFormat:#"%i%#",(int)distanceInMeter,unite];
}
}
[pathNames addObject:recordPathData];
}
sqlite3_finalize(statement);
sqlite3_close(database);
}
return pathNames;
}
return nil;
}
}
any suggestion or advice will be a great help , thanks!
If you're using SQLite from Objective C, you should use a wrapper, such as FMDatabase. It will handle the memory management for you and ensure you don't leak.