Jump to content

David Schwartz

  • Content Count

  • Joined

  • Last visited

  • Days Won


Everything posted by David Schwartz

  1. David Schwartz

    Delphi PAServer arm RPi compilation

    Check out TMS Software. They built an RPi app over Christmas and made an extensive case study of it. https://www.tmssoftware.com/site/blog.asp?post=872
  2. David Schwartz

    New Delphi job opportunity

    I know, it's very odd to me as well. When I graduated from college I got hired by Intel. They tended to hire EEs; my degree was in math / computer science. Everything I worked with there was proprietary. I got caught up in their first layoff 5-1/2 years later. Looking for what was next, people kept telling me, "Well, you've got a CS degree ... you can learn anything pretty quickly, right?" I ended up getting hired at a Motorola division and they wanted me to learn C and Unix. C++ was just coming to the fore as well. After the world didn't come to an end on Jan 1, 2000 (Y2K) the market was flooded with about one million excess programmers, most of whom were here on H-1B visas. That changed the entire complexion of hiring practices across the software and IT industry. Jobs that used to get 5-10 job applicants were now getting hundreds. Executive Recruiters who used to have the ear of hiring managers disappeared, and everything was moved to automated systems. Job descriptions became more standardized and HR people didn't really have any clue what any given job entailed. People learned they could "keyword stuff" their resumes to improve their chances of getting a call-back, if not an interview, whether they knew what the jobs were or not. Things have devolved to the point where it hardly matters what your educational background is -- if you don't have 3-5 years immediate experience with whatever platform or stack a project is using, they won't consider you. Nobody wants to pay for on-the-job training any more. I was at the event when Delphi was announced in 1995 and got a free copy of it. I started playing with it and was quite amazed. Unlike VB, you could build Delphi extensions (components) in Delphi itself, you didn't need to use another language. And unlike VB and other things where all "extensions" were DLLs, Delphi's components could be linked into the EXE as normal library code, so there was no run-time penalty to use them. Over the next 5 years, I switched my focus from C++ to Delphi, mainly because Delphi was so much easier to work with, especially for UI-based apps. Since 2005, I've had a bunch of different roles that I got mainly because of my Delphi expertise. Every one of them had fairly complex systems that took many months to learn and were in application domains that were new to me and had very little in common other than they were all built in Delphi. Most of them were, in the words of one colleague, "keeping a comatose patient alive until the new system was built", usually that meant "porting" it over to C#/.NET. I never saw any of those "ports" get completed. The last place I was at, I kept hearing people at all levels of the organization say things like, "Well, you're the Delphi expert, so you understand how all of this stuff works, right?" (IOW, since I knew Windows, I obviously must also know how ALL Windows apps work.) This was an incredibly complex system and it took most of a year to start making sense to me. A guy they hired 8 months after I'd started didn't know much about Delphi but had 10 years of app domain experience, and he was able to come up to speed much faster than I did because of his extensive domain expertise. I discovered that the entire (Delphi) dev team quit in 2011, although very little had changed since 2009. My first day on the job I was told, "Do not touch ANY of the code!" It has always struck me as odd that hiring managers seem to think there's more relevance in knowing a given programming language / platform versus an application domain. The app domains are usually far more complicated and take a lot longer to learn than a new programming language / platform. I mean ... at some point programming is programming. Every imperative programming language is pretty much the same, and they all tend to have the same structure, so learning one more isn't a big deal. (Actually, they're all easy to read; writing new code takes a little more time.) I'm semi-retired now so I don't have to deal with this crap any more. I can do what I want with my time now.
  3. D10.4.2: I've been getting a lot of instances lately with the IDE locking up when I opened a Debug Inspector window and tried to adjust the divider after making the window wider. All I can do is kill Delphi then restart it. It's not what I would call "reproducible" although it does sometimes happen repeatedly on the same variable a few times.
  4. David Schwartz

    IDE locks up on Debug instpectors

    Maintenance fees seem to pay for more useless features in future releases, not ensuring previous releases get bugs fixed. I'm done playing that game. If it wasn't for all the corporate licenses that get automatically renewed every year even when they're using much older versions for their production needs, we might see bug fix releases for older versions.
  5. David Schwartz

    IDE locks up on Debug instpectors

    Nope. It has been happening in 10.4.2 and 10.4.3. I have not upgrade my Delphi to 11 yet so I can't tell you about that.
  6. David Schwartz

    how to go to a specific time in a video

    Suppose you have a video and a list of times that identify where specific words or topics appear. (Here is an example of what YouTube generates when it transcribes a video you post) I'd like to basically import this data into a ListView with 2 cols (time, text), allow it to be filtered, then click on a line and have the video start playing at the time indicated. I'm curious what options are available to do that. I'm sure there are several, but I've never done anything to control videos other than just PLAY, PAUSE, and STOP.
  7. David Schwartz

    how to go to a specific time in a video

    Sorry, I was referring to using the VCL's embedded media player to play local video files. (Does it let you play videos on other sites via URLs?)
  8. David Schwartz

    tabbed video player ?

    I've got a bunch of live performance videos (> 1hr) open in QuickTime Player on one of my Mac's desktops (Spaces). I typically just select one and start it playing. But I'm thinking it would be nice to have a tabbed interface with a tab for each video; or maybe just one tab with a listbox + a list of flienames and Titles that you can select to play, then flip it to a player tab to play it. If you were going to build a simple video player app this, what would you use for the player component? I'm mainly interested in something that runs on a Mac. I know there's TMediaPlayer, but I think it's for Windows only. FMX has one I imagine (I don't do much with FMX). TMS has some options, including FNC and WebCore I believe. Maybe something already exists? (I did a bit of Google searching, but didn't find anything but a lot of requests for such a tool.)
  9. CONTEXT: (this is an analogy to make it easier to explain) A class has a bunch of students. You keep their scores on a variety of required and optional assignments. Each one has a record with their name and a few scores in different categories. <name>, <score#1>, <score#2>, <score#3>, <score#4> I want to create a TListView that has one <name> line per student, and each column has a TOTAL of the scores for that column in all records with the same name. Some may only have one <name> record, and some might have 10, and any number in between. It's rather clumsy to use the columns themselves to do the math (they're strings), so I made this object TSnapTally, to carry some integer fields that's attached to the .Data property where I update the numbers then update the line in the LV. I'm having some problems with the TSnapTally instances either getting freed multiple times or NOT being freed (seems to be mostly the former). So I defined an interface ISnapTally and derived class TSnapTally and I wanted to attach the interfaced object to the .Data property so that later on I can simply assign NIL to .Data and let the interface deal with deleting the instances. In this code snippet, I'm looping over the contents of a TListview to see if the string deets[n] is in the LV's Caption column; if so, it assigns that TListItem to 'li' and also returns it. If not, li and returned value = NIL. The first time it sees this name and it's not in the list, it adds a new item to the LV, sets the caption and four subitems, then assigns the newly created snap_tally to the .Data property. Then I call TallyToListItem with the list item (li) that was either just created or already existed in the LV. Here's the problem: At the top of TallyToListItem, it blows up when I assign li.Data to 'st' (of type ISnapTally). I don't understand why. It works fine if I use TSnapTally rather than ISnapTally. This is Delphi 10.4.2, and li.Data is typed as a POINTER. Can you not assign an Interfaced object instance to a POINTER? Maybe there's a better way to do this; I'm certainly open to suggestions. if not Assigned( ARDomainsLV_ItemWithCaption( deets[n], li ) ) then begin var snap_tally : ISnapTally; snap_tally := TSnapTally.Create( aSnap ); li := AnalysisResultsDomains_lview.Items.Add; li.Caption := deets[n]; li.SubItems.Add( '' ); // #detail recs li.SubItems.Add( '' ); // LM (1,2,3) li.SubItems.Add( '' ); // Org 1-10 li.SubItems.Add( '' ); // Org 11-20 li.Data := snap_tally; // TSnapTally end; TallyToListItem( li, dom_deets, aSnap ); . . . procedure TallyToListItem( li : TListItem; aDomDeets : TDomainDetails; aSnap : TLSHMSnapshot ); var st : ISnapTally; begin st := TSnapTally( li.Data ); <-- Blows up here st.IncNumDetailRecs;
  10. David Schwartz

    Virus? How odd.

    I gave up trying to send these files via email ages ago. Most MTAs have squeezed down the size of attachments they'll deliver to 25MB, which even makes sending PPTs and some PDFs dicey. Most places I've worked really crank down on this stuff, and insist everything be sent using links to things in SharePoint or version control. Personally, I use Dropbox to host files and send links to folders or files there. Some places block Dropbox, some block all outside URLs. So you finagle the text so it doesn't recognize it as a URL. Curiously, a lot of places I've worked at that have ridiculously tight security have no problem letting you access Dropbox directly in your browser, and some even allow you to run the Dropbox app on the computer.
  11. David Schwartz

    What is this IDE feature called?

    It seems to rely on the same logic that the refactoring uses, and the inline var declarations break both of them. Try looking at a unit with no inline var declarations and see if it looks more useful. It's useless in 10.4.2, along with most Refactoring functions.
  12. David Schwartz

    simple SFTP-like server for Windows?

    Anybody know of any simple SFTP-like servers I can run on a windows server to avoid having to deal with the built-in Windows crap? I just want a simple way to push files from my dev machine to a host running a service. Setting them up in Explorer gives Windows fits ... I don't know how many times it has to download every file just to display the directory! But it seems to go out to lunch for several minutes and freeze up the entire frigging desktop and the RDP itself. Something like Dropbox would be perfect. I just don't want to install Dropbox there b/c I only want it to mirror one single small folder, not my entire Dropbox. I have a list of files and I want to click a button and they'll be sent up to a folder on this other machine completely in the background, nothing on either end will freeze-up or even know something is going on. They'll just pop out the other end a minute or so later. Any ideas what might work?
  13. David Schwartz

    simple SFTP-like server for Windows?

    This is perfect for what I'm looking for. It's secure and there are lots of help videos on YouTube. HFS looks interesting, but the lack of secure connections bothers me. Also, I tried to build it and there are all sorts of components that need to be installed but I didn't see them documented anywhere. Not fun. I'm going with SyncThing.
  14. David Schwartz

    best way to structure an application

    TMS Web Update https://www.tmssoftware.com/site/wupdate.asp
  15. David Schwartz

    Delphi on Windows 11 on MacBook Pro 16 (2021)

    I'm still getting used to Win 10 after being pretty much forced to give up Win 7. Win 11 is not even on the horizon for me yet. I'm using Delphi 10.4.2 and even though my maint subscription expired, I wouldn't bother with D11 because there are still too many bugs in 10.4.2 IDE that haven't been fixed in D11 and nothing that seems worth the bother of upgrading. My main computer right now is a Late 2018 Mac Mini with 6-core i7, 36 GB of RAM, and 2TB of SSD. The only thing it's slow at is rendering long videos on Camtasia. 🙂 It's faster than any other computer anybody has ever given me to work on! When Apple introduces a Mac Mini with an M2 Max, I might upgrade. But it bugs me that it's not possible to upgrade the RAM and/or SSD yourself any more. Apple charges WAY too much for them. The biggest problem is not Delphi or the VM, but the fricking browsers. They seem to fragment the crap out of the system's memory and it just slows down to the point where it reboots itself after a month or so. For what I do, a faster CPU would not make much of a difference to me. But for really huge projects, I can see how it might shorten compile times a bit. One tip I have for anybody using VMs for stuff like this: they tend to grow. And grow. And GROW. Mine are pushing 125 GB now and take forever to backup to spinning HDs. (I exclude the VM folder from Time Machine.) I do periodically copy them to the backup drive by hand. It bugs me that there's no easy way to do a diff back up of them, because they'd be awfully small diffs. I also make periodic backups to a Samsung T5 1TB USB drive. You can get the T7's now that are twice as fast as the T5's. It takes about 5 mins to copy the VM to the T5. I expect the T7 would take half that. (It doesn't make much sense to pay for a super-fast box then have to wait 30+ minutes to copy your VM in or out!) That's my tip: get a Samsung T7 1TB USB 3.2 Gen 2 device to back up your VMs to. Also, if you get one or two T7's, you can probably get by with just 256GB of SSD and plug one of the T7's in and use it as a backing store while keeping your currently active files on-board.
  16. David Schwartz

    Interface question

    Uwe, I've been meaning to thank you for this. Not for anything related to the Interface, per se, but it solves a problem I've encountered many times in the past dealing with the fact that these TListItem.Data members are Pointers rather than Objects, and they get gnarly to deal with because you constantly have to cast them. Sometimes I cast them improperly and sometimes they get deleted or orphaned unintentionally. Here just pretend that ISnapTally is really TSnapTally, and that's really just some type <T> that I happen to be working with. In this case, I thought creating an interface would make managing the Data members easier, but it didn't. What I ended up doing was creating a TListItemHelper class that has three different "overlays" for the Data member depending on context. (Different ListViews save different objects in their Data members. Since you can only have one helper per class, I just put support for all three types into the helper, since the TListItem is unrelated to the ListView that's holding the data. I mean, I could derive different ListViews but the TListItem is the same for all of them; it isn't easily subclassed to override the type of the Data element depending on the ListView. So while this is not a very elegant solution, it's simple and it works nicely.) However, what I did to solve the persistency issues was I created a separate TList<TSnapTally> and called it SnapTallyBag. Then modified the Set and Get to work indirectly by saving the index into the list as the value of the Data item, rather than a pointer to the item itself. I simply add stuff to the bag, doing a test for existing instances so there are no duplicates. And I never delete anything until I get to a point where I need to clear the ListView, then I just flush the contents of the bag. When the form closes, if it's not empty, then I flush it at that point as well. It just never occurred to me to use a class helper this way. So that's what I got from this, and it was far more helpful than the Interface hack. 🙂 In fact, I ended up ditching the use of the Interface, and all of the other issues I was having disappeared with this approach.
  17. David Schwartz

    simple SFTP-like server for Windows?

    This looks very interesting.
  18. sometimes the test routines to check that my own memory is still working go a little haywire....
  19. I don't throw away dollars to save pennies. That is to say, I value my time more than the cost of computer memory and CPU cycles, because the value of my time keeps going up while the cost of memory and CPU cycles drops much faster.
  20. I'm really not sure what to make of this because you have to declare these things somewhere, right? Putting them in a DataModule is one option, of many. There is no "bloat" if there are no components other than two lines in the DFM: object TmyDataModule end nothing else is stored in the DFM, and there's no more code required than you'd have if you understood the proper role of "encapsulation" in OOP design. Which explains why you obsessively prefer the use of records over classes -- so you don't have to bother with calling Create or Free or dealing with any sort of memory management. Which is to say, you make them all global variable to avoid "bloat". That's NOT proper OOP design! But yes, it certainly is another option. Just for the record, the point you're trying to make is that one should avoid the use of proper OOP design techniques in a full OOP language simply to avoid unavoidable "bloat" that comes with using an OOP language. There are people who claim you can do everything in C that you can do in C++ without the supposed "overhead". Then they proceed to write code that has 5x the SLOC as the equivalent C++ code would have, is harder to maintain, has a similar memory footprint, and benchmarks within a few percent of the other. Only it took a lot longer to write and costs more to maintain. This is the thing that opponents of OOP don't understand: the faster computers get, the less that alleged "bloat" actually costs. That is, bloat costs less and less every year. But the cost of programming and maintenance just keep going UP and UP! So sticking with programming methods that forsake programming and maintenance costs in favor of reducing "bloat" is a fool's errand -- you're constantly increasing your budget, spending more to save less over time. And that is a choice you have as well.
  21. Just more of the same debate about how many angels can dance on the head of a pin, and the debate either devolves into what the angels are wearing or how big the head of the pin is. If you don't like using properties, don't use them. It's that simple. If you think having functions called by a property adds more overhead than calling a function yourself (as if that's a big deal) then just put "inline" after the function declaration. If you'd rather have longer, more descriptive names, then just give them longer more descriptive names: property GetThisViaRESTService : integer read gtvrs; I find far more advantage to using properties than not using them. And for every (infrequent) instance where there's a limitation, it's easy to get around it. I only wish it were easier to type in a bunch of property declarations that follow a simple pattern: a popup box that asks for the property name, its type, checkbox for read and write and whether they're a local var or a method. Is there anything that simple that doesn't require me to install a huge amount of other stuff at the same time? The most frequent problem I have is when I try to pass one into a var or out parameter in a method call. Thankfully those are not very common.
  22. David Schwartz

    The Curiously Recurring Generic Pattern

    You're saying this is simpler than saying something like: var TAddressList = TList<TAddress>; // or var TAddressList = TList<TEyObjectList>; I don't understand the last paragraph at all. What are you referring to?
  23. I don't see multi-threading as a solution for reducing the complexity of having too many global variables. I imagine it just creates more complexity. Also, I don't say this to be critical, but you don't seem to understand OOP. There are a LOT of programmers who don't. And that's fine. Delphi's language is called "Object Pascal" to differentiate it from original Pascal that was more like 'C'. The Delphi IDE generates forms that are all objects and a 'main' procedure that's used to create everything. The entire Visual Control Library (VCL) as well as FireMonkey (FMX) is based around objects. The component libraries are all objects. Everything in Delphi is oriented around objects. If there are a bunch of global variables in a Delphi form unit, that means that whomever wrote it was probably not skilled with OOP. You should probably refactor the code to get all of those global vars into classes, along with all of the methods that read and write to them. It's not entirely straightforward, but a lot of it is. There's a free book available that teaches a lot of this basic OOP stuff. Object Pascal Handbook by Marco Cantu If you login to your Embarcadero Code Central portal, it's hiding there somewhere as a free download. I also found this link: http://forms.embarcadero.com/DownloadMarcoCantueBook
  24. I think that if Delphi was created today, the DFM file would be a JSON file. Since you're familiar with JSON, you know that if there's nothing in it, it's very small. The format used by DFM files is like JSON only simpler. DFM files are used to save property values defined in the Object Inspector at design time for a given form or DFM. If there are no components on the form or DM canvas, then the DFM file is basically empty. Also, since it's managed the same way as any other form in Delphi, you have the same degree of control of when they're created. By default, they're created automatically. But you can right-click on your project, select Options... then Forms and move it to the right-hand column which represents all of the forms and DMs that you do NOT want to be created automatically. A simpler way is to just right-click on the project, select View Source, and delete the line where a form or DM is created, then save it. In your code, simply call Create where you want an instance and save the reference in a variable somewhere. You can use the one that's emitted in the file by default (a global var in the unit), or you can use any other variable. You can also call it multiple times to create multiple instances. When you're done, just just Free them. I'm sorry for so many words, but I take a lot of words to explain stuff because it seems a lot of people cannot read between the lines of one-line answers. Since I have taken so many words to explain this, I hope you'll actually try it out and see that what I said earlier is correct.
  25. Yeah, I caught the "... and so on" part. That's where you wave your hands to refer to everything that happens when you push the button to launch the space shuttle, right? It does not matter what kind of bucket or box or container you put global variables into -- they're still defined at the global level, and they do not belong there. A Data Module is simply a class, which is a container just like records. It's referenced by the global instance var that every auto-created form in Delphi has, and there's usually just one of them. You can put anything into it that you want because, as I said, it's just a class. If one is senseless to use as a container, then the other is equally senseless for the same reasons. It's not worth arguing about or defending. You are free to have a preference for records over classes, and forms over data modules. It doesn't matter. They're all containers available to Delphi programmers and mostly interchangeable. Encapsulation in OOP terms is a way of creating abstractions around collections of related data and methods. Classes are an abstraction mechanism that lets you encapsulate state and model related behaviors that maintain the state, all in a single "object". Forms and Data Modules are both classes. Records are very similar only they have "pass by value" semantics rather than "pass by reference", so local instances usually take up a LOT of space on the stack. You also need to manage dynamic instances of them wtih additional syntactical decorations. I'm not talking about your personal preferences here, I'm talking about basic OOP principles, and particularly encapsulation. Because that's what the OP asked for help with.