Author Topic: Tags Library  (Read 63358 times)

EWeiss

  • Posts: 355
Re: Tags Library
« Reply #425 on: 8 Dec '17 - 12:19 »
Quote
EWeiss: When passing a variable by reference, the pointer to the variable is sent. When passing a variable by value, the variable's value is copied to the stack (depends on the calling convention, might be a register too) for the function that expects it. If you pass a reference (pointer) to a struct only the pointer is copied to the stack, if you send the struct by value, the whole structure is copied to the stack.

What are you trying to tell me?
I worked with VB6 for 15 years before I went to Delphi..

read all my hints and do not tell me what and why something is not working.
I told you that it does not work with ByVal only over ByRef
so do not tell me anything.

That's clear to me.

for you too? i hope now

greets
« Last Edit: 9 Dec '17 - 06:50 by EWeiss »

Steve Grant

  • Posts: 148
Re: Tags Library
« Reply #426 on: 8 Dec '17 - 22:15 »
I have tried the latest. It works!!!!

Test Code:

Code: [Select]
Dim CoverArt As TCoverArtData, lTags As Long, FileName As String
    ChDrive App.Path '//This just forces the program to look in the current folder
    ChDir App.Path '//This just forces the program to look in the current folder
    FileName = App.Path & "\Bonanza.flac"
    If lTags = 0 Then lTags = TagsLibrary_Create
    TagsLibrary_Load lTags, StrPtr(FileName), ttAutomatic, True
    ImageStart.Picture = LoadPicture(App.Path & "\Pic.jpg")
    CoverArt.Name = StrPtr("Cover Art 1")
    CoverArt.CoverType = 3 '//* ID3v2 cover type (3: front cover)
    CoverArt.MIMEType = StrPtr("image/jpeg")
    CoverArt.Description = StrPtr("Front")
    CoverArt.width = ScaleX(ImageStart.width, vbTwips, vbPixels)
    CoverArt.height = ScaleY(ImageStart.height, vbTwips, vbPixels)
    CoverArt.ColorDepth = 24
    CoverArt.NoOfColors = 0
    CoverArt.PictureFormat = tpfJPEG
    CoverArt.Data = 0 '; //PictureStream.Memory;
    CoverArt.DataSize.LowPart = 0 '//PictureStream.Size;
    CoverArt.DataSize.HighPart = 0 '//PictureStream.Size;
    TagsLibrary_AddCoverArtFromFile lTags, ttAutomatic, StrPtr(App.Path & "\Pic.jpg"), CoverArt
    TagsLibrary_Save lTags, StrPtr(FileName), ttAutomatic
    TagsLibrary_Free lTags

This is the Declare:

Code: [Select]
Public Declare Function TagsLibrary_AddCoverArtFromFile Lib "TagsLib.dll" (ByVal Tags As Long, ByVal TagType As TTagType, ByVal FileName As Long, ByRef CoverArt As TCoverArtData) As Long
As I won't know the parameters of the downloaded image, is it safe to always use 24 for the BitDepth?

Many many thanks.


EWeiss

  • Posts: 355
Re: Tags Library
« Reply #427 on: 9 Dec '17 - 06:52 »
Quote
is it safe to always use 24 for the BitDepth?
read the Bitmap Header and use the BitDeph from Image Handle which your use.
see! bmBitsPixel

Code: [Select]
Public Function GetBitmapInfo(ByVal hBitmap As Long, _
                              Optional ByRef Return_Height As Long, _
                              Optional ByRef Return_Width As Long, _
                              Optional ByRef Return_BitsPerPixel As Integer, _
                              Optional ByRef Return_Size As Double, _
                              Optional ByRef Return_PointerToBits As Long) As Boolean
On Error Resume Next
 
  Dim BMP As BITMAP
 
  ' Clear the return variables
  Return_Height = 0
  Return_Width = 0
  Return_BitsPerPixel = 0
  Return_Size = 0
  Return_PointerToBits = 0
 
  ' Check that there's a valid input
  If hBitmap = 0 Then Exit Function
 
  ' Get the information
  If GetObjectAPI(hBitmap, Len(BMP), BMP) = 0 Then Exit Function
 
  ' Return the information
  With BMP
    Return_Height = .bmHeight
    Return_Width = .bmWidth
    Return_BitsPerPixel = (.bmBitsPixel * .bmPlanes)
    Return_Size = ((.bmWidth * 3 + 3) And &HFFFFFFFC) * .bmHeight
    Return_PointerToBits = .bmBits
  End With
 
  ' Function succeeded
  GetBitmapInfo = True
 
End Function

greets
« Last Edit: 9 Dec '17 - 07:01 by EWeiss »

Steve Grant

  • Posts: 148
Re: Tags Library
« Reply #428 on: 9 Dec '17 - 09:23 »
@Emil many thanks.

Is Return_Size always aligned?

Greets

EWeiss

  • Posts: 355
Re: Tags Library
« Reply #429 on: 9 Dec '17 - 10:24 »
@Emil many thanks.

Is Return_Size always aligned?

Greets

what your mean?
the size is from Original File.. is not the size from Picturebox if your load it and resize (align) it to PictureBox.

Code: [Select]
    Return_Height = .bmHeight
    Return_Width = .bmWidth

is the correct size of the original Image to.
test it should not be a Problem i think ;)

greets

Steve Grant

  • Posts: 148
Re: Tags Library
« Reply #430 on: 9 Dec '17 - 21:36 »
@Emil, sorry I should have been clearer. When reading up on this to try and learn, I read that the returned Data Size has to be DWord aligned.  (divisible by 4)

3delite

  • Posts: 907
Re: Tags Library
« Reply #431 on: 10 Dec '17 - 09:59 »
Good to hear that it works now! :)

The package has been updated, download link in the first post:

  • New function TagsLibrary_AddCoverArtFromFile() for the .dll version
  • Fixed (ID3v2) 'PlayTime' for exotic MPEG formats
  • Delphi ID3v2 unit: changed all {$IFDEF CPUX64} to {$IFDEF WIN64}
  • Updates for Lazarus/Free Pascal for the ID3v1 unit

3delite

  • Posts: 907
Re: Tags Library
« Reply #432 on: 11 Dec '17 - 11:32 »
I was against adding picture processing code to the library but it came to my mind that I could use Free Image Library for this purpose. The TagsLib.dll size increased only by 50 KB.

Added 2 new functions to simplify managing cover arts:

function TagsLibrary_GetCoverArtBitmapHandle(Tags: TTags; TagType: TTagType; Index: Integer; var CoverArt: TCoverArtData; var BitmapHandle: THandle; Width: Integer; Height: Integer; KeepAspectRatio: LongBool; Resampler: Integer; Handle: THandle): LongBool;
       Get the cover art's HBITMAP handle specified by 'Index' using Free Image Library with optional resize. All picture formats supported by Free Image Library are supported.
       The cover art details are returned in 'CoverArt'.
   The HBITMAP handle is returned in 'BitmapHandle'.
   'Width' and 'Height' are opional, use '0' to retrieve the picture in it's original size.
   Set 'KeepAspectRatio' to True to resize the picture based on max. 'Width' or 'Height'.
   'Resampler' is used to specify a Free Image Library resampler to be used for resizing the picture, Lanczos3 is recommended for sharpest result.
       'Handle' specifies a Handle to be used for GetDC() when creating the DIB (eg. use a windows' HWND handle here).
       Return value is 'True' on success.
       This function is only available on Windows, 'FreeImage.dll' must be available on the .dll load path (eg. beside the .exe). On Win64 'vcomp120.dll' is also needed. 'FreeImage.dll' is loaded dynamicaly on first call to this function, if you don't call this function 'FreeImage.dll' will not be loaded at all, so it's not needed then.
   
function TagsLibrary_AddCoverArtFromFileAutomatic(Tags: TTags; TagType: TTagType; FileName: PChar; Name: PChar; Description: PChar; CoverType: Integer; Handle: THandle): Integer;
       Add a cover art specified by 'FileName' using Free Image Library. Picture formats supported: JPEG, PNG, GIF, BMP and TIFF.
       'Name' is only used with APEv2, should be 'Cover Art (Front)'.
       'Description' is self explanatory.
       'CoverType': ID3v2 cover type, use '3' as front cover.
       'Handle' specifies a Handle to be used for GetDC() when creating the DIB (eg. use a windows' HWND handle here).
       Return value is the new cover art index on success, - 1 on fail.
       This function is only available on Windows, 'FreeImage.dll' must be available on the .dll load path (eg. beside the .exe). On Win64 'vcomp120.dll' is also needed. 'FreeImage.dll' is loaded dynamicaly on first call to this function, if you don't call this function 'FreeImage.dll' will not be loaded at all, so it's not needed then.
   
Not sure if the VB6 and C++ header is right, please let me know if there are any problems!

Download (beta): Tags Library.zip

In Delphi now it's this simple to load a cover art:

Code: [Select]
procedure TForm1.DisplayCoverArt(Index: Integer);
var
    CoverArtData: TCoverArtData;
    BitmapHandle: THandle;
begin
    if TagsLibrary_GetCoverArtBitmapHandle(Tags, ttAutomatic, Index, CoverArtData, BitmapHandle, Image1.Width, Image1.Height, True, FILTER_LANCZOS3, Handle) then begin
        Image1.Picture.Bitmap.Handle := BitmapHandle;
    end;
end;

...and to add a new:

Code: [Select]
procedure TForm1.Button2Click(Sender: TObject);
begin
    if OpenDialog1.Execute then begin
        if TagsLibrary_AddCoverArtFromFileAutomatic(Tags, ttAutomatic, PChar(OpenDialog1.FileName), 'Cover Art (Front)' {This field is only used for APEv2 and should be always 'Cover Art (Front)'}, 'My description', 3, Handle) < 0 then begin
            MessageDlg('Error while adding cover art.', mtError, [mbCancel], 0);
        end;
        ListCoverArts;
    end;
end;

Steve Grant

  • Posts: 148
Re: Tags Library
« Reply #433 on: 11 Dec '17 - 14:14 »
Hi, no time at present but I will test this for you to ensure the VB6 stuff is ok.

I downloaded FreeImage.dll and it is almost 6.5 MB for the 64bit. I am getting stunning results using Emil's class and it is just 14KB.

More soon.

Steve Grant

  • Posts: 148
Re: Tags Library
« Reply #434 on: 12 Dec '17 - 08:43 »
As promised I have tested it. The msgbox pops up. I guess I have missed some steps! FreeImage (32) is sitting beside TagsLib (32) Here is my code:

Code: [Select]
Private Sub Form_Load()
    Dim lTags As Long
    ChDrive App.Path
    ChDir App.Path
    lTags = TagsLibrary_Create
    TagsLibrary_Load lTags, StrPtr(App.Path & "\Test.mp3"), ttAutomatic, True
    If TagsLibrary_AddCoverArtFromFileAutomatic(lTags, ttAutomatic, StrPtr(App.Path & "\Pic.jpg"), StrPtr("Cover Art (Front)"), StrPtr("My description"), 3, Me.hWnd) Then
        'TagsLibrary_Save lTags, StrPtr(App.Path & "\Test.mp3"), ttAutomatic
    Else
        MsgBox "Something Wrong!"
    End If
    TagsLibrary_Free lTags
End Sub

3delite

  • Posts: 907
Re: Tags Library
« Reply #435 on: 12 Dec '17 - 16:48 »
Probably the issue is that the function TagsLibrary_AddCoverArtFromFileAutomatic() returns the index of the new cover art that is added, not a boolean value, and maybe this index is 0, that is, it is the first cover art. If the function fails it should return '-1'.
Please try just saving the tags after the function regardless of the return value.

Thank you very much for testing this!

EWeiss

  • Posts: 355
Re: Tags Library
« Reply #436 on: 12 Dec '17 - 17:02 »
Quote
If the function fails it should return '-1'.
You should be clear that everything is more or less than 0 in VB6 and other languages was true.

greets

3delite

  • Posts: 907
Re: Tags Library
« Reply #437 on: 12 Dec '17 - 17:06 »
Yes that's so, I wrote above:

Quote
Return value is the new cover art index on success, - 1 on fail.

The function returns an integer not a boolean.

jpf

  • Posts: 48
Re: Tags Library
« Reply #438 on: 12 Dec '17 - 17:57 »
@3dlite

I'm amazed that I was able to set tags and save them to the original file even while the file was being played by bass! How did you accomplish that ? Isn't the file locked? Well, I tried just a few files / formats, maybe it'll fail sometime...

I'd like to be able to do that sort of things myself! By now I'm trying to move / rename a file while it's being played by bass. Not the same sort of thing, I guess. Maybe you can give me some tips...

Steve Grant

  • Posts: 148
Re: Tags Library
« Reply #439 on: 12 Dec '17 - 19:27 »
@3delite. Ignoring the return value (which actually is 0) embeds the image into the file perfectly.

So, whilst it is nice not to have to fill in the CoverArt structure, it is not worth the large size of the FreeImage.dll.

You could easily achieve the same using Bitmap info. For showing the image use a simple GDI+ class similar to Emils.

All the best.

3delite

  • Posts: 907
Re: Tags Library
« Reply #440 on: 12 Dec '17 - 22:29 »
Ok, thank you very much for testing! The package has been updated, download link in the first post.

jpf: This depends whether the tags can be updated without rewriting the whole file and if BASS does not exclude write access when opens the file then it's possible for some formats.
For example if ID3v2 tag in the file has enough padding for the new tag then the file's beginning is updated and the rest of the file is unchanged.

jpf

  • Posts: 48
Re: Tags Library
« Reply #441 on: 13 Dec '17 - 00:43 »
Ok, that explains it. You've done a great work. Thanks for sharing it!