Trouble with NSString: using a controller to set an NSTextField? - objective-c

I am using Xcode 4 writing a simple program to generate text based on user input. Im reading from two text fields successfully, but I am unable to send the result to a separate NSTextField. I'm confident I've made all the right connections in IB, and I'm sending the NSTextField the setStringValue method. I have created a ScaleGenerator object that I believe may be improperly creating the string itself. My Controller header looks like this:
#import <Cocoa/Cocoa.h>
#interface Controller : NSObject
{
IBOutlet NSTextField * notesField;
IBOutlet NSTextField * midiField;
IBOutlet NSTextField * resultField;
IBOutlet id scalegenerator;
}
- (IBAction) generate: (id) sender;
#end // Controller
The Controller implementation looks like this:
#import "Controller.h"
#import "ScaleGenerator.h"
#import <Foundation/foundation.h>
#implementation Controller
- (IBAction) generate: (id) sender
{
int midinote;
int notes;
NSString * scale;
midinote = [midiField intValue];
if(midinote < 0 || midinote > 127) {
NSRunAlertPanel(#"Bad MIDI", #"That MIDI note is out of range! (0 - 127)", #"OK", nil, nil);
return;
}
notes = [notesField intValue];
if(notes < 2 || notes > 24) {
NSRunAlertPanel(#"Bad Scale Size", #"You must have at least two notes in your scale, and no more than 25 notes!", #"OK", nil, nil);
return;
}
scale = [scalegenerator generateScale: midinote and: notes];
[resultField setStringValue:scale];
}
#end
My ScaleGenerator code looks like this:
#import "ScaleGenerator.h"
#import <math.h>
#implementation ScaleGenerator
- (NSMutableString *) generateScale: (int) midinote and: (int) numberOfNotes
{
double frequency, ratio;
double c0, c5;
double intervals[24];
int i;
NSMutableString * result;
/* calculate standard semitone ratio in order to map the midinotes */
ratio = pow(2.0, 1/12.0); // Frequency Mulitplier for one half-step
c5 = 220.0 * pow(ratio, 3); // Middle C is three semitones above A220
c0 = c5 * pow(0.5, 5); // Lowest MIDI note is 5 octaves below middle C
frequency = c0 * pow(ratio, midinote); // the first frequency is based off of my midinote
/* calculate ratio from notes and fill the frequency array */
ratio = pow(2.0, 1/numberOfNotes);
for(i = 0; i < numberOfNotes; i++) {
intervals[i] = frequency;
frequency *= ratio;
}
for(i = 0; i < n; i++){
[result appendFormat: #"#%d: %f", numberOfNotes + 1, intervals[i]];
}
return (result);
}
#end // ScaleGenerator
My ScaleGenerator object has one function, which is where I believe I may be messing things up. What kind of string can I iteratively append formatted text to?? And what method do I call??

You have not allocated/initialized your NSMutableString. Therefore the message appendFormat: goes to nil. Replace the line
NSMutableString * result;
with
NSMutableString * result = [[NSMutableString alloc] init];

Related

Using NSUInteger Input to insertObject:___ atIndex:___

I'm trying to create a simple commandline tic-tac-toe game using an NSMutableArray.
Created a class called "Board" with the method "getPosition"
(I'm assuming this is the best way to get a user input)
I'm asking for position, then casting from int to NSUInteger)
#import "Board.h"
#implementation Board
-(void)getPosition;
{
int enteredPosition;
scanf("%i", &enteredPosition);
NSUInteger nsEnteredPosition = (NSUInteger ) enteredPosition;
NSLog(#"Position = %lu", (unsigned long)nsEnteredPosition);
}
#import <Foundation/Foundation.h>
#import "Board.h"
int main(int argc, const char * argv[])
{
#autoreleasepool {
NSString *currentPlayer;
NSMutableArray *gameBoard=[[NSMutableArray alloc] initWithCapacity:9];
for(int i; i<=2; i++)
{
if(i %2)
{
currentPlayer=#"X";
}
else
{
currentPlayer=#"O";
}
NSLog(#"Player %#, select an open spot 1 - 9 on the board", currentPlayer);
Board *currentPosition = [[Board alloc] init];
[currentPosition getPosition];
[gameBoard insertObject:currentPlayer atIndex:currentPosition]; //this is where i have a problem
}
As I understand it atIndex requires an NSUInteger parameter, but I'm receiving the error message:
"Incompatible pointer to integer conversion sending 'Board *_strong"
to parameter of type 'NSUInteger' (aka 'unassigned long')
You're using currentPosition as your index which is a Board object. Perhaps [currentPosition getPosition] is supposed to return an NSUInteger. If so, try rewriting the last portion of your code like this:
Board *theBoard = [[Board alloc] init];
NSUInteger currentPosition = [theBoard getPosition];
[gameBoard insertObject:currentPlayer atIndex:currentPosition]; //this is where i have a problem

SegmentedControl Always Zero

I am trying to build an application that rolls dice. Nothing fancy at all. However, I'm using a segmented control to determine the number of dice and the sides of the dice.
Here is the RollPressed code.
#import "DiceBrain.h"
#import "ViewController.h"
#interface ViewController ()
#property (readonly) DiceBrain *brain;
#end
#implementation ViewController
- (DiceBrain *) brain {
if (!brain) brain = [[DiceBrain alloc] init];
return brain;
}
- (IBAction)RollPressed:(id)sender {
int num_dice = dice.selectedSegmentIndex;
int num_sides = sides.selectedSegmentIndex;
NSLog(#"Number of Dice is %u and Number of Sides is %u", num_dice, num_sides);
int result = [self.brain RollDice:num_dice Sides: num_sides];
display.text = [NSString stringWithFormat:#"%g", result];
}
#end
According to NSLog there, I'm always using a zero. Of course, actuating using this logic to roll the dice results in the display showing me something like 3.82652e-308.
The logic used to roll the dice is
- (int)RollDice:(int)dice Sides:(int)num_sides{
total = 0;
for (int i = 0; i < dice; i++) {
total += (arc4random() % num_sides) + 1;
}
return total;
}
What could cause the segmented control to give me such funky results?
Sounds like your IBOutlets for sides and dice are not connected.
Check their value; it's probably NULL.

How to wait finish current audio for playing next audio?

I'm working with cocos2d. How to wait finish current audio for playing next audio? I can't make it with SimpleAudioEngine.
http://www.cocos2d-iphone.org/api-ref/0.99.0/interface_c_d_sound_engine.html
use CDAudioEngine. It have the method you want. By the way SimpleAudioEngine is using CDAudioEngine to play sounds.
EDIT
When your button is clicked first time - play the sound and save the sound's interval to some of your lass variable. Then in next click use this variable to determine the "enough interval". Or just use some maximum.
EDIT 2
If you'll take a look at SimpleAudioEngine implementation you will notice that it's using CDSoundEngine to play sounds. Here is the init method of SimpleAudioEngine:
static SimpleAudioEngine *sharedEngine = nil;
static CDSoundEngine* soundEngine = nil;
static CDAudioManager *am = nil;
static CDBufferManager *bufferManager = nil;
-(id) init
{
if((self=[super init])) {
am = [CDAudioManager sharedManager];
soundEngine = am.soundEngine;
bufferManager = [[CDBufferManager alloc] initWithEngine:soundEngine];
mute_ = NO;
enabled_ = YES;
}
return self;
}
So we can also access to CDSoundEngine:
CDSoundEngine *engine = [CDAudioManager sharedManager].soundEngine;
When calling playEffect method on SimpleAudioEngine (when your button is clicked) save the returned sound id.
ALuint soundId = [[SimpleAudioEngine sharedEngine] playEffect:...];
Now we can get the interval using our CDSoundEngine:
float seconds = [engine bufferDurationInSeconds:soundId];
That's the answer!
By the way you can also stop a sound with CDSoundEngine if you know the sound id.
From CocosDenshion.h
#class CDSoundSource;
#interface CDSoundEngine : NSObject <CDAudioInterruptProtocol> {
bufferInfo *_buffers;
sourceInfo *_sources;
sourceGroup *_sourceGroups;
ALCcontext *context;
int _sourceGroupTotal;
UInt32 _audioSessionCategory;
BOOL _handleAudioSession;
BOOL mute_;
BOOL enabled_;
ALfloat _preMuteGain;
ALenum lastErrorCode_;
BOOL functioning_;
float asynchLoadProgress_;
BOOL getGainWorks_;
//For managing dynamic allocation of sources and buffers
int sourceTotal_;
int bufferTotal;
}
#property (readwrite, nonatomic) ALfloat masterGain;
#property (readonly) ALenum lastErrorCode;//Last OpenAL error code that was generated
#property (readonly) BOOL functioning;//Is the sound engine functioning
#property (readwrite) float asynchLoadProgress;
#property (readonly) BOOL getGainWorks;//Does getting the gain for a source work
/** Total number of sources available */
#property (readonly) int sourceTotal;
/** Total number of source groups that have been defined */
#property (readonly) int sourceGroupTotal;
/** Sets the sample rate for the audio mixer. For best performance this should match the sample rate of your audio content */
+(void) setMixerSampleRate:(Float32) sampleRate;
/** Initializes the engine with a group definition and a total number of groups */
-(id)init;
/** Plays a sound in a channel group with a pitch, pan and gain. The sound could played looped or not */
-(ALuint) playSound:(int) soundId sourceGroupId:(int)sourceGroupId pitch:(float) pitch pan:(float) pan gain:(float) gain loop:(BOOL) loop;
/** Creates and returns a sound source object for the specified sound within the specified source group.
*/
-(CDSoundSource *) soundSourceForSound:(int) soundId sourceGroupId:(int) sourceGroupId;
/** Stops playing a sound */
- (void) stopSound:(ALuint) sourceId;
/** Stops playing a source group */
- (void) stopSourceGroup:(int) sourceGroupId;
/** Stops all playing sounds */
-(void) stopAllSounds;
-(void) defineSourceGroups:(NSArray*) sourceGroupDefinitions;
-(void) defineSourceGroups:(int[]) sourceGroupDefinitions total:(int) total;
-(void) setSourceGroupNonInterruptible:(int) sourceGroupId isNonInterruptible:(BOOL) isNonInterruptible;
-(void) setSourceGroupEnabled:(int) sourceGroupId enabled:(BOOL) enabled;
-(BOOL) sourceGroupEnabled:(int) sourceGroupId;
-(BOOL) loadBufferFromData:(int) soundId soundData:(ALvoid*) soundData format:(ALenum) format size:(ALsizei) size freq:(ALsizei) freq;
-(BOOL) loadBuffer:(int) soundId filePath:(NSString*) filePath;
-(void) loadBuffersAsynchronously:(NSArray *) loadRequests;
-(BOOL) unloadBuffer:(int) soundId;
-(ALCcontext *) openALContext;
/** Returns the duration of the buffer in seconds or a negative value if the buffer id is invalid */
-(float) bufferDurationInSeconds:(int) soundId;
/** Returns the size of the buffer in bytes or a negative value if the buffer id is invalid */
-(ALsizei) bufferSizeInBytes:(int) soundId;
/** Returns the sampling frequency of the buffer in hertz or a negative value if the buffer id is invalid */
-(ALsizei) bufferFrequencyInHertz:(int) soundId;
/** Used internally, never call unless you know what you are doing */
-(void) _soundSourcePreRelease:(CDSoundSource *) soundSource;
#end
I'm using cocos2D 0.99.5
implementation:
-(float) bufferDurationInSeconds:(int) soundId {
if ([self validateBufferId:soundId]) {
float factor = 0.0f;
switch (_buffers[soundId].format) {
case AL_FORMAT_MONO8:
factor = 1.0f;
break;
case AL_FORMAT_MONO16:
factor = 0.5f;
break;
case AL_FORMAT_STEREO8:
factor = 0.5f;
break;
case AL_FORMAT_STEREO16:
factor = 0.25f;
break;
}
return (float)_buffers[soundId].sizeInBytes/(float)_buffers[soundId].frequencyInHertz * factor;
} else {
return -1.0f;
}
}
// to Play the sound
Aluint soundID = [[SimpleAudioEngine sharedEngine] playEffect:#"sound.mp3"];
// to stop the sound you need to use the same soundID when you play it
[[SimpleAudioEngine sharedEngine] stopEffect:soundID];

Lua and Objective C not running script

I am trying to create an objective c interface that encapsulates the functionality of storing and running a lua script (compiled or not.) My code for the script interface is as follows:
#import <Cocoa/Cocoa.h>
#import "Types.h"
#import "lua.h"
#include "lualib.h"
#include "lauxlib.h"
#interface Script : NSObject<NSCoding> {
#public
s32 size;
s8* data;
BOOL done;
}
#property s32 size;
#property s8* data;
#property BOOL done;
- (id) initWithScript: (u8*)data andSize:(s32)size;
- (id) initFromFile: (const char*)file;
- (void) runWithState: (lua_State*)state;
- (void) encodeWithCoder: (NSCoder*)coder;
- (id) initWithCoder: (NSCoder*)coder;
#end
#import "Script.h"
#implementation Script
#synthesize size;
#synthesize data;
#synthesize done;
- (id) initWithScript: (s8*)d andSize:(s32)s
{
self = [super init];
self->size = s;
self->data = d;
return self;
}
- (id) initFromFile:(const char *)file
{
FILE* p;
p = fopen(file, "rb");
if(p == NULL) return [super init];
fseek(p, 0, SEEK_END);
s32 fs = ftell(p);
rewind(p);
u8* buffer = (u8*)malloc(fs);
fread(buffer, 1, fs, p);
fclose(p);
return [self initWithScript:buffer andSize:size];
}
- (void) runWithState: (lua_State*)state
{
if(luaL_loadbuffer(state, [self data], [self size], "Script") != 0)
{
NSLog(#"Error loading lua chunk.");
return;
}
lua_pcall(state, 0, LUA_MULTRET, 0);
}
- (void) encodeWithCoder: (NSCoder*)coder
{
[coder encodeInt: size forKey: #"Script.size"];
[coder encodeBytes:data length:size forKey:#"Script.data"];
}
- (id) initWithCoder: (NSCoder*)coder
{
self = [super init];
NSUInteger actualSize;
size = [coder decodeIntForKey: #"Script.size"];
data = [[coder decodeBytesForKey:#"Script.data" returnedLength:&actualSize] retain];
return self;
}
#end
Here is the main method:
#import "Script.h"
int main(int argc, char* argv[])
{
Script* script = [[Script alloc] initFromFile:"./test.lua"];
lua_State* state = luaL_newstate();
luaL_openlibs(state);
luaL_dostring(state, "print(_VERSION)");
[script runWithState:state];
luaL_dostring(state, "print(_VERSION)");
lua_close(state);
}
And the lua script is just:
print("O Hai World!")
Loading the file is correct, but I think it messes up at pcall.
Any Help is greatly appreciated.
Heading
Your code is so complex that there are no obvious faults. However, your next step should be to check the return value from lua_pcall. If it is nonzero, there will be an error message on the top of the stack which you can print via
fprintf(stderr, "Pcall failed: %s\n", lua_tostring(state, -1));
If you don't get a useful error message, my next step would be to dump the Lua stack. How many elements are on it? What is the (Lua) type of each element? What is the value. Functions lua_top, and luaL_typename will be useful. To print the value you will have to switch on the results of lua_type. Good luck.
I didn't run your code. But at first glance, I found that the signature of initWithScript: are different between header file (using u8*) and source file (using s8*).

program not displaying simple side values for my triangle object properly in nslog

Project file here if you want to download: http://files.me.com/knyck2/918odc
So I am working on the book "programming in Objective c 2.0" and working on exercise 8.5, where you have to build a bunch of classes and subclass a homemade abstract class into a square class a triangle class and a circle class. you also have to calculate the area and perimiter/circumference through methods on each object and display it on nslog.
Everything is pretty much set, but some weird values are being returned when i display the size of each side from my triangle class and I'm not sure why. one of the sides display as 0.000000 and the other two display as these huge floats/doubles:
521556413499497987605515504756958465074645713473678706698073680750705671496313493175192637227720116636212033961634738517717834352497805734697302078530634879721347399811072.000000
and
661675923659048238438515844320261245751425513854584815925028483891542482488445146590620251584462848.000000
When i go to debug it appears as if all values assign correctly so i am at a loss as to why this is displaying so funkily.
Thanks for any help you can provide,
Nick
here's the main:
#import <Foundation/Foundation.h>
#import "Rectangle.h"
#import "Triangle.h"
#import "Circle.h"
int main (int argc, const char * argv[])
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
Rectangle *myRect = [[Rectangle alloc] init];
Circle *myCircle = [[Circle alloc] init];
Triangle *myTriangle = [[Triangle alloc] init];
myRect.fillColor = 12345;
myRect.filled = NO;
myRect.lineColor = 29999;
[myRect setWidth:15.3 andHeight:22.3];
NSLog(#"the rectangle has a filled color of %i,line color of %i",
myRect.fillColor, myRect.lineColor);
if (myRect.filled == YES)
NSLog(#"The rectangle is also filled");
else if (myRect.filled == NO)
NSLog(#"The rectangle is not filled");
NSLog(#" rectangle %f, %f, area %f, perimeter %f",
myRect.w , myRect.h, myRect.area, myRect.perimeter);
myCircle.fillColor = 15555;
myCircle.filled = NO;
myCircle.lineColor = 32349;
[myCircle setR:15.2];
NSLog(#"the circle has a radius of %f ,color of %i, line color of %i",
myCircle.r, myCircle.fillColor, myCircle.lineColor);
NSLog(#"Also the circles area is %f and the circumference is %f",
myCircle.area, myCircle.circumference );
myTriangle.fillColor = 71611;
myTriangle.filled = NO;
myTriangle.lineColor = 78998;
[myTriangle setSide1:13];
[myTriangle setSide2:19];
[myTriangle setSide3: 27.5];
NSLog(#"triangle sides %g, %g and %g."), // << error
myTriangle.side1 , myTriangle.side2 , myTriangle.side3 ;
NSLog(#"triangle area %f, perimeter %f.",
myTriangle.area, myTriangle.perimeter );
NSLog(#"triangle fill color %i, line color %i",
myTriangle.fillColor, myTriangle.lineColor);
[myCircle release];
[myRect release];
[myTriangle release];
[pool drain];
return 0;
}
and here's the interface and implementation:
#import <Foundation/Foundation.h>
#import "GraphicObject.h"
#interface Triangle : GraphicObject
{
double side1;
double side2;
double side3;
}
#property double side1, side2, side3;
-(void) setSides: (double)s1: (double)s2 : (double)s3;
-(double) area;
-(double) perimeter;
#end
Triangle.m
#import "Triangle.h"
#import <math.h>
#implementation Triangle
#synthesize side1, side2, side3;
-(void) setSides: (double) s1: (double) s2:(double) s3
{
side1 = s1;
side2 = s2;
side3 = s3;
}
-(double) area
{
return sqrt( (side1 + side2 + side3)
* (side1 + side2 - side3)
* (side2 + side3 - side1)
* (side3 + side1 - side2) / 16);
}
-(double) perimeter
{
return side1 + side2 + side3;
}
#end
also here is the super class, GraphicObject.h
#import <Foundation/Foundation.h>
#interface GraphicObject : NSObject
{
int fillColor;
BOOL filled;
int lineColor;
}
#property int fillColor, lineColor;
#property BOOL filled;
#end
GraphicObject.m
#import "GraphicObject.h"
#implementation GraphicObject
#synthesize fillColor, lineColor, filled;
#end
The problem is this line:
NSLog(#"the triangle has the sides of sizes %g, %g and %g."), myTriangle.side1 , myTriangle.side2 , myTriangle.side3 ;
Using ) before the , means that your call to NSLog provides no values to substitute for those %g when formatting for output. It appears unintentional, as my old friend used to say "All errors stem from copy and paste.... all of them".
The fix is to move the ) to just before the ; like so:
NSLog(#"the triangle has the sides of sizes %g, %g and %g.", myTriangle.side1 , myTriangle.side2 , myTriangle.side3);