/////////////////////////////////////////////////////////////////////////////// //> Name: GetFileName // // Type: Function // // Description: Used when no ID3v1 tag is available. Clears title, artist, album, genre. // Fills in the title field with the filename. // // Inputs: Pointer to meta-data struct, pointer to path and filename. // Outputs: 0 if Success, -1 if Failure. // //< ///////////////////////////////////////////////////////////////////////////////// INT _reentrant GetFileName(FILE_META_DATA * MetaData,_packed BYTE * pcFilePathName) { INT i; INT iLength; BYTE wChar; BOOL bFound = FALSE; UCS3 * pcFileName; UCS3 * pcStringPtr; _packed BYTE btPackedFileName[8+1+3+1];//8.3 plus null. //find the last '/' for(i=packed_strlen(pcFilePathName);i>=0;i--) {//start at the end, go backward until the char is '/' if(packed_get(pcFilePathName,i)==0x2f) break; } //now go forward until we hit the terminating NULL, copying each byte iLength = 0; i = i+1; // Don't display the '/'. while((wChar=packed_get(pcFilePathName,i++))) { packed_set(btPackedFileName,iLength++,wChar); } packed_set(btPackedFileName,iLength++,0); if(MetaData->wTitle) DBCSToUnicode(btPackedFileName,MetaData->wTitle,MetaData->iTitleBufferLength); return(SUCCESS); }
/* the error name vector, etc. */ int array_get(const gs_memory_t *mem, const ref * aref, long index_long, ref * pref) { if ((ulong)index_long >= r_size(aref)) return_error(e_rangecheck); switch (r_type(aref)) { case t_array: { const ref *pvalue = aref->value.refs + index_long; ref_assign(pref, pvalue); } break; case t_mixedarray: { const ref_packed *packed = aref->value.packed; uint index = (uint)index_long; for (; index--;) packed = packed_next(packed); packed_get(mem, packed, pref); } break; case t_shortarray: { const ref_packed *packed = aref->value.packed + index_long; packed_get(mem, packed, pref); } break; default: return_error(e_typecheck); } return 0; }
/* * Ensure that a dictionary uses the unpacked representation for keys. * We can't just use dict_resize, because the values slots mustn't move. */ int dict_unpack(ref * pdref, dict_stack_t *pds) { dict *pdict = pdref->value.pdict; if (!dict_is_packed(pdict)) return 0; /* nothing to do */ { gs_ref_memory_t *mem = dict_memory(pdict); uint count = nslots(pdict); const ref_packed *okp = pdict->keys.value.packed; ref old_keys; int code; ref *nkp; old_keys = pdict->keys; if (ref_must_save_in(mem, &old_keys)) ref_do_save_in(mem, pdref, &pdict->keys, "dict_unpack(keys)"); code = dict_create_unpacked_keys(count, pdref); if (code < 0) return code; for (nkp = pdict->keys.value.refs; count--; okp++, nkp++) if (r_packed_is_name(okp)) { packed_get((const gs_memory_t *)mem, okp, nkp); ref_mark_new_in(mem, nkp); } else if (*okp == packed_key_deleted) r_set_attrs(nkp, a_executable); if (!ref_must_save_in(mem, &old_keys)) gs_free_ref_array(mem, &old_keys, "dict_unpack(old keys)"); if (pds) dstack_set_top(pds); /* just in case */ } return 0; }
_reentrant RETCODE Fast_Playlist_GetLFN(INT iEntryType,INT pEntry,INT* pName){ _packed BYTE sFileSpec[SFN_LENGTH]; Finddata finddata; int find_handle ; int iDirHandle; int i; WORD iStrLen; RETCODE rtn = PLAYLIST_TRACK_NOT_FOUND; sFileSpec[0] = 0; packed_strcpy((_packed BYTE *)pName,g_CurrentSongName); iStrLen= packed_strlen((_packed BYTE *)pName); while(iStrLen--) { if(packed_get((_packed BYTE *)pName,iStrLen)=='/') { for (i = 0; i < SFN_LENGTH; i++) packed_set(sFileSpec,i,packed_get((_packed BYTE *)pName,iStrLen+1+i)); packed_set((_packed BYTE *)pName,iStrLen+1,0); break; } } Chdir((_packed char *)pName); iDirHandle = GetCWDHandle(); _memset(&finddata,0,sizeof(finddata)); finddata.device = 0; finddata.startrecord = 0;//start at the 0th record. find_handle = FindFirst(&finddata,(_packed char*) sFileSpec); if( find_handle > 0 ) { g_FileKey = finddata.Key; song_info.g_songFastKey=g_FileKey; packed_strcpy((_packed BYTE *)g_shortname, (_packed BYTE *)finddata.name); if (ConstructLongFileName(iDirHandle, finddata.startrecord - 1, pName ) > 0) rtn = PLAYLIST_SUCCESS; Fclose(iDirHandle); Fclose(find_handle); } return rtn; }
/* <array> aload <obj_0> ... <obj_n-1> <array> */ static int zaload(i_ctx_t *i_ctx_p) { os_ptr op = osp; ref aref; uint asize; ref_assign(&aref, op); if (!r_is_array(&aref)) return_op_typecheck(op); check_read(aref); asize = r_size(&aref); if (asize > ostop - op) { /* Use the slow, general algorithm. */ int code = ref_stack_push(&o_stack, asize); uint i; const ref_packed *packed = aref.value.packed; if (code < 0) return code; for (i = asize; i > 0; i--, packed = packed_next(packed)) packed_get(imemory, packed, ref_stack_index(&o_stack, i)); *osp = aref; return 0; } if (r_has_type(&aref, t_array)) memcpy(op, aref.value.refs, asize * sizeof(ref)); else { uint i; const ref_packed *packed = aref.value.packed; os_ptr pdest = op; for (i = 0; i < asize; i++, pdest++, packed = packed_next(packed)) packed_get(imemory, packed, pdest); } push(asize); ref_assign(op, &aref); return 0; }
/*---------------------------------------------------------------------------- Function Name: WORD _reentrant Playlist_GetFileExtention(_packed BYTE* pFileName) FunctionType: Function Inputs: _packed BYTE* File Name String Outputs: WORD File Extension Description: Finds the file extension 1 - Find length of file 2 - Find the "." by traversing backwards from the end of the string 3 - Fill File Extention string 4 - Return the file extention as a word ----------------------------------------------------------------------------*/ _reentrant INT Playlist_GetFileExtention(INT iIgnored1, INT iIgnored2, INT* pPtr) { WORD wFileExtension; WORD wStrLen; int i; _packed BYTE* pFileName = (_packed BYTE*) pPtr; //Get length of file name wStrLen= packed_strlen(pFileName); //Check File Length, return error if too long if(wStrLen>(MAX_FILENAME_LENGTH-1)) return META_DATA_FILE_NOT_SUPPORTED; //Find the "."; Traverse backwards from EOF while(wStrLen--) { wFileExtension = packed_get(pFileName,wStrLen); if(wFileExtension=='.') break; } //if the '.' could not be found return an error; else fill up wFileExtension if(!wStrLen) return META_DATA_FILE_NOT_SUPPORTED; else { //Pack 1st 3 characters after '.' for the extension for(i=0;i<3;i++) { packed_set((void*)&wFileExtension,i,packed_get(pFileName,++wStrLen)); } } //If we got here, a valid file extension was found. return wFileExtension; }
/* its length; nothing else has been checked. */ static int copy_interval(i_ctx_t *i_ctx_p /* for ref_assign_old */, os_ptr prto, uint index, os_ptr prfrom, client_name_t cname) { int fromtype = r_type(prfrom); uint fromsize = r_size(prfrom); if (!(fromtype == r_type(prto) || ((fromtype == t_shortarray || fromtype == t_mixedarray) && r_type(prto) == t_array)) ) return_op_typecheck(prfrom); check_read(*prfrom); check_write(*prto); if (fromsize > r_size(prto) - index) return_error(e_rangecheck); switch (fromtype) { case t_array: { /* We have to worry about aliasing, */ /* but refcpy_to_old takes care of it for us. */ return refcpy_to_old(prto, index, prfrom->value.refs, fromsize, idmemory, cname); } case t_string: { /* memmove takes care of aliasing. */ memmove(prto->value.bytes + index, prfrom->value.bytes, fromsize); } break; case t_mixedarray: case t_shortarray: { /* We don't have to worry about aliasing, because */ /* packed arrays are read-only and hence the destination */ /* can't be a packed array. */ uint i; const ref_packed *packed = prfrom->value.packed; ref *pdest = prto->value.refs + index; ref elt; for (i = 0; i < fromsize; i++, pdest++) { packed_get(imemory, packed, &elt); ref_assign_old(prto, pdest, &elt, cname); packed = packed_next(packed); } } break; } return 0; }
/* Get a FontBBox parameter from a font dictionary. */ int font_bbox_param(const gs_memory_t *mem, const ref * pfdict, double bbox[4]) { ref *pbbox; /* * Pre-clear the bbox in case it's invalid. The Red Books say that * FontBBox is required, but old Adobe interpreters don't require * it, and a few user-written fonts don't supply it, or supply one * of the wrong size (!); also, PageMaker 5.0 (an Adobe product!) * sometimes emits an absurd bbox for Type 1 fonts converted from * TrueType. */ bbox[0] = bbox[1] = bbox[2] = bbox[3] = 0.0; if (dict_find_string(pfdict, "FontBBox", &pbbox) > 0) { if (!r_is_array(pbbox)) return_error(e_typecheck); if (r_size(pbbox) == 4) { const ref_packed *pbe = pbbox->value.packed; ref rbe[4]; int i; int code; float dx, dy, ratio; const float max_ratio = 12; /* From the bug 687594. */ for (i = 0; i < 4; i++) { packed_get(mem, pbe, rbe + i); pbe = packed_next(pbe); } if ((code = num_params(rbe + 3, 4, bbox)) < 0) return code; /* Require "reasonable" values. */ dx = bbox[2] - bbox[0]; dy = bbox[3] - bbox[1]; if (dx <= 0 || dy <= 0 || (ratio = dy / dx) < 1 / max_ratio || ratio > max_ratio ) bbox[0] = bbox[1] = bbox[2] = bbox[3] = 0.0; } } else if (gs_currentcpsimode(mem)) { return_error(e_invalidfont); /* CPSI requires FontBBox */ } return 0; }
/* Continuation operator for packed arrays */ static int packedarray_continue(i_ctx_t *i_ctx_p) { os_ptr op = osp; es_ptr obj = esp - 1; if (r_size(obj)) { /* continue */ const ref_packed *packed = obj->value.packed; r_dec_size(obj, 1); push(1); packed_get(imemory, packed, op); obj->value.packed = packed_next(packed); esp += 2; *esp = obj[1]; return o_push_estack; } else { /* done */ esp -= 3; /* pop mark, object, proc */ return o_pop_estack; } }
/* Dump an array. */ void debug_dump_array(const ref *array) { const ref_packed *pp; unsigned int type = r_type(array); uint len; switch (type) { default: dprintf2 ("%s at 0x%lx isn't an array.\n", (type < countof(type_strings) ? type_strings[type] : "????"), (ulong)array); return; case t_oparray: /* This isn't really an array, but we'd like to see */ /* its contents anyway. */ debug_dump_array(op_array_table.value.refs + op_index(array) - op_def_count); return; case t_array: case t_mixedarray: case t_shortarray: ; } /* This "packed" loop works for all array-types. */ for ( len = r_size (array), pp = array->value.packed; len > 0; len--, pp = packed_next(pp)) { ref temp; packed_get(pp, &temp); dprintf3("..%04x%c 0x%02x ", (uint)pp & 0xffff, ((r_is_packed(pp)) ? '*' : ':'), r_type(&temp)); debug_dump_one_ref(&temp); dputc ('\n'); } }
/* ensuring that refs in mixed arrays are properly aligned. */ #undef idmemory /****** NOTA BENE ******/ int make_packed_array(ref * parr, ref_stack_t * pstack, uint size, gs_dual_memory_t *idmemory, client_name_t cname) { uint i; const ref *pref; uint idest = 0, ishort = 0; ref_packed *pbody; ref_packed *pdest; ref_packed *pshort; /* points to start of */ /* last run of short elements */ gs_ref_memory_t *imem = idmemory->current; uint space = imemory_space(imem); int skip = 0, pad; ref rtemp; int code; /* Do a first pass to calculate the size of the array, */ /* and to detect local-into-global stores. */ for (i = size; i != 0; i--) { pref = ref_stack_index(pstack, i - 1); switch (r_btype(pref)) { /* not r_type, opers are special */ case t_name: if (name_index(imem, pref) >= packed_name_max_index) break; /* can't pack */ idest++; continue; case t_integer: if (pref->value.intval < packed_min_intval || pref->value.intval > packed_max_intval ) break; idest++; continue; case t_oparray: /* Check for local-into-global store. */ store_check_space(space, pref); /* falls through */ case t_operator: { uint oidx; if (!r_has_attr(pref, a_executable)) break; oidx = op_index(pref); if (oidx == 0 || oidx > packed_int_mask) break; } idest++; continue; default: /* Check for local-into-global store. */ store_check_space(space, pref); } /* Can't pack this element, use a full ref. */ /* We may have to unpack up to align_packed_per_ref - 1 */ /* preceding short elements. */ /* If we are at the beginning of the array, however, */ /* we can just move the elements up. */ { int i = (idest - ishort) & (align_packed_per_ref - 1); if (ishort == 0) /* first time */ idest += skip = -i & (align_packed_per_ref - 1); else idest += (packed_per_ref - 1) * i; } ishort = idest += packed_per_ref; } pad = -(int)idest & (packed_per_ref - 1); /* padding at end */ /* Now we can allocate the array. */ code = gs_alloc_ref_array(imem, &rtemp, 0, (idest + pad) / packed_per_ref, cname); if (code < 0) return code; pbody = (ref_packed *) rtemp.value.refs; /* Make sure any initial skipped elements contain legal packed */ /* refs, so that the garbage collector can scan storage. */ pshort = pbody; for (; skip; skip--) *pbody++ = pt_tag(pt_integer); pdest = pbody; for (i = size; i != 0; i--) { pref = ref_stack_index(pstack, i - 1); switch (r_btype(pref)) { /* not r_type, opers are special */ case t_name: { uint nidx = name_index(imem, pref); if (nidx >= packed_name_max_index) break; /* can't pack */ *pdest++ = nidx + (r_has_attr(pref, a_executable) ? pt_tag(pt_executable_name) : pt_tag(pt_literal_name)); } continue; case t_integer: if (pref->value.intval < packed_min_intval || pref->value.intval > packed_max_intval ) break; *pdest++ = pt_tag(pt_integer) + ((short)pref->value.intval - packed_min_intval); continue; case t_oparray: case t_operator: { uint oidx; if (!r_has_attr(pref, a_executable)) break; oidx = op_index(pref); if (oidx == 0 || oidx > packed_int_mask) break; *pdest++ = pt_tag(pt_executable_operator) + oidx; } continue; } /* Can't pack this element, use a full ref. */ /* We may have to unpack up to align_packed_per_ref - 1 */ /* preceding short elements. */ /* Note that if we are at the beginning of the array, */ /* 'skip' already ensures that we don't need to do this. */ { int i = (pdest - pshort) & (align_packed_per_ref - 1); const ref_packed *psrc = pdest; ref *pmove = (ref *) (pdest += (packed_per_ref - 1) * i); ref_assign_new(pmove, pref); while (--i >= 0) { --psrc; --pmove; packed_get(imem->non_gc_memory, psrc, pmove); } } pshort = pdest += packed_per_ref; } { int atype = (pdest == pbody + size ? t_shortarray : t_mixedarray); /* Pad with legal packed refs so that the garbage collector */ /* can scan storage. */ for (; pad; pad--) *pdest++ = pt_tag(pt_integer); /* Finally, make the array. */ ref_stack_pop(pstack, size); make_tasv_new(parr, atype, a_readonly | space, size, packed, pbody + skip); } return 0; }
//////////////////////////////////////////////////////////////////////////////// // //> Name: GetFileMetaData // // Type: Function // // Description: Determines type of file and calls type-specific meta data program. // // Inputs: Ptr to pathname, current device id, meta-data struct location // // Outputs: RETCODE (0 if MetaData found, -1 if not) // // Notes: none //< //////////////////////////////////////////////////////////////////////////////// RETCODE _reentrant GetFileMetaData(INT PackedPathNameAddress, INT btCurrentDevice, FILE_META_DATA *MetaData) { RETCODE rtn = META_DATA_FOUND; WORD wExtension; WORD iStrLen; INT i; int CurrentFolder; _packed BYTE * pcFilePathName = (_packed BYTE*)PackedPathNameAddress; // check if path + filename will fit in unpacked buffer iStrLen= packed_strlen(pcFilePathName); if(iStrLen>(MAX_FILENAME_LENGTH-1)) return META_DATA_NOT_FOUND; // clear out the artist field if(MetaData->wTitle) *MetaData->wTitle = 0; if(MetaData->wArtist) *MetaData->wArtist = 0; // clear out the album field if(MetaData->wAlbum) *MetaData->wAlbum = 0; #ifdef USE_PLAYLIST3 // clear out the genre field if(MetaData->wGenre) *MetaData->wGenre = 0; // clear out the genre field if(MetaData->wYear) *MetaData->wYear = 0; #endif // Clear the genre byte MetaData->btGenre = (BYTE)0; #ifdef SYNC_LYRICS // Init. Lyric's Data Buffer SysCallFunction(RSRC_LYRICS_API_CODEBANK,LyricsInit,0,0,0); #endif #ifdef JPEG_ALBUM_ART // Initialize the APIC values SysCallFunction(RSRC_APIC_FRAME_CODEBANK, ApicInit, 0, 0, NULL); #endif if(iStrLen > 4) { // Use C Speed client Increase call // Defines are in SysSpeed.inc. Sysspeed.h is generated SysSpeedIncrease(SPEED_MAX, SPEED_CLIENT_METADATA); //find the '.' while(iStrLen--) { wExtension = packed_get(pcFilePathName,iStrLen); if(wExtension=='.') break; } if(iStrLen) { for(i=0;i<3;i++) { packed_set((void*)&wExtension,i,packed_get(pcFilePathName,++iStrLen)); } // Search file path/name for "." -- get the extension // Call Decoder Specific MetaData routine for file extension found. //pcExtString should point to ".mp3" or ".wma", etc #ifdef AUDIBLE g_AudibleFlags.bits.IsAudibleFile = FALSE; #endif switch(wExtension) { case 0x33504d: //"MP3" rtn = SysCallFunction(RSRC_MP3_METADATA_CODEBANK,GetMp3MetaData,(INT)pcFilePathName,btCurrentDevice,(void*)MetaData); #ifdef USE_PLAYLIST3 g_unicode = 0; MetaData->dwStartPos = 0; #endif break; case 0x414D57: //"WMA" #ifdef USE_PLAYLIST3 #ifdef JPEG_ALBUM_ART bPicOnlyFlag = TRUE; #endif #endif rtn = SysCallFunction(RSRC_WMA_METADATA_CODEBANK,GetWmaMetaData,(INT)pcFilePathName,btCurrentDevice,(void*)MetaData); #ifdef USE_PLAYLIST3 g_unicode = 1; MetaData->dwStartPos = 0; #endif break; case 0x564157: //"WAV" rtn = SysCallFunction(RSRC_WAV_METADATA_CODEBANK,GetWavMetaData,(INT)pcFilePathName,btCurrentDevice,(void*)MetaData); #ifdef USE_PLAYLIST3 g_unicode = 1; MetaData->dwStartPos = 0; #endif break; #ifdef MOTION_VIDEO case 0x564d53: // "SMV" rtn = SysCallFunction(RSRC_SMV_METADATA_CODEBANK,GetSMVMetaData,(INT)pcFilePathName,btCurrentDevice,(void*)MetaData); #ifdef USE_PLAYLIST3 g_unicode = 1; MetaData->dwStartPos = 0; #endif break; #endif #ifdef AUDIBLE case 0x004141: //"AA " LoadAudibleMetadataResource(RSRC_AUDIBLE_METADATA_Y, RSRC_TYPE_DATA, (_lc_u_e_AUDIBLE_METADATA_Y-_lc_u_b_AUDIBLE_METADATA_Y)*3, (int)_lc_u_b_AUDIBLE_METADATA_Y, TARGET_MEM_Y); rtn = SysCallFunction(RSRC_AUDIBLE_METADATA_P,GetAudibleMetaData,(INT)pcFilePathName,btCurrentDevice,(void*)MetaData); if ( rtn == META_DATA_FOUND ) g_AudibleFlags.bits.IsAudibleFile = TRUE; break; #endif default: rtn = META_DATA_NOT_FOUND; break; } } if(!strlen(MetaData->wTitle)){ //if the string length is zero then check if LFN or SFN is present. //!!HACK!! Following LFN will work only for current track. //Ideally, a SFN should be passed to playlists and long filename for that file should be returned. #ifdef USE_PLAYLIST1 if(SysCallFunction(RSRC_PLAYLIST_CODEBANK,Playlist_LFNGetFileName,g_iInternalTrack,0,(void*)MetaData->wTitle) >0 ) //is there a LFN #else #ifdef USE_PLAYLIST2 if(SysCallFunction(RSRC_PLAYLIST_CODEBANK,Playlist_GetLFN,TYPE_FILE,(INT) g_CurrentTrack.pFileEntry,(INT*)MetaData->wTitle) == PLAYLIST_SUCCESS) //is there a LFN #else #ifdef USE_PLAYLIST3 if (1) #else #ifdef USE_PLAYLIST5 { PL5_PL_QITEM * tmp; int recordnum; LONG fastkey; tmp = g_PL5_PL_queue.pos + g_PL5_Playback.currentplay; recordnum = tmp->file.iRecordNum; fastkey = (tmp->folder + tmp->depth - 1)->record.lFastKey; if(SysCallFunction(RSRC_PLAYLIST_CODEBANK,Playlist_GetLFN,(INT)(&fastkey), recordnum,(INT*)MetaData->wTitle) == PLAYLIST_SUCCESS) // is there a LFN #endif #endif #endif #endif // #ifdef USE_PLAYLIST1 { } else //no long file name so we must diplay the short one { GetFileName(MetaData,pcFilePathName); #ifdef USE_PLAYLIST3 g_unicode = 1; #endif } #ifdef USE_PLAYLIST5 } #endif } TrimString(MetaData->wArtist); TrimString(MetaData->wTitle); TrimString(MetaData->wAlbum); #ifdef USE_PLAYLIST3 TrimString(MetaData->wGenre); TrimString(MetaData->wYear); #endif // C Speed client free call SysSpeedClockFree(SPEED_CLIENT_METADATA); // free the shared speed resource } else rtn = META_DATA_NOT_FOUND; return rtn; }