Ejemplo n.º 1
0
int pix_share_write :: getShm(int argc,t_atom*argv)
{
  int fake = 0;

  size_t size=0;
  int    xsize=1;
  int    ysize=1;
  GLenum color=GL_RGBA;

  if(argc<1)return 7;
#ifdef _WIN32
#else
  if(shm_id>0)freeShm();
#endif
  if(A_FLOAT==argv->a_type){
    char buf[MAXPDSTRING];
    snprintf(buf, MAXPDSTRING-1, "%g", atom_getfloat(argv));
    buf[MAXPDSTRING-1]=0;
    fake = hash_str2us(buf);
  } else if(A_SYMBOL==argv->a_type){
    fake = hash_str2us(atom_getsymbol(argv)->s_name);
  }
  if(fake<=0)return 8;

  argc--; argv++;

  switch(argc)
    {
    case 1: /* just the size */
      {
        if(A_FLOAT!=argv->a_type)return 1;
        size=atom_getint(argv);
        if(size<0)return 2;
      }
      break;
    case 2: /* x*y; assume GL_RGBA */
      {
        if((A_FLOAT!=(argv+0)->a_type)||(A_FLOAT!=(argv+1)->a_type))return 3;
        xsize=atom_getint(argv);
        ysize=atom_getint(argv+1);
      }
      break;
    case 3:
      {
        if((A_FLOAT!=(argv+0)->a_type)||(A_FLOAT!=(argv+1)->a_type))return 3;
        xsize=atom_getint(argv);
        ysize=atom_getint(argv+1);
        if(A_FLOAT==(argv+2)->a_type)
          {
            int csize=atom_getint(argv+2);
            switch(csize)
              {
              case 1:
                color = GL_LUMINANCE;
                break;
              case 2:
                color = GL_YUV422_GEM;
                break;
              case 4:
                color = GL_RGBA;
                break;
              default:
                return 4;
                break;
              }
          } else { // the 4th argument is a symbol: either "RGBA", "YUV" or "Grey"
          char c=atom_getsymbol(argv+2)->s_name[0];
          switch(c)
            {
            case 'G': case 'g':
              color = GL_LUMINANCE;
              break;
            case 'Y': case 'y':
              color = GL_YUV422_GEM;
              break;
            case 'R': case 'r':
              color = GL_RGBA;
              break;
            default:
              return 4;
              break;
            }
        }
      }
      break;
    default:
      return 5;
    }
  
  if (xsize <= 0 || ysize <= 0){
    return 3;
  }

  imageStruct dummy;
  dummy.setCsizeByFormat(color);

  m_size = (size)?(size):(xsize * ysize * dummy.csize);
	
  logpost(NULL, 5, "%dx%dx%d: %d",
       xsize,ysize,dummy.csize, m_size);

#ifdef _WIN32
  error("no shared memory on w32!");
#else

  /* get a new segment with the size specified by the user
   * OR an old segment with the size specified in its header
   * why: if somebody has already created the segment with our key
   * we want to reuse it, even if its size is smaller than we requested
   */
  errno=0;
  shm_id = shmget(fake,m_size+sizeof(t_pixshare_header), IPC_CREAT | 0666);

  if((shm_id<0) && (EINVAL==errno)){
    errno=0;
    // the segment already exists, but is smaller than we thought!
    int id = shmget(fake,sizeof(t_pixshare_header),0666);
    if(id>0){ /* yea, we got it! */
      t_pixshare_header*h=(t_pixshare_header*)shmat(id,NULL,0666);
      /* read the size of the blob from the shared segment */
      if(h&&h->size){
        error("someone was faster: only got %d bytes instead of %d",
              h->size, m_size);
        m_size=h->size;

        /* so free this shm-segment before we re-try with a smaller size */
        shmdt(h);

        /* now get the shm-segment with the correct size */
        shm_id = shmget(fake,m_size+sizeof(t_pixshare_header), IPC_CREAT | 0666);
      }
    }
  }

  if(shm_id>0){
    /* now that we have a shm-segment, get the pointer to the data */
    shm_addr = (unsigned char*)shmat(shm_id,NULL,0666);

    if (!shm_addr) return 6;
    shmctl(shm_id,IPC_STAT,&shm_desc);
    /* write the size into the shm-segment */
    t_pixshare_header *h=(t_pixshare_header *)shm_addr;
    h->size = (shm_desc.shm_segsz-sizeof(t_pixshare_header));
    
    logpost(NULL, 5, "shm:: id(%d) segsz(%d) cpid (%d) mem(0x%X)",
         shm_id,shm_desc.shm_segsz,shm_desc.shm_cpid, shm_addr);
  } else {
    error("couldn't get shm_id: error %d", errno);
  }
#endif /* _WIN32 */
  return 0;
}
Ejemplo n.º 2
0
int pix_share_write :: getShm(int argc,t_atom*argv)
{
  int fake = 0;

  size_t size=0;
  int    xsize=1;
  int    ysize=1;
  unsigned int color=GEM_RGBA;

  if(argc<1) {
    return 7;
  }
#ifdef _WIN32
  if ( shm_addr ) {
    UnmapViewOfFile( shm_addr );
  }
  if ( m_MapFile ) {
    CloseHandle( m_MapFile );
  }
  if(A_FLOAT==argv->a_type) {
    snprintf(m_fileMappingName, MAXPDSTRING-1,
             "gem_pix_share-FileMappingObject_%g", atom_getfloat(argv));
  } else if (A_SYMBOL==argv->a_type) {
    snprintf(m_fileMappingName, MAXPDSTRING-1,
             "gem_pix_share-FileMappingObject_%s", atom_getsymbol(argv)->s_name);
  }

#elif USE_SHM
  if(shm_id>0) {
    freeShm();
  }
  if(A_FLOAT==argv->a_type) {
    char buf[MAXPDSTRING];
    snprintf(buf, MAXPDSTRING-1, "%g", atom_getfloat(argv));
    buf[MAXPDSTRING-1]=0;
    fake = hash_str2us(buf);
  } else if(A_SYMBOL==argv->a_type) {
    fake = hash_str2us(atom_getsymbol(argv)->s_name);
  }
  if(fake<=0) {
    return 8;
  }
#else
  return -1;
#endif /* _WIN32, USE_SHM */

  argc--;
  argv++;

  switch(argc) {
  case 1: { /* just the size */
    if(A_FLOAT!=argv->a_type) {
      return 1;
    }
    int ssize=atom_getint(argv);
    if(ssize<0) {
      return 2;
    }
    size=ssize;
  }
  break;
  case 2: { /* x*y; assume GL_RGBA */
    if((A_FLOAT!=(argv+0)->a_type)||(A_FLOAT!=(argv+1)->a_type)) {
      return 3;
    }
    xsize=atom_getint(argv);
    ysize=atom_getint(argv+1);
  }
  break;
  case 3: {
    if((A_FLOAT!=(argv+0)->a_type)||(A_FLOAT!=(argv+1)->a_type)) {
      return 3;
    }
    xsize=atom_getint(argv);
    ysize=atom_getint(argv+1);
    if(A_FLOAT==(argv+2)->a_type) {
      int csize=atom_getint(argv+2);
      switch(csize) {
      case 1:
        color = GEM_GRAY;
        break;
      case 2:
        color = GEM_YUV;
        break;
      case 4:
        color = GEM_RGBA;
        break;
      default:
        return 4;
        break;
      }
    } else { // the 4th argument is a symbol: either "RGBA", "YUV" or "Grey"
      char c=atom_getsymbol(argv+2)->s_name[0];
      switch(c) {
      case 'G':
      case 'g':
        color = GEM_GRAY;
        break;
      case 'Y':
      case 'y':
        color = GEM_YUV;
        break;
      case 'R':
      case 'r':
        color = GEM_RGBA;
        break;
      default:
        return 4;
        break;
      }
    }
  }
  break;
  default:
    return 5;
  }

  if (xsize <= 0 || ysize <= 0) {
    return 3;
  }

  imageStruct dummy;
  dummy.setCsizeByFormat(color);

  m_size = (size)?(size):(xsize * ysize * dummy.csize);

  verbose(1, "%dx%dx%d: %d",
          xsize,ysize,dummy.csize, m_size);

#ifdef _WIN32
  size_t segmentSize=m_size+sizeof(t_pixshare_header);

  m_MapFile = CreateFileMapping(
                INVALID_HANDLE_VALUE,    // use paging file
                NULL,                    // default security
                PAGE_READWRITE,          // read/write access
                (segmentSize & 0xFFFFFFFF00000000) >>
                32,         // maximum object size (high-order DWORD)
                segmentSize & 0xFFFFFFFF,         // maximum object size (low-order DWORD)
                m_fileMappingName);      // name of mapping object

  if (m_MapFile == NULL) {
    error("Could not create file mapping object %s - error %ld.",
          m_fileMappingName, GetLastError());
    return -1;
  }

  shm_addr = (unsigned char*) MapViewOfFile(
               m_MapFile,   // handle to map object
               FILE_MAP_ALL_ACCESS, // read/write permission
               0,
               0,
               segmentSize);

  if ( !shm_addr ) {
    error("Could not get a view of file %s - error %ld",m_fileMappingName,
          GetLastError());
    return -1;
  } else {
    verbose(0,"File mapping object %s successfully created.",
            m_fileMappingName);
  }

#elif USE_SHM

  /* get a new segment with the size specified by the user
   * OR an old segment with the size specified in its header
   * why: if somebody has already created the segment with our key
   * we want to reuse it, even if its size is smaller than we requested
   */
  errno=0;
  shm_id = shmget(fake,m_size+sizeof(t_pixshare_header), IPC_CREAT | 0666);

  if((shm_id<0) && (EINVAL==errno)) {
    errno=0;
    // the segment already exists, but is smaller than we thought!
    int id = shmget(fake,sizeof(t_pixshare_header),0666);
    if(id>0) { /* yea, we got it! */
      t_pixshare_header*h=(t_pixshare_header*)shmat(id,NULL,0666);
      if (!shm_addr || shm_addr==(void *)-1) {
        shm_addr=NULL;
        return 8;
      }
      /* read the size of the blob from the shared segment */
      if(h&&h->size) {
        error("someone was faster: only got %d bytes instead of %d",
              h->size, m_size);
        m_size=h->size;

        /* so free this shm-segment before we re-try with a smaller size */
        shmdt(h);

        /* now get the shm-segment with the correct size */
        shm_id = shmget(fake,m_size+sizeof(t_pixshare_header), IPC_CREAT | 0666);
      }
    }
  }

  if(shm_id>0) {
    /* now that we have a shm-segment, get the pointer to the data */
    shm_addr = (unsigned char*)shmat(shm_id,NULL,0666);
    if (!shm_addr || shm_addr==(void *)-1) {
      shm_addr=NULL;
      return 8;
    }

    if(shmctl(shm_id,IPC_STAT,&shm_desc)<0) {
      return 8;
    }
    /* write the size into the shm-segment */
    t_pixshare_header *h=(t_pixshare_header *)shm_addr;
    h->size = (shm_desc.shm_segsz-sizeof(t_pixshare_header));

    verbose(1, "shm:: id(%d) segsz(%d) cpid (%d) mem(%p)",
            shm_id,shm_desc.shm_segsz,shm_desc.shm_cpid, shm_addr);
  } else {
    error("couldn't get shm_id: error %d", errno);
    return -1; // AV : added because i'm usure of what value is returned when we get this error...
  }
#endif /* _WIN32, SHM */
  return 0;
}
Ejemplo n.º 3
0
pix_share_write :: ~pix_share_write()
{
  freeShm();
}
Ejemplo n.º 4
0
pix_share_write :: ~pix_share_write()
{
  freeShm();
  outlet_free(m_outlet);
}