Posts Tagged ‘objective-c’

Retrieve system volume and mute status via objective-c

Saturday, July 25th, 2015

Here’s a little objective-c program to grab the Mac OS X system volume and mute status (and then multiply them to get the effective volume).

#import <AudioToolbox/AudioServices.h>
#import <Foundation/NSObject.h>

@interface Volume : NSObject
{
}
 +(AudioDeviceID)defaultOutputDeviceID;
 +(float)volume;
 +(bool)mute;
 +(float)effective_volume;
@end

@implementation Volume : NSObject
+(AudioDeviceID)defaultOutputDeviceID;
{
    AudioDeviceID   outputDeviceID = kAudioObjectUnknown;
    // get output device device
    UInt32 propertySize = 0;
    OSStatus status = noErr;
    AudioObjectPropertyAddress propertyAOPA;
    propertyAOPA.mScope = kAudioObjectPropertyScopeGlobal;
    propertyAOPA.mElement = kAudioObjectPropertyElementMaster;
    propertyAOPA.mSelector = kAudioHardwarePropertyDefaultOutputDevice;
    if (!AudioHardwareServiceHasProperty(kAudioObjectSystemObject, &propertyAOPA))
    {
        NSLog(@"Cannot find default output device!");
        return outputDeviceID;
    }
    propertySize = sizeof(AudioDeviceID);
    status = AudioHardwareServiceGetPropertyData(kAudioObjectSystemObject, &propertyAOPA, 0, NULL, &propertySize, &outputDeviceID);
    if(status) 
    {
        NSLog(@"Cannot find default output device!");
    }
    return outputDeviceID;
}

+(float)volume 
{
    Float32         outputVolume;
    UInt32 propertySize = 0;
    OSStatus status = noErr;
    AudioObjectPropertyAddress propertyAOPA;
    propertyAOPA.mElement = kAudioObjectPropertyElementMaster;
    propertyAOPA.mSelector = kAudioHardwareServiceDeviceProperty_VirtualMasterVolume;
    propertyAOPA.mScope = kAudioDevicePropertyScopeOutput;
    AudioDeviceID outputDeviceID = [[self class] defaultOutputDeviceID];
    if (outputDeviceID == kAudioObjectUnknown)
    {
        NSLog(@"Unknown device");
        return 0.0;
    }
    if (!AudioHardwareServiceHasProperty(outputDeviceID, &propertyAOPA))
    {
        NSLog(@"No volume returned for device 0x%0x", outputDeviceID);
        return 0.0;
    }
    propertySize = sizeof(Float32);
    status = AudioHardwareServiceGetPropertyData(outputDeviceID, &propertyAOPA, 0, NULL, &propertySize, &outputVolume);
    if (status)
    {
        NSLog(@"No volume returned for device 0x%0x", outputDeviceID);
        return 0.0;
    }
    if (outputVolume < 0.0 || outputVolume > 1.0) return 0.0;
    return outputVolume;
}

+(bool)mute
{
    UInt32 mute;
    UInt32 propertySize = 0;
    OSStatus status = noErr;
    AudioObjectPropertyAddress propertyAOPA;
    propertyAOPA.mElement = kAudioObjectPropertyElementMaster;
    propertyAOPA.mSelector = kAudioDevicePropertyMute;
    propertyAOPA.mScope = kAudioDevicePropertyScopeOutput;
    AudioDeviceID outputDeviceID = [[self class] defaultOutputDeviceID];
    if (outputDeviceID == kAudioObjectUnknown)
    {
        NSLog(@"Unknown device");
        return 0.0;
    }
    if (!AudioHardwareServiceHasProperty(outputDeviceID, &propertyAOPA))
    {
        NSLog(@"No volume returned for device 0x%0x", outputDeviceID);
        return 0.0;
    }
    propertySize = sizeof(UInt32);
    status = AudioHardwareServiceGetPropertyData(outputDeviceID, &propertyAOPA, 0, NULL, &propertySize, &mute);
    if (status)
    {
        NSLog(@"No volume returned for device 0x%0x", outputDeviceID);
        return 0.0;
    }
    return mute;
}
+(float)effective_volume
{
  return [[self class] volume] * (![[self class] mute]);
}

@end

int main(int argc, const char * argv[])
{
  printf("%g",[Volume effective_volume]);
}

Compile with something like:

clang volume.m -o volume -framework Cocoa -framework AudioToolbox

Then when you run it will simply return a number representing the current effective volume:

0.25

Paste directly from clipboard into matlab image array

Sunday, October 12th, 2014

I find myself often wanting to experiment with images from papers I’m reading. To load the image into matlab properly I should extract it from the pdf, save it in a file and load the file via matlab. Often I skip the first step and just take a screengrab. But I still need to create a dummy file just to load it into matlab.

Here’s a mex function to load images directly from the clipboard. It even maintains all color channels (RGB, CMYK, RGBA, etc.)

Save this in a file paste.h:

#include <cstddef>
// Get image from clipboard as an RGB image
//
// Outputs:
//   IM  h*w*c list of rgb pixel color values as uint8, running over height,
//     then width, then rgb channels
//   h  height
//   w  width
//   c  channels
bool paste(unsigned char *& IM,size_t & h, size_t & w, size_t & c);

and in paste.mm:

#import "paste.h"
#import <Foundation/Foundation.h>
#import <Cocoa/Cocoa.h>
#import <unistd.h>

bool paste(unsigned char *& IM,size_t & h, size_t & w, size_t & c)
{
  NSPasteboard *pasteboard = [NSPasteboard generalPasteboard];
  NSArray *classArray = [NSArray arrayWithObject:[NSImage class]];
  NSDictionary *options = [NSDictionary dictionary];
  BOOL ok = [pasteboard canReadObjectForClasses:classArray options:options]; 
  if(!ok)
  {
    //printf("Error: clipboard doesn't seem to contain image...");
    return false;
  }
  NSArray *objectsToPaste = [pasteboard readObjectsForClasses:classArray options:options];
  NSImage *image = [objectsToPaste objectAtIndex:0];
  NSBitmapImageRep* bitmap = [NSBitmapImageRep imageRepWithData:[image TIFFRepresentation]];
  // http://stackoverflow.com/a/19649616/148668
  w = [bitmap pixelsWide];
  h = [bitmap pixelsHigh];
  size_t rowBytes = [bitmap bytesPerRow];
  c = rowBytes/w;
  unsigned char* pixels = [bitmap bitmapData];
  IM = new unsigned char[w*h*c];
  for(size_t y = 0; y < h ; y++)
  {
    for(size_t x = 0; x < w; x++)
    {
      for(size_t d = 0;d<c;d++)
      {
        // For some reason colors are invertex
        IM[y+h*(x+d*w)] = pixels[y*rowBytes + x*c + d];
      }
    }
  }
  [image release];
  return true;
}

and in impaste.cpp

#ifdef MEX
#include <mex.h>
#include "paste.h"
#include <iostream>

void mexFunction(
  int nlhs, mxArray *plhs[], 
  int nrhs, const mxArray *prhs[])
{
  unsigned char * IM;
  size_t h,w,c;
  if(!paste(IM,h,w,c))
  {
    mexErrMsgTxt("Clipboard doesn't contain image.");
  }
  switch(nlhs)
  {
    default:
    {
      mexErrMsgTxt("Too many output parameters.");
    }
    case 1:
    {
      size_t dims[] = {h,w,c};
      plhs[0] = mxCreateNumericArray(3,dims,mxUINT8_CLASS,mxREAL);
      unsigned char * IMp = (unsigned char *)mxGetData(plhs[0]);
      std::copy(IM,IM+w*h*c,IMp);
      // Fall through
    }
    case 0: break;
  }
}

#endif

Then compile on Mac OS X using something like:

mex -v -largeArrayDims -DMEX CXX='/usr/bin/clang++' LD='/usr/bin/clang++' LDOPTIMFLAGS='-O ' LDFLAGS='\$LDFLAGS -framework Foundation -framework AppKit' -o impaste impaste.cpp paste.mm

Notice, I’m forcing the mex compiler to use clang and include the relevant frameworks.

Then you can call from matlab using something like:

IM = impaste();

or

imshow(impaste());

Render to Mac OS X clipboard from GLUT OpenGL app

Saturday, January 25th, 2014

Here’s a proof of concept application that renders the current viewport to the mac os x clipboard. Then you can paste into Preview.app or Photoshop etc. Save the following in render_to_clipboard.m:

#include <GLUT/GLUT.h>
#import <Foundation/Foundation.h>
#import <Cocoa/Cocoa.h>
#include <stdlib.h>
#include <unistd.h>

void reshape(int width,int height)
{
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  glViewport(0,0,width,height);
  gluPerspective(40, (double)width/height, 1, 10);
  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();
  gluLookAt(0,0,3, 0,0,0, 0,1,0);
  glTranslatef(0, 0.0f, -1);
}

bool buffer_to_clipboard(
  const GLubyte * pixels, 
  const int w, 
  const int h, 
  const int components)
{
  const int length = w*h*components;
  NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
  // http://stackoverflow.com/a/3416891/148668
  size_t bufferLength = w * h * components;
  CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, pixels, bufferLength, NULL);
  size_t bitsPerComponent = 8;
  size_t bitsPerPixel = bitsPerComponent * components;
  size_t bytesPerRow = components * w;
  CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
  CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault | kCGImageAlphaPremultipliedLast;
  CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault;

  CGImageRef iref = CGImageCreate(
    w, 
    h, 
    bitsPerComponent, 
    bitsPerPixel, 
    bytesPerRow, 
    colorSpaceRef, 
    bitmapInfo, 
    provider,   // data provider
    NULL,       // decode
    YES,        // should interpolate
    renderingIntent);

  NSImage * temp_image = [[NSImage alloc] initWithCGImage:iref size:NSMakeSize(w, h)];

  // Painfully flip image across x-axis
  NSSize newSize = NSMakeSize(w,h);
  NSImage *image = [[NSImage alloc] initWithSize:newSize];
  [image lockFocus];
  NSAffineTransform *flip = [NSAffineTransform transform];
  [flip translateXBy: 0 yBy: h];
  [flip scaleXBy:1 yBy:-1];
  [flip concat];
  NSRect r1 = NSMakeRect(0, 0, w,h);
  [[temp_image bestRepresentationForRect:r1 context:nil hints:nil] drawInRect: r1];
  [image unlockFocus];

  BOOL copied = false;
  if (image != nil)
  {
    NSPasteboard *pasteboard = [NSPasteboard generalPasteboard];
    [pasteboard clearContents];
    NSArray *copiedObjects = [NSArray arrayWithObject:image];
    copied = [pasteboard writeObjects:copiedObjects];
    [pasteboard release];
  }
  [image release];
  [pool release];
  return true;
}

bool render_to_clipboard()
{
  GLenum format = GL_RGBA;
  int components = 4;
  int VP[4];
  glGetIntegerv(GL_VIEWPORT,VP);
  // OpenGL by default tries to read data in multiples of 4, if our data is
  // only RGB or BGR and the width is not divible by 4 then we need to alert
  // opengl
  if((VP[2] % 4) != 0 && 
   (format == GL_RGB || 
    format == GL_BGR))
  {
    glPixelStorei(GL_PACK_ALIGNMENT, 1);
  }
  GLubyte *pixels;
  pixels = (unsigned char *) malloc (VP[2]* VP[3]* components);
  glReadPixels( VP[0], VP[1], VP[2], VP[3], format, GL_UNSIGNED_BYTE, pixels);
  return buffer_to_clipboard(pixels, VP[2], VP[3], components);
}

void display()
{
  glClearColor(1,0,0,1);
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glutWireTeapot(1.0);
  glutSwapBuffers();
  render_to_clipboard();
}

void exitCB()
{
  exit(0);
}

int main(int argc, char * argv[])
{
  glutInit(&argc,argv);
  glutInitDisplayString( "rgba depth double samples>=8 ");
  glutInitWindowSize(401,301);
  glutCreateWindow("test");
  glutDisplayFunc(display);
  glutReshapeFunc(reshape);
  // Render once and quit
  glutIdleFunc(exitCB);
  glutMainLoop();
  return 0;
}

Then you can compile with

cc -o render_to_clipboard render_to_clipboard.m -framework GLUT -framework OpenGL -lobjc -framework Foundation -framework AppKit

And run with:

./render_to_clipboard

This will flash a GLUT window, render once and quit. You can then paste your frame, which should be:

render teaport to mac os x clipboard

Copy image file to clipboard

Saturday, January 25th, 2014

Here’s a small objective-c program to take an image file and copy it to the clipboard on Mac OS X. Dump this in a file called impbcopy.m:

#import <Foundation/Foundation.h>
#import <Cocoa/Cocoa.h>
#import <unistd.h>
BOOL copy_to_clipboard(NSString *path)
{
  // http://stackoverflow.com/questions/2681630/how-to-read-png-image-to-nsimage
  NSImage * image;
  if([path isEqualToString:@"-"])
  {
    // http://caiustheory.com/read-standard-input-using-objective-c 
    NSFileHandle *input = [NSFileHandle fileHandleWithStandardInput];
    image = [[NSImage alloc] initWithData:[input readDataToEndOfFile]];
  }else
  { 
    image =  [[NSImage alloc] initWithContentsOfFile:path];
  }
  // http://stackoverflow.com/a/18124824/148668
  BOOL copied = false;
  if (image != nil)
  {
    NSPasteboard *pasteboard = [NSPasteboard generalPasteboard];
    [pasteboard clearContents];
    NSArray *copiedObjects = [NSArray arrayWithObject:image];
    copied = [pasteboard writeObjects:copiedObjects];
    [pasteboard release];
  }
  [image release];
  return copied;
}

int main(int argc, char * const argv[])
{
  NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
  if(argc<2)
  {
    printf("Usage:\n\n"
      "Copy file to clipboard:\n    ./impbcopy path/to/file\n\n"
      "Copy stdin to clipboard:\n    cat /path/to/file | ./impbcopy -");
    return EXIT_FAILURE;
  }
  NSString *path= [NSString stringWithUTF8String:argv[1]];
  BOOL success = copy_to_clipboard(path);
  [pool release];
  return (success?EXIT_SUCCESS:EXIT_FAILURE);
}

Then compile with:

gcc -Wall -g -O3 -ObjC -framework Foundation -framework AppKit -o impbcopy impbcopy.m

And run with something like:

./impbcopy path/to/file.png

or from stdin use:

cat path/to/file.jpg | ./impbcopy -

Update: For completeness, here’s a small program to paste the clipboard image to a file:

#import <Foundation/Foundation.h>
#import <Cocoa/Cocoa.h>
#import <unistd.h>

@interface NSImage(saveAsPNGWithName)
- (void) saveAsPNGWithName:(NSString*) fileName;
@end

@implementation NSImage(saveAsPNGWithName)

- (void) saveAsPNGWithName:(NSString*) fileName
{
    // Cache the reduced image
    NSData *imageData = [self TIFFRepresentation];
    NSBitmapImageRep *imageRep = [NSBitmapImageRep imageRepWithData:imageData];
    NSDictionary *imageProps = [NSDictionary dictionaryWithObject:[NSNumber numberWithFloat:1.0] forKey:NSImageCompressionFactor];
    imageData = [imageRep representationUsingType:NSPNGFileType properties:imageProps];
    [imageData writeToFile:fileName atomically:NO];        
}

@end

BOOL paste_from_clipboard(NSString *path)
{
  // http://stackoverflow.com/a/18124824/148668
  NSPasteboard *pasteboard = [NSPasteboard generalPasteboard];
  NSArray *classArray = [NSArray arrayWithObject:[NSImage class]];
  NSDictionary *options = [NSDictionary dictionary];
  BOOL ok = [pasteboard canReadObjectForClasses:classArray options:options]; 
  if(ok)
  {
    NSArray *objectsToPaste = [pasteboard readObjectsForClasses:classArray options:options];
    NSImage *image = [objectsToPaste objectAtIndex:0];
    // http://stackoverflow.com/a/3213017/148668
    [image release];
  }else
  {
    printf("Error: Clipboard doesn't seem to contain an image.\n");
  }
  return ok;
}

int main(int argc, char * const argv[])
{
  NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
  if(argc<2)
  {
    printf("Usage:\n\n"
      "Paste clipboard to file:\n    ./impbcopy path/to/file\n\n");
    return EXIT_FAILURE;
  }
  NSString *path= [NSString stringWithUTF8String:argv[1]];
  BOOL success = paste_from_clipboard(path);
  [pool release];
  return (success?EXIT_SUCCESS:EXIT_FAILURE);
}

Compile with:

clang -Wall -g -O3 -ObjC -framework Foundation -framework AppKit -o impbpaste impbpaste.m

and run:

./impbpaste foo.png

Update: could also try the command line program pngpaste which has more features.

Brightness Menulet (revised)

Monday, June 21st, 2010

I’ve taken another swing at making a brightness menulet like the volume menulet. My old version could only toggle brightness (because of UI problems). But the new version is a full on slider!
brightness menulet slider
Here’s the xcode project and intel/ppc builds for at least mac os x 10.5:
Brightness Menulet Xcode Project
Brightness Menulet (intel)
Brightness Menulet (ppc)

Note: This menulet (and the original brightness code) does not work with 10.6 on my Mac Cinema HD display, but it does work with 10.6 on my girlfriend’s MacBook.