Re: [fpc-pascal] Selecting Records with a variable
James, I remember going through some similar motions as you are. Looks like you are searching for a form of indexing your record fields. So many good suggestions, I had to join the fray and try something... My preferred approach would also be an ordinal type for the axes and a record variant, as already suggested. Objects and advanced records would be fine too. That way you get to keep both worlds while evolving your software to a more elegant approach along the lines of some of the suggested solutions. Here is something I tried on top of your example to make sure it actually works. program example1; Type Axis_Name=(anX,anY,anZ,anA,anB,anC); Axis_Array=array[Axis_Name] of Double; Axis_Record = Record X,Y,Z,A,B,C: Double; End; Axis_Record_variant = Record case boolean of false: (AxRec:Axis_Record); true: (AxArr:Axis_Array); End; Var AxisValueVar : Axis_Record_variant; AxisValue : Axis_Record absolute AxisValueVar.AxRec; //Instead of this: Procedure ShowAxis(Axisletter:Char); Begin If AxisLetter = 'X' Then Writeln(AxisValue.X); If AxisLetter = 'Y' Then Writeln(AxisValue.Y); If AxisLetter = 'Z' Then Writeln(AxisValue.Z); If AxisLetter = 'A' Then Writeln(AxisValue.A); If AxisLetter = 'B' Then Writeln(AxisValue.B); If AxisLetter = 'C' Then Writeln(AxisValue.C); End; //I would rather have something like this: Procedure ShowAxisVariant(AxisName:Axis_Name); Begin Writeln(AxisValueVar.AxArr[AxisName]); End; begin AxisValue.Z := 1234.5678; ShowAxis('Z'); ShowAxisVariant(anZ); end. On Sun, Dec 20, 2020 at 2:01 PM James Richters via fpc-pascal < fpc-pascal@lists.freepascal.org> wrote: > Yes, I was trying to keep my data structure, because there were thousands > of occurrences .. > This project has had that structure since Turbo Pascal back in the 80s > when it only had 3 axis > It seemed like a good way to have variables all with the same name, and > back then it wasn't so bad to have repeated code, > but now I have 9 axis and it's getting ridiculous.. once I realized that > Arrays would allow me to simplify things greatly, > it turned out to not be so bad to change it... just a bunch of global > search and replaces and a little fixing here and there that actually made > it cleaner, > and the whole project has been changed over in a relatively short amount > of time... and now I can start consolidating all those functions and > procedures. > It was way less work to just change it all to a better structure than it > was to work around it. > > James > > >I think this is a typical example where properly thinking about a > solution for a programming issue BEFORE going with > >what seems as the logical choice at first glance leads to a much simpler > solution without coming up with all kinds of fancy workarounds... > > ___ > fpc-pascal maillist - fpc-pascal@lists.freepascal.org > https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal > ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] USB Human Interface Devices
I see your point. But since libusbhid is mostly a wrapper library, its messages are going to be a higher level of debugging anyway - mostly related to how you handle a particular device. So once you are confident that things are working for your device, turning debug off completely seems the way to go, programs will be smaller and faster (no continuous checking for debug messages are to be displayed). If bugs or problems resurface, the underlying libusb is going to yell at you anyway. Alternatively, you can just compile one release and one debug version of your executable. On Thu, Aug 29, 2019 at 1:21 PM James Richters < ja...@productionautomation.net> wrote: > Yes, and besides the errors, everything else seems to work properly. I > did notice that the one machine uses an AMD processor and all the others > are Intel, not sure what that would have to do with anything, but it is a > major system configuration difference. > > > > Thanks for the debug level information. I will probably just shut off all > messages but it would be nice to have a way to turn them on if I need to > debug something on a remote system. > > > > How about the libusbxhid debug messages? Since they are controlled with > {$ifdef DEBUG_MSG} you can’t really turn them on and off without > re-compiling. Could another variable be used to make libusbxhid messages > optional but only if {$ifdef DEBUG_MSG} is used? It would be helpful to > be able to hide them most of the time but show them if trying to debug > without re-compiling. > > > > James > > > > *From:* fpc-pascal *On Behalf > Of *Stefan V. Pantazi > *Sent:* Thursday, August 29, 2019 1:11 PM > *To:* FPC-Pascal users discussions > *Subject:* Re: [fpc-pascal] USB Human Interface Devices > > > > I would chalk this up to differences between OS versions, configurations, > devices, etc and move on. I see all memory is released. At least it does > not crash and burn badly. > > > > The function call you want to play with is: > > libusb_set_debug > > > http://libusb.sourceforge.net/api-1.0/group__lib.html#ga5f8376b7a863a5a8d5b8824feb8a427a > > > > Of course, you can set the level dynamically, from your program. > > > > > > > > On Thu, Aug 29, 2019 at 12:34 PM James Richters < > ja...@productionautomation.net> wrote: > > At least I can shut off the messages with that.. but any idea what these > messages actually mean? It’s an init_device error but no one was tying to > do anything but get the list of devices from the system. > > > > Is there a description of the verbosity level anywhere? > > > > Is this a variable I can change during program execution without > re-compiling it? It would be helpful if I was having an issue to turn on > debug info, then turn it back off without exiting my program or needing to > compile. > > > > James > > > > > > >libusb has a debug verbosity level which currently is set to 3 (i.e., > very verbose) in the device open function. > > >There is a define in libusbx.pas that you can change to shut off debug > messages. > > ___ > fpc-pascal maillist - fpc-pascal@lists.freepascal.org > https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal > > ___ > fpc-pascal maillist - fpc-pascal@lists.freepascal.org > https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal > ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] USB Human Interface Devices
I would chalk this up to differences between OS versions, configurations, devices, etc and move on. I see all memory is released. At least it does not crash and burn badly. The function call you want to play with is: libusb_set_debug http://libusb.sourceforge.net/api-1.0/group__lib.html#ga5f8376b7a863a5a8d5b8824feb8a427a Of course, you can set the level dynamically, from your program. On Thu, Aug 29, 2019 at 12:34 PM James Richters < ja...@productionautomation.net> wrote: > At least I can shut off the messages with that.. but any idea what these > messages actually mean? It’s an init_device error but no one was tying to > do anything but get the list of devices from the system. > > > > Is there a description of the verbosity level anywhere? > > > > Is this a variable I can change during program execution without > re-compiling it? It would be helpful if I was having an issue to turn on > debug info, then turn it back off without exiting my program or needing to > compile. > > > > James > > > > > > >libusb has a debug verbosity level which currently is set to 3 (i.e., > very verbose) in the device open function. > > >There is a define in libusbx.pas that you can change to shut off debug > messages. > ___ > fpc-pascal maillist - fpc-pascal@lists.freepascal.org > https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal > ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] USB Human Interface Devices
libusb has a debug verbosity level which currently is set to 3 (i.e., very verbose) in the device open function. There is a define in libusbx.pas that you can change to shut off debug messages. On Thu, Aug 29, 2019 at 12:03 PM James Richters < ja...@productionautomation.net> wrote: > Now I have a new strange issue. I've been working with my sample program > here: https://github.com/Zaaphod/libusbxhid/blob/WHB04B-4/whb04b.pas > > And it's been working just fine for me.. just some minor little tweaks and > adding new functionality.. etc.. I was just about to start to merge this > into my large project when I sent the sample program to my dad... on his > system he just gets a screen full of errors... but on mine, it's nice and > clean. I don't understand what is happening.. I reduced my test program > down to the most basic sample that demonstrates the issue here: > https://github.com/Zaaphod/libusbxhid/blob/System_Specific_Bug/bugtest.pas > > All this program does is checks to see if a specific device exists.. this > program works perfectly on 4 computers and has no issue, but on one of my > dad's computers I get the following errors: > > libusb: error [init_device] device > 'USB\VID_2109_2812_HUB\0830' is no longer connected! > libusb: error [init_device] device 'USB\VID_1778_0224\4030' is no > longer connected! > libusb: info [cache_config_descriptors] could not access configuration > descriptor 0 (dummy) for 'USB\VID_2109_2811\5&34472DFD&0&4': [31] A > device attached to the system is not functioning. > libusb: error [init_device] device > 'USB\VID_1058_10B8\57583631413934354E345939' is no longer connected! > > > I don't know why Libusb is reporting this, no one tried to open anything > so who cares if some devices are not connected, and how does it know they > were connected at one time... this is not even an error.. if it's not > connected, just ignore it, nobody cares about that device anyway. > So I have two questions: > 1. any idea why these errors are being generated and how to fix it? > 2. Is there a way to turn off libusb errors, info and warnings? > > All systems are windows 10 Pro 64 bit, program was compiled for windows > 64bit as well. > > Here is the complete output with debug info: > > K:\ProAuto>bugtest.exe > libusb: error [init_device] device > 'USB\VID_2109_2812_HUB\0830' is no longer connected! > libusb: error [init_device] device 'USB\VID_1778_0224\4030' is no > longer connected! > libusb: info [cache_config_descriptors] could not access configuration > descriptor 0 (dummy) for 'USB\VID_2109_2811\5&34472DFD&0&4': [31] A > device attached to the system is not functioning. > libusb: error [init_device] device > 'USB\VID_1058_10B8\57583631413934354E345939' is no longer connected! > Looking for $10CE, $EB93: DEBUG Found 20 devices attached > DEBUG 1038:1310, bus: 7, address: 6 > DEBUG 1002:4399, bus: 10, address: 0 > DEBUG 1B21:1142, bus: 3, address: 0 > DEBUG 046D:C31C, bus: 7, address: 3 > DEBUG 1B21:1142, bus: 1, address: 0 > DEBUG 2109:0812, bus: 1, address: 1 > DEBUG 2109:2812, bus: 7, address: 2 > DEBUG 1002:4397, bus: 6, address: 0 > DEBUG 1002:4397, bus: 5, address: 0 > DEBUG 0A12:0001, bus: 5, address: 1 > DEBUG 2109:2811, bus: 7, address: 9 > DEBUG 1002:4397, bus: 9, address: 0 > DEBUG 0C45:7403, bus: 7, address: 4 > DEBUG 1002:4396, bus: 8, address: 0 > DEBUG 1002:4396, bus: 7, address: 0 > DEBUG 0E50:0002, bus: 7, address: 7 > DEBUG 1B21:1142, bus: 2, address: 0 > DEBUG 1002:4396, bus: 4, address: 0 > DEBUG 1A40:0101, bus: 7, address: 1 > DEBUG 2109:2812, bus: 7, address: 5 > DEBUG Index of device 4302:60307=-1 > DEBUG Freeing device list with 20 devices > DEBUG USB device list freed. good boy! > FALSE > libusb: error [init_device] device > 'USB\VID_2109_2812_HUB\0830' is no longer connected! > libusb: error [init_device] device 'USB\VID_1778_0224\4030' is no > longer connected! > libusb: info [cache_config_descriptors] could not access configuration > descriptor 0 (dummy) for 'USB\VID_2109_2811\5&34472DFD&0&4': [31] A > device attached to the system is not functioning. > libusb: error [init_device] device > 'USB\VID_1058_10B8\57583631413934354E345939' is no longer connected! > Looking for $10CE, $EB93: DEBUG Found 20 devices attached > DEBUG 1038:1310, bus: 7, address: 6 > DEBUG 1002:4399, bus: 10, address: 0 > DEBUG 1B21:1142, bus: 3, address: 0 > DEBUG 046D:C31C, bus: 7, address: 3 > DEBUG 1B21:1142, bus: 1, address: 0 > DEBUG 2109:0812, bus: 1, address: 1 > DEBUG 2109:2812, bus: 7, address: 2 > DEBUG 1002:4397, bus: 6, address: 0 > DEBUG 1002:4397, bus: 5, address: 0 > DEBUG 0A12:0001, bus: 5, address: 1 > DEBUG 2109:2811, bus: 7, address: 9 > DEBUG 1002:4397, bus: 9, address: 0 > DEBUG 0C45:7403, bus: 7, address: 4 > DEBUG 1002:4396, bus: 8, address: 0 > DEBUG 1002:4396, bus: 7, address: 0 > DEBUG 0E50:0002, bus: 7, address: 7 > DEBUG 1B21:1142, bus: 2, address: 0 > DEBUG 1002:4396, bus: 4, address: 0 > DEBUG 1A40:0101, bus: 7, address: 1 >
Re: [fpc-pascal] USB Human Interface Devices
I was wondering whether it works on Windows - I only had time to test on Linux. It looks like bad news. Error code -12 is LIBUSB_ERROR_NOT_SUPPORTED Operation not supported or unimplemented on this platform. On 8/28/19 6:24 AM, James Richters wrote: I tried the hotplug test on Windows with my device, but I am getting a return code of -12 from libusb_hotplug_register_callback I put some extra writeln's the test program: https://github.com/Zaaphod/libusbxhid/blob/Test/libusbx_hotplug_test.pp Here is the output: Running "i:\programming\gcode\libusbxhid\libusbx_hotplug_test.exe " Testing With: $10CE $EB93 0 Libusb Initialized register done, Result:-12 Heap dump by heaptrc unit of i:\programming\gcode\libusbxhid\libusbx_hotplug_test.exe 54 memory blocks allocated : 1913/2120 54 memory blocks freed : 1913/2120 0 unfreed memory blocks : 0 True heap size : 98304 (192 used in System startup) True free heap : 98112 James -Original Message- From: fpc-pascal On Behalf Of James Richters Sent: Wednesday, August 28, 2019 5:03 AM To: 'FPC-Pascal users discussions' Subject: Re: [fpc-pascal] USB Human Interface Devices Thanks for adding the hotplug functions and the sample program. I will give that a try. I have come up with another solution before I saw you added the hotplug functions: My thinking is that the interrupt read is going to know about the missing device before anything because it will be constantly reading as fast is it can and my main thread will be cycling much slower, so detecting the failure of the interrupt read would be the fastest way to know the device was not connected anymore. I noticed that lib_interupt_transfer produces a return code if anything prevents the transfer from being completed. But this information is only used for optional debug reports, and not returned from the libusbhid_interrupt_write and libusbhid_interrupt_read functions, they only return the number of bytes transferred. Since the number of bytes read or sent is irrelevant due to an error, and the error codes seem to always be negative, then there is no ambiguity if we return the error if it is negative or bytes transferred if it is not negative. That way calls to libusbhid_interrupt_write and libusbhid_interrupt_read can quckly get the return code and / or the number of bytes transferred, just by checking if the result is negative or not. Since the interrupt read is happening in a tight loop and running way faster than anything else, it's likely that this will be the fastest way to stop the read thread when the device is unplugged, then I can go back to looking for it in the main program again. The first read that produces an error will stop the thread. I have tested this on my test branch. I get one negative return code during normal use... and that is if I get a timeout, I get a -7, perhaps because I asked for 8 bytes maybe? This is also useful information to have in my loop as if I get a -7, I don't need to bother checking the data at all since it was not read, it was just a timeout. https://github.com/Zaaphod/libusbxhid/tree/Test James -Original Message- From: fpc-pascal On Behalf Of Stefan V. Pantazi Sent: Tuesday, August 27, 2019 10:35 PM To: fpc-pascal@lists.freepascal.org Subject: Re: [fpc-pascal] USB Human Interface Devices libusbhid_interrupt_read. failed! return code: -1 0libusb: error [winusbx_submit_bulk_transfer] ReadPipe/WritePipe failed: [2] The system cannot find the file specified. But I don't really know how I can detect this and exit the process and signal my other program that the device is no longer present. My read command: hidReportData[reportIdx].dataLen:=libusbhid_interrupt_read(device_context,$81{endpoint},{out}hidReportData[reportIdx].hid_data,64{report length, varies by device}, {timeout=}50); only reports the number of bytes read, and when the device is removed, the result of the libusbhid_interrupt_read seems to be 64. I’m wondering what the proper way to gracefully detect the device has been disconnected is so I can just exit out of the mode the uses the device and return to normal processing without generating any errors. You can try to handle the error return code by checking that a device that was present before has actually disappeared for the libusb device list. It also appears that in newer versions of libusb, there are provisions for registering and unregistering a hotplug callback. http://libusb.sourceforge.net/api-1.0/hotplug.html It it easy to add the calls to libusbx but they need to be tested that they actually work as expected. Any ideas? James -Original Message- From: fpc-pascal On Behalf Of Stefan V. Pantazi Sent: Friday, August 23, 2019 10:54 AM To: fpc-pascal@lists.freepascal.org Subject: Re: [fpc-pascal] USB Human Interface Devices Thanks for pushing on this. I think any pending timeout/transfer must be explicitly canceled before closing the
Re: [fpc-pascal] USB Human Interface Devices
Yeah you are right, Windows was less forgiving. Sorry about that and thank you Jean. For simple data structures written only from one thread, using critical section may be overkill. But if your data structure is a queue or a longer buffer, with length, etc. that is being produced by one thread and consumed by another (i.e., modified by more than one thread) then you should use some form of synchronization such as a critical section. On 8/28/19 7:26 AM, James Richters wrote: Thanks for figuring out the critical section needs to be initialized. Stefan's example did not do this: https://github.com/svpantazi/libusbxhid/blob/master/libusbhid_test_with_thread.pp maybe it's something you can get away with on Linux... I'll put in the init and done. Should I enter critical section only for writing to shared variables, or also when reading them? I'm also wondering if there is some way to tell if a thread is currently running or not... I don't want to try to start it again if it's already running. I can make some flag that the threat sets when it starts and clears when it exits, but I am wondering if there already something in place to check to see if a thread exists. James -Original Message- From: fpc-pascal On Behalf Of Jean SUZINEAU Sent: Wednesday, August 28, 2019 7:04 AM To: fpc-pascal@lists.freepascal.org Subject: Re: [fpc-pascal] USB Human Interface Devices Hello, It seems you didn't initialized you critical section using InitCriticalSection. The documentation of EnterCriticalSection : https://www.freepascal.org/docs-html/rtl/system/entercriticalsection.html The one of InitCriticalSection: https://www.freepascal.org/docs-html/rtl/system/initcriticalsection.html At the end, you need to call DoneCriticalSection to release the associated system resources ( https://www.freepascal.org/docs-html/rtl/system/donecriticalsection.html). Note: these is related to freepascal implementation of critical sections, in windows API, the function names are slightly different, InitializeCriticalSection/EnterCriticalSection/DeleteCriticalSection (https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-entercriticalsection) Le 28/08/2019 à 01:50, James Richters a écrit : One thing I wasn't able to duplicate however was the use of EnterCriticalsection(criticalSection); and LeaveCriticalsection(criticalSection); when writing to shared variables. If I try to ever use EnterCriticalsection(criticalSection); in the read thread, My program just instantly locks up and I can't even break out of it.If I try to use it in the main program I instantly get EAccessViolation: Access violation $7FFF18A2DF23 $7FFF189E9BBC $7FFF189E9AD0 $0001DCDA $0001D54B $0001218B PROCESS_USB_DATA, line 475 of WHB04B-4_test.pas $00012B37 SIMPLETERMINAL, line 641 of WHB04B-4_test.pas $00012DDD USE_MPG_DEVICE, line 675 of WHB04B-4_test.pas $00012F93 main, line 699 of WHB04B-4_test.pas $00012FE6 $000100011350 $00011980 $7FFF17B47E94 $7FFF18A4A251 Line 475 isEnterCriticalsection(criticalSection); I left where I had the criticalsection stuff in the program but commented out. It does seem to work fine without it though.. since the read, I am curious what I'm doing wrong, or if I need to do something else because I'm on Windows. ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal -- ___ ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] USB Human Interface Devices
I agree with you: the libusbhid_interrupt_read and libusb_interrupt_transfer are very close semantically and returning as a result either the length of transferred data or the error code would make a lot of sense. But in rare cases one may still need to check both parameters: http://libusb.sourceforge.net/api-1.0/group__syncio.html#gac412bda21b7ecf57e4c76877d78e6486 "Also check transferred when dealing with a timeout error code. libusb may have to split your transfer into a number of chunks to satisfy underlying O/S requirements, meaning that the timeout may expire after the first few chunks have completed. libusb is careful not to lose any data that may have been transferred; do not assume that timeout conditions indicate a complete lack of I/O." At any rate, switching around and returning both: the error code as the result of libusb_interrupt_transfer and the length of data transfer as an out parameter maybe the right thing to do. That would probably make the semantics of libusbhid_interrupt_read and libusb_interrupt_transfer almost identical. On 8/28/19 5:03 AM, James Richters wrote: Thanks for adding the hotplug functions and the sample program. I will give that a try. I have come up with another solution before I saw you added the hotplug functions: My thinking is that the interrupt read is going to know about the missing device before anything because it will be constantly reading as fast is it can and my main thread will be cycling much slower, so detecting the failure of the interrupt read would be the fastest way to know the device was not connected anymore. I noticed that lib_interupt_transfer produces a return code if anything prevents the transfer from being completed. But this information is only used for optional debug reports, and not returned from the libusbhid_interrupt_write and libusbhid_interrupt_read functions, they only return the number of bytes transferred. Since the number of bytes read or sent is irrelevant due to an error, and the error codes seem to always be negative, then there is no ambiguity if we return the error if it is negative or bytes transferred if it is not negative. That way calls to libusbhid_interrupt_write and libusbhid_interrupt_read can quckly get the return code and / or the number of bytes transferred, just by checking if the result is negative or not. Since the interrupt read is happening in a tight loop and running way faster than anything else, it's likely that this will be the fastest way to stop the read thread when the device is unplugged, then I can go back to looking for it in the main program again. The first read that produces an error will stop the thread. I have tested this on my test branch. I get one negative return code during normal use... and that is if I get a timeout, I get a -7, perhaps because I asked for 8 bytes maybe? This is also useful information to have in my loop as if I get a -7, I don't need to bother checking the data at all since it was not read, it was just a timeout. https://github.com/Zaaphod/libusbxhid/tree/Test James ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] USB Human Interface Devices
libusbhid_interrupt_read. failed! return code: -1 0libusb: error [winusbx_submit_bulk_transfer] ReadPipe/WritePipe failed: [2] The system cannot find the file specified. But I don't really know how I can detect this and exit the process and signal my other program that the device is no longer present. My read command: hidReportData[reportIdx].dataLen:=libusbhid_interrupt_read(device_context,$81{endpoint},{out}hidReportData[reportIdx].hid_data,64{report length, varies by device}, {timeout=}50); only reports the number of bytes read, and when the device is removed, the result of the libusbhid_interrupt_read seems to be 64. I’m wondering what the proper way to gracefully detect the device has been disconnected is so I can just exit out of the mode the uses the device and return to normal processing without generating any errors. You can try to handle the error return code by checking that a device that was present before has actually disappeared for the libusb device list. It also appears that in newer versions of libusb, there are provisions for registering and unregistering a hotplug callback. http://libusb.sourceforge.net/api-1.0/hotplug.html It it easy to add the calls to libusbx but they need to be tested that they actually work as expected. Any ideas? James -Original Message- From: fpc-pascal On Behalf Of Stefan V. Pantazi Sent: Friday, August 23, 2019 10:54 AM To: fpc-pascal@lists.freepascal.org Subject: Re: [fpc-pascal] USB Human Interface Devices Thanks for pushing on this. I think any pending timeout/transfer must be explicitly canceled before closing the USB device, so that the thread can end gracefully. The only way I see is to use something like libusb_handle_events_timeout_completed http://libusb.sourceforge.net/api-1.0/group__poll.html#ga43e52b912a760b41a0cf8a4a472fbd5b before closing the USB device context. That function is not currently part of the libusbx and has a time_t parameter that appears C-specific but for some reason is not included in ctypes unit. But I am sure Pascal equivalents can be defined. I will do some tests to include the libusb_handle_events_timeout_completed in libusbx and libusbhid and let you know. On 8/23/19 7:07 AM, James Richters wrote: Stefan , Do you get the following errors when you exit your program? Is there some way I should shut down the read thread so I don't get this error? I've been using a timeout of 0 libusb: error [do_close] Device handle closed while transfer was still being processed, but the device is still connected as far as we know libusb: error [do_close] A cancellation hasn't even been scheduled on the transfer for which the device is closing libusb: warning [libusb_exit] some libusb_devices were leaked Assertion failed! Program: i:\programming\gcode\libusbxhid\whb04b-4_test.exe File: os/poll_windows.c, Line 145 Expression: fd != NULL Heap dump by heaptrc unit of i:\programming\gcode\libusbxhid\whb04b-4_test.exe 50 memory blocks allocated : 1782/1968 50 memory blocks freed : 1782/1968 0 unfreed memory blocks : 0 True heap size : 131072 (160 used in System startup) True free heap : 130912 ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal -- ___ ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal -- ___ ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] USB Human Interface Devices
Thanks for pushing on this. I think any pending timeout/transfer must be explicitly canceled before closing the USB device, so that the thread can end gracefully. The only way I see is to use something like libusb_handle_events_timeout_completed http://libusb.sourceforge.net/api-1.0/group__poll.html#ga43e52b912a760b41a0cf8a4a472fbd5b before closing the USB device context. That function is not currently part of the libusbx and has a time_t parameter that appears C-specific but for some reason is not included in ctypes unit. But I am sure Pascal equivalents can be defined. I will do some tests to include the libusb_handle_events_timeout_completed in libusbx and libusbhid and let you know. On 8/23/19 7:07 AM, James Richters wrote: Stefan , Do you get the following errors when you exit your program? Is there some way I should shut down the read thread so I don't get this error? I've been using a timeout of 0 libusb: error [do_close] Device handle closed while transfer was still being processed, but the device is still connected as far as we know libusb: error [do_close] A cancellation hasn't even been scheduled on the transfer for which the device is closing libusb: warning [libusb_exit] some libusb_devices were leaked Assertion failed! Program: i:\programming\gcode\libusbxhid\whb04b-4_test.exe File: os/poll_windows.c, Line 145 Expression: fd != NULL Heap dump by heaptrc unit of i:\programming\gcode\libusbxhid\whb04b-4_test.exe 50 memory blocks allocated : 1782/1968 50 memory blocks freed : 1782/1968 0 unfreed memory blocks : 0 True heap size : 131072 (160 used in System startup) True free heap : 130912 ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal -- ___ ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] USB Human Interface Devices
I suspect when the timeout time has been reached interrupt_read is calling libusb_cancel_transfer to stop waiting for the transfer. It seems likely that what's happening is that once in a while it tries to cancel the transfer, but before libusb_cancel_transfer has a chance to cancel it, some data comes in real quick and now it's done and there is nothing to cancel.. that would explain why it happens only intermittently.. it just has to happen that some data comes in at almost the exact same time as the timeout time. Since this error is generated by:LIBUSB_ERROR_NOT_FOUND if the transfer is not in progress, already complete, or already cancelled. And nothing else could have cancelled it except the timeout, and the timeout would not have been issued if the transfer was in progress.. that leaves that the transfer popped in real quick and completed before the timeout was done calling for a cancel transfer. Here is something you can try immediately. How about setting the timeout on interrupt read to some ridiculously larger value, say 20 seconds to see if the error happens less frequently. Of course, when you close the program you may have to wait up to 20 seconds for the read thread to finish. ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] USB Human Interface Devices
I added libusbhid_test_with_thread.pp to github. In that test you will notice I also attempted to test sharing across threads a data structure with (hypothetical) pen positions, using critical sections. Seems to work ok, but more testing is needed to make sure there are no problems. The way I see this working in your particular context, would be that the shared data structure would be written to/updated in the read thread and read less frequently in the main thread in order to update the display. On 8/22/19 11:21 AM, James Richters wrote: That sounds like exactly like what I was trying to do.. would you mind sending me your graphic tablet test? Maybe I can learn something from seeing how you do things. clear halt failed it seems to work fine.. but I always get that error.. not sure where that is coming from, or if that might be related to these other issues. That error message is fine. It is an attempt to revive an USB endpoint that has stalled, just in case. If your devices are behaving, then you may even skip that attempt in the open function call. It seems no matter what I do... even write out dummy data so I'm not even using the same variables I am reading at all.. I either get a fatal error on read, a fatal error on write, or occasional libusb: warning [handle_timeout] async cancel failed -5 errno=0 messages. -5 is LIBUSB_ERROR_NOT_FOUND - this may give a clue http://libusb.sourceforge.net/api-1.0/group__asyncio.html#ga685eb7731f9a0593f75beb99727bbe54 As to why your transfers are being canceled, I have no idea. Anyway, keep in mind that I am using Linux and a completely different USB device - so libusb implementations, OS and device differences may play a role in how the programs behave. ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] USB Human Interface Devices
On 8/21/19 6:35 PM, James Richters wrote: I had them separated, but whenever it happened that I tried to write while it was waiting to read, I would get the error below. If it was reading all the time it seemed fine.. just if it was idle waiting to read and I did a write that it would fail with EAccessViolation: Access violation That should not happen - out of curiosity I modified a graphic tablet test program and included: - a separate read thread with a timeout of 1 second and - in the main thread, one set feature report call followed by a get feature report call (every 1 second). This was the behaviour: 1) if there is no input: - the main thread keeps calling set report +get report every 1 second - in the read thread, the interrupt read times out every second but generates report data every 5 seconds (tablet generates an interrupt read even if there is no input - a sort of heartbeat); 2) if there is input (pen approaches tablet or writes on tablet) there is a flurry of data from the read thread and of course, no more interrupt read timeouts; the main thread is business as usual, setting and getting feature reports every second; see the attached debug log Note that the interrupt read report size is specific to the device (10 bytes for the tablet); is the length for your device correct? DEBUG Found 15 devices attached [...] DEBUG Found device with vid:pid 1386:222 at idx:12! DEBUG Device instance found: 1 at idx:12! [...] DEBUG Device opened. Next I must claim the interface. [...] DEBUG Claiming interface.fingers crossed... DEBUG Interface claimed ... yay! DEBUG 22:13:42:711 libusbhid_interrupt_read. received: 10 bytes from device DEBUG 22:13:42:713 libusbhid_interrupt_read. received: 10 bytes from device DEBUG 22:13:43:711 libusbhid_set_report. written: 2 bytes to device DEBUG 22:13:43:715 libusbhid_interrupt_read. TIMEOUT bytes read: 0 DEBUG 22:13:43:812 libusbhid_get_report. received: 2 bytes from device DEBUG 22:13:44:718 libusbhid_interrupt_read. TIMEOUT bytes read: 0 DEBUG 22:13:44:812 libusbhid_set_report. written: 2 bytes to device DEBUG 22:13:44:913 libusbhid_get_report. received: 2 bytes from device DEBUG 22:13:45:720 libusbhid_interrupt_read. TIMEOUT bytes read: 0 DEBUG 22:13:45:914 libusbhid_set_report. written: 2 bytes to device DEBUG 22:13:46:014 libusbhid_get_report. received: 2 bytes from device DEBUG 22:13:46:722 libusbhid_interrupt_read. TIMEOUT bytes read: 0 DEBUG 22:13:46:852 libusbhid_interrupt_read. received: 10 bytes from device DEBUG 22:13:46:858 libusbhid_interrupt_read. received: 10 bytes from device DEBUG 22:13:46:866 libusbhid_interrupt_read. received: 10 bytes from device DEBUG 22:13:46:874 libusbhid_interrupt_read. received: 10 bytes from device DEBUG 22:13:46:882 libusbhid_interrupt_read. received: 10 bytes from device DEBUG 22:13:46:888 libusbhid_interrupt_read. received: 10 bytes from device DEBUG 22:13:46:895 libusbhid_interrupt_read. received: 10 bytes from device DEBUG 22:13:46:904 libusbhid_interrupt_read. received: 10 bytes from device DEBUG 22:13:46:912 libusbhid_interrupt_read. received: 10 bytes from device DEBUG 22:13:46:918 libusbhid_interrupt_read. received: 10 bytes from device DEBUG 22:13:46:926 libusbhid_interrupt_read. received: 10 bytes from device DEBUG 22:13:46:934 libusbhid_interrupt_read. received: 10 bytes from device DEBUG 22:13:46:942 libusbhid_interrupt_read. received: 10 bytes from device DEBUG 22:13:46:948 libusbhid_interrupt_read. received: 10 bytes from device DEBUG 22:13:46:956 libusbhid_interrupt_read. received: 10 bytes from device DEBUG 22:13:46:964 libusbhid_interrupt_read. received: 10 bytes from device DEBUG 22:13:46:972 libusbhid_interrupt_read. received: 10 bytes from device DEBUG 22:13:46:978 libusbhid_interrupt_read. received: 10 bytes from device DEBUG 22:13:46:986 libusbhid_interrupt_read. received: 10 bytes from device DEBUG 22:13:46:994 libusbhid_interrupt_read. received: 10 bytes from device DEBUG 22:13:47:002 libusbhid_interrupt_read. received: 10 bytes from device DEBUG 22:13:47:008 libusbhid_interrupt_read. received: 10 bytes from device DEBUG 22:13:47:015 libusbhid_set_report. written: 2 bytes to device DEBUG 22:13:47:015 libusbhid_interrupt_read. received: 10 bytes from device DEBUG 22:13:47:024 libusbhid_interrupt_read. received: 10 bytes from device DEBUG 22:13:47:032 libusbhid_interrupt_read. received: 10 bytes from device DEBUG 22:13:47:038 libusbhid_interrupt_read. received: 10 bytes from device DEBUG 22:13:47:046 libusbhid_interrupt_read. received: 10 bytes from device DEBUG 22:13:47:054 libusbhid_interrupt_read. received: 10 bytes from device DEBUG 22:13:47:062 libusbhid_interrupt_read. received: 10 bytes from device DEBUG 22:13:47:068 libusbhid_interrupt_read. received: 10 bytes from device DEBUG 22:13:47:076 libusbhid_interrupt_read. received: 10 bytes from device DEBUG 22:13:47:084 libusbhid_interrupt_read. received: 10
Re: [fpc-pascal] USB Human Interface Devices
From your example it looks like you placed the device reading (interrupt read) and writing (set report) into the same read thread. I thought keeping them separate was a good idea: tight loop reads and less frequent writes (LCD updates). Libusb is supposed to be thread-safe. Not really an issue for your app but if you need to make sure only one thread out of multiple threads is processing libusb events the library has asynchronous API that does offer locking functionality. On 8/21/19 3:48 PM, James Richters wrote: Well.. It doesn’t always work just reading constantly and writing in a different thread.. So I have my fast read loop always reading then my LCD write loop sending the 3 packets every 0.3 Seconds.. and it functions ok, and I don’t miss too many counts... but every so often I get this message: libusb: warning [handle_timeout] async cancel failed -5 errno=0 I have a timeout on my read loop of 10ms. I tried setting that to 0 so it would just wait for input in it's thread.. but when I do that I get this as soon as I attempt to write to it: An unhandled exception occurred at $7FFF189F03C6: EAccessViolation: Access violation $7FFF189F03C6 $7FFF189EDA21 $7FFF17AAA1A1 $7FFF17AA9CB5 $6B607FFB $6B6081E7 $6B60C695 $6B605D6F $6B607E40 $00010001B1CA $000121BF main, line 445 of whb04b-4_test.pas $000122B6 $0001EC20 $00011880 $7FFF17B47E94 $7FFF18A4A251 Also if I put in a really long timeout like 1000ms I get that. Line 445 is libusbhid_set_report(device_context, HID_REPORT_TYPE_FEATURE, $6 , 8 , WhB04_Packet1 ); so I can't write while I'm reading or waiting for a read after all. So I came up with a scheme to set all the variables in the slow loop then set a Boolean variable when it's done.. then the fast loop checks for the flag if it is idle for a time, meaning it's not trying to keep up with input.. and that does work.. and I don't miss many counts... but it does miss a few... but I STILL get this libusb: warning [handle_timeout] async cancel failed -5 errno=0 even though as far as I can tell, I can't possible be reading and writing at the same time. I've updated my test project here: https://github.com/Zaaphod/libusbxhid/blob/master/WHB04B-4_test.pas I don't really know what libusb: warning [handle_timeout] async cancel failed -5 errno=0 is trying to tell me... it is having an issue canceling waiting for data after the time out I guess.. but why is that a problem? Any Ideas? James -Original Message- From: fpc-pascal On Behalf Of James Richters Sent: Wednesday, August 21, 2019 8:30 AM To: 'FPC-Pascal users discussions' Subject: Re: [fpc-pascal] USB Human Interface Devices I FINALLY wrote some data to the LCD!! YAY !!! I was trying to get the python application to work.. without any luck.. but I ended up going ahead and trying Zadig changing the driver to libusb-win32... After I gave up on Python, I went back to FPC and just ran my existing sample program, and I noticed where it used have an error sending to device, it now said 8 bytes sent!! It's very strange I could read it just fine but not write to it without messing with the driver... but it's working now! I tried suspending the read thread to write to it.. and well it must have ended up suspending in the middle of a read because the whole thing locked up.. so I just tried as suggested and let it keep reading in a tight loop in it's own thread and then just throw in a write every few seconds on the main program.. and that actually worked fine.. I guess libusb takes care of worry about finishing a read before writing.. I think I did see libusb had something to do with threads. So now it's just a matter of small details. The display is a little odd... in that instead of sending it just a real number, you send it an integer for the numbers before the decimal and another integer for the numbers after the decimal.. but it's 2 bytes for each (4 bytes total) but they are in reverse order.. I need to send LowByte_Integer, High_Byte_Integer, LowByte_decimal, High_Byte_decimal so the bits from a 16 bit integer end up being 76543210,FEDCBA98 I think this is that edian byte order thing that was mentioned. I'm just curious if there is already a function available to reverse these like this.. or if I just need to write my own. It's just some rotates and then split it, so I can do that, but I'm just wondering if there is something already there to do this.. I seem to recall that this kind of thing needs to happen quite a bit. Also I need to stick a $06 in front of all my packets to send to the device. I have my data all in arrays, so I want to do something like this Device_Array[0]:=$06; Device_Array[1..7] := LCD_Array[0..6] ; Ah.. but that doesn't work.. is there a way to do this with syntax or do I just need to make a
Re: [fpc-pascal] USB Human Interface Devices
On 8/21/19 8:30 AM, James Richters wrote: I FINALLY wrote some data to the LCD!! YAY !!! I was trying to get the python application to work.. without any luck.. but I ended up going ahead and trying Zadig changing the driver to Persistence pays off. Congrats! Also I need to stick a $06 in front of all my packets to send to the device. I have my data all in arrays, so I want to do something like this Device_Array[0]:=$06; Device_Array[1..7] := LCD_Array[0..6] ; Try Move (https://www.freepascal.org/docs-html/rtl/system/move.html) Move(LCD_Array[0..6],Device_Array[1],7) ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] USB Human Interface Devices
My guess is that it would be better to leave the time sensitive read thread to do the fast reads and immediate calculations and leave writing to the device screen in a separate thread (even main thread), with a lower update frequency! Yes, that was what I was attempting to describe.. but I can't write to the usb device if the read thread happens to be in the middle of a read... so how do I pause the read thread at the correct time so it's not partially in the middle of reading a packet, and I can't read again until I'm done writing. I figure I can just check for some period of time of idle handwheel input before I stop the read thread and do the write then start the read thread again, because only the handwheel produces such a large stream of data.. but still I’m not sure how to make sure I stop it at the correct time. I do not get why should you stop the read thread, when that is the actual advantage of having multiple threads. While the read thread is busily reading input in a buffer/queue/what have you, you are free within limits) to do whatever you need to do (e.g., output to LCD display, do calculations) in the other threads, including the main thread, after which, you can get back to consuming and processing the (hopefully only slightly larger now) data from the read thread buffer/queue. After you figured writing to the LCD screen you could try writing random data to it while reading and processing handwheel and button input *at the same time*. Hope this makes sense. ___ ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] USB Human Interface Devices
On 8/18/19 3:58 PM, James Richters wrote: As far as reading it goes, things are going pretty well.. I still have yet to write to the display.. I can't get any of my attempts to send data to it to be successful at all.. I get "control transfer to usb device failed!" Assuming there are no other bugs in the libusbxhid library, for writing data you have to guess the reportType (in, out, feature) and reportNum parameter and set the report data buffer correctly (first byte is the report number) for your device. Have a look at similar devices. One thing I'm really not sure how to handle with threads is this ok so I have my main fast read thread going in the tightest loop possible... but now I want to write something to the display (assuming I ever figure that out and don't just put a sticker over the display and look at the screen instead :D ) It seems I would have to stop reading to get a chance to write something.. I did a little test and I can do a suspend(Thread_ID) and resume(Thread_ID) but what if it's in the middle of a read.. but only got 6 of the 8 bytes when I do the suspend?? Now I am not really ready to write. so what method can I use to do a suspend_thread_just_before_the_next_read_happens() ? so that when the thread is suspended, the read is completed and the buffer updated.. etc.. and the USB system and libusb are all ready for me to send my write commands? Resuming would be no problem.. because it was suspended at the correct position.. I can just resume when I am done with the write and everything should be fine. My guess is that it would be better to leave the time sensitive read thread to do the fast reads and immediate calculations and leave writing to the device screen in a separate thread (even main thread), with a lower update frequency! I also still am hoping to find a method of making the device wait for me to read it... even with threads in my program, the operating system could go off and do something that takes all the processor time for a second and I would just not know about events that happened during that time. If an operating system were realtime that should not happen. This is why LinuxCNC uses the realtime extensions (http://linuxcnc.org/) Some devices have multiple functional modes that can be selected by writing their appropriate settings/registers. For example, a graphic tablet I used before has a finger input mode (really becomes a trackpad) and a pen mode (uses the stylus, as usual). For more complex devices, guessing such things is less practical, you really need knowledge of the device or similar ones. ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] USB Human Interface Devices
James, From the looks of it you made good progress reading the hardware and using a dedicated thread for it. Congrats! Seems you're in the thick of it now ready to get the minute details sorted out. Anyway, just a heads up that concurrent programming (threads, synchronization, etc) has many pitfalls. My armchair guess is that your program is just not reading fast enough to keep up with the rate of data that the hardware is generated. Having time sensitive code in a separate thread is a good idea but you should also store the report data in an adequately sized and thread safe data structure such as a thread-safe list/queue. FreePascal has something you could use (https://www.freepascal.org/docs-html/rtl/classes/tthreadlist.html) and although dynamically allocated, it may be fast enough for your purposes. Thread safety is crucial to avoid multiple threads overwriting the data structures they share. The way I see it, your timing sensitive hardware reading thread would fill up the queue and then, every so often, your main thread would consume the data from it. You have to also imagine mechanisms to check that one can keep up with the other and signal errors when that is not the case. Hope this helps, and good luck! On 8/18/19 12:05 PM, James Richters wrote: I have a question about USB data transfer.. but it's going to take some explanation... I've been doing more testing with my device and Libusbxhid. Here's the device: https://www.amazon.com/gp/product/B07M5ZY1P2 I have all the inputs working, still have to figure out how to output to the LCD... I've implemented a test program that shows what button I have pressed, and it also processes the switches and handwheel properly... The hand wheel has 100 indents on it, and if I rotated it clockwise, it gives me a positive count, and if I rotate it counter-clockwise, it gives me two's compliment representation of a negative count, it only sends a single byte, and the number it sends is the number of ticks since the last time it reported so it would have to be read at least every 127 ticks. ok.. so I got that all working but then I discovered an issue... I thought the count on the hand wheel was the number of ticks since the last time I got the report... because if I turn the when very slow, I only get 1 or -1... but if I turn it faster, I get larger numbers... but once I got it reporting the total count... I found that if I start with the wheel at the 0 mark, and turn it really slow, it will count exactly 100 times when it returns to the zero point.. but if I got at even a slow (but not ridiculous) speed, then the count would come up short, and if I turned it fast, it would come up really short... So I tried a test, and disabled the writeln to the console... and now it is much more accurate.. at slow and medium speeds it is exact but at really fast speeds it is still slightly short. So I thought this would be a great use for a thread! So I looked into it.. and I guess in windows I don't even need a unit to run a thread.. I just need to define a function and do a BeginThread() to run the function in a thread... well I didn't think it would be THAT easy.. but yes it works! Now I'm going to have threads everywhere LOL. I have the thread running the tightest possible loop to just read the data and store it in the fastest way possible so it can get back to reading again... then outside the thread I read the variables once every 5 seconds and just put where it is... well this improved things greatly, and I will probably use the thread method in the final program... but one thing is still bugging me... it's just not 100% exact all the time, even with the thread method, I still miss count here and there... So back to the in-line code with writeln's of a minute... I tried another test... this time I read the device as normal, then I put a huge delay in.. 5 seconds or so, then I started reading it again.. now if my previous theory was correct, then I should be able to give up to 127 pulses during the delay and it would show the total since the last report... but that's not what happened.. it just forgets about whatever happened during the delayI was careful to only do 1/2 rotation which would be about 50 pulses so I know I didn't make it overflow so this behavior makes me think I am not reading it the correct way it's like it sends the report out every so often whether I am reading it or not.. and when I do read it I get whatever count it is since the last OUTPUT, even if I missed the last output... also if I push a button and release it during the delay, I have no indication it was ever pressed. So my question is.. does this behavior suggest that the device is expecting some other transfer method that would guarantee synchronization? I see in pas-libusb there are test2controlsync and test test3controlasync I'm curious if synchronous transfer would be the way to
Re: [fpc-pascal] USB Human Interface Devices
Is the segfault in the same place or has it changed? To debug further, you have to compare sizes of data structures, field types and function call parameter types between the libusb 1.0 and the old libusb0.1. - any mismatch could result in a segfault. On 8/17/19 3:51 PM, James Richters wrote: Oops, I got mixed up.. it's usb.pas that isn't used anymore... I changed LibUsb to stdcall and not it compiles again.. but I still get he access violation with stdcall. James from the copy of your github, looks like libusboop.pas has a uses statement for libusb.pas; so libusb.pas is still used https://github.com/Zaaphod/pas-libusb/blob/Hack/src/libusboop.pas (line 30) Uses Classes, SysUtils, LibUsb; ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal -- ___ ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] USB Human Interface Devices
fromt he copy of your github, looks like libusboop.pas has a uses statement for libusb.pas; so libusb.pas is still used https://github.com/Zaaphod/pas-libusb/blob/Hack/src/libusboop.pas (line 30) Uses Classes, SysUtils, LibUsb; On 8/17/19 1:39 PM, James Richters wrote: I think maybe it is the calling convention... First I tried to change libusboop.pas (libusb.pas is the old unit, libusboop.pas is the one it uses) to stdcall, I was unable to compile it, I get an error libusboop.pas(1456,28) Error: Incompatible types: got "" expected "" libusboop.pas(1726) Fatal: There were 1 errors compiling module, stopping I'm not sure where or how it's expecting CDecl or how to change that to use stdcall. So for fun I tried doing it the other way around, and changed libusbxhid to cdecl... well it compiled ok but then I tried to run it I got this: device attempting go clear halt on ep $81 libusb: error [hid_clear_halt] unable to match endpoint to an open interface - cannot clear clear halt failed So I don't know what all that really means, but it was an endpoint match problem causing access denied. so maybe just need to figure out how to get stdcall to properly work with pas-libusb. James -Original Message- From: fpc-pascal On Behalf Of Stefan V. Pantazi Sent: Saturday, August 17, 2019 12:11 PM To: fpc-pascal@lists.freepascal.org Subject: Re: [fpc-pascal] USB Human Interface Devices Libusb can be compiled with either calling convention - one just has to be sure which one. In https://github.com/Zaaphod/libusbxhid/blob/master/libusbx.pas (line 35), the windows calling convention is stdcall and that apparently works for both 64 and 32 bit windows. So, James' libusb10 dlls use stdcall. Also, I was under the impression that unlike linux, Windows apps would compile regardless of the calling convention. Only when launching the app and loading a dynamic library a wrong calling convention make things blow up. Anyway, this is definitely something to look into. On 8/17/19 11:46 AM, Jean SUZINEAU wrote: Le 17/08/2019 à 17:10, Stefan V. Pantazi a écrit : The obvious first thing to make sure is that the calling convention matches the library for the platform. I see that in https://github.com/Zaaphod/pas-libusb/blob/Hack/src/libusb.pas 9line 46) the calling convention on Windows is cdecl (the stdcall is commented out). In libusbxhid, if I remember correctly, the calling convention for windows dlls is set to stdcall. Yes it's curious. Usually with Microsoft dlls from the Windows API, you use stdcall. Here with stdcall I get an error "Import library not found for libusb-1.0". So I commented out the stcall changed it to cdecl. This allows to compile without errors and test1library.pas works without error, it seems cdecl is the right calling convention for libusb-1.0. One other thing is that debugging is much more tedious without an integrated debugger that allows you to step through each line before you can see which function call blows up with a segfault. James works on the command line but fp.exe seems to integrate gdb.exe the same way that lazarus does, you nearly have the same shortcuts keys for debugging between Turbo Pascal 5.5, fp.exe and lazarus ... ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal -- ___ ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal -- ___ ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] USB Human Interface Devices
Libusb can be compiled with either calling convention - one just has to be sure which one. In https://github.com/Zaaphod/libusbxhid/blob/master/libusbx.pas (line 35), the windows calling convention is stdcall and that apparently works for both 64 and 32 bit windows. So, James' libusb10 dlls use stdcall. Also, I was under the impression that unlike linux, Windows apps would compile regardless of the calling convention. Only when launching the app and loading a dynamic library a wrong calling convention make things blow up. Anyway, this is definitely something to look into. On 8/17/19 11:46 AM, Jean SUZINEAU wrote: Le 17/08/2019 à 17:10, Stefan V. Pantazi a écrit : The obvious first thing to make sure is that the calling convention matches the library for the platform. I see that in https://github.com/Zaaphod/pas-libusb/blob/Hack/src/libusb.pas 9line 46) the calling convention on Windows is cdecl (the stdcall is commented out). In libusbxhid, if I remember correctly, the calling convention for windows dlls is set to stdcall. Yes it's curious. Usually with Microsoft dlls from the Windows API, you use stdcall. Here with stdcall I get an error "Import library not found for libusb-1.0". So I commented out the stcall changed it to cdecl. This allows to compile without errors and test1library.pas works without error, it seems cdecl is the right calling convention for libusb-1.0. One other thing is that debugging is much more tedious without an integrated debugger that allows you to step through each line before you can see which function call blows up with a segfault. James works on the command line but fp.exe seems to integrate gdb.exe the same way that lazarus does, you nearly have the same shortcuts keys for debugging between Turbo Pascal 5.5, fp.exe and lazarus ... ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal -- ___ ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] USB Human Interface Devices
The obvious first thing to make sure is that the calling convention matches the library for the platform. I see that in https://github.com/Zaaphod/pas-libusb/blob/Hack/src/libusb.pas 9line 46) the calling convention on Windows is cdecl (the stdcall is commented out). In libusbxhid, if I remember correctly, the calling convention for windows dlls is set to stdcall. One other thing is that debugging is much more tedious without an integrated debugger that allows you to step through each line before you can see which function call blows up with a segfault. On 8/17/19 9:00 AM, James Richters wrote: I’m trying to figure out why I get an access violation when I try to open my device with pas-libusb but it works with libusbxhid they both are using libusb-1.0.dll I put a bunch of hacks into pas-libusb to try to figure it out… just a lot of writeln’s so I can try to track down exactly what’s happening. Because if I try to trace through the program I get “Program received signal SIGSEGV Segmentation fault” before I get to the problem I put this in a branch here: https://github.com/Zaaphod/pas-libusb/tree/Hack/src I’m using testopendevic_vidpid2.pas to test it with. Here’s my output: start 1 2 a05472131 a10CEEB93 b c FALSE 8086 10CE A36D EB93 FALSE 8087 10CE 0AAA EB93 FALSE 0424 10CE 2734 EB93 FALSE 1D50 10CE 6015 EB93 FALSE 1B1C 10CE 0C15 EB93 TRUE 10CE 10CE EB93 EB93 FALSE 05E3 10CE 0610 EB93 FALSE 04E8 10CE 61F5 EB93 FALSE 1B1C 10CE 0C10 EB93 FALSE 0424 10CE 274C EB93 FALSE 047D 10CE 1020 EB93 FALSE 1B1C 10CE 1B4F EB93 FALSE 1A40 10CE 0101 EB93 FALSE 0C45 10CE 7403 EB93 FALSE 10C4 10CE EA60 EB93 d e H1 I 4 Cousldn't connect to device: Access violation Here’s as far as I could get…. (** * Find endpoint according to MatchFunc * * @param MatchFunc method to compare a given endpoint descriptor with a * criterion * * @returns endpoint or Nil *) Function TLibUsbInterface.FindEndpoint(MatchFunc : TLibUsbEndpointMatchMethod) : Plibusb_endpoint_descriptor; Var IEP : Integer; ED : Plibusb_endpoint_descriptor; Begin writeln('H',FInterface^.bNumEndpoints); For IEP := 0 to FInterface^.bNumEndpoints-1 do Begin Writeln('I'); ED:= @(FInterface^.endpoint^[IEP]); if MatchFunc(ED) then Begin Writeln('J'); Exit(ED); End else Writeln('K'); End; Result := Nil; End; MatchFunc(ED) is where the access violation occurs, but I can’t trace any further because I can’t find the function MatchFunc() I just don’t understand where the actual function is. Maybe I made an error in the way I’m trying to open the device? It can’t be any problem with the device itself or using libusb-1.0.dll because that is all working with libusbxhid.. in fact I have all inputs from my device mapped out.. Still don’t have the LCD working…. I can just use libusbxhid, but this is bugging me and I wanted to try to figure out what’s going on. James ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal -- ___ ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] USB Human Interface Devices
On 8/16/19 11:11 AM, James Richters wrote: Remember that interrupt reads are blocking so the way to deal with them is to put them away from the main thread, in their own thread. The moment something is available from the device, then the main thread of your application is signaled to read a buffer with the device report data. So, I can see some thread programming in your future or, I see I did not finish my sentence. What I had in mind is that you could use a library that already implements (using a thread I assume) a call with a timeout. I checked and it looks like the original libusb call that I used did have a timeout parameter that I hardcoded to 0 (infinite timeout). libusb report a timeout as an error code. That did not sit well with me and I preferred to use threads instead of time-out mechanism. > Is there another way to do a read that has a timeout? yes, it took only a few minutes to add the time-out parameter to the libusbhid_interrupt_read call. Have a look at the github repository for the updated version. Can I even do threads in a console program? Sure you can, here is one of the simplest example you can start with should you ever need to have multiple threads in your programs. https://github.com/graemeg/freepascal/blob/master/packages/fcl-base/examples/threads.pp -- ___ ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] USB Human Interface Devices
On 8/16/19 6:23 AM, James Richters wrote: DATA!! Is there a way I can read data from the device with a timeout instead of just waiting forever for it? It doesn't send anything unless I push a button, but I need to do other things like update the LCD if I am not pushing a button. My python example uses a function called hid.read(size,timeout) so I'm trying to do something similar. This is going to be a console application when I am done, do I don't have a way to do anything else, so a timeout would work best. Remember that interrupt reads are blocking so the way to deal with them is to put them away from the main thread, in their own thread. The moment something is available from the device, then the main thread of your application is signaled to read a buffer with the device report data. So, I can see some thread programming in your future or, I'm also trying to figure out how to write to the LCD... I think there is a bug because 7 bytes would be data[0..6] and it would not duplicate byte 7 but the 0x06 must tell it to send from bytes 0 to 6... but anyway, regardless of that, how do I do something like hid.send_feature_report? I have checked an old example where I use a HID set feature report. I can see that the first byte of the output data (your hidOutData array) is always set to the reportNum. So the length of the hidOutData array send to the device includes the actual report number which prepends one byte to the data. So the Python example is correct. For example, in this call where I was trying to set a Wacom graphic tablet mode, the length of hid_data is 3 bytes (the first being the report number) but the report length in the call is 2 (WACOM_FEATURE_REPORT_LENGTH). hid_data[0]:=WACOM_REPORT_NUMBER; hid_data[1]:=WACOM_TABLET_MODE_FINGER_ENABLED; hid_data[2]:=0; libusbhid_set_report(device_context,HID_REPORT_TYPE_FEATURE{=$03}, WACOM_REPORT_NUMBER_ID{=2}, WACOM_FEATURE_REPORT_LENGTH{=2}, hid_data); I'm guessing that libusbhid_set_report() is maybe something similar? But it has parameters for reportType and reportNum... any clue what to put there? Or is this not even the right You got it. Report type can be input, output or feature, just choose the appropriate constant. Report number, for me was a lot of guesses, trial and error combined with other examples of similar devices, etc. function? I thought maybe putting HID_REPORT_TYPE_FEATURE would mean to send a feature report? But reportNum I have no idea... I stuck a 1 in there just to see and tried: libusbhid_set_report(device_context,HID_REPORT_TYPE_FEATURE,1,7,hidOutData[0..6]); but then I get: libusb: warning [_hid_set_report] mismatched report ID (data is FE, parameter is 01) control transfer to usb device failed! $FE is what I have in hidOutData[0], but I'm not sure what it wants for a report id? Just make hidOutData[0]=Report_id (i.e., the first byte of your array) and cross your fingers that the report id is correct. Can you tell me where to get libusb_1.0_X86.dll ?I had the x64 version from the sample Jean sent me, but I would like to make my program work on 32bit machines as well. I remember that I had to build those from source but I am sure you can find binaries online. Happy hacking! ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] USB Human Interface Devices
Well, I am sure you can find some devices lying around. For once your USB mouse and keyboard are HID devices - but one usually avoids messing with them for obvious reasons, in case an USB interface claimed by a test program is not released. Out of curiosity, just now I opened my keyboard device (046d:c517 Logitech, Inc. LX710 Cordless Desktop Laser) and interrupt data reports came right in as I pressed keys (looks like my keyboard generates 16 bytes of data for every key press). Decoding the data though is another problem altogether. Can't test if this also works in Windows but in Linux appears to work ok. But you should be safer testing with a USB game controller or Wii remote as they are also HID devices. I was amazed that the Wii (being wireless and all actually worked.) I also just checked and realized that my APC UPS is also a HID device (ID 051d:0002 American Power Conversion Uninterruptible Power Supply). In sum, plenty of devices to play around with. Have fun! On 8/15/19 8:28 PM, James Richters wrote: Thanks for posting the examples and the information. I'll have a look... I am thinking maybe I should buy some of those USB relays or something simpler just to get SOMETHNG to work so I can figure out what's supposed to even be happening. James -Original Message- From: fpc-pascal On Behalf Of Stefan V. Pantazi Sent: Thursday, August 15, 2019 5:31 PM To: fpc-pascal@lists.freepascal.org Subject: Re: [fpc-pascal] USB Human Interface Devices Hi James, I remember going through many similar difficulties with HID. A few years ago I was trying to connect to much simpler devices than yours (game controllers, weather station base, graphic tablet, etc). USB programming is confusing and many abstraction layers have been created aiming at simplifying it. Unfortunately this introduces dependencies. I remember trying to port hidapi headers to Pascal and tried to use the hidraw backend (in linux) with mixed results. Also tried the libhid cross-platform library. In the end I went with libusb 1.0 for which a Pascal header already existed (https://forum.lazarus.freepascal.org/index.php?topic=11435.0) and used it to implement on top of it a subset of the HID API calls that suited my needs and kept things simple. I just posted an example on github: https://github.com/svpantazi/libusbxhid Hope it helps. In theory you could use the Windows HID API but, as others have suggested, the solution would not be cross platform, or, to put it another way, Windows HID API would become your dependency. My suggestion is also to go the libusb 1.0 route and use a Pascal HID library that depends only on libusb 1.0. Your device appears to be HID-compliant so no additional drivers should be needed for it. As far as I know, the Zadig generic driver is necessary only for non-HID devices. I remember using it for a rtl-sdr USB device on Windows. Hope you find your solution. Good luck. On 8/15/19 9:11 AM, James Richters wrote: Yes, in device manager I see it listed as "HID-compliant vendor-defined device" also Zadig identifies it as "USB Input Device" and it shows Driver: HidUsb (v10.1.17763.1) Is there a way to use the windows system HID interface with FPC already in place as there is for other windows APIs? James -Original Message- From: fpc-pascal On Behalf Of José Mejuto Sent: Thursday, August 15, 2019 8:34 AM To: fpc-pascal@lists.freepascal.org Subject: Re: [fpc-pascal] USB Human Interface Devices El 14/08/2019 a las 16:29, James Richters escribió: I'll have a look at your project.. maybe it will give me some clues. Can you tell me how to get hid.dll? I find it all very confusing, can I just download the dll somewhere or do I have to get this huge confusing package and built it myself? The sample code that is able to access my device with python on Linux uses hid.dll I would like to at least be able to try the hid.dll... if I can get hid.dll somewhere. Hello, hid.dll is the windows system HID interface, the API provided by Windows. In the other hand, the hardware you are trying to manage is 10CE:EB93 ? Yes, I got a listing of all devices, then I plugged in the new one, and that is the ID that was not there before. If the answer is yes, that device is *not* HID compatible so you can not use hid.dll for native access, you must use WinUSB API set, or the libusb-1.0 abstraction layer. I'm curious how you can tell that by looking at the number of it? No, I just look for the product and try to find its drivers, no one name the HID interface. Do you see the device in windows device manager under the HID section "Human Interface Devices (HID)" ? -- ___ ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal _
Re: [fpc-pascal] USB Human Interface Devices
Hi James, I remember going through many similar difficulties with HID. A few years ago I was trying to connect to much simpler devices than yours (game controllers, weather station base, graphic tablet, etc). USB programming is confusing and many abstraction layers have been created aiming at simplifying it. Unfortunately this introduces dependencies. I remember trying to port hidapi headers to Pascal and tried to use the hidraw backend (in linux) with mixed results. Also tried the libhid cross-platform library. In the end I went with libusb 1.0 for which a Pascal header already existed (https://forum.lazarus.freepascal.org/index.php?topic=11435.0) and used it to implement on top of it a subset of the HID API calls that suited my needs and kept things simple. I just posted an example on github: https://github.com/svpantazi/libusbxhid Hope it helps. In theory you could use the Windows HID API but, as others have suggested, the solution would not be cross platform, or, to put it another way, Windows HID API would become your dependency. My suggestion is also to go the libusb 1.0 route and use a Pascal HID library that depends only on libusb 1.0. Your device appears to be HID-compliant so no additional drivers should be needed for it. As far as I know, the Zadig generic driver is necessary only for non-HID devices. I remember using it for a rtl-sdr USB device on Windows. Hope you find your solution. Good luck. On 8/15/19 9:11 AM, James Richters wrote: Yes, in device manager I see it listed as "HID-compliant vendor-defined device" also Zadig identifies it as "USB Input Device" and it shows Driver: HidUsb (v10.1.17763.1) Is there a way to use the windows system HID interface with FPC already in place as there is for other windows APIs? James -Original Message- From: fpc-pascal On Behalf Of José Mejuto Sent: Thursday, August 15, 2019 8:34 AM To: fpc-pascal@lists.freepascal.org Subject: Re: [fpc-pascal] USB Human Interface Devices El 14/08/2019 a las 16:29, James Richters escribió: I'll have a look at your project.. maybe it will give me some clues. Can you tell me how to get hid.dll? I find it all very confusing, can I just download the dll somewhere or do I have to get this huge confusing package and built it myself? The sample code that is able to access my device with python on Linux uses hid.dll I would like to at least be able to try the hid.dll... if I can get hid.dll somewhere. Hello, hid.dll is the windows system HID interface, the API provided by Windows. In the other hand, the hardware you are trying to manage is 10CE:EB93 ? Yes, I got a listing of all devices, then I plugged in the new one, and that is the ID that was not there before. If the answer is yes, that device is *not* HID compatible so you can not use hid.dll for native access, you must use WinUSB API set, or the libusb-1.0 abstraction layer. I'm curious how you can tell that by looking at the number of it? No, I just look for the product and try to find its drivers, no one name the HID interface. Do you see the device in windows device manager under the HID section "Human Interface Devices (HID)" ? -- ___ ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] specify variable name with string variable
Haev a look at rtti and the functionality available in the typinfo unit. The tests included in fpc are a good resource. Have a look at the trtti*.pp tests: https://svn.freepascal.org/cgi-bin/viewvc.cgi/trunk/tests/test/ Start with trtti4.pp and work your way up to more complex examples. On 7/8/19 6:04 PM, James Richters wrote: I’m curious how use classes together with published properties would work, is there a sample of how to use this somewhere? James From: fpc-pascal On Behalf Of Sven Barth via fpc-pascal Sent: Monday, July 8, 2019 5:31 PM To: FPC-Pascal users discussions Cc: Sven Barth Subject: Re: [fpc-pascal] specify variable name with string variable James Richters mailto:ja...@productionautomation.net> > schrieb am Mo., 8. Juli 2019, 22:44: SetStoragePinByName('Ini_Opto_Enable_Positive_Pin', True) ; And it would somehow get the value of 'Ini_Opto_Enable_Positive_Pin That indeed sounds like something where you could use classes together with published properties. At least if you're willing to spend a bit of effort. Regards, Sven ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal -- ___ ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] specify variable name with string variable
sure, but you end up with a separate dictionary for each type. Or, you can try variants, as originally suggested, but then you need to declare all your variables as a Variant type. uses fgl, variants; type TVariableDictionary = specialize TFPGMap; On 7/8/19 11:20 AM, James Richters wrote: Thank you, using fgl; did work. Am I correct in assuming that if I want other types of Variables I would change PWord in specialize TFPGMap; to something else, maybe PString, PDouble, PLongint etc? James -Original Message- From: fpc-pascal On Behalf Of Stefan V. Pantazi Sent: Monday, July 8, 2019 10:54 AM To: fpc-pascal@lists.freepascal.org Subject: Re: [fpc-pascal] specify variable name with string variable You can use the TFPGMap class in fgl unit to implement the dictionary. fgl should be available in 3.0.4. Try to replace the Generics.Collections with fgl and the type definition in the example code from zh loza. The rest should be identical. [...] uses fgl; type TVariableDictionary = specialize TFPGMap; [...] On 7/8/19 8:09 AM, James Richters wrote: I'm on windows Generics.Collections seems to be something that was added after 3.0.4, I've downloaded the current FPC source code, but I’m not sure how to build it.. can someone point me in the right direction on how to compile the current source code? James -Original Message- From: fpc-pascal On Behalf Of James Richters Sent: Monday, July 8, 2019 6:48 AM To: 'FPC-Pascal users discussions' Subject: Re: [fpc-pascal] specify variable name with string variable Thank you for the answer and the example... I didn't know there was such a thing as a variable dictionary, but It looks like that may work for me, I'll give it a try! James -Original Message- From: fpc-pascal On Behalf Of zh loza Sent: Sunday, July 7, 2019 4:34 PM To: FPC-Pascal users discussions Subject: Re: [fpc-pascal] specify variable name with string variable Hi all! It's my first answer to the mailing list, hopefully I won't screw anything up. On Sun, Jul 7, 2019 at 10:58 PM James Richters wrote: This might sound silly, but is it possible to somehow specify a variable with a string containing the name of the variable? You might want to try using generic dictionaries. E.g. like this: program Project1; uses SysUtils, Generics.Collections; type TVariableDictionary = specialize TDictionary; var MyDictionary: TVariableDictionary; MyVariable1: Word; begin MyDictionary := TVariableDictionary.Create; MyDictionary.Add('MyVariable1', @MyVariable1); MyDictionary['MyVariable1']^ := 100; WriteLn(MyVariable1); WriteLn(MyDictionary['MyVariable1']^); FreeAndNil(MyDictionary); end. If you need to address variables of different type, try Variants ( https://wiki.freepascal.org/Variant ). ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal -- ___ ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal -- ___ ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] specify variable name with string variable
You can use the TFPGMap class in fgl unit to implement the dictionary. fgl should be available in 3.0.4. Try to replace the Generics.Collections with fgl and the type definition in the example code from zh loza. The rest should be identical. [...] uses fgl; type TVariableDictionary = specialize TFPGMap; [...] On 7/8/19 8:09 AM, James Richters wrote: I'm on windows Generics.Collections seems to be something that was added after 3.0.4, I've downloaded the current FPC source code, but I’m not sure how to build it.. can someone point me in the right direction on how to compile the current source code? James -Original Message- From: fpc-pascal On Behalf Of James Richters Sent: Monday, July 8, 2019 6:48 AM To: 'FPC-Pascal users discussions' Subject: Re: [fpc-pascal] specify variable name with string variable Thank you for the answer and the example... I didn't know there was such a thing as a variable dictionary, but It looks like that may work for me, I'll give it a try! James -Original Message- From: fpc-pascal On Behalf Of zh loza Sent: Sunday, July 7, 2019 4:34 PM To: FPC-Pascal users discussions Subject: Re: [fpc-pascal] specify variable name with string variable Hi all! It's my first answer to the mailing list, hopefully I won't screw anything up. On Sun, Jul 7, 2019 at 10:58 PM James Richters wrote: This might sound silly, but is it possible to somehow specify a variable with a string containing the name of the variable? You might want to try using generic dictionaries. E.g. like this: program Project1; uses SysUtils, Generics.Collections; type TVariableDictionary = specialize TDictionary; var MyDictionary: TVariableDictionary; MyVariable1: Word; begin MyDictionary := TVariableDictionary.Create; MyDictionary.Add('MyVariable1', @MyVariable1); MyDictionary['MyVariable1']^ := 100; WriteLn(MyVariable1); WriteLn(MyDictionary['MyVariable1']^); FreeAndNil(MyDictionary); end. If you need to address variables of different type, try Variants ( https://wiki.freepascal.org/Variant ). ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal -- ___ ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] Virtual object methods
Read down the first page, the section "Objects - Dynamic Variables" - all will become clear. By avoiding the virtual methods, you can keep your objects static, all stored on stack, no need for constructors. I personally find very useful for my projects. Find fixed example below. Hope it helps, Stefan // http://wiki.freepascal.org/Programming_Using_Objects //Objects - Dynamic Variables type TA = object constructor Init(); procedure DoThis; virtual; end; procedure TA.DoThis; begin writeln('TA.DoThis'); end; type PTB=^TB; TB = object (TA) procedure DoThis; virtual; end; procedure TB.DoThis; begin writeln('TB.DoThis'); end; constructor TA.Init(); begin inherited; end; var obj: PTB; begin obj:=New(PTB,Init()); obj^.DoThis; end. On 6/27/19 4:17 PM, Ryan Joseph wrote: Why do I get a runtime error with this? == {$mode objfpc} program test; // http://wiki.freepascal.org/Programming_Using_Objects // http://wiki.freepascal.org/Programming_Using_Objects_Page_2 type TA = object procedure DoThis; virtual; end; procedure TA.DoThis; begin writeln('TA.DoThis'); end; type TB = object (TA) procedure DoThis; virtual; end; procedure TB.DoThis; begin writeln('TB.DoThis'); end; var obj: TB; begin obj.DoThis; end. Regards, Ryan Joseph ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal -- ___ ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] CRT unit and Windows' terminal
I had a similar problem when trying to represent trees using extended ASCII characters. My solution was to adapt my character representations to UTF8. To see what I mean you can have a look at https://github.com/svpantazi/catalan-monoid-generator. The generate_catalan_monoid.pp contains a PrintASCIITree function that does the obvious. The examples folder contains actual outputs (e.g., examples/n_5_output_example.txt) of ASCII trees such as this one (I pasted it here but may not survive the message): 0─┬─1─┬─12───123 │ └─13───132 ├─2─┬─21───213───2132 │ └─23 └─3───32───321 On Fri, Oct 13, 2017 at 9:39 AM, James Richters < ja...@productionautomation.net> wrote: > >I want to create console app that's using box drawing characters from > unicode. Before CRT unit is used, it's all fine and my program could draw > > >table beautifully. But once I put CRT unit, those characters became > garbages. But strangely, it's only happen on Windows' terminal (win10). > > >I tried the same exact program in Mac and Linux, using each CRT unit, and > they all run fine. I need CRT unit to make my console program more > >interactive (i.e. cursor positioning, keyboard handling, text coloring, > etc). > > > > > > >So, what's wrong with CRT unit on Windows? Can anybody explain the > strange behaviour and how to solve the problem? > > > > From my own failed attempts at getting box characters to work with both > crt and ptccrt I can confirm that it’s not working in windows, but I am > actually very surprised to hear it’s working on Linux and Mac. Perhaps > there is a possibility to fix the CRT unit on Windows. > > > > In my opinion, the CRT unit SHOULD be drawing boxes with the ORGINAL > Extended ASCII codes, not Unicode, at least by default. > > The CRT unit is supposed to be compatible with the original turbo pascal > CRT unit, and in turbo pascal if you writeln(Chr(201)) you get a upper left > corner, not a funny looking E, Perhaps there could be an option to use the > unicode characters, but displaying the correct ASCII characters should be > the default. Unfortunatly it’s not doing either correctly… if it’s going > to use Unicode it should use the entire character set, if it’s not going to > do that, then it should be using extended ASCII as the original CRT unit > did. > > > > The strange thing is, my ancient turbo pascal program that draws ACSII > boxes, looks fine in the FPC Text mode IDE, (which itself uses box > characters!) but when running the program, even while in the same console > window that FPC text mode ide is currently running in, I get the unicode > characters.If I’m in the textmode IDE and I enter a character sequence > of ALT+201 I get the upper right corner symbol, not a Unicode symbol… but > run the program, and I get the Unicode sysmbol. If I don’t use the CRT > unit, I do indeed get the full Unicode character set, but then you can’t > use cursor positioning etc… > > > > I have tried to replace the ASCII characters in my program with the > Unicode characters, but I can’t because they are so far out in the table, > they are beyond the 255 character limit of the CRT unit; For example an > upper right corner character used to be #201, now it is #9556. I can’t > find any way to display #9556 with the CRT unit, I‘ve tried > Writeln(Chr(9556)) but chr() has a limit of 255, and I’ve tried just > Writeln(#9556) and while that compiles and runs, it doesn’t produce the > correct character.. I have a feeling (but have not tested it) that it keeps > cycling around the first 256 characters if you use anything above 255….. > pretty sure a character is defined as a byte here. > > > > I have attached screen shots and a sample program that demonstrates this > frustrating situation. I have simply abandoned a quite a few really good > console applications because of this. > > > > Box characters are great, I don’t understand why it’s become so difficult > to incorporate them. But I’m really hoping a solution can be found as I > have reports I display in console windows, even on my graphics programs > that would be so much nicer if I could use box characters again, since I > make use of the console window while the graphics window is also open. > > > > > > James > > ___ > fpc-pascal maillist - fpc-pascal@lists.freepascal.org > http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal > ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] If vs case or something else?
I am not sure I follow. If switching on strings, or any sparse value set, you can use the balanced tree approach or better yet, a hash table. But when switching on a compact, limited set of integer values (as the case seems to be), I do not see how you can compete with constant time procedure table/array lookups. Stefan You can skip large blocks of tests coding like this Not as fast as a tree search balanced with probabilities (no answer to my question on the list afew days ago...), but probably ten time faster then what you proposed. Cheers, Ched' Le 06.07.2017 à 20:41, Stefan V. Pantazi a écrit : That is quite the case statement you have there. You may benefit greatly from re-analyzing and refactoring your programs by splitting them in multiple individual units, if possible. That should be perfectly possible if Dosomething();DoSomethingelse(); keep repeating across your 70+ switch cases. Anyway, here you go, you can try something like the attached. Good luck! Stefan On 07/06/2017 12:33 PM, James Richters wrote: I'm trying to optimize a console application ported over from Turbo Pascal with a huge set of if then else statements like this: Var TXT : String; If TXT = 'Thing1' then Begin Dosomething(); DoSomethingelse(); End else If TXT = 'AnotherThing' then Begin Dosomethinganotherway(); DoSomethingelsetoo(); End Else If TXT = 'Thing3' then Begin Dosomethingathirdtime(); DoSomethingelse3(); End else etc.. over 70 times... etc It works but it's hard to follow and not so fast. It has to run through this for every line of a file to see what's in the file and do the right things with it. So I'm thinking of undertaking a huge re-organization of it and I'm wondering what the best way would be to do it. I can use case statement with strings apparently now, but the thing is, I create this file myself in an earlier stage, so I do not need to create the file with strings at all, I could use some codes and do something like this: Const Thing1 = 1 Another_Thing = 2 Thing3 = 3 Var Codenum: Word; Case Codenum of Thing1: Begin DoSomethng() DoSomethingElse() End; Another_Thing: Begin ... etc ... I'm guessing that would be faster as I wouldn't have to keep evaluating all the strings for every condition. As I was searching for the best way to do this, I came across something about making an Array of Procedures, or something to that effect. Does anyone know how to do that, and are there performance advantages to doing that? It's going to take a bit of work to straighten all this out so it would be best if I just did it the best way instead of doing it one way then finding out it could have been better another way. Any other ideas on how to handle this? Any advice on this is greatly appreciated James ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal -- ___ ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] If vs case or something else?
That is quite the case statement you have there. You may benefit greatly from re-analyzing and refactoring your programs by splitting them in multiple individual units, if possible. That should be perfectly possible if Dosomething(); DoSomethingelse(); keep repeating across your 70+ switch cases. Anyway, here you go, you can try something like the attached. Good luck! Stefan On 07/06/2017 12:33 PM, James Richters wrote: I'm trying to optimize a console application ported over from Turbo Pascal with a huge set of if then else statements like this: Var TXT : String; If TXT = 'Thing1' then Begin Dosomething(); DoSomethingelse(); End else If TXT = 'AnotherThing' then Begin Dosomethinganotherway(); DoSomethingelsetoo(); End Else If TXT = 'Thing3' then Begin Dosomethingathirdtime(); DoSomethingelse3(); End else etc.. over 70 times... etc It works but it's hard to follow and not so fast. It has to run through this for every line of a file to see what's in the file and do the right things with it. So I'm thinking of undertaking a huge re-organization of it and I'm wondering what the best way would be to do it. I can use case statement with strings apparently now, but the thing is, I create this file myself in an earlier stage, so I do not need to create the file with strings at all, I could use some codes and do something like this: Const Thing1 = 1 Another_Thing = 2 Thing3 = 3 Var Codenum: Word; Case Codenum of Thing1: Begin DoSomethng() DoSomethingElse() End; Another_Thing: Begin ... etc ... I'm guessing that would be faster as I wouldn't have to keep evaluating all the strings for every condition. As I was searching for the best way to do this, I came across something about making an Array of Procedures, or something to that effect. Does anyone know how to do that, and are there performance advantages to doing that? It's going to take a bit of work to straighten all this out so it would be best if I just did it the best way instead of doing it one way then finding out it could have been better another way. Any other ideas on how to handle this? Any advice on this is greatly appreciated James ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal -- ___ program fast_switch; uses sysutils, fast_switch_handler_unit;//implements case handlers const TEST_COUNT=100; function GetCodeNum():word; begin Result:=Random(MAX_HANDLER_IDX); end; var i:Integer; Codenum: Word; //or enum begin Randomize; for i:=0 to TEST_COUNT-1 do begin WriteLn('Test switching #',i); repeat codeNum:=GetCodeNum(); //execute procedure with index codeNum from PROC_TABLE if (Codenum>0) and (Codenum<=MAX_HANDLER_IDX) then PROC_TABLE[CodeNum]; Sleep(50); until codeNum=0; WriteLn('Done switching test #',i); end; WriteLn('Done switching test program.'); end. unit fast_switch_dosomething_unit; {$mode objfpc}{$H+} interface uses Classes, SysUtils; procedure Dosomething(); procedure DoSomethingelse(); procedure Dosomethinganotherway(); procedure DoSomethingelsetoo(); procedure Dosomethingathirdtime(); procedure DoSomethingelse3(); implementation procedure Dosomething(); begin WriteLn('Dosomething()'); end; procedure DoSomethingelse(); begin WriteLn('DoSomethingelse()'); end; procedure Dosomethinganotherway(); begin WriteLn('Dosomethinganotherway()'); end; procedure DoSomethingelsetoo(); begin WriteLn('DoSomethingelsetoo()'); end; procedure Dosomethingathirdtime(); begin WriteLn('Dosomethingathirdtime()'); end; procedure DoSomethingelse3(); begin WriteLn('DoSomethingelse3()'); end; end. unit fast_switch_handler_unit; {$mode objfpc}{$H+} interface uses fast_switch_dosomething_unit;//implements DoSomething* const MAX_HANDLER_IDX=3;// or 70 procedure Thing1_Handler(); procedure AnotherThing_Handler(); procedure Thing3_Handler(); const PROC_TABLE:array[1..MAX_HANDLER_IDX] of procedure=( @Thing1_Handler, @AnotherThing_Handler, @Thing3_Handler // ... //@Thing70_Handler ); implementation procedure Thing1_Handler(); Begin Dosomething(); DoSomethingelse(); End; procedure AnotherThing_Handler(); Begin Dosomethinganotherway(); DoSomethingelsetoo(); End; procedure Thing3_Handler(); Begin Dosomethingathirdtime(); DoSomethingelse3(); End; end. ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] Can't close and reopen ptcgraph
add ptcwrapper to uses list. I get reopengraph.pas(32,23) Error: Identifier not found "TPTCWrapperThread" ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] Implementing AggPas with PtcGraph
On 06/26/2017 10:21 AM, James Richters wrote: Is there a way to re-scale a drawing with agg_2D? I think so, scaling is one of the transformations that agg supports well. The way I would go about this would be to study how agg manages the parsing, storage and display of svg drawings, which are basically collections of drawing commands, just like yours. Compile, run and analyze the code of svg examples, in particular svg_test demo (the one with the lion head). I found a scale feature in aggpas but it only seems to scale items drawn after the command is issued. Scaling is done through matrix multiplication but you need to have all your drawing commands stored in a similar way agg does it for svg, so that they can be redrawn. This is a more flexible approach than reiterating over hardcoded drawing commands. The cost is the increased complexity. I'm wondering if there is a way to send aggpas all my lines and arcs, then give it a scale and offset, display it that way, then a different scale and offset, then redisplay it that way, I think doing this in a way similar to svg routines is one way to go and may have its limitations. While significantly more complicated, you also get as a byproduct the capability of saving your screen (think screenshots, etc.) in standard svg format that can be persisted beyond your application lifecycle. ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] JSON SAX-based reader
Thank you for this, Michael. I think it is wonderful work. I've done some old tests of the new implementation and it looks very good. The only failed tests were related to date and time representation. This appears to be fixed in the new version. Most importantly, I see no memory leaks when parsing fails due to malformed JSON, and that is great! The only fixes I had to do to my own software to accommodate the new implementation, were: 1) comment out the "Strict" property of the TJSONParser (it appears it no longer exists); I used to set it to false, to allow for more flexibility in JSON syntax. 2) add the missing procedure SetKey(obj:TJSONObject); to TJSONConfig since it was removed from the new version of jsonconf.pp; anyway, in this particular case, it may be me that has to rethink and simplify my use of the json config component that does not need SetKey. Hope this helps, Stefan On 06/23/2017 02:48 AM, Michael Van Canneyt wrote: Hello, I have changed the JSON parser, it is now written on top of a SAX-like JSON reader (which is available separately). All unit tests work fine, and the few extra tests which I did also, but I would like to hear if someone has code that no longer works. The change is committed in trunk. The new JSON reader is available in the unit jsonreader. Useful if you want to process large amounts of JSON data without building the whole JSON document in memory. Michael. ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal -- ___ ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] Implementing AggPas with PtcGraph
When in doubt, have a look at the source code of the graphical primitives to determine the semantics of each one. Unlike line primitive which draws a path immediately, lineto is meant to be used multiple times, as part of a draw path. So, lineto does not really draw, it just adds a vertex to a vertex storage object. To draw a path, you need to use the drawPath(option): agg^.lineWidth(4); agg^.lineColor(0, 155, 0, 255); agg^.rectangle(10, 10, 50, 50); agg^.lineColor(155, 0, 0, 255); agg^.line(60, 10, 60, 50); agg^.lineto(100,50); //no line drawn here, just adds to vertex storage agg^.drawPath(StrokeOnly); //draw path agg^.lineColor(0, 0, 155, 255); agg^.moveto(100, 10); agg^.lineto(100,50); //no line drawn here, just adds to vertex storage agg^.drawPath(StrokeOnly); //draw path agg^.lineColor(155, 0, 155, 255); agg^.line(120, 10, 120, 50); On 06/23/2017 01:27 PM, James Richters wrote: I'm trying to switch over a program to use aggpas but I'm not getting any results from moveto or lineto am I missing something? ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] Can't close and reopen ptcgraph
I think I figured it out. It hink ptcgraph was not designed with that functionality in mind. If you take a look at the ptcgraph unit, it has initialization and finalization sections where the ptc wrapper object is created and freed. That happens only at application start and finish not during run, as you require. As a workaround, you can manually take care of the ptcwrapper object like this, in between closegraph and initgraph calls, but first ask yourself, do you really need this? [...] //close graph window ptcgraph.Closegraph; //manually terminate the ptcwrapper thread and free object PTCWrapperObject.Terminate; PTCWrapperObject.WaitFor; PTCWrapperObject.Free; //manually create the ptcwrapper thread PTCWrapperObject := TPTCWrapperThread.Create; //init graph windows as usual ptcgraph.Initgraph(gd,gm,''); [...] Stefan On 06/23/2017 11:20 AM, James Richters wrote: I ran into an unexpected issue with ptcgraph. If I use closegraph, I cannot re-open a new ptcgraph window with Initgraph. It looks like it opens the second graph window but then closes it immediately after.. my program is then appears to be locked up after this happens.. no errors, just locked up. test program is below. If I comment out ptcgraph and ptccrt and uncomment graph and wincrt, it works as expected. ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] Can't close and reopen ptcgraph
On Linux 64bit, reopening of a second window works fine, as expected. On Windows it does not, and behaves as you reported. This is most likely related to the use of a separate thread (TPTCWrapperThread) in ptcgraph. As far as I know graph and wincrt do not use threads. I suspect that on windows, the ptc thread is not properly terminating for some reason. Stefan On 06/23/2017 11:20 AM, James Richters wrote: I ran into an unexpected issue with ptcgraph. If I use closegraph, I cannot re-open a new ptcgraph window with Initgraph. It looks like it opens the second graph window but then closes it immediately after.. my program is then appears to be locked up after this happens.. no errors, just locked up. test program is below. If I comment out ptcgraph and ptccrt and uncomment graph and wincrt, it works as expected. ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] Implementing AggPas with PtcGraph
Good find and great sleuth work. It is possible that the original reason for switching R and B channels was to make the agg color object more compatible with LCL which seems to prefer BGR, order, but who knows... One obvious problem seems to be function AggToLCLColor(const c: TAggColor): TColor; in Agg_LCL, that relies for conversion on RGBToColor in the Graphics unit. function RGBToColor(R, G, B: Byte): TColor; begin Result := (B shl 16) or (G shl 8) or R; end; Anyway, a quick search of the agg source code shows that the rgba8 object is used only by a handful of units directly. Most agg units and demos use the more complicated aggclr object to represent color. I tried a few demos and seem unaffected by your fix. This explains why the bug was only clearly visible in your case, most of the other agg demos seem indiferent to the bug. On the other hand, besides agg_2D there are agg_fpimage, Agg2D (the one that integrates with LCL) that also use the rgba8 (through the TAggColor alias) and are clearly affected by the R and B swap when using canvas methods that involve the TAggColor object (e.g., AggClearAll, AggClearClipBox, etc). These would need to be updated as well. As an example, after your fix, the call canvas.AggClearAll(255,0,0) to TAggFPCanvas.AggClearAll(const r ,g ,b : byte; a : byte = 255 ) produces a blue background, which is clearly wrong. On 06/18/2017 08:35 PM, James Richters wrote: I finally partially figured out the red / blue color problem. After single stepping through tons of the aggpas code for hours (it's quite complicated even to draw a line) with a sample program that just made a red line at the top, I discovered that it's actually doing everything exactly correct! The problem is not with rendering with rgb565, the problem is something in the original that was patched with the setcolor function: Line 122 of agg_color pas has: constructor rgba8.Construct; begin b{*}:=int8u(r_ ); g:=int8u(g_ ); r:=int8u(b_ ); a:=int8u(a_ ); end; This switches red and blue... if I correct it to: constructor rgba8.Construct; begin b{*}:=int8u(b_ ); g:=int8u(g_ ); r:=int8u(r_ ); a:=int8u(a_ ); end; now my colors with rgb565 are correct. Since this is no logical reason to make b:=R_ and r:=B_ it seems more likely that with the rgba format somewhere along the way someone got lazy and just switched red and blue instead of fixing the pixelformat. ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] Implementing AggPas with PtcGraph
I was waiting for the right time to also offer my sincere thanks to all teams and individual contributors. I have been using fpc and Lazarus IDE for quite some years now and I am very pleased with the constant progress and improvement of these development tools. I have enjoyed reading and learned a lot on these mailing lists as well. My hope is that contributions continue for many years to come and that the community remains helpful as it has always been. Stefan Also when looking through the fpGUI as well as the Freepascal repositories, there are just thousands of commits. looking at all those commits gives a real appreciation for the amount of work that has gone into the project. So a huge thank you goes out to everyone who has worked so hard to make freepascal as awesome as it is, as well as the people who are such a tremendous help on this list. Honestly if not for FreePascal, I would still be trying to put together Pentium 233 computers to run my old DOS applications on. (not fun, components are getting hard even to find on ebay now) I just don't have time to do a massive re-write all at once, and FreePascal let me drop in my Turbo Pascal programs and pretty much just run them. James ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] Implementing AggPas with PtcGraph
I think you need to use a global define passing a -d??? parameter (-dAGG2D_USE_FREETYPE) to the compiler. Just adding it to a unit only defines for that unit and to any file included in that one unit. On 06/14/2017 09:40 PM, James Richters wrote: The font rendering should all be controlled by compiler defines. You don't need to modify the unit to make it work. Simply add the correct define in your project's Compiler Settings and recompile the code. That is what I thought should happen, but I put {$DEFINE AGG2D_USE_FREETYPE} In my program under {$mode objfpc}{$H+} I still get: FreeType: FALSE Win32 True Type: TRUE But if I uncomment {$DEFINE AGG2D_USE_FREETYPE} In agg_2D.pas It's the only way I can get FreeType: TRUE Win32 True Type: FALSE I don't know why the define isn't making it to the unit. Do I need to do something else? It's as if it's being un-defined somewhere else but I don't know where.. maybe the same place that is {$DEFINE AGG2D_USE_WINFONTS} because that is defiantly being set somewhere before the agg_2D.Pas unit and the only way to not get an error is for me to have this at the top of agg_2D.pas {$IFDEF AGG2D_USE_FREETYPE } {$UNDEF AGG2D_USE_WINFONTS} {$ENDIF } And if you look in the "develop" branch of fpGUI, there is an even later AggPas version - last updated a month ago. Maybe I should go get this.. maybe some of these things are fixed already Thank you for the help with this. James ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal -- ___ ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] Implementing AggPas with PtcGraph
Yes, it is puzzling. Different pointer sizes, compilers, OS, 32/64 bit library dependencies, can be potential causes. Again, note that I compiled the example on a CentOS 7, 64bit Linux with Lazarus 1.5 + fpc 3.0.1 I can also confirm that the test program compiles and works fine on Ubuntu 16.04 64bit, with Lazarus 1.7 + fpc 3.1.1 On 06/13/2017 10:16 PM, James Richters wrote: but I don't know what I can do about it and why you are able to cross compile for win64 and it works. ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] Implementing AggPas with PtcGraph
While in lazarus open agg_rasterizer_scanline_aa.pas, go ro line 611 press Ctr and click on ptrcomp. It should open agg_basics.pas, the comment may apply to your situation. It is unclear to me whether you are on a win32 or win64 OS? If you are already on a win64 machine then your default target CPU should already be x86_64. why do you need fpc-3.0.2-cross-i386-win32-win64? On 06/13/2017 08:25 PM, James Richters wrote: Noting your problems with compilation, you may want to consider using Lazarus IDE as well. I have just installed Lazarus but still can't get the aggpas_ptcgraph_output.pas sample program to run when compiled for x64. Here is what I have done. Downloaded and installed lazarus-1.6.0-fpc-3.0.0-win64.exe and accepted all defaults Downloaded and installed lazarus-1.6.4-fpc-3.0.2-cross-i386-win32-win64.exe and accepted the default install directory. Copied aggpas to C:\lazarus\fpc\3.0.2\units\i386-win32 Copied aggpas to C:\lazarus\fpc\3.0.2\units\x86_64-win64 Opened a sample program the uses just ptcgraph, when it asked to create a project I said yes then selected 'Program' from the list I was able to compile and run it with options for OS win32 CPU i386 as well as OS win64 CPU x86_64 and it ran fine with both versions I opened aggpas_ptcgraph_output.pas the same way and selected program. If I select OS win32 CPU i386 it compiles and runs fine, no problems When I select OS win64 CPU x86_64 and try to run it, it opens both the console window and graphics window, then I get an error box reading: Project aggpas_ptcgraph_output raised exception class 'external: SIGSEGV' In file 'C:\lazarus\fpc\3.0.2\u..\agg_rasterizer_scanline_aa.pas' at line 611 while cell_aa_ptr_prt(ptrcomp(j) + 1 * 4^^.x
Re: [fpc-pascal] Implementing AggPas with PtcGraph
Looks like it may be something specific to your setup. In my tests I used Lazarus 1.5 as IDE and fpc 3.0.1 on Linux. Crosscompiled example ran on Win7 64 bit. So there are already differences with your environment. Noting your problems with compilation, you may want to consider using Lazarus IDE as well. You get a debugger too. One other thing that comes to mind is to be mindful of calls like this agg^.rectangle(0, 0, IMAGE_WIDTH, IMAGE_HEIGHT); If the default fill color is black, then the result will be a black window, albeit not unresponsive. Again, if your program hangs for some reason, a debugger may come in handy. Stefan On 06/13/2017 04:44 PM, James Richters wrote: I've tested the example on 64 bit linux as a native application as well cross compiled for a x86_64 windows target. Worked fine in both Wine and on a Win64 machine. In my experience, the one dependency that AggPas has potential to fail may be related to the freetype library. If you plan to run your app on windows only, then you can turn freetype off and AggPas will happily use windows font libraries. Search for the AGG2D_USE_FREETYPE define and comment it out. I thought I would try to compile the example for x86_64, because I would eventually like to make my final program an x86_64 program. When I compile it with the command: fpc -Fu'J:\programming\fpc\3.0.2\units\$fpctarget\*' aggpas_ptcgraph_output.pas it works fine. When I try fpc -Fu'J:\programming\fpc\3.0.2\units\$fpctarget\*' -Px86_64 aggpas_ptcgraph_output.pas it compiles fine with no errors, and it executes with no errors, however I do not get any output in either window at all, they are both just black, and unresponsive. I've commented out the AGG2D_USE_FREETYPE for now, because I'm not sure if the freetype.dll I have will work on 64bit programs, and thought I would eliminate that as a possible issue. I am using FPC v3.0.2 on a windows 10 x64 machine I normally use the freepascal IDE to compile my programs, so I'm not too familiar with compiling from the command line. I'm wondering if I am doing something wrong. Also, is there some way to set a default for my units so I don't have to use Fu'J:\programming\fpc\3.0.2\units\$fpctarget\*' all the time? If I don't use that, then it can't find any units, even though it's set in the directories with the IDE I have some other sample programs that use ptcgraph (without AggPas) that do not have this issue, they compile as 64bit programs and run fine. This seems to be something with using AggPas that appears to be causing the problem. I put in a writeln('test'); at the beginning of the program and it does do that, and I move ptcgraph.Rectangle(10,10,100,100); to before drawstuff(agg); I will get the rectangle on the graph screen. So I thought I would try to narrow down what was happening by drawing different rectangles in the middle of the code like this: ptcgraph.Rectangle(30,30,200,200); agg^.clearAll(0, 0, 0); agg^.lineColor(0, 0, 0, 255); agg^.lineWidth(3); agg^.rectangle(0, 0, IMAGE_WIDTH, IMAGE_HEIGHT); ptcgraph.Rectangle(30,30,200,300); agg^.lineWidth(1); agg^.lineColor(0, 155, 0, 255); agg^.rectangle(10, 10, 50, 50); ptcgraph.Rectangle(30,30,300,300); I get the first rectangle right away, the second rectangle after 6 seconds, and the third after 6 more seconds. I tried commenting out everything else, but I still never get the image from putimage(); I'm very confused by this and don't have a clue what could be wrong. If I take out the -Px86_64 in the compile command line, the program runs as expected. Since Stefan said he compiled 64bit versions of the example program and it worked, I wonder why I am having this issue. James ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal -- ___ ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] Implementing AggPas with PtcGraph
There is a minus sign in the call: agg^.attach(@graph_buffer.data, IMAGE_WIDTH, IMAGE_HEIGHT, -(IMAGE_WIDTH * RGB_WIDTH)) Removing it will flip the Y axis. With regard to color, there may be two options: 1) the ideal way would be to specify the rgb order of a pixel format in the Agg_2D constructor. The m_pixFormat has a m_order field with the type order_type defined in agg_color.pas; have not figured it yet 2) knowing the R and B channels are swapped, you can do all your drawing with colors there R and B are switched. Stefan On 06/13/2017 12:42 PM, James Richters wrote: I've just realized that the red and blue channels are reversed. The sample program aggpas_ptcgraph_output.pas has the star filled in with a red fade and a blue series of random lines while the original test.png file had a blue fade in the star with red random lines. Also, the image is flipped on the Y axis compared to the original example. The small green square is in the upper left corner of test.png, but it is in the lower left corner of aggpas_ptcgraph_output.pas I've been able to duplicate the results of test.png by shifting the left 5 bits 11 positions to the right and the right 5 bits 11 positions to the left and flipping the Y axis, but I can only do that with putpixel and a nested loop, which is quite a bit slower than putimage. Any ideas how I can build the data correctly so putimage will work? James ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal -- ___ ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] Implementing AggPas with PtcGraph
How did you build/get freetype.dll? If it was built using Visual Studio, freetype.dll might have been linked against a newer C++ runtime such as msvcr71.dll that is not shipped with windows by default. You clearly need to deploy C++ runtime libs as well with your product. You may benefit from such tool as a dependency walker (https://en.wikipedia.org/wiki/Dependency_Walker). On linux you can just use ldd. Hope this helps, Stefan On 06/05/2017 05:00 PM, James Richters wrote: As for font support under Windows. Yes you can use GDI for font rendering, but I highly recommend using freetype.dll even under Windows. It has more features than GDI font support and the quality is better too. Is it the fonts causing the dependency then? I have freetype.dll included in the directory with my programs, do I need to include other files / dlls if I want them to run without installing anything? the programs I am getting the dependency issue with are based on and including Graeme's original sample program Agg2DColsole.dpr , they use: Ptcgraph, Ptccrt, Sysutils, Fpimage, Fpwritepng, Agg_2d, Agg_Basics James -Original Message- From: fpc-pascal [mailto:fpc-pascal-boun...@lists.freepascal.org] On Behalf Of Graeme Geldenhuys Sent: Monday, June 05, 2017 2:25 PM To: fpc-pascal@lists.freepascal.org Subject: Re: [fpc-pascal] Implementing AggPas with PtcGraph On 2017-06-05 03:12, Stefan V. Pantazi wrote: In my experience, the one dependency that AggPas has potential to fail may be related to the freetype library. If you plan to run your app on windows only, then you can turn freetype off and AggPas will happily use windows font libraries. Search for the AGG2D_USE_FREETYPE define and comment it out. Correct, though even font support is optional in AggPas. So if you don't render text via AggPas, it has zero dependency - everything is done in pure Object Pascal code. As for font support under Windows. Yes you can use GDI for font rendering, but I highly recommend using freetype.dll even under Windows. It has more features than GDI font support and the quality is better too. Regards, Graeme -- fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal http://fpgui.sourceforge.net/ My public PGP key: http://tinyurl.com/graeme-pgp ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal -- ___ Stefan V. Pantazi, MD, PhD Professor, Health Informatics School of Health & Life Sciences and Community Services Conestoga College Institute of Technology and Advanced Learning 299 Doon Valley Drive Kitchener, ON, Canada, N2G 4M4 office: 1C23 phone: (519) 748-5220 ext. 3950 email: svpant...@gmail.com web:https://sites.google.com/site/stefanvpantazi/ ___ ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] Implementing AggPas with PtcGraph
I've tested the example on 64 bit linux as a native application as well cross compiled for a x86_64 windows target. Worked fine in both Wine and on a Win64 machine. In my experience, the one dependency that AggPas has potential to fail may be related to the freetype library. If you plan to run your app on windows only, then you can turn freetype off and AggPas will happily use windows font libraries. Search for the AGG2D_USE_FREETYPE define and comment it out. Hope this helps, Stefan On 06/04/2017 06:30 PM, James Richters wrote: Thanks for figuring out how to make this work, I would have never figured it out with the documentation I was able to find. I'm out of town this week so I tried to download the sample program to my laptop and discovered another issue. While I can normally just compile my programs on my laptop and run them, I have noticed that I can't do this with programs with aggpas in them. They compile successfully but when I try to run them I get a "system error: The Program can't start because MSVCR71.dll is missing from your computer. Try reinstalling the program to fix this problem" I suspect I get this because I have never actually installed free Pascal or something that I happened to install on my development pc on my laptop, I have always run freepascal it from a backup made from my development machine. I have not tried installing freepascal on my lap top yet because I would like to figure out what I will need to do on my target installations where freepascal will not be installed. Any ideas on what causes this error and advice on how to install what is needed on client (non-development) systems? James -Original Message- From: fpc-pascal [mailto:fpc-pascal-boun...@lists.freepascal.org] On Behalf Of Stefan V. Pantazi Sent: Saturday, June 03, 2017 12:45 PM To: FPC-Pascal users discussions <fpc-pascal@lists.freepascal.org> Subject: Re: [fpc-pascal] Implementing AggPas with PtcGraph I seem to have some problems with logging on the bug tracker. I've used it in the recent past a couple of time but I am unable to log on for some reason. I will try later to create a new account and submit a fpc doc bug report. At any rate, I attached the updated example based on Nikolay's recent post which had the correct information. There was a third "reserved" parameter that had to be added to the bitmap buffer structure. Without it, the output was slightly clipped to the right. Also, for the example to work, the agg object constructor must be modified as well, I included all the info in the example header. I think the example program (aggpas_ptcgraph_output.pas) fits well together with the other demos in fpGUI and PtcPas/ptcgraph packages, so adding it to the packages would help, regardless whether graph.PutImage documentation is updated. Stefan On 06/03/2017 06:52 AM, Graeme Geldenhuys wrote: On 2017-06-03 01:56, Stefan V. Pantazi wrote: http://pascal.net.ru/PutImage+(en) [...] "BitMap is an untyped parameter that contains the height and width of the region, and the bit image that will be put onto the screen." [...] Could you file a FPC Documentation bug report and ask that this information be added. As you found out (very difficultly), this is vital information. Regards, Graeme ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal -- ___________ Stefan V. Pantazi, MD, PhD Professor, Health Informatics School of Health & Life Sciences and Community Services Conestoga College Institute of Technology and Advanced Learning 299 Doon Valley Drive Kitchener, ON, Canada, N2G 4M4 office: 1C23 phone: (519) 748-5220 ext. 3950 email: svpant...@gmail.com web:https://sites.google.com/site/stefanvpantazi/ ___ ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] Implementing AggPas with PtcGraph
The easiest workaround I could figure was to add a parameter to the Agg2D object constructor. That should, in theory, allow the use of any pixel format available in AggPas. The ptcpas/ptcgraph units I used are the ones that came with fpc 3.0.1, there was no need to download anything. They worked fine, except for one 48 bytes memory leak reported by heaptrc and that I left unfixed. Stefan On 06/03/2017 03:37 PM, Graeme Geldenhuys wrote: On 2017-06-03 17:45, Stefan V. Pantazi wrote: Also, for the example to work, the agg object constructor must be modified as well, I included all the info in the example header. I noted the remarks on the image buffer format being hard-coded for the Agg_2D unit. I'll make a plan for improving that, using some Factory (design) Pattern to register the pixel buffer format of interest. I think the example program (aggpas_ptcgraph_output.pas) fits well together with the other demos in fpGUI and PtcPas/ptcgraph packages, so adding it to the packages would help, regardless whether graph.PutImage documentation is updated. Thanks. I'll download the ptcgraph unit and give it a test. I'll all the demo to fpGUI's AggPas demos too. It will be a good addition. Regards, Graeme ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] Implementing AggPas with PtcGraph
I seem to have some problems with logging on the bug tracker. I've used it in the recent past a couple of time but I am unable to log on for some reason. I will try later to create a new account and submit a fpc doc bug report. At any rate, I attached the updated example based on Nikolay's recent post which had the correct information. There was a third "reserved" parameter that had to be added to the bitmap buffer structure. Without it, the output was slightly clipped to the right. Also, for the example to work, the agg object constructor must be modified as well, I included all the info in the example header. I think the example program (aggpas_ptcgraph_output.pas) fits well together with the other demos in fpGUI and PtcPas/ptcgraph packages, so adding it to the packages would help, regardless whether graph.PutImage documentation is updated. Stefan On 06/03/2017 06:52 AM, Graeme Geldenhuys wrote: On 2017-06-03 01:56, Stefan V. Pantazi wrote: http://pascal.net.ru/PutImage+(en) [...] "BitMap is an untyped parameter that contains the height and width of the region, and the bit image that will be put onto the screen." [...] Could you file a FPC Documentation bug report and ask that this information be added. As you found out (very difficultly), this is vital information. Regards, Graeme (* This is a minimalistic console application demo derived from the Agg2DConsole.dpr at https://github.com/graemeg/fpGUI/tree/develop/src/corelib/render/software/agg-demos It uses the Agg2D object in AggPas, which has a much friendlier API, to do all the drawing. The drawing buffer is then displayed in a window using ptcgraph and 16 bit RGB565 color format. Uses a GraphBitmapBuffer record type that includes the width and height of the image as well as a reserved parameter per the info in this post: http://lists.freepascal.org/pipermail/fpc-pascal/2017-June/051524.html [...] "The structure, used by putimage is as follows: 3 longints (12 bytes): - image width - image height - reserved followed by width*height 16-bit words. [...] Agg2D object constructor requires a modification to use pixel formats other than rgba32 (e.g., 16 bit RGB565 color format) as follows: [...] public constructor Construct(pixfmt:define_pixfmt); destructor Destruct; [...] { CONSTRUCT } constructor Agg2D.Construct(pixfmt:define_pixfmt); begin m_rbuf.Construct; pixfmt(m_pixFormat ,@m_rbuf); pixfmt_custom_blend_rgba(m_pixFormatComp ,@m_rbuf ,@comp_op_adaptor_rgba ,rgba_order ); pixfmt(m_pixFormatPre ,@m_rbuf); pixfmt_custom_blend_rgba(m_pixFormatCompPre ,@m_rbuf ,@comp_op_adaptor_rgba ,rgba_order); [...] ADDITIONAL NOTES: - although rendering appears to work with pixel formats other than rgba32, custom blending may need further testing. - there may other implementations of graph units and video modes requiring a different bitmap structure than the one used below. - example is tested with fpc 3.0.1 and Agg2D - Version 1.0 Release Milano 3 (AggPas 2.4 RM3) *) program aggpas_ptcgraph_output; {$mode objfpc}{$H+} uses ptcgraph, ptccrt, agg_pixfmt_rgb_packed, //for pixfmt_rgb565 agg_2D; const IMAGE_WIDTH = 800; IMAGE_HEIGHT = 600; RGB_WIDTH =2; //16bit RGB565 format LINE_COUNT = 30; type TGraphBitmapBuffer=packed record width, height, reserved: longint;//per info in http://lists.freepascal.org/pipermail/fpc-pascal/2017-June/051524.html data: array[0..RGB_WIDTH*IMAGE_WIDTH*IMAGE_HEIGHT-1] of byte; end; var gd,gm : smallint; graph_buffer: TGraphBitmapBuffer; procedure DrawStuff(agg: Agg2D_ptr); var i: Integer; x, y, px, py, d: Double; c1, c2: Color; begin // draw a full screen graph with grid agg^.clearAll(0, 0, 0); agg^.lineColor(0, 0, 0, 255); agg^.lineWidth(3); agg^.rectangle(0, 0, IMAGE_WIDTH, IMAGE_HEIGHT); agg^.lineWidth(1); agg^.lineColor(0, 155, 0, 255); agg^.rectangle(10, 10, 50, 50); // agg^.font(fontfile, 16); d := IMAGE_WIDTH / LINE_COUNT; agg^.lineColor(0, 0, 0, 100); agg^.lineWidth(1); for i := 1 to LINE_COUNT - 1 do begin x := i * d; agg^.line(x, 0, x, IMAGE_HEIGHT); end; for i := 1 to trunc(IMAGE_HEIGHT / d) do begin y := i * d; agg^.line(0, y, IMAGE_WIDTH, y); end; x := 0; y := IMAGE_HEIGHT / 2; px := x; py := y; agg^.lineColor(255, 0, 0, 200); agg^.fillColor(0, 0, 0, 200); agg^.lineWidth(1); for i := 0 to LINE_COUNT - 1 do begin x := x + d; y := y + Random(Round(IMAGE_HEIGHT / 3)) - IMAGE_HEIGHT / 6; if y < 0 then y := IMAGE_HEIGHT / 6; if y >= IMAGE_HEIGHT then y := IMAGE_HEIGHT - IMAGE_HEIGHT / 6; agg^.line(px, py, x, y); //agg^.text(x, y, char_ptr(IntToStr(i) + ' point')); px := x; py := y; end; // Star shape agg^.LineCap(CapRound); agg^.LineWidth(5); agg^.LineColor($32 ,$cd ,$32 ); c1.Construct(0, 0 , 255, 200); c2.Construct(0, 0, 255, 50); agg^.F
Re: [fpc-pascal] Implementing AggPas with PtcGraph
An interesting challenge. It works now. I updated your test program, made it as minimal as possible (see attached). The key to solving the problem was the info available here: http://pascal.net.ru/PutImage+(en) [...] "BitMap is an untyped parameter that contains the height and width of the region, and the bit image that will be put onto the screen." [...] Enjoy, Stefan On 06/02/2017 07:40 AM, James Richters wrote: Thanks for the help. I was able to make a little progress. There is another agg unit agg_pixfmt_rgb_packed that seem to have the 565 format that you need. Add it to the uses list and try to replace the pixfmt_rgba32 calls with pixfmt_rgb565. That will make agg use that format. The pixfmt_custom_blend_rgba calls may need further hacking too to make things work, however, Agg2D should use a 16 bit format if you use pixfmt_rgb565 callse instead of pixfmt_rgba32. You should also set RGBA_Width =2; in your program to reflect the change. I did as you suggest here and changed my buffer to be an array of words, and I am able to get a representation of the image to screen by reading elements of the array and using putpixel() to put them on the screen, however the colors are all wrong. I am wondering if this m_pixformat variable that shows up everywhere needs to be set also? The pixfmt_custom_blend_rgba calls may also be the problem with the colors. There are no corresponding custom blend procedures in agg_pixfmt_rgb_packed. Anyway, this will probably still not make ptcgraph.putimage(0,0,buf[0],0); No this still does not work, I am able to use a nested loop and putpixel() but that is very slow. I still think something is missing with putimage because I don't see how it knows the shape of the image, maybe I need to actually do a getimage() at some point to set the shape of before putimage will work.. I'll do some experiments with it. James -Original Message- From: fpc-pascal [mailto:fpc-pascal-boun...@lists.freepascal.org] On Behalf Of Stefan V. Pantazi Sent: Thursday, June 01, 2017 9:47 AM To: FPC-Pascal users discussions <fpc-pascal@lists.freepascal.org> Subject: Re: [fpc-pascal] Implementing AggPas with PtcGraph Have a look at the agg_2D unit. The agg_2D uses .. agg_pixfmt , agg_pixfmt_rgba , .. Therefore, the rgba format is pretty much baked in. That is to say that the constructor of the main object Agg2D uses the pixfmt_rgba32 to set the pixel format. ... { CONSTRUCT } constructor Agg2D.Construct; begin m_rbuf.Construct; pixfmt_rgba32 (m_pixFormat ,@m_rbuf ); pixfmt_custom_blend_rgba(m_pixFormatComp ,@m_rbuf ,@comp_op_adaptor_rgba ,rgba_order ); pixfmt_rgba32 (m_pixFormatPre ,@m_rbuf ); pixfmt_custom_blend_rgba(m_pixFormatCompPre ,@m_rbuf ,@comp_op_adaptor_rgba ,rgba_order ); ... There is another agg unit agg_pixfmt_rgb_packed that seem to have the 565 format that you need. Add it to the uses list and try to replace the pixfmt_rgba32 calls with pixfmt_rgb565. That will make agg use that format. The pixfmt_custom_blend_rgba calls may need further hacking too to make things work, however, Agg2D should use a 16 bit format if you use pixfmt_rgb565 callse instead of pixfmt_rgba32. You should also set RGBA_Width =2; in your program to reflect the change. Anyway, this will probably still not make ptcgraph.putimage(0,0,buf[0],0); work, but that may be a ptcgraph problem. Hope this helps, Stefan On 05/31/2017 02:57 PM, James Richters wrote: And AggPas already has support for that pixel format How do I define that as the format I want? I've been looking all through the example and do not see how this is defined. I've attached a test program, it's basically Graeme's sample but going to screen instead of a file. I just don't see where the pixel format is defined. I have it kind of working in a funny way by just forcing the existing pixels to conform to the required format. -Original Message- From: fpc-pascal [mailto:fpc-pascal-boun...@lists.freepascal.org] On Behalf Of Graeme Geldenhuys Sent: Wednesday, May 31, 2017 1:17 PM To: fpc-pascal@lists.freepascal.org Subject: Re: [fpc-pascal] Implementing AggPas with PtcGraph On 2017-05-31 18:03, Reimar Grabowski wrote: I'm not sure what that's called RGB565, maybe? And AggPas already has support for that pixel format. Regards, Graeme ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal ___ fpc-pascal maillist - fpc-pascal@lists.fre
Re: [fpc-pascal] Implementing AggPas with PtcGraph
I literally just sent a reply with the solution. I had to guess the width and height were longints. Your message confirmed it. I attached an updated version of the test program, the old one had a few typos. Thank you for your work on the ptcpas, I found it very useful for my projects. On 06/02/2017 08:39 PM, Nikolay Nikolov wrote: On 05/31/2017 02:51 PM, James Richters wrote: I was doing some tests with Putpixel and that seems to be a word in the format of RGBA with 4 bits each.I would think putimage would use the same format, but I haven't tested that yet. I'm still a bit confused by putimage, since it only has an X and Y startpoint, how do you define the height and width of the bitmap? Getimage() specifies a rectangle, and imagesize() figures out how much memory you need, but I just don't what defines the size and shape of the image to putimage. The structure, used by putimage is as follows: 3 longints (12 bytes): - image width - image height - reserved followed by width*height 16-bit words. If you're a using a 16-bit color mode (that's the highest supported - it's a limitation of the graph unit include files, which ptcgraph reuses from the fpc sources), the color format is rgb565. Nikolay ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal { This is a console application demo. It uses the Agg2D object, which has a much friendlier API, to do all the drawing. The drawing buffer is then displayed in a window using ptcgraph and 16 bit RGB565 color format. Requires modification of Agg2D object constructor to use the 16 bit RGB565 color format. Uses a GraphBitmapBuffer type that includes contains the width and height of the image per the info at this URL: http://pascal.net.ru/PutImage+(en) [...] "BitMap is an untyped parameter that contains the height and width of the region, and the bit image that will be put onto the screen." [...] } program console_aggpas_2; {$mode objfpc}{$H+} uses ptcgraph, ptccrt, agg_2D, agg_basics; const IMAGE_WIDTH = 800; IMAGE_HEIGHT = 600; RGBA_WIDTH =2; //16bit 565 format LINE_COUNT = 30; {$IFDEF Unix} FontFile = '../../arial.ttf'; {$ENDIF} {$IFDEF Windows} FontFile = 'Arial'; {$ENDIF} type TGraphBitmapBuffer=packed record width, height: longint; data: array[0..2*IMAGE_WIDTH*IMAGE_HEIGHT-1] of byte; end; var gd,gm : smallint; graph_buffer: TGraphBitmapBuffer; procedure DrawStuff(agg: Agg2D_ptr); var i: Integer; x, y, px, py, d: Double; c1, c2: Color; begin // draw a full screen graph with grid agg^.clearAll(0, 0, 0); agg^.lineColor(0, 0, 0, 255); agg^.lineWidth(3); agg^.rectangle(0, 0, IMAGE_WIDTH, IMAGE_HEIGHT); agg^.lineWidth(1); agg^.lineColor(0, 155, 0, 255); agg^.rectangle(10, 10, 50, 50); // agg^.font(fontfile, 16); d := IMAGE_WIDTH / LINE_COUNT; agg^.lineColor(0, 0, 0, 100); agg^.lineWidth(1); for i := 1 to LINE_COUNT - 1 do begin x := i * d; agg^.line(x, 0, x, IMAGE_HEIGHT); end; for i := 1 to trunc(IMAGE_HEIGHT / d) do begin y := i * d; agg^.line(0, y, IMAGE_WIDTH, y); end; x := 0; y := IMAGE_HEIGHT / 2; px := x; py := y; agg^.lineColor(255, 0, 0, 200); agg^.fillColor(0, 0, 0, 200); agg^.lineWidth(1); for i := 0 to LINE_COUNT - 1 do begin x := x + d; y := y + Random(Round(IMAGE_HEIGHT / 3)) - IMAGE_HEIGHT / 6; if y < 0 then y := IMAGE_HEIGHT / 6; if y >= IMAGE_HEIGHT then y := IMAGE_HEIGHT - IMAGE_HEIGHT / 6; agg^.line(px, py, x, y); //agg^.text(x, y, char_ptr(IntToStr(i) + ' point')); px := x; py := y; end; // Star shape agg^.LineCap(CapRound); agg^.LineWidth(5); agg^.LineColor($32 ,$cd ,$32 ); c1.Construct(0, 0 , 255, 200); c2.Construct(0, 0, 255, 50); agg^.FillLinearGradient(100, 100, 150, 150, c1, c2); agg^.Star(100 ,150 ,30 ,70 ,55 ,5 ); // Draw Arc from 45 degrees to 270 degrees agg^.LineColor($4C, $6C, $9C); agg^.LineWidth(5 ); agg^.Arc(300 ,320 ,80 ,50 ,Deg2Rad(45 ) ,Deg2Rad(270 ) ); end; procedure DrawAndDisplay; var agg: Agg2D_ptr; begin //agg draw New(agg, Construct); agg^.attach(@graph_buffer.data, IMAGE_WIDTH, IMAGE_HEIGHT, -(IMAGE_WIDTH * RGBA_WIDTH)); DrawStuff(agg); Dispose(agg, Destruct); // not necessary to keep it after rendering is finished //display on ptc surface graph_buffer.width:=IMAGE_WIDTH; graph_buffer.height:=IMAGE_HEIGHT; ptcgraph.PutImage(0,0,graph_buffer,NormalPut); ptcgraph.Rectangle(10,10,100,100); ptcgraph.PieSlice(100,100,0,25,30); ptcgraph.OutTextXY(80,80,'It works!'); end; begin gd:=d16Bit; gm:=m800x600; //Windowtitle:='ptcgraph'; ptcgraph.Initgraph(gd,gm,''); Randomize; DrawAndDisplay; ReadKey; end. ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org
Re: [fpc-pascal] Implementing AggPas with PtcGraph
Have a look at the agg_2D unit. The agg_2D uses .. agg_pixfmt , agg_pixfmt_rgba , .. Therefore, the rgba format is pretty much baked in. That is to say that the constructor of the main object Agg2D uses the pixfmt_rgba32 to set the pixel format. ... { CONSTRUCT } constructor Agg2D.Construct; begin m_rbuf.Construct; pixfmt_rgba32 (m_pixFormat ,@m_rbuf ); pixfmt_custom_blend_rgba(m_pixFormatComp ,@m_rbuf ,@comp_op_adaptor_rgba ,rgba_order ); pixfmt_rgba32 (m_pixFormatPre ,@m_rbuf ); pixfmt_custom_blend_rgba(m_pixFormatCompPre ,@m_rbuf ,@comp_op_adaptor_rgba ,rgba_order ); ... There is another agg unit agg_pixfmt_rgb_packed that seem to have the 565 format that you need. Add it to the uses list and try to replace the pixfmt_rgba32 calls with pixfmt_rgb565. That will make agg use that format. The pixfmt_custom_blend_rgba calls may need further hacking too to make things work, however, Agg2D should use a 16 bit format if you use pixfmt_rgb565 callse instead of pixfmt_rgba32. You should also set RGBA_Width =2; in your program to reflect the change. Anyway, this will probably still not make ptcgraph.putimage(0,0,buf[0],0); work, but that may be a ptcgraph problem. Hope this helps, Stefan On 05/31/2017 02:57 PM, James Richters wrote: And AggPas already has support for that pixel format How do I define that as the format I want? I've been looking all through the example and do not see how this is defined. I've attached a test program, it's basically Graeme's sample but going to screen instead of a file. I just don't see where the pixel format is defined. I have it kind of working in a funny way by just forcing the existing pixels to conform to the required format. -Original Message- From: fpc-pascal [mailto:fpc-pascal-boun...@lists.freepascal.org] On Behalf Of Graeme Geldenhuys Sent: Wednesday, May 31, 2017 1:17 PM To: fpc-pascal@lists.freepascal.org Subject: Re: [fpc-pascal] Implementing AggPas with PtcGraph On 2017-05-31 18:03, Reimar Grabowski wrote: I'm not sure what that's called RGB565, maybe? And AggPas already has support for that pixel format. Regards, Graeme ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal