Csound Csound-dev Csound-tekno Search About

[CSOUND-DEV:4230] plugin opcodes for Mac

Date2004-03-04 02:12
FromAnthony Kozar
Subject[CSOUND-DEV:4230] plugin opcodes for Mac
Hello all, 

I just finished implementing and testing plugin opcodes for Csound 4 on the
Legacy Mac platform.  I built and tested the pans, metro, and testOpcode
libraries, all with success (a few changes were needed to compile testOpcode
"ANSI-strict", though).

I went the route of using dl_opcodes.c since this file was already being
used in the Mac build.  I was not sure if load_opcodes.c was working yet,
but it should be pretty easy to convert my code over to use the API instead.

So, I am pretty excited about having this new functionality available for
the Mac! 

:)

Code is below.

Anthony Kozar
anthony.kozar@utoledo.edu


/*  
    dl_opcodes.c:

    Copyright (C) 2002 John ffitch

    This file is part of Csound.

    The Csound Library is free software; you can redistribute it
    and/or modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    Csound is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with Csound; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
    02111-1307 USA
*/
#define BETA
#include "cs.h"
#ifdef LINUX
#include 
#elif WIN32
#undef u_char
#undef u_short
#undef u_int
#undef u_long

#define PUBLIC __declspec(dllexport)
#define LIBRARY_CALL WINAPI
#include 
#endif

int csoundLoadExternal(void)
{
  return 0;
}

int csoundLoadExternals(void)
{
    char *libname;
#ifdef LINUX
    void *handle;
#elif WIN32
    long handle;
#elif defined(mac_classic)
    CFragConnectionID  handle;
    OSErr              err;
    Str63              macLibName;
    Str255             errName;
    Ptr                mainAddr;
    Ptr                symAddr;
    CFragSymbolClass   symClass;
#else
    void *handle = NULL;
#endif
    char *error;
    char buffer[256];
    OENTRY *(*init)(GLOBALS*);
    long (*size)(void);

    if (cglob.oplibs==NULL) return 1;
    printf("Loading libraries %s\n", cglob.oplibs);
    strcpy(buffer, cglob.oplibs);
    libname = strtok(buffer, ",");
#ifdef BETA
    printf("libname %s\n", libname);
#endif
    while (libname!=NULL) {
#ifdef LINUX
      handle = dlopen (libname, RTLD_NOW | RTLD_GLOBAL);
#elif WIN32
      handle = (long) LoadLibrary(libname);
#elif defined(mac_classic)
    if    (strlen(libname) < 64)    {
        strcpy((char*)macLibName, libname);
        c2pstr((char*)macLibName);
    }
    else    {
        printf("%s is not a valid library name because it is too long.\n",
libname);
        goto next;
    }
    err = GetSharedLibrary(macLibName, kPowerPCCFragArch, kLoadCFrag,
&handle, &mainAddr, errName);
    if (err!=0) printf("Failed to load opcode library %s with Mac error
%d.\n", libname, err);
#endif
      if (!handle) {
#ifdef LINUX
        printf("Failed to load %s for %s.\n", libname, dlerror());
#elif WIN32
                printf("Failed to load %s.\n", libname);
#endif
      }
      else {
        OENTRY *opcodlst_n;
        long length, olength;
#ifdef BETA
        printf("Found handle\n");
#endif
#ifdef LINUX
        size = dlsym(handle, "opcode_size");
        if ((error = dlerror()) != NULL)  {
          printf("Failed to initialise %s: %s", libname, error);
          goto next;
        }
#ifdef BETA
        printf("Found size\n");
#endif
        length = (*size)();
#ifdef BETA
        printf("Length=%d\n", length);
#endif
        init = dlsym(handle, "opcode_init");
#ifdef BETA
        printf("Found init\n");
#endif
        if ((error = dlerror()) != NULL)  {
          printf("Failed to initialise %s: %s", libname, error);
          goto next;
        }
#ifdef BETA
        printf("Calling init\n");
#endif
        opcodlst_n = (*init)(&cglob);
        olength = oplstend-opcodlst;
/* end  LINUX */
#elif WIN32
        size = (long(*)(void))GetProcAddress((HINSTANCE)handle,
"opcode_size");
        if (size == NULL)  {
          printf("Failed to initialise %s", libname);
          goto next;
        }
#ifdef BETA
        printf("Found size\n");
#endif
        length = (*size)();
#ifdef BETA
        printf("Length=%d\n", length);
#endif
        init = (OENTRY *(*)(GLOBALS*))GetProcAddress((HINSTANCE)handle,
                                                     "opcode_init");
#ifdef BETA
        printf("Found init\n");
#endif
        if (init == NULL)  {
          printf("Failed to initialise %s", libname);
          goto next;
        }
#ifdef BETA
        printf("Calling init\n");
#endif
        opcodlst_n = (*init)(&cglob);
        olength = oplstend-opcodlst;
/* end  WIN32 */
#elif defined(mac_classic)
        err = FindSymbol(handle, "\popcode_size", &symAddr, &symClass);
        if (err!=0)  {
          printf("Failed to initialise %s with Mac error %d.\n", libname,
err);
          goto next;
        }
        else if (symClass == kDataCFragSymbol)    {
          printf("Failed to initialise %s because opcode_size it not a code
symbol.\n", libname);
          goto next;
        }
        size = (long (*)(void))symAddr;
#ifdef BETA
        printf("Found size\n");
#endif
        length = (*size)();
#ifdef BETA
        printf("Length=%d\n", length);
#endif
        err = FindSymbol(handle, "\popcode_init", &symAddr, &symClass);
        if (err!=0)  {
          printf("Failed to initialise %s with Mac error %d.\n", libname,
err);
          goto next;
        }
        else if (symClass == kDataCFragSymbol)    {
          printf("Failed to initialise %s because opcode_init it not a code
symbol.\n", libname);
          goto next;
        }
        init = (OENTRY *(*)(GLOBALS*))symAddr;
#ifdef BETA
        printf("Found init\n");
        printf("Calling init\n");
#endif
        opcodlst_n = (*init)(&cglob);
        olength = oplstend-opcodlst;
#endif /* mac_classic */

#ifdef BETA
        printf("Got opcodlst %p\noplstend=%p, opcodlst=%p, length=%d\n",
               opcodlst_n, oplstend, opcodlst, olength);
        printf("Adding %d(%d) -- first opcode is %s\n",
               length, length/sizeof(OENTRY), opcodlst_n[0].opname);
#endif
        opcodlst = (OENTRY*) mrealloc(opcodlst, olength*sizeof(OENTRY) +
length);
        memcpy(opcodlst+olength, opcodlst_n, length);
        oplstend = opcodlst +  olength + length/sizeof(OENTRY);
      }
    next:
      libname = strtok(NULL, ",");
    }
#ifdef BETA
    printf("All loaded\n");
#endif
    return 1;
}