oF, Max/MSP, QC에서 외부 명령을 실행하는 방법

TL;DR



크리에이티브 코딩 Advent Calendar 2016 에 3번째의 투고입니다.

MacOS가 BSD계 UNIX인 것을 최대한 살리면, 크리에이티브 코딩이 조금 편해집니다.
「oF로 디렉토리 만들 때는 ofDirectory::createDirectory(const string &dirPath, bool bRelativeToData=true, bool recursive=false) …?」라고 하지 않아도 됩니다.
그래, 평소와 같이 mkdir 로 좋네요.

예를 들면…


  • 일별로 로그 파일을 정리하고 싶다 → MV , date
  • 내보낸 파일을 압축하고 싶다 → zip , 타르
  • 처리가 끝나면 통지를 내고 싶다 → terminal-notifier , osascript
  • 말하고 싶다 → say
  • 웹 API를 두드린 결과를 원한다 → curl , wget , jq
  • 적당한 앱으로 열고 싶다 → open

  • 정직, osascript 에서 AppleScript가 두드리면, 즉 MacOS의 대부분이 제어할 수 있게 되므로,
    클립보드를 공유하고 커서를 움직여 볼륨을 극대화하고 다른 앱을 전면으로 가져와 뭐든지 잡아.
    이러한 커맨드를 구사할 수 있기 때문에 크리에이티브 코딩은 최대한 MacOS에서 하고 싶습니다.

    참고로 openFrameworks와 Max/MSP, QuartzComposer에서 쉘을 두드리는 방법을 소개합니다.

    w/ openFrameworks



    ofSystem() 사용



    가장 간단한 것은 ofSystem 를 사용하는 방법.
    ofSystem("say -v Kyoko こんにちは");
    

    제대로 PIPE


    ofSystem() 그럼 도중 출력을 받을 수 없고, 처리가 끝날 때까지 thread가 블록 되므로,
    Brett씨가 Gist 에 올리고 있던 구현이 참고가 됩니다.

    SysCommand.h
    //
    //  SysCommand.h
    //
    //  Created by Brett Renfer on 2/22/12.
    //
    
    #pragma once
    #include "ofThread.h"
    
    class SysCommand : private ofThread
    {
    public:
        ofEvent<string> commandComplete;
    
        void callCommand( string command ){
            cmd = command;
            stopThread();
            startThread();
        }
    
        // CALL THIS DIRECTLY FOR BLOCKING COMMAND
        // thanks to: http://stackoverflow.com/questions/478898/how-to-execute-a-command-and-get-output-of-command-within-c
        std::string exec(char* cmd) {
            FILE* pipe = popen(cmd, "r");
            if (!pipe) return "ERROR";
            char buffer[128];
            std::string result = "";
            while(!feof(pipe)) {
                if(fgets(buffer, 128, pipe) != NULL)
                    result += buffer;
            }
            pclose(pipe);
            return result;
        }
    
    private:
        void threadedFunction(){
            ofLog( OF_LOG_VERBOSE, "call "+cmd );
            string result = exec( (char *) cmd.c_str() );
            ofLog( OF_LOG_VERBOSE, "RESULT "+result );
            stopThread();
            ofNotifyEvent( commandComplete, result, this );
        }
        string cmd;
    };
    

    w/ Max/MSP



    Bill의 "shell"객체 사용





    공식 포럼 에서 다운로드할 수 있습니다.
    내용을 보면 C에서 pthread하고 있네요.

    아카마츠 선생님의 "aka.shell" 사용





    아카마츠 선생님의 웹 에서 다운로드할 수 있습니다.
    이쪽은 popen에서의 구현입니다만, 보다 메이저이므로 참고가 되는 기사가 많이 발견됩니다.
    Qiita에 자세한 기사도있었습니다. → Unix 명령을 인터페이스로 사용하는 Max-External 앱 간의 연동 방법

    w/ Quartz Composer



    CommandLineTool



    개발자 라이브러리 에서 근사 샘플 코드를 얻을 수 있습니다.
    낡아서 Xcode로 로드한 후 미세 수정이 필요합니다.
    일본어로 쓰여진 참고 기사가 있었습니다. → UNIX Command – execute in Quartz Composer

    ShellCommand 패치 사용




    Kosada inc.이 게시하는 ShellCommand 패치를 사용하는 방법도 있습니다.
    키네마 에서 다운로드할 수 있습니다.

    요약



    모든 도구/프레임워크는 외부 명령을 실행할 수 있는 여러 가지 메커니즘이 있습니다.
    그 정도 강력한 연계입니다만, 모두 「터무니 없는 인수를 건네주고 있었다!」 「커맨드를 절대 패스로 하지 않으면 움직이지 않는다!」라고 하는 리스크& 있는 존재가 있거나 하므로, 마음으로 사용해 주세요 .

    좋은 웹페이지 즐겨찾기