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; }
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; }
pix_share_write :: ~pix_share_write() { freeShm(); }
pix_share_write :: ~pix_share_write() { freeShm(); outlet_free(m_outlet); }