Пример #1
0
def trimwavdata(wavedatain, start, duration=None):
    # check for a PCM file format
    if wavedatain[:4]!='RIFF' or wavedatain[8:12]!='WAVE' or \
       wavedatain[12:16]!='fmt ' or common.LSBUint16(wavedatain[20:22])!=1:
        raise ValueError, 'not a PCM file'
    subchunk1size = common.LSBUint32(wavedatain[16:20])
    subchunk2start = 20 + subchunk1size
    subchunk2size = common.LSBUint32(wavedatain[subchunk2start +
                                                4:subchunk2start + 8])
    subchunk2datastart = subchunk2start + 8
    samplerate = common.LSBUint32(wavedatain[24:28])
    blockalign = common.LSBUint16(wavedatain[32:34])
    # compute new start & duration
    new_start = int(start * samplerate) * blockalign
    newsubchunk2datastart = subchunk2datastart + new_start
    new_size = subchunk2size - new_start
    if duration is not None:
        i = int(duration * samplerate) * blockalign
        if i < new_size:
            new_size = i
    # return new data
    return 'RIFF'+common.LSBstr32(4+8+subchunk1size+8+new_size)+\
           wavedatain[8:subchunk2start]+\
           'data'+common.LSBstr32(new_size)+\
           wavedatain[newsubchunk2datastart:newsubchunk2datastart+new_size]
Пример #2
0
def trimwavfile(wavfilename, wavoutfilename, start, duration=None, gain=None):
    with file(wavfilename, 'rb') as f:
        # read in the headers
        headers = f.read(20)
        subchunk1size = common.LSBUint32(headers[16:20])
        headers += f.read(subchunk1size)
        subchunk2id = f.read(4)
        subchunk2size = common.LSBUint32(f.read(4))
        # check for a PCM file format
        if headers[:4]!='RIFF' or headers[8:12]!='WAVE' or \
        headers[12:16]!='fmt ' or common.LSBUint16(headers[20:22])!=1:
            # not a PCM file
            raise TypeError
        subchunk2start = 20 + subchunk1size
        subchunk2datastart = subchunk2start + 8
        samplerate = common.LSBUint32(headers[24:28])
        blockalign = common.LSBUint16(headers[32:34])
        # compute new start & duration
        new_start = int(start * samplerate) * blockalign
        new_size = subchunk2size - new_start
        if duration is not None:
            i = int(duration * samplerate) * blockalign
            if i < new_size:
                new_size = i
        # go get it
        f.seek(new_start, 1)
        open(wavoutfilename, 'wb').write("".join([
            'RIFF',
            common.LSBstr32(4 + 8 + subchunk1size + 8 + new_size), headers[8:],
            'data',
            common.LSBstr32(new_size),
            f.read(new_size)
        ]))
        if gain is not None:
            adjustwavfilevolume(wavoutfilename, gain)
Пример #3
0
def adjustwavfilevolume(wavfilename, gain):
    """ Ajdust the volume of a wav file.
    """
    with file(wavfilename, 'rb') as f:
        # read in the headers
        headers = f.read(20)
        subchunk1size = common.LSBUint32(headers[16:20])
        headers += f.read(subchunk1size)
        headers += f.read(8)  # 4 byte ID and 4 byte length
        subchunk2size = common.LSBUint32(headers[-4:])
        bitspersample = common.LSBUint16(headers[34:36])
        if bitspersample != 16:
            print 'Volume adjustment only works with 16-bit wav file', bitspersample
            return
        sample_num = subchunk2size / 2  # always 16-bit per channel per sample
        temp_name = common.gettempfilename("wav")
        with file(temp_name, 'wb') as f_temp:
            f_temp.write(headers)
            delta = pow(10.0, (gain / 10.0))
            for i in range(sample_num):
                d = int(struct.unpack('<h', f.read(2))[0] * delta)
                if d > 32767:
                    d = 32767
                elif d < -32768:
                    d = -32768
                f_temp.write(struct.pack('<h', d))
    os.remove(wavfilename)
    os.rename(temp_name, wavfilename)
Пример #4
0
def convertlgbittobmp(bit_data):
    """Takes a BIT image file (LG proprietary) and returns BMP

    @param bit_data: 16BPP BIT image file data
    @return: 24BPP BMP image file data
    """
    width = common.LSBUint16(bit_data[0:2])
    height = common.LSBUint16(bit_data[2:4])
    img = 'BM'
    img += common.LSBstr32(width * height * 3 + 54)  # file size
    img += common.LSBstr16(0)  # unused
    img += common.LSBstr16(0)  # unused
    img += common.LSBstr32(54)  # offset to pixel data (from byte 0)
    img += common.LSBstr32(40)  # info section size
    img += common.LSBstr32(width)  # image width
    img += common.LSBstr32(height)  # image height
    img += common.LSBstr16(1)  # image planes
    img += common.LSBstr16(24)  # bits-per-pixel
    img += common.LSBstr32(0)  # compression type (0=uncompressed)
    img += common.LSBstr32(0)  # image size (may be 0 for uncompressed images)
    img += common.LSBstr32(0)  # (ignored)
    img += common.LSBstr32(0)  # (ignored)
    img += common.LSBstr32(0)  # (ignored)
    img += common.LSBstr32(0)  # (ignored)
    # Now on to the char data
    for h in range(height):
        for w in range(width):
            # images can be zero len on phone
            if len(bit_data) == 0:
                bitdata = 0xffff
            else:
                bitind = (height - h - 1) * width * 2 + (w * 2) + 4
                bitdata = common.LSBUint16(bit_data[bitind:bitind + 2])
            red = (bitdata & 0xf800) >> 8
            green = (bitdata & 0x07e0) >> 3
            blue = (bitdata & 0x001f) << 3
            if (red & 0x8) != 0:
                red = red | 0x7
            if (green & 0x4) != 0:
                green = green | 0x3
            if (blue & 0x8) != 0:
                blue = blue | 0x7
            img += chr(blue)
            img += chr(green)
            img += chr(red)
    return img
Пример #5
0
def convertbmptolgbit(bmp_data):
    """Takes a BMP image file and returns BIT image file (LG proprietary)

    @param bit_data: 8BPP or 24BPP BMP image file data
    @return: 16BPP LGBIT image file data
    """
    # This function only exists for the LG proprietary images (wallpaper, etc.)
    # on the LG-VX3200.
    if bmp_data[0:2] != 'BM':
        return None
    width = common.LSBUint32(bmp_data[18:22])
    height = common.LSBUint32(bmp_data[22:26])
    offset = common.LSBUint32(bmp_data[10:14])
    bpp = common.LSBUint16(bmp_data[28:30])
    img = common.LSBstr16(width)
    img += common.LSBstr16(height)
    # Now on to the char data
    if bpp == 8:
        # 8BPP (paletted) BMP data
        palette = bmp_data[54:54 + 256 * 4]
        for h in range(height):
            for w in range(width):
                bitind = (height - h - 1) * width + w + offset
                palind = ord(bmp_data[bitind:bitind + 1]) * 4
                blue = ord(palette[palind:palind + 1])
                green = ord(palette[palind + 1:palind + 2])
                red = ord(palette[palind + 2:palind + 3])
                bitval = ((red & 0xf8) << 8) | ((green & 0xfc) << 3) | (
                    (blue & 0xf8) >> 3)
                img += common.LSBstr16(bitval)
    elif bpp == 24:
        # 24BPP (non-paletted) BMP data
        for h in range(height):
            for w in range(width):
                bitind = (height - h - 1) * width * 3 + (w * 3) + offset
                blue = ord(bmp_data[bitind:bitind + 1])
                green = ord(bmp_data[bitind + 1:bitind + 2])
                red = ord(bmp_data[bitind + 2:bitind + 3])
                bitval = ((red & 0xf8) << 8) | ((green & 0xfc) << 3) | (
                    (blue & 0xf8) >> 3)
                img += common.LSBstr16(bitval)
    else:
        return None
    return img
Пример #6
0
    def savemedia(self, mediakey, mediaindexkey, maps, results, merge, reindexfunction):
        """Actually saves out the media

        @param mediakey: key of the media (eg 'wallpapers' or 'ringtone')
        @param mediaindexkey:  index key (eg 'wallpaper-index')
        @param maps: list index files and locations
        @param results: results dict
        @param merge: are we merging or overwriting what is there?
        @param reindexfunction: the media is re-indexed at the end.  this function is called to do it
        """
        print results.keys()
        # I humbly submit this as the longest function in the bitpim code ...
        # wp and wpi are used as variable names as this function was originally
        # written to do wallpaper.  it works just fine for ringtones as well
        #
        # LG-VX3200 special notes:
        # The index entries for both the wallpaper and ringers are
        # hacked just a bit AND are hacked in slightly different
        # ways. In addition to that the media for the wallpapers is
        # currently in BMP format inside the program and must be
        # converted to BIT (LG proprietary) on the way out.
        #
        # In the following:
        #   wp has file references that nave no suffixes
        #   wpi has file references that are mixed, i.e. some have file suffixes (comes from UI that way)
        wp=results[mediakey].copy()
        wpi=results[mediaindexkey].copy()
        
        # Walk through wp and remove any suffixes that make their way in via the UI
        for k in wp.keys():
            wp[k]['name']=re.sub("\....$", "", wp[k]['name'])
            
        # remove builtins
        for k in wpi.keys():
            if wpi[k]['origin']=='builtin':
                del wpi[k]
                
        # build up list into init
        init={}
        for offset,indexfile,location,type,maxentries in maps:
            init[type]={}
            for k in wpi.keys():
                if wpi[k]['origin']==type:
                    index=k-offset
                    name=wpi[k]['name']
                    data=None
                    del wpi[k]
                    for w in wp.keys():
                        if wp[w]['name']==name and wp[w]['origin']==type:
                            data=wp[w]['data']
                            del wp[w]
                    if not merge and data is None:
                        # delete the entry
                        continue
                    init[type][index]={'name': name, 'data': data}

        # init now contains everything from wallpaper-index
        print init.keys()
        # now look through wallpapers and see if anything remaining was assigned a particular
        # origin
        for w in wp.keys():
            o=wp[w].get("origin", "")
            if o is not None and len(o) and o in init:
                idx=-1
                while idx in init[o]:
                    idx-=1
                init[o][idx]=wp[w]
                del wp[w]
            
        # we now have init[type] with the entries and index number as key (negative indices are
        # unallocated).  Proceed to deal with each one, taking in stuff from wp as we have space
        for offset,indexfile,location,type,maxentries in maps:
            if type=="camera": break
            index=init[type]
            try:
                dirlisting=self.getfilesystem(location)
            except com_brew.BrewNoSuchDirectoryException:
                self.mkdirs(location)
                dirlisting={}
            # rename keys to basename
            for i in dirlisting.keys():
                dirlisting[i[len(location)+1:]]=dirlisting[i]
                del dirlisting[i]
            # what we will be deleting
            dellist=[]
            if not merge:
                # get existing wpi for this location
                wpi=results[mediaindexkey]
                for i in wpi:
                    entry=wpi[i]
                    if entry['origin']==type:
                        # it is in the original index, are we writing it back out?
                        delit=True
                        for idx in index:
                            if index[idx]['name']==entry['name']:
                                delit=False
                                break
                        if delit:
                            # Add the media file suffixes back to match real filenames on phone
                            if type=="ringers":
                                entryname=entry['name']+".mid"
                            else:
                                entryname=entry['name']+".bit"
                            if entryname in dirlisting:
                                dellist.append(entryname)
                            else:
                                self.log("%s in %s index but not filesystem" % (entryname, type))
            # go ahead and delete unwanted files
            print "deleting",dellist
            for f in dellist:
                self.mediacache.rmfile(location+"/"+f)
            # LG-VX3200 special case:
            # We only keep (upload) wallpaper images if there was a legit
            # one on the phone to begin with. This code will weed out any
            # attempts to the contrary.
            if type=="images":
                losem=[]
                # get existing wpi for this location
                wpi=results[mediaindexkey]
                for idx in index:
                    delit=True
                    for i in wpi:
                        entry=wpi[i]
                        if entry['origin']==type:
                            if index[idx]['name']==entry['name']:
                                delit=False
                                break
                    if delit:
                        self.log("Inhibited upload of illegit image (not originally on phone): "+index[idx]['name'])
                        losem.append(idx)
                # Now actually remove any illegit images from upload attempt
                for idx in losem:
                    del index[idx]
            #  slurp up any from wp we can take
            while len(index)<maxentries and len(wp):
                idx=-1
                while idx in index:
                    idx-=1
                k=wp.keys()[0]
                index[idx]=wp[k]
                del wp[k]
            # normalise indices
            index=self._normaliseindices(index)  # hey look, I called a function!
            # move any overflow back into wp
            if len(index)>maxentries:
                keys=index.keys()
                keys.sort()
                for k in keys[maxentries:]:
                    idx=-1
                    while idx in wp:
                        idx-=1
                    wp[idx]=index[k]
                    del index[k]

            # Now add the proper media file suffixes back to the internal index
            # prior to the finish up steps coming
            for k in index.keys():
                if type=="ringers":
                    index[k]['name']=index[k]['name']+".mid"
                else:
                    index[k]['name']=index[k]['name']+".bit"
                    
            # write out the new index
            keys=index.keys()
            keys.sort()
            ifile=self.protocolclass.indexfile()
            ifile.numactiveitems=len(keys)
            for k in keys:
                entry=self.protocolclass.indexentry()
                entry.index=k
                entry.name=index[k]['name']
                ifile.items.append(entry)
            while len(ifile.items)<maxentries:
                ifile.items.append(self.protocolclass.indexentry())
            buffer=prototypes.buffer()
            ifile.writetobuffer(buffer, autolog=False)
            if type!="images":
                # The images index file on the LG-VX3200 is a noop - don't write
                self.logdata("Updated index file "+indexfile, buffer.getvalue(), ifile)
                self.writefile(indexfile, buffer.getvalue())
                
            # Write out files - we compare against existing dir listing and don't rewrite if they
            # are the same size
            for k in keys:
                entry=index[k]
                entryname=entry['name']
                data=entry.get("data", None)
                # Special test for wallpaper files - LG-VX3200 will ONLY accept these files
                if type=="images":
                    if entryname!="wallpaper.bit" and entryname!="poweron.bit" and entryname!="poweroff.bit":
                        self.log("The wallpaper files can only be wallpaper.bmp, poweron.bmp or poweroff.bmp. "+entry['name']+" does not conform - skipping upload.")
                        continue
                if data is None:
                    if entryname not in dirlisting:
                        self.log("Index error.  I have no data for "+entryname+" and it isn't already in the filesystem - skipping upload.")
                    continue
                # Some of the wallpaper media files came here from the UI as BMP files.
                # These need to be converted to LGBIT files on the way out.
                if type=="images" and data[0:2]=="BM":
                    data=conversions.convertbmptolgbit(data)
                    if data is None:
                        self.log("The wallpaper BMP images must be 8BPP or 24BPP, "+entry['name']+", does not comply - skipping upload.")
                        continue
                # Can only upload 128x128 images
                if type=="images" and (common.LSBUint16(data[0:2])!=128 or common.LSBUint16(data[2:4])!=128):
                        self.log("The wallpaper must be 128x128, "+entry['name']+", does not comply - skipping upload.")
                        continue
                # This following test does not apply to wallpaper - it is always the same size on the LG-VX3200!
                if type!="images":
                    if entryname in dirlisting and len(data)==dirlisting[entryname]['size']:
                        self.log("Skipping writing %s/%s as there is already a file of the same length" % (location,entryname))
                        continue
                self.mediacache.writefile(location+"/"+entryname, data)
                self.log("Wrote media file: "+location+"/"+entryname)
        # did we have too many
        if len(wp):
            for k in wp:
                self.log("Unable to put %s on the phone as there weren't any spare index entries" % (wp[k]['name'],))
                
        # Note that we don't write to the camera area

        # tidy up - reread indices
        del results[mediakey] # done with it
        # This excessive and expensive so do not do
        # self.mediacache.flush()
        # self.log("Flushed ringer cache")
        reindexfunction(results)
        return results