UnsafeMutablePointer in AURenderCallback - swift3

I can't understand, how I should use UnsafeMutablePointer in Swift 3. Especially in AURenderCallback.
I try below code:
import Foundation
import AudioToolbox
let sineFrequency = 880.0
// MARK: User data struct
struct SineWavePlayer {
var outputUnit: AudioUnit? = nil
var startingFrameCount: Double = 0
}
// MARK: Callback function
let SineWaveRenderProc: AURenderCallback = {(inRefCon, ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames, ioData) -> OSStatus in
var player = UnsafeMutablePointer<SineWavePlayer>(inRefCon)
var j = player.pointee.startingFrameCount
let cycleLength = 44100 / sineFrequency
for frame in 0..<inNumberFrames {
var buffers = UnsafeMutableAudioBufferListPointer(ioData)
UnsafeMutablePointer<Float32>(buffers[0].mData)[Int(frame)] = Float32(sin(2 * M_PI * (j / cycleLength)))
UnsafeMutablePointer<Float32>(buffers[1].mData)[Int(frame)] = Float32(sin(2 * M_PI * (j / cycleLength)))
// Or iterate through array:
// for buffer in buffers {
// UnsafeMutablePointer<Float32>(buffer.mData)[Int(frame)] = Float32(sin(2 * M_PI * (j / cycleLength)))
// }
j++
if j > cycleLength {
j -= cycleLength
}
}
player.pointee.startingFrameCount = j
return noErr
}
// MARK: Utility function
func CheckError(_ error: OSStatus, operation: String) {
guard error != noErr else {
return
}
var result: String = ""
var char = Int(error.bigEndian)
for _ in 0..<4 {
guard isprint(Int32(char&255)) == 1 else {
result = "\(error)"
break
}
result.append(String(describing: UnicodeScalar(char&255)))
char = char/256
}
print("Error: \(operation) (\(result))")
exit(1)
}
func CreateAndConnectOutputUnit(_ player: inout SineWavePlayer) {
// Generate a description that matches the output device (speakers)
var outputcd = AudioComponentDescription(componentType: kAudioUnitType_Output, componentSubType: kAudioUnitSubType_DefaultOutput, componentManufacturer: kAudioUnitManufacturer_Apple, componentFlags: 0, componentFlagsMask: 0)
let comp = AudioComponentFindNext(nil, &outputcd)
if comp == nil {
print("Can't get output unit")
exit(-1)
}
CheckError(AudioComponentInstanceNew(comp!, &player.outputUnit),
operation: "Couldn't open component for outputUnit")
// Register the render callback
var input = AURenderCallbackStruct(inputProc: SineWaveRenderProc, inputProcRefCon: &player)
CheckError(AudioUnitSetProperty(player.outputUnit!, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &input, UInt32(MemoryLayout<AURenderCallbackStruct>.size)),
operation: "AudioUnitSetProperty failed")
// Initialize the unit
CheckError(AudioUnitInitialize(player.outputUnit!),
operation: "Couldn't initialize output unit")
}
func main() {
var player = SineWavePlayer()
// Set up output unit and callback
CreateAndConnectOutputUnit(&player)
// Start playing
CheckError(AudioOutputUnitStart(player.outputUnit!),
operation: "Couldn't start output unit")
// Play for 5 seconds
sleep(5)
// Clean up
AudioOutputUnitStop(player.outputUnit!)
AudioUnitUninitialize(player.outputUnit!)
AudioComponentInstanceDispose(player.outputUnit!)
}
main()
But this line of code
var player = UnsafeMutablePointer<SineWavePlayer>(inRefCon)
is not working. How to translate this line to Swift 3?
Please, help me.

In Swift 3, initializers cannot be used to convert pointer types. In your case, the type of inRefCon is UnsafeMutableRawPointer, so you need to use assumingMemoryBound(to:) method.
And one more, the address of player passed to the callback needs to be stable all while the sound is playing, addresses taken from inout arguments (specified by & prefix) does not fulfil this requirement.
The two things above fixed, your code would be something like this:
import Foundation
import AudioToolbox
let sineFrequency = 880.0
// MARK: User data struct
struct SineWavePlayer {
var outputUnit: AudioUnit? = nil
var startingFrameCount: Double = 0
}
// MARK: Callback function
let SineWaveRenderProc: AURenderCallback = {(inRefCon, ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames, ioData) -> OSStatus in
var player = inRefCon.assumingMemoryBound(to: SineWavePlayer.self)
var j = player.pointee.startingFrameCount
let cycleLength = 44100 / sineFrequency
for frame in 0..<inNumberFrames {
var buffers = UnsafeMutableAudioBufferListPointer(ioData)
buffers?[0].mData?.assumingMemoryBound(to: Float32.self)[Int(frame)] = Float32(sin(2 * M_PI * (j / cycleLength)))
buffers?[1].mData?.assumingMemoryBound(to: Float32.self)[Int(frame)] = Float32(sin(2 * M_PI * (j / cycleLength)))
j += 1
if j > cycleLength {
j -= cycleLength
}
}
player.pointee.startingFrameCount = j
return noErr
}
// MARK: Utility function
func CheckError(_ error: OSStatus, operation: String) {
guard error != noErr else {
return
}
var result: String = ""
var char = Int(error.bigEndian)
for _ in 0..<4 {
guard isprint(Int32(char&255)) == 1 else {
result = "\(error)"
break
}
result.append(String(describing: UnicodeScalar(char&255)))
char = char/256
}
print("Error: \(operation) (\(result))")
exit(1)
}
func CreateAndConnectOutputUnit(_ playerPtr: UnsafeMutablePointer<SineWavePlayer>) {
// Generate a description that matches the output device (speakers)
var outputcd = AudioComponentDescription(componentType: kAudioUnitType_Output, componentSubType: kAudioUnitSubType_DefaultOutput, componentManufacturer: kAudioUnitManufacturer_Apple, componentFlags: 0, componentFlagsMask: 0)
let comp = AudioComponentFindNext(nil, &outputcd)
if comp == nil {
print("Can't get output unit")
exit(-1)
}
CheckError(AudioComponentInstanceNew(comp!, &playerPtr.pointee.outputUnit),
operation: "Couldn't open component for outputUnit")
// Register the render callback
var input = AURenderCallbackStruct(inputProc: SineWaveRenderProc, inputProcRefCon: playerPtr)
CheckError(AudioUnitSetProperty(playerPtr.pointee.outputUnit!, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &input, UInt32(MemoryLayout<AURenderCallbackStruct>.size)),
operation: "AudioUnitSetProperty failed")
// Initialize the unit
CheckError(AudioUnitInitialize(playerPtr.pointee.outputUnit!),
operation: "Couldn't initialize output unit")
}
func main() {
let playerPtr = UnsafeMutablePointer<SineWavePlayer>.allocate(capacity: 1)
defer {playerPtr.deallocate(capacity: 1)}
playerPtr.initialize(to: SineWavePlayer())
defer {playerPtr.deinitialize()}
// Set up output unit and callback
CreateAndConnectOutputUnit(playerPtr)
// Start playing
CheckError(AudioOutputUnitStart(playerPtr.pointee.outputUnit!),
operation: "Couldn't start output unit")
// Play for 5 seconds
sleep(5)
// Clean up
AudioOutputUnitStop(playerPtr.pointee.outputUnit!)
AudioUnitUninitialize(playerPtr.pointee.outputUnit!)
AudioComponentInstanceDispose(playerPtr.pointee.outputUnit!)
}

Related

How to alter this script to add another condition

I have this piece of code which has been working great for me, however, I need a minor alteration to it and don't know how to proceed.
I would like for 'Multiple Use' to be added as another condition, alongside 'Yes' for the onEdit() to work.
function numberToLetter(number){
// converts the column number to a letter
var temp = "";
var letter = "";
while (number > 0){
temp = (number - 1) % 26;
letter = String.fromCharCode(temp + 65) + letter;
number = (number - temp - 1) / 26;
}
return letter;
}
function obtainFirstBlankRow() {
var sheet = SpreadsheetApp.getActive().getSheetByName('Aug2019');
// search for first blank row
var col = sheet.getRange('A:A');
var vals = col.getValues();
var count = 0;
while (vals[count][0] != "") {
count++;
}
return count + 1;
}
function onEdit(e) {
var ss = SpreadsheetApp.getActiveSheet();
if (ss.getName() == 'ProspectiveSites' && e.range.getColumn() == 26) {
if (e.range.getValue() != 'Yes'){
Logger.log('test');
return;
}
var sourceSheet = SpreadsheetApp.getActive().getSheetByName('ProspectiveSites');
var targetSheet = SpreadsheetApp.getActive().getSheetByName('Aug2019');
//Logger.log('O' + e.getRow() + ':O' + e.getRow());
Logger.log(e);
Logger.log(e.range.getValue());
var cell15 = sourceSheet.getRange('O' + e.range.getRow() + ':O' + e.range.getRow()).getValue();
var cell24 = sourceSheet.getRange('X' + e.range.getRow() + ':X' + e.range.getRow()).getValue();
Logger.log(cell15);
Logger.log(cell24);
var row = obtainFirstBlankRow();
targetSheet.getRange(row, 1).setValue(cell15);
targetSheet.getRange(row, 2).setValue(cell24);
}
}
Solution
What stops you from adding another condition for the if statement? Please, take some time to research JS documentation, it will greatly help you in the long run (see useful links after the sample).
Modifications
This modification assumes that you need to exit if value is not equal to "Multiple use" and not equal to "Yes". Also, note that there are a few additional changes made for optimization purposes (I changed all comparison operators to strict as well).
Sample
/**
* onEdit simple trigger;
* #param {Object} event object;
*/
function onEdit(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var actS = ss.getActiveSheet(); //active sheet === source sheet;
//access event object params;
var range = e.range;
var row = range.getRow();
var column = range.getColumn();
var value = range.getValue();
if (actS.getName()==='ProspectiveSites' && column===26) {
if (value!=='Yes'&&value!=='Multiple Use') {
Logger.log('test');
return;
}
var augS = ss.getSheetByName('Aug2019'); //target sheet;
var cell15val = actS.getRange('O'+row+':O'+row).getValue();
var cell24val = actS.getRange('X'+row+':X'+row).getValue();
var rowBlank = obtainFirstBlankRow();
var target = augS.getRange(rowBlank,1,1,2); //idx, first col, 1 row, 2 cols;
target.setValues([[ cell15val , cell24val ]]);
}
}
Useful links
if..else statement reference on MDN;
Comparison operators reference on MDN;
getRange() method reference;
setValues() method reference;

Panic because parameters must be struct and not interface, in web.Router?

In testing the following code:
package logHandler
import (
"ezsoft/apiserver_sdk/context"
"github.com/hsoshiant/web"
)
// Build simply builds a log handler router
//
// Parameters:
//
// - `mainRouter` : the main Router
//
// Returns:
//
// - a sub Router made specifically for logging
func Build(mainRouter *web.Router) *web.Router {
return mainRouter.Subrouter(context.Context{}, "/log").
Post("/", doLog)
}
I hit a panic. context.Context is defined thus:
//BaseContext contains all the base context to be helpful when using the utilities
type BaseContext struct {
Session session.Store
ResponseWriter *web.ResponseWriter
RequestReader *web.Request
}
//Context contains all values needed when using the utilities
type Context struct {
BaseContext
JSONBody map[string]interface{}
tokenHandler *apiToken.APITokenHandlerSt
OAuthInstance *oAuth2.OAuth2St
}
and with testability/flexibility in mind, the developers wrote the middleware functions to take context.ContextIntf, which context.Context implements, which is defined as follows:
//ContextIntf is the interface to use when using the context interface functions.
type ContextIntf interface {
SetUniversalHeaders(header map[string]string) map[string]string
GetInfo() *Context
GetOAuth() *oAuth2.OAuth2St
}
Here's one such middleware func:
//AuthenticationMiddleware Middleware which handles all of the authentication.
func AuthenticationMiddleware(mw AuthenticationMiddlewareIntf, context context.ContextIntf, w web.ResponseWriter, r *web.Request, next web.NextMiddlewareFunc) {
//Check if the url should be public.
for _, url := range mw.GetInfo().nonAuthURLs {
if url.Method == r.Method && strings.Contains(r.URL.Path, url.DomainName) {
key := utilities.GetRemoteAdd(r) + ";" + r.URL.Path
if timeSince, ok := NonAuthSecurityMap[key]; ok {
var (
timeSinceTime, _ = time.Parse(time.UnixDate, timeSince)
timeSinceDuration = time.Since(timeSinceTime)
)
if timeSinceDuration < nonAuthTimeReset {
// will sleep for `nonAuthTimeReset` - `timeSinceDuration` > 0
time.Sleep(-(timeSinceDuration - nonAuthTimeReset))
}
}
NonAuthSecurityMap[key] = time.Now().Format(time.UnixDate)
next(w, r)
return
}
}
if errSt := CheckForAuthorization(mw, context, r, w); errSt != nil {
responses.Write(w, responses.Unauthorized(*errSt))
return
}
defer context.GetInfo().Session.SessionRelease(w)
next(w, r)
}
I am unsure which middleware business functions that package web is checking, let alone what business packages they reside in, and the call stack trace returns no such clues.
The error I get is thus:
* You are adding a handler to a router with context type 'Context'
*
*
* Your handler function can have one of these signatures:
*
* // If you don't need context:
* func YourFunctionName(rw web.ResponseWriter, req *web.Request)
*
* // If you want your handler to accept a context:
* func (c *Context) YourFunctionName(rw web.ResponseWriter, req *web.Request) // or,
* func YourFunctionName(c *Context, rw web.ResponseWriter, req *web.Request)
*
* Unfortunately, your function has this signature: func(context.ContextIntf, web.ResponseWriter, *web.Request)
*
************************************************************************************************************************
Why is this requesting a Context struct, instead of the ContextIntf that it implements?!
The stack trace
Looks like this:
goroutine 20 [running]:
testing.tRunner.func1(0xc04213e1e0)
C:/Go/src/testing/testing.go:742 +0x2a4
panic(0x7633c0, 0xc0421320a0)
C:/Go/src/runtime/panic.go:502 +0x237
github.com/hsoshiant/web.validateHandler(0x778420, 0x80d8f0, 0x13, 0x8405c0, 0x7b7960)
D:/dev2017/GO/src/github.com/hsoshiant/web/router_setup.go:286 +0x242
github.com/hsoshiant/web.(*Router).addRoute(0xc042106680, 0x7eeb93, 0x4, 0x7ee4bd, 0x1, 0x778420, 0x80d8f0, 0xc042051f80)
D:/dev2017/GO/src/github.com/hsoshiant/web/router_setup.go:223 +0x94
github.com/hsoshiant/web.(*Router).Post(0xc042106680, 0x7ee4bd, 0x1, 0x778420, 0x80d8f0, 0xc042106680)
D:/dev2017/GO/src/github.com/hsoshiant/web/router_setup.go:193 +0x6f
ezsoft/apiserver_sdk/logger/logHandler.Build(0xc0421064e0, 0xc042051f40)
D:/dev2017/GO/src/ezsoft/apiserver_sdk/logger/logHandler/handler.go:20 +0xcf
ezsoft/apiserver_sdk/logger/logHandler.TestBuild.func1(0xc04213e1e0)
D:/dev2017/GO/src/ezsoft/apiserver_sdk/logger/logHandler/handler_test.go:16 +0x91
testing.tRunner(0xc04213e1e0, 0x80d8e0)
C:/Go/src/testing/testing.go:777 +0xd7
created by testing.(*T).Run
C:/Go/src/testing/testing.go:824 +0x2e7
UPDATE : It's hitting the private method doLog, which is defined thus:
func doLog(contextIntf context.ContextIntf, rw web.ResponseWriter, req *web.Request) {
var (
logType int = 0
code string = ""
message string = ""
context = contextIntf.GetInfo()
)
if val, OK := context.JSONBody["type"]; OK {
if val1, noErr := val.(float64); noErr {
logType = int(val1)
}
}
if logType == 0 {
responses.Write(rw, responses.FreeUnprocessableEntity("Type"))
return
}
if val, OK := context.JSONBody["code"]; OK {
if val1, noErr := val.(string); noErr {
code = val1
} else {
responses.Write(rw, responses.FreeUnprocessableEntity("Code"))
return
}
}
if val, OK := context.JSONBody["message"]; OK {
if val1, noErr := val.(string); noErr {
message = val1
}
}
if message == "" {
responses.Write(rw, responses.FreeUnprocessableEntity("message"))
return
}
if code > "" {
code = " (" + code + ") "
}
switch logType {
case 1:
logger.Instance.LogError(code + message)
case 2:
logger.Instance.LogWarning(code + message)
case 3:
logger.Instance.LogInfo(code + message)
default:
logger.Instance.LogWarning(code + message)
}
responses.Write(rw, responses.OK(0))
}
I still don't get why that argument needs to be a context.Context, or what I, the unit-tester, can do about it.

Why doesn't this Javascript succesfully change the background on the second mouseover?

The function is supposed to increment x by 1 every time it launches, thus forcing the code to choose a different option on the next launch.
function changeBackground() {
var x = 0;
if (x % 2 === 0) {
document.getElementById("sample").style.backgroundColor = "purple";
}
else {
document.getElementById("sample").style.backgroundColor = "white";
}
x++;
}
var x = document.getElementById("sample");
x.onmouseover = changeBackground;
This is just grabbing a heading and launching changeBackground every time the cursor is placed on it. The background color stays on purple.
because you set it to 0 every time in the beginning of the function.. you need to set the variable outside of the function
var x = 0;
function changeBackground() {
if (x % 2 === 0) {
document.getElementById("sample").style.backgroundColor = "purple";
}
else {
document.getElementById("sample").style.backgroundColor = "white";
}
x++;
}
var x = document.getElementById("sample");
x.onmouseover = changeBackground;

Object reference not set to an instance Of Object

Good day to all,
Please I need somebody to help me have a look at my codes.I am having this error of** Object reference not set to an instance Of Object**.It appears the error is within this lines of codes
if (_scrollingTimer == null)
{
_scrollingTimer = new Timer()
{
Enabled = false,
Interval = 500,
Tag = (sender as TrackBar).Value
};
but unfortunately I was unable to resolve this error.I would be very glad if somebody could help me out.thank you for the usual support.best regards.
Firstoption.
Below are the remaining part of the codes.
byte[] data = new byte[5];
private Timer _scrollingTimer = null;
private void button3_Click(object sender, EventArgs e)
{
UInt32 numBytesWritten = 0;
data[0] = 1;
myFtdiDevice.Write(data, 1, ref numBytesWritten);
data[0] = 0x6A;
myFtdiDevice.Write(data, 1, ref numBytesWritten);
}
private void trackBar1_Scroll(object sender, EventArgs e)
{
if(!backgroundWorker1.IsBusy)
{
backgroundWorker1.RunWorkerAsync();
}
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
UInt32 numBytesWritten = 1;
string dataToWrite = "#0";
if (_scrollingTimer == null)
{
_scrollingTimer = new Timer()
{
Enabled = false,
Interval = 500,
Tag = (sender as TrackBar).Value
};
_scrollingTimer.Tick += (s, ea) =>
{
if (trackBar1.Value == (int)_scrollingTimer.Tag)
{
_scrollingTimer.Stop();
myFtdiDevice.Write(dataToWrite, dataToWrite.Length, ref numBytesWritten);
int percent = (int)(((double)trackBar1.Value / (double)trackBar1.Maximum) * 100);
label2.Text = (percent.ToString()) + "%";
data[0] = Convert.ToByte(percent);
data[1] = 0x6A;
myFtdiDevice.Write(data, 2, ref numBytesWritten);
_scrollingTimer.Dispose();
_scrollingTimer = null;
}
else
{
_scrollingTimer.Tag = trackBar1.Value;
}
};
_scrollingTimer.Start();
}
}
sender is not a TrackBar. Looks like it's probably backgroundWorker1.

CouchDB list view error when no key requested

Having trouble with a list function I wrote using CouchApp to take items from a view that are name, followed by a hash list of id and a value to create a CSV file for the user.
function(head, req) {
// set headers
start({ "headers": { "Content-Type": "text/csv" }});
// set arrays
var snps = {};
var test = {};
var inds = [];
// get data to associative array
while(row = getRow()) {
for (var i in row.value) {
// add individual to list
if (!test[i]) {
test[i] = 1;
inds.push(i);
}
// add to snps hash
if (snps[row.key]) {
if (snps[row.key][i]) {
// multiple call
} else {
snps[row.key][i] = row.value[i];
}
} else {
snps[row.key] = {};
snps[row.key][i] = row.value[i];
}
//send(row.key+" => "+i+" => "+snps[row.key][i]+'\n');
}
}
// if there are individuals to write
if (inds.length > 0) {
// sort keys in array
inds.sort();
// print header if first
var header = "variant,"+inds.join(",")+"\n";
send(header);
// for each SNP requested
for (var j in snps) {
// build row
var row = j;
for (var k in inds) {
// if snp[rs_num][individual] is set, add to row string
// else add ?
if (snps[j][inds[k]]) {
row = row+","+snps[j][inds[k]];
} else {
row = row+",?";
}
}
// send row
send(row+'\n');
}
} else {
send('No results found.');
}
}
If I request _list/mylist/myview (where mylist is the list function above and the view returns as described above) with ?key="something" or ?keys=["something", "another] then it works, but remove the query string and I get the error below:
{"code":500,"error":"render_error","reason":"function raised error: (new SyntaxError(\"JSON.parse\", \"/usr/local/share/couchdb/server/main.js\", 865)) \nstacktrace: getRow()#/usr/local/share/couchdb/server/main.js:865\n([object Object],[object Object])#:14\nrunList(function (head, req) {var snps = {};var test = {};var inds = [];while ((row = getRow())) {for (var i in row.value) {if (!test[i]) {test[i] = 1;inds.push(i);}if (snps[row.key]) {if (snps[row.key][i]) {} else {snps[row.key][i] = row.value[i];}} else {snps[row.key] = {};snps[row.key][i] = row.value[i];}}}if (inds.length > 0) {inds.sort();var header = \"variant,\" + inds.join(\",\") + \"\\n\";send(header);for (var j in snps) {var row = j;for (var k in inds) {if (snps[j][inds[k]]) {row = row + \",\" + snps[j][inds[k]];} else {row = row + \",?\";}}send(row + \"\\n\");}} else {send(\"No results found.\");}},[object Object],[object Array])#/usr/local/share/couchdb/server/main.js:979\n(function (head, req) {var snps = {};var test = {};var inds = [];while ((row = getRow())) {for (var i in row.value) {if (!test[i]) {test[i] = 1;inds.push(i);}if (snps[row.key]) {if (snps[row.key][i]) {} else {snps[row.key][i] = row.value[i];}} else {snps[row.key] = {};snps[row.key][i] = row.value[i];}}}if (inds.length > 0) {inds.sort();var header = \"variant,\" + inds.join(\",\") + \"\\n\";send(header);for (var j in snps) {var row = j;for (var k in inds) {if (snps[j][inds[k]]) {row = row + \",\" + snps[j][inds[k]];} else {row = row + \",?\";}}send(row + \"\\n\");}} else {send(\"No results found.\");}},[object Object],[object Array])#/usr/local/share/couchdb/server/main.js:1024\n(\"_design/kbio\",[object Array],[object Array])#/usr/local/share/couchdb/server/main.js:1492\n()#/usr/local/share/couchdb/server/main.js:1535\n#/usr/local/share/couchdb/server/main.js:1546\n"}
Can't say for sure since you gave little detail, however, a probable source of problems, is the use of arrays to collect data from every row: it consumes an unpredictable amount of memory. This may explain why it works when you query for a few records, and fails when you query for all records.
You should try to arrange data in a way that eliminates the need to collect all values before sending output to the client. And keep in mind that while map and reduce results are saved on disk, list functions are executed on every single query. If you don't keep list function fast and lean, you'll have problems.