Hacker Public Radio

Follow Hacker Public Radio
Share on
Copy link to clipboard

Hacker Public Radio is an podcast that releases shows every weekday Monday through Friday. Our shows are produced by the community (you) and can be on any topic that are of interest to hackers and hobbyists.

feedback@NOSPAM-hackerpublicradio.org (HPR Feedback)


    • Oct 1, 2026 LATEST EPISODE
    • weekdays NEW EPISODES
    • 1,507 EPISODES


    Search for episodes from Hacker Public Radio with a specific topic:

    Latest episodes from Hacker Public Radio

    HPR4739: Happy by shower # 3

    Play Episode Listen Later Oct 1, 2026


    This show has been flagged as Explicit by the host. We focused, until now, on things external as examples. Let's proceed to internal. Before, I want to note that any of these is a formula. It's not like we can repeat a past experience we ourselves or someone lived, and feel the same thing. It's not a guarantee, and not even the idea in sharing. It's only this: to share and to provoke reflection. I was abused as a child. Hard as it is, and unerasarable, also hard was to tell someone important and do not be trusted. Child abuse is associated with multiple disorders further in life. Remembering what I passed is a relief in what gives respect to where I am now. Not to authorize me to feel anger, or as a free pass to throw everything to the air without feeling guilty — that would make something, but not good after all —, but to recognize better what is real and what is important now, and that's much more relevant, and influential to my being in the world, than that past experience. Coincidences sometimes make me “wow”. When I ask, and even when I don't directly ask, specific direction in choices, or in what to trust, it's not rare to receive something that I see as very clear. Even when it comes as a reproach, remembering me about what I should and could be doing, but am not because of many excuses, even then, I'm still impressed, and feeling loved, because someone cares specifically – about – me . In general, remembering something that gave me a bad taste when thinking about before, and then, as of now, feeling differently about that event, gives me a sense of maturity. Like, what a child I was to pay so much attention to this, or to that, and now those things, unimportant as they are, don't matter any more. I find myself trying to remember a word, or a concept or memorized Bible verse. Sometimes I forget, and then I go to a chain of thoughts about and end up remembering, or forget about and it comes to mind minutes or hours later. Those are “aha!” moments, as discovering something, very beautiful, for the first time. Some people have a wrong notion of memory, as if it was created once and evoked latter. No, every moment one evokes a piece of information, he is reworking that piece, and every experience after the creation of the memory potentially affects that bit of information we call a part of the memory. It's not static, it's dynamic. And so it's not objective, is it? Yeah, that's it. Thank you and bye bye. Provide feedback on this episode.

    HPR4738: Programmable Logic Controls - Episode 4

    Play Episode Listen Later Sep 30, 2026


    This show has been flagged as Clean by the host. -------------------- 01 Introduction This is the fourth episode in an 8 part series. 02 In the previous episode we looked at the Allen Bradley PLC2, one of the very early successful Programmable Logic Controllers. In this episode we will look at another early PLC, the Siemens S5 series, and use it as an example of both how PLCs became more sophisticated, as well as an example of a different approach to the overall software architecture. Again, I will only touch on this topic lightly, this is not a course on how to program PLCs. However, I will give you enough technical detail to give you are rough idea of what they were like. -------------------- 03 S5 Historical Background Siemens are the largest PLC vendor on a global basis, and have been since the early days. Their first PLC was the S3, released in 1975, two years before Allen Bradley released the PLC2. There seems to be almost no information available on the S3, so I can't say much about it. In 1978 or 1979, sources are unclear about the exact date, Siemens released the S5 series. This was a huge step forward in capability and was the foundation of their PLC product line until replaced by the S7 series in the mid 1990s. In this episode I will focus on the U series, which were an upgrade to the original S5. -------------------- 04 A Complete Family of PLCs Fully developed, the Siemens S5 series was a complete family of products covering the entire size spectrum from smallest to largest. Siemens covered the entire industrial control market, and there was almost nothing they didn't have somewhere in their catalogue. You could spend an entire career using nothing but Siemens products for everything. 05 At the lowest end were the S5-100 series, consisting of the S5-100, 102, 103, 90, and 95. These covered everything from the small "shoebox" all in one form factor to ones which overlapped the mid range in terms of capability except for their compact I/O cards which were smaller and slower than the full size models. The S5-115 formed the mid range, coming in a "full size" form factor in terms of packaging and rack size. The S5-135 and S5-155 extended the S5-115 in terms of speed and memory. 06 In this episode I will focus on the lower end S5-100 series for the sake of simplicity, and will not make any reference to any additional capabilities of the larger models. It will be much too time consuming and confusing to try to cover everything, and there wouldn't be much point to it. -------------------- 07 Data Memory Types If you recall the previous episode, the Allen Bradley PLC2 had a data table, or memory system, that was a single linear range of memory with all I/O and internal capabilities mapped into fixed numerical addresses. Allen Bradley were to abandon this approach in their later PLC5 series introduced in the mid to late 1980s, but we won't cover that here. The Siemens S5 series however took the approach of having different types of memory addresses for different purposes. I will describe those for the S5-100 series now. 08 Input and Output Addresses The standard I/O modules for these compact PLCs had 8 inputs or 8 outputs per I/O module. These module plugged into a flat bus (as opposed to an enclosed rack) with slots numbered from 0 through 31 in decimal. Each of these slots had an associated byte number, and each I/O point on the individual modules had a bit number. 09 Input and output addresses had the following format. Letter , number, decimal point, number. The letter was either I or Q. I indicated inputs. Q indicated outputs. The first number was the byte number, which corresponded to the physical I/O module slot. The second number was the bit number within the byte, starting from zero. 10 So "I2.3" indicated an input module located in the third slot (numbered from zero) and addressed the fourth input (numbered from zero) on that module. Outputs worked the same way. For example "Q 5.1" 11 Analogue modules could be located slots 0 through 7. Analogue if you recall, refers to voltages which have varying levels rather than just on or off, and can represent things like temperature. Each analogue module was assigned 8 bytes per slot, starting at address 64 and going up to 127. In practice many of these so called "analogue" modules had nothing to do with actual analogue voltages, but rather any advanced module which needed more address space was used here. Even later high density digital I/O used these addresses. 12 Each of these addresses could be addressed as bytes or words. In this case input bytes were indicated by an "IB" prefix, and input words were indicated by a "IW" prefix. Output bytes used a "QB" prefix and output words used a "QW" prefix. 13 Flags Flags are individual bits of internal memory that are used for storing intermediate logic values. These began with an "F" prefix. An S5-103 had a total of 2048, numbered from F0.0 to F255.7. 14 Counters Counters started with a "C" prefix. An S5-103 had 128 of these numbered from C0 to C127. 15 Timers Timers started with a "T" prefix. An S5-103 had 128 of these numbered from T0 to T127. 16 Data Blocks Programs needing to deal with byte and word memory could create what were known as "Data Blocks". These were blocks of PLC memory that could be created as the discretion of the programmer. An S5-103 could have a maximum of 254 data blocks numbered from DB2 to DB255. Two additional data blocks were reserved for the PLC's internal operations. Data blocks could contain up to 255 16 bit words. 17 However, the actual number and size of data blocks would in practice be limited by available memory. Even 20 kilo bytes was considered to be a large memory, and this had to be shared with the program. A data block would be "called" to make it the current data block. Then individual words would be addressed with the "DW" prefix. For example "DW5". -------------------- 18 Program Blocks If you recall with the PLC2, there was a "main" program and a series of optional numbered subroutines. In the S5, programs were split into "blocks". These were Organization Blocks Program Blocks Function Blocks Sequence Blocks An S5-103 could have up to 256 of each of these blocks. 19 Organization Blocks When the PLC started up, it would look for Organization Block 1 and begin execution there. You could consider this to be the equivalent of the "main" function in a C program. Organization blocks had an OB prefix. For example OB1. With a very simple program in a very small S5 PLC, all of the program logic could be simply put in OB1. However, with larger programs , it was convention to put the logic in subroutines and simply have OB1 call each subroutine. 20 Program Blocks These had a PB prefix. For example PB10. Normal ladder logic style programming would go in these. It was convention to split up a program into pieces and put piece in its own program block. Normal practice was to have a program block correspond to a particular part of the machine. 21 Function Blocks These had an FB prefix. For example FB64. Function blocks differed from program blocks in that they could take parameters. This allowed you to write an FB that performed some sort of complex data transforms and re-use it by calling it with different parameters. Some instructions could only be used in FBs, not in other types of blocks. There were also built in FBs in some CPU models which performed certain operations such as converting BCD (or Binary Coded Decimal) to normal integer. 22 Sequence Blocks These has an SB prefix. For example, SB25. These were like PBs, but were intended for controlling sequences of operations where each SB performed as single step of the sequence and multiple blocks were used for a sequence. -------------------- 23 Programming Languages The S5 series offered four different programming languages. These were Ladder (abbreviated as LAD) Statement List (abbreviated as STL) Control System Flowchart (abbreviated as SCF) GRAPH 5 24 You should be familiar with ladder if you listened to previous episodes. Briefly however, it is a graphical programming language which followed the appearance of electrical ladder wiring diagrams which were familiar to engineers, technicians and electricians working with manufacturing equipment. 25 Statement List is a text based programming language which resembles an assembly language for an abstract processor architecture. Boolean logic results were calculated and saved on a stack, while integer values were operated on directly from memory or in two accumulators, ACCU1 and ACCU 2. 26 Control System Flowchart is a graphical language that takes the form of rectangular blocks with one or more inputs and an output. These blocks are laid out on a screen and then wired together rather like logic gates in a electronic schematic. 27 GRAPH 5 is Siemens' implementation of the GRAFCET (Graphe Fonctionnel de Commande Étapes Transitions) IEC 60848 flow chart standard. The IEC are the International Electrotechnical Commission, an international standards organization. 28 I will focus on Ladder and Statement List, as these were by far the most commonly used and we have limited time to discuss the S5. -------------------- 29 Statement List As mentioned above, Statement List can be thought of as the assembly language for an abstract CPU architecture. The firmware in the S5 PLC will run the instructions in an interpreter. 30 The RLO Boolean or bit oriented instructions operate on a logic stack known as the RLO, or Result of Logic Operation. Boolean operations typically take one operand. When a boolean operation is executed, if the RLO is empty it simply loads the operand onto the RLO. If the RLO is not empty, then the instruction is executed using the operand and the RLO, and the result replaces the value on the top of the RLO stack. Some boolean instructions do not take an operand, but rather work on the two topmost values on the RLO. If you are familiar with languages such as FORTH, this should sound very familiar. 31 The Accumulators Word oriented instructions work on two accumulators, ACCU 1 and ACCU 2. A load instruction will load a word or byte value from a memory location or a constant into ACCU 1. The value that was in ACCU 1 then gets shifted into ACCU 2. A transfer instruction will write the value in ACCU 1 to memory. The remaining word oriented instructions will operate on the values in ACCU 1 and ACCU 2, and place their result in ACCU 1, overwriting the existing contents. So for example, an add instruction will add the value in ACCU 2 to the value in ACCU 1, leaving the sum in ACCU 1. 32 Ladder As mentioned above, ladder is a graphical programming language which has the appearance of an electrical control ladder diagram as used with actual relays. The is by far the most common programming language used with PLCs. A ladder program however is just another way of presenting statement list. 33 To put it another way, a statement list program can be displayed on a computer screen as either lines of text, or a graphical symbols laid out in a meaningful pattern. All valid ladder programs can be represented as statement list. However, not all valid statement list sequences can be represented as ladder. Statement list is inherently more flexible than ladder, which means that you simply can't always translate both ways fully. 34 None the less, most typical control logic can be represented as ladder, and ladder is the preferred representation as it is quicker to understand at a glance when debugging a software or hardware problem. On the other hand, some statement list instructions have no ladder equivalent, or the algorithm may not lend itself to being represented in ladder. In these cases normal practice is to put the simple control logic in ladder in Program Blocks, and put the non-translatable statement list logic in Function Blocks. 35 Control System Flowchart and GRAPH 5 Like ladder, CSF and GRAPH 5 are actually implemented in statement list, and many of the considerations mentioned above apply to those as well. However, I won't go into any further detail on these here. -------------------- 36 Programming Software and Hardware There were two ways of entering a program into an S5 PLC. One way was the hand held programming terminal. The other was via the STEP 5 programming software. 37 Hand Held Terminal Like many if not most PLC vendors, Siemens sold a hand held programming terminal. There were a series of these, an example being the PG 605. This was a box like a large calculator which had buttons and a small display. The buttons corresponded to various instructions and a numeric keypad, and the display would show the current instruction being entered. To use it you would plug a cable attached to the hand held terminal into the programming port on the front of the PLC CPU module. You could then enter or view the program, one instruction at a time. 38 STEP 5 Programming Software The other way of programming was to use software running on a PC. Siemens called their software STEP 5. This was an integrated editing and debugging program. Originally it ran on CP/M. 39 Siemens sold their own portable PCs with the software preloaded, and with additional built in hardware features such as an EPROM burner. These computers were also known as "PGs". STEP 5 was later ported to MS-DOS by running it on a CP/M emulator which people would use to run it on an off the shelf PC such as a laptop. Later still a native MS-DOS port was produced. 40 This had modes for Statement List. Ladder, and Control System Flowchart. GRAPH 5 was a separate program. You could toggle between STL, LAD, and CSF modes, and if the software could translate what was there form one mode to another, it would. 41 The PC would be connected to the PLC by a cable which had an interface box in the middle. This could be used to download a program to the PLC, upload a program to take a backup, modify a running program, or debug a running program. -------------------- 42 Instructions I won't list all the instructions, as that would take too long. I will instead give a brief overview of them. I will deliberately skip over obscure instructions that would take too long to explain. 43 Basic Operations Boolean Operations There is a full set of boolean operations including and, and not, or, or not, set, reset, and assign. The assign operation would assign the RLO value to the address of the specified operand. 44 Load and Transfer The Load instruction would load the value of a memory address word or byte or a constant into accumulator 1. There are about 2 dozen variations on the load instruction. The transfer operation would write a word or byte from accumulator 1 into memory. There are about a dozen variations of the transfer operation. 45 Timers and Counters There are 5 different types of timers. Timers take the value in accumulator 1 as their preset when started. There are up counters and down counters, which count up and down respectively. Again, these take the value in accumulator 1 as the preset. 46 Arithmetic Operations The only native arithmetic operations in the S5-100U series are addition and subtraction. These add or subtract the values in accumulator 1 and 2. Another set of add instructions allows adding a constant. However, the 103 and 95 CPUs offered integer multiple and divide as integrated function blocks, FB242 and FB243. You would call these function blocks with the desired parameters and they would return their results in other parameters. 47 Comparison Operations There are a complete set of integer comparison operations which operate on the values in the two accumulators. These include greater than, greater than or equal to, etc. The boolean result is saved on the RLO. 48 Block Call and Return There is a complete set of unconditional and conditional call operations to call all of the various types of blocks. There are also unconditional and conditional return operations. Calling a data block makes it the current data block, for load and transfer operations on data words 49 NOP or No Op As implied these instructions have no result. 50 Stop This stops the program executing 51 Binary Word Operations These operate on words in the accumulators. These include AND, OR, XOR, Shift Left, and Shift Right. 52 Bit Operations These test, set, or reset individual bits in data words or in timers and counters. 53 Conversion Instructions There are instructions to perform one's complement or two's complement of the value in accumulator 1. 54 Jump Operations There are unconditional and conditional operations to jump forward or back to a label. This is equivalent to a GOTO operation. 55 Indirect Addressing or "DO" operations These instructions allow jumping to a block or selecting a data word or flag word according to a number stored in another address. Essentially, these instructions are like pointers. 56 Miscellaneous There are also various other instructions that do things like copy blocks of words, or swap the contents of the accumulators, 57 Other Instructions There are still more instructions which I have skipped over as it would take too much time to explain them. 58 Instruction Summary As you can see the S5 PLC offers a very comprehensive set of operations which go well beyond what most people would think of as what a PLC does. This is a very powerful instruction set. 59 On the one hand this is a good thing, as you can do nearly anything. On the other hand, this is a bad thing, as some people take this as license to do nearly anything. In the hands of the wrong person, this results in a complex mass of spaghetti code that not even the person who wrote it can figure out later. 60 This goes against the philosophy of PLC programming, which is to make things as simple and obvious as possible. With a PLC program, perfection is achieved not when it has as many advanced features as possible, but rather when it is not possible to make it any simpler. 61 While Siemens gave the programmer a range of powerful low level instructions from which he could construct nearly anything, many other vendors took a different approach. They instead studied what was needed in major market segments and provided the programmer with instructions that operated at a higher level of abstraction, allowing programs to be written in less time and with fewer instructions. -------------------- 62 Execution Speed Execution speed of instructions varied depending on the PLC CPU model. Here are some typical values for the low end S5-100 series CPUs. 63 A boolean AND instruction executed in 70 microseconds on a S5-100U, or in 4 microseconds on an S5-102U, or in 1.6 microseconds on an S5-103U. 64 Adding two words in the accumulators executed in 55 microseconds on a S5-100U, or in 23 microseconds on an S5-102U, or in 1.6 microseconds on an S5-103U. 65 The S5-103U had a custom logic coprocessor chip, known as the M5. Instructions that were executed on the M5 coprocessor tended to take a uniform 1.6 microseconds. However, complex instructions that were not executed on the M5 coprocessor were often slower than on CPUs that didn't have a coprocessor, such as the 100 or 102. I suspect this is due to some sort of overhead relating to coordination of the two processors. 66 However, most instructions in a normal program are boolean logic, so very fast boolean execution time is what matters. Since every instruction is executed every scan cycle, large programs require faster instruction execution in order to keep up with demand. -------------------- 67 The S7 Series Replaces the S5 In the mid 1990s, Siemens began introducing the S7 series which would ultimately replace the S5, although that took a number of years to happen. 68 The hardware was all new, but from a programmer's perspective, the S7 was an evolution of the S5. Some statement list instructions were dropped and others were added. Most of the basic concepts however remained the same. Porting an S5 program to an S7 was a complete re-write, but it was a fairly straightforward one. 69 The exception to this was the S7-200 series, which came into Siemens from the outside as part of their take over of of the PLC division of Texas Instruments. The S7-200 was an American knock off of a Japanese PLC and sold as a German product. It was none the less an excellent PLC and sold in very large numbers. The S7-200 was eventually replaced by something that was compatible with the rest of the S7 line 70 The S7 series has gone through a number of hardware revisions and remains Siemens' main PLC line today. It can via the S5 trace its lineage back to the 1970s and the early days of PLCs. -------------------- 71 Other Developments Japanese PLC Vendors I haven't covered any Japanese PLC vendors in the same way that I covered the PLC2 or S5. I had planned on doing another episode on one but I don't think it would really add much to what we have already discussed. However, PLCs from Japan are among the top sellers world wide and are generally very highly regarded. 72 Pace of Innovation In terms of general history across the industry, in the early days of PLCs evolution was fairly rapid. Later on, innovation slowed down as compatibility with the existing install base became a bigger factor. Technology has become fairly static, but that isn't necessarily a bad thing from a business perspective. I will return to this subject later however. -------------------- 73 Conclusion In this episode we covered the Siemens S5 series of PLCs. We covered the history of the S5, it memory and addressing, the different types of subroutines, programming languages, the instructions, and how it was succeeded by the S7 series. 74 We saw how PLCs had rapidly evolved from their very early relay-replacement origins to become powerful programmable devices. In the next episode we will look at I/O modules and how they allow a PLC CPU to interface to hardware and control machines. 75 This has been the fourth episode in an 8 part series. -------------------- Provide feedback on this episode.

    HPR4737: Keep spare parts for Ethernet run

    Play Episode Listen Later Sep 29, 2026


    This show has been flagged as Clean by the host. Quick show on what I used to run 25 feet of Ethernet cable Amazon Cable Matters 10Gbps Snagless Cat 6 Ethernet Cable, 25ft, Blue 24 AWG Bare Copper, Gold-Plated RJ45, PoE++, 550MHz Other supplies • 1/2 inch length of blue pex tubing from local hardware store Leftover from previous project • Electrical tape • Extendable pole which has a clamp and a trigger mechanism for use with wasp spray • Hyper Tough 3/4 inch Hex Shank Spade Drill Bit • Random Hyper Tough (maybe 3/8 inch) drill bit All purpose • White silicone sealant Reference hpr4654 :: What's in my component Box? Images First part of cable run, internet router side. Ethernet cable, with electrical tape to pex pipe. Extension pole with pex pipe attached by electrical tape. Angle cut on pex pipe. Taped pex pipe with cable, ready to feed to other side. Extension to other side of the mobile home. Success! Fed through the other side. 8 foot extension, suitable to hang an antenna. Silicone to seal the holes. Provide feedback on this episode.

    HPR4736: How to replace the battery in a car key fob

    Play Episode Listen Later Sep 28, 2026


    This show has been flagged as Clean by the host. Replacing battery Remove the emergency key Pry open the fob around the seam with a blunt knife or similar Note the polarity of the battery, ie which way up the battery is. Replace the battery and close. Emergency usage Use the emergency key to enter the car. Hold the key fob to the Start/Stop button Press the Start/Stop button Links https://en.wikipedia.org/wiki/Nissan_Micra#Fifth_generation_(K14;_2016) https://en.wikipedia.org/wiki/Button_cell https://en.wikipedia.org/wiki/Near-field_communication https://www.youtube.com/watch?v=IBP5EEm1oSI Provide feedback on this episode.

    HPR4735: hpr4715 :: friedcamp interviews part 5: Yvon Masyn

    Play Episode Listen Later Sep 25, 2026


    This show has been flagged as Clean by the host. https://www.instructables.com/member/masynmachien/ https://www.masynmachien.be/ https://www.instagram.com/masynmachien/ Provide feedback on this episode.

    HPR4734: HPR Beer Garden 20 - TuxJam Half-cut Special

    Play Episode Listen Later Sep 24, 2026


    This show has been flagged as Clean by the host. The usual trio of Dave , Kevie and Paul meet up for the first time in person and are joined by Al , Andrew , Joe and Rainy. The meet up was for the TuxJam Half-cut live event in Manchester. Rather than the usual style of show this is a (mostly) unedited recording of the beers that we are trying and general yarns around the table. We were interrupted by a yelling numpty, a middle-aged boy racer and a tram (these were edited out), but otherwise the recording is pretty much as is. The show was recorded outside the Sureshot Brewery Taproom . Connect with the guys on Untappd: Dave Paul Kevie The intro sounds for the show are used from: https://freesound.org/people/mixtus/sounds/329806/ https://freesound.org/people/j1987/sounds/123003/ https://freesound.org/people/greatsoundstube/sounds/628437/ Upcoming beers: Mild Bitter Pale Ale Provide feedback on this episode.

    HPR4733: Static Adict Episode 1: Pulse Demon

    Play Episode Listen Later Sep 23, 2026


    This show has been flagged as Explicit by the host. Sources (yes I used wikipedia, I am a hack, what else do you expect) https://en.wikipedia.org/wiki/Merzbow https://en.wikipedia.org/wiki/Pulse_Demon Band/Artist website https://merzbow.net/ Where to listen to or buy the album Original Release (stream) https://merzbow.bandcamp.com/album/pulse-demon Remaster Release (stream) https://merzbow.bandcamp.com/album/pulse-demon-remaster-reissue Link to buy a physical copy new https://www.relapse.com/products/merzbow-pulse-demon-reissue-2x12 Next album I'm reviewing, Lou Reed's Metal Machine Music https://tidal.com/album/50021Provide feedback on this episode.

    HPR4732: Webp

    Play Episode Listen Later Sep 22, 2026


    This show has been flagged as Clean by the host. Webp is meant to replace GIF, JPEG, and PNG. Its features include: Lossy compression Lossless compression Metadata, including Exchangeable Image File Format (EXIF) and Extensible Metadata Platform (XMP) Transparency (an "alpha channel") Embedded ICC (International Color Consortium) profile Multiple frames (animation) The typical expectation is to achieve equal or better visual quality as a JPEG or PNG or GIF, but with a savings of 25% to 35% on file size. This is famously difficult to measure, because if you concede to an equal file size, then the quality ought to be better, but there is a "ceiling" to quality that can be detected by the majority of human eyes. So the metric is the unmeasurable: How good does it look to you? If it looks as good or better, and the file size is smaller, then it can be said that the format is superiour. The best and most common test is to look at an image compressed with JPEG or PNG compression, and then look at the same image compressed by WEBP. If you can't tell the difference, and the file size of WEBP is smaller, then it's an improvement for disk space and bandwidth. WEBP is an 8-bit format (based on the VP8 video codec) and lacks support for 10-bit, 12-bit, or 16-bit colour. Specifically, WEBP is YUV420, where Y is Luma (brightness and darkness), and U and V are Chroma (colour). Each 8-bit pixel in the UV (Chroma) corresponds to a 2-by-2 block of 8-bit Luma pixels, or in other words, Chroma gets half the resolution of Luma. This is not uncommon, because how sharp an image appears to the human eye is mostly (not entirely, to be fair) influenced by Luma. Our eyes differentiate bright from dark better than our eyes perceive subtle shifts in hue. The ICCP chunk starts with a 4-byte declaration (the ASCII string "ICCP"), then a 32-bit integer representing the length of the payload, then the payload (the ICC profile specification according to the International Color Consortium), and then optionally a byte to pad the header. The embedded ICC profile can define any old colour space you want. If none is defined, sRGB is assumed. The libwebp library only parses the ICC profile, it doesn't actually handle conversion. That's left to the client application, which is why you might get a notice sometimes in GIMP or a similar application about a colour space mismatch. (It's generally safe to convert to your current colour space, and if it's not then you'd know it because you're working in a multimedia production house where colour spaces and colour profiles are significant.) Converting to WEBP is available in most applications, at this point, including Image Magick and the cwebp command. Image Magick: $ convert foo.tiff foo.webp Or using cwebp with -q for a quality 0 (low) to 100 (high), and -o for output: $ cwebp foo.tiff -q 60 -o foo.webp Test images are available from a Mozilla test suite. Or you can test on a Hacker Public Radio image, such as the screenshot of the upload form on the episode_show_notes page: $ wget https://hackerpublicradio.org/images/upload_form.png $ cwebp upload_form.png -q 50 -o upload_form.webp $ ls -gl -rw-r--r-- 1 users 308K Sep 16 13:56 upload_form.png -rw-r--r-- 1 users 79K Sep 16 13:57 upload_form.webp References Developers Google Salivity.github.io Mozilla Provide feedback on this episode.

    HPR4731: A Website Hacked

    Play Episode Listen Later Sep 21, 2026


    This show has been flagged as Clean by the host. [WP2Shell is] a pre-authentication RCE in WordPress Core . The attack has no preconditions and can be exploited by an anonymous user in a stock install of WordPress with no plugins. - from wp2shell.com Wordpress.org - https://en-gb.wordpress.org/ Searchlight WP2Shell Website - https://wp2shell.com/ CVE-2026-63030 - https://nvd.nist.gov/vuln/detail/CVE-2026-63030 CVE-2026-60137 - https://nvd.nist.gov/vuln/detail/CVE-2026-60137 OpenSSH - https://www.openssh.org/ FileZilla - https://filezilla-project.org/ GNU Tar - https://savannah.gnu.org/git/?group=tar GZip - https://www.gzip.org/ Provide feedback on this episode.

    HPR4730: Playing Civilization VI Part 1

    Play Episode Listen Later Sep 18, 2026


    This show has been flagged as Clean by the host. Civilization VI, made a number of changes, and one of the biggest was the introduction of Districts. Buildings that perviously would have just been part of the city now had to be built in special districts, and the game limited how many of them you could build in any one city. This forced you to make choices, and making choices is the heart of the Civilization series. Playing Civilization VI, Part 1 Districts As we have said before, the rule for each new version of Civilization is that 1/3 stays the same, 1/3 is tweaked, and 1/3 is new. So among things staying the same is the Hexagonal grid first introduced in Civ V, along with the usual roaming tribe in 4000BC. But the handling of terrain that a city can use has changed. The old Big Fat Cross was dropped in Civ V, and replaced with a large Hexagon. And how you use the terrain has changed. In older versions of Civilization, the terrain was mostly used for either farming or mining. It was all about resource extraction, in other words. All of the Buildings you constructed you could think of as abstract, or as all living in the City Center. The only reason you had for making different choices in the Build queue was if you didn't have enough time or resources to build everything. As a result, many cities looked very similar in what got built. You would put a Granary in each city to help it grow, a Barracks in each to build your troops, a Temple in each city to gather Faith, and so on. There wasn't much a decision here, or at least not enough to satisfy Ed Beach, the Chief Designer of Civ VI. So he came up with a new land use system involving Districts. With this system, you had to allocate land in your city for most things you would build. If you wanted to focus on Science, for instance, you would have to allocate a tile to a Campus district. Then, inside this district you could build a Library, a University, an Obervatory, and a Research Lab. But that is the only place they could be built. Furthermore, to prevent you from building every district, they limited the number of districts each city could have based on its population. You can always build one district with a new city, but to build another you need to get to a population of 4, and you get the ability to add a District with each additional increment of 3, so at Population 7, 10, 13 you get the ability to add a District. And these Districts have to be constructed as part of the normal city Build process. So in the above example, you would first have to build the Campus district, and when that was complete you could then build the Library to put inside it. And for both the Districts and the buildings inside of them you need to research certain technologies before they become available to you. Where to locate your districts becomes an issue as well. First of all, the tiles available to you are also your stock of tiles for building Farms and Mines, so you need to make choices here. Of course, making choices is the basis them of all Civilization games. Then there are the adjacency effects of terrain tiles. Both Campus (Science) and Holy Site (Faith) districts benefit from being adjacent to Mountains, and the adjacency effects are cumulative, so a tile with mountains on 3 sides can have major bonuses. But since this affects both kinds of Districts, again you have to make a choice. If you are aiming at a Science Victory, or a Religious victory, the choice will be easier, but in case you need to choose. As to placing a District, when you decide to build one you will get a highlight on the map of locations that are permissable. But if you have several such sites, you need to choose which one fits your strategy best. District Types There are a lot of Districts you can build and listing every one of them here would be tedious. Some are only relevant to late-game situations, others address issues like Housing and Amenities, which we will discuss separately. But there is group of core Districts that every player will need to deal with from the beginning: City Center – This is one you get automatically when you build a city, and can hold a Granary, a Monument, a Water Mill, and various levels of Walls, ranging from Ancient to Renaissance. Campus – This is the Science district, and is unlocked by discovering Writing. That comes pretty early so you will get this capability quite easily, but if you are going for a Science victory you might want to make a beeline for Writing. Remember that if you go into the Tech Tree you can click on a tech to select it, and the game will automatically research it and all of its prerequisites. This is very handy for simplifying Research choices. As mentioned, an adjacency bonus is +1 Science for every adjacent Mountain, but you can also get #1 Science for every 2 Rainforest or District tiles. Don't worry about memorizing these bonuses, they will appear on the map when you are selecting a spot to place your District. Campuses contain Libraries, Universities, Observatories, and Research Labs. And the more built up your Campus Disctrict is, the more Great Scientist points you accumulate. If you want a Science victory you should make it a priority to get Camapus districts put down ASAP in at least a couple of cities, since the effects build like compound interest. Theater Square – This is the Culture District, and is unlocked by discovering Drama and Poetry. That is a somewhat later tech, use the technique of clicking on it in the Tech Tree to get there quickly if you want to pursue a Culture victory. It contains the Amphitheater, Art Museum, Archeaological Museum, and Broadcast Center. It gives +2 Culture from each adjacent Wonder, and +1 Culture from each 2 adjacent Discrticts. The buildings all have slots for holding Great Works, and generate points for Great Writers, Great Artists, and Great Musicians. Holy Site – This is the Religious district, and is unlocked when you discover Astrology, which is a fairly early tech. This district contains Shrines, Temples, and other Worship buildings. It generates Faith, which can be surprisingly useful. Civ VI introduced a new system of relgious warfare and new Religious victory type, but in some circumstances you can use Faith to purchase Units and Buildings, so even if you are not intending a Religious victory you should not overlook it. This district generates Great Profit points. It has adjacency bonuses of +1 Faith from every adjacent Mountain tile, and +2 Faith from every adjacent Natural Wonder, so if you are lucky enough to have a Natural Wonder in your city keep this in mind. Encampment – This is the Military district, and is unlocked by discovering Bronze Working, a very early tech. By building an encampment you can build units that start out with higher Veteran status. In Civ VI I like to build one or two of these in my Empire and use them to construct all of my units. Remember, in Civilization you always want to maintain a strong military to deter your rivals. Buildings include Barracks, Stable, Armory, and Military Academy. This District produces Great General points. It has no adjacency bonus, and cannot be built next to the City Center. But it has strong Defense and can function like the City Center in terms of defense and bombardment capabilities. All newly produced or purchased units will appear in this District, not in the City Center as would otherwise happen. I like to build this on land that is otherwise of low value, like a Desert tile. Commercial Hub – This is the Commerce district, and is unlocked by discovering Currency. The Buildings you can place in this include the Market, the Bank, and the Stock Exchange. Adjacency bonuses include +2 Gold from an adjacent Harbor, and +2 Gold for each Adjacent river. So if your city includes a river that runs into the ocean, place a Harbor in the right spot and then a Commercial Hub and watch the Gold pile up! The Commercial Hub generates Great Merchant points. In addition, a Commercial Hub gives you one additional Trade Route, another way to generate more cash. As we have seen in this series, in all Civilization games a healthy Treasury is a major part of a successful game no matter what Victory type you are pursuing. Harbor – This is the Seafaring District and is unlocked when you discover Celestial Navigation. Buildings in this district include Lighthouse, Shipyard, and Seaport. And if you don't have a Commercial Hub in the city, adding a harbor can give you one additional Trade Route. Adjacency bonuses include +1 Gold from each adjacent Coastal resource, and +1 Gold from every 2 adjacent District tiles. There is also a bonus of +2 Gold if adjacent to the City Center. This district has to be built in Coastal waters adjacent to Land, but note that the City Center does not need to be on the Coast to build this. You just need to have Coastal Waters available within your city. This district generates Great Admiral points. While this district is important for projecting Maritime power, it is equally useful for generating Gold, reflecting the fact that historically Maritime powers have been the most successful traders and the wealthiest nations. Industrial Zone – This is the Production district, and is unlocked when you discover Apprenticeship. Its buildings include the Workshop, the Factory, and the Power Plant. Adjacency bonuses include +1 Production from each adjacent Quarry or Mine, and +1 from each two adjacent Districts. One interesting thing is that some of the prodction bonuses from this district can applly to any City whose City Center is within 6 tiles, so it is possible by careful placement to have one Industrial Zone that benefits 2-3 cities. This district generates Great Engineer points. These are the major districts you will be dealing with, and note that each one generates Great Person points. But note also that there are 7 of them. You can certainly have a large Empire that contains at least one of each. But to have all of them in one city would require a population of 22, which can happen if you aim for it, but also would mean very little in the way of farming or mining. I have seen expert players do a “one city challenge” where they attempt to win a victory with only one very large city, but I have never been interested in that sort of thing. I play to relax and enjoy myself. And one more thing about adjacency bonuses: you get bonuses even from Districts in a different city. As an example if you place a Commercial Hub from City A next to a Theater Square from City B, both Districts can benefit from the adjacency. Links https://civilization.fandom.com/wiki/District_(Civ6) https://www.palain.com/gaming/civilization-vi/playing-civilization-vi-part-1/ Provide feedback on this episode.

    HPR4722: Show and tell: AI tropes

    Play Episode Listen Later Sep 8, 2026


    This show has been flagged as Explicit by the host. Obviously, I'll need to introduce why I'm the best person to explain this concept and how I did my research. After that, I dive into the core of he episode: the research. The Ultimate Guide To Spotting AI Generated Text That Every Writer Needs To Read. That title already has two tells: Title case : every word capitalised, which conveniently cannot be read out loud Hyperbole : a promise of ultimacy, for a ten minute podcast For most of this episode I am not myself, I am the machine, and every sentence I say is an example of the thing it describes. This page is the key to that part of the show: the tells in the order you hear them, with what they sound like in the recording. Most names come from tropes.fyi , so you can look them up there and get the longer explanation. As also stated in the podcast: these aren't errors. They are ordinary figures of speech that human writers have used for centuries. The tell is the density. Part one: Vocabulary Prestige vocabulary : words nobody uses out loud. e.g. delve, harness, utilise, robust, foster Grand nouns for ordinary things : e.g. tapestry, landscape, realm, ecosystem, paradigm Magic adverbs : imply significance, carry no information. e.g. quietly, fundamentally, arguably, remarkably Avoiding the verb "to be" : plain "is" swapped for something that sounds busier. e.g. serves as, stands as, represents, marks Invented concept labels : an abstract problem noun (trap, creep, paradox, inversion) welded onto a domain word, then used as if it were established. e.g. "the fluency trap", "prestige creep" Vague attributions : authority without a name. e.g. "experts agree", "industry reports suggest", "observers have noted" Appeal to familiarity : consensus claimed rather than proven. e.g. "a classic", "famously", "as we all know" Promotional register : describing turns into selling. e.g. unlocks, seamless, unprecedented Part two: Sentence shapes Negative parallelism : the "it's not X, it's Y" pattern, and the most reported tell of all. e.g. "This isn't a stylistic quirk, it's a structural signature." Not X. Not Y. Just Z. : the same move tripled, building tension for a reveal that needed none. e.g. "Not a habit. Not a tic. A tell." Sets of three : one tricolon is elegant, three in a row is a stuck needle. e.g. "it arrives in threes, it lands in threes, it exhausts in threes" Short punchy fragments : emphasis manufactured by full stops instead of earned by content. e.g. "Short. Parallel. Relentless." Self-answered questions : asks what nobody asked, answers it immediately. e.g. "The problem? Nobody asked." Anaphora : the same sentence opening until it becomes furniture. e.g. "They open sentences the same way. They open the next one the same way." Trailing "-ing" analysis : shallow significance bolted onto a finished sentence. e.g. "highlighting its enduring importance", "reflecting broader trends" False ranges : "from X to Y" where there is no scale and no middle. e.g. "from cesspit to citation" Filler transitions : connect nothing to nothing. e.g. "it's worth noting", "importantly", "notably" The interjection reflex : every sentence broken in half, whatever the punctuation. e.g. em-dash, double hyphen, comma pair, colon Comma-clipped tail : a short phrase hung off a comma instead of landing the point. e.g. "above the content, and save." Part three: Tone Manufactured suspense : the buildup arrives, the revelation does not. e.g. "here's the thing", "here's the kicker" Patronising analogy : teacher mode, uninvited. e.g. "think of it as a Swiss Army knife for condescension" Forced figurative language : a metaphor picked for cleverness rather than clarity. e.g. "Picture a bicycle. Now picture that the bicycle is prose." Stakes inflation : everything is historic. e.g. "a pivotal moment in the evolution of reading itself" False vulnerability : honesty performed, never risked. e.g. "let me be honest with you here. Genuinely honest." Assertion in place of evidence : e.g. "history is unambiguous on this point", "the evidence is clear" "Imagine a world where..." : the futurism sales pitch, pleasant outcomes if you accept the premise. e.g. "imagine a world where every paragraph carries a quiet intelligence" Quotable one-liners : slide bait that survives being pulled out of context because it never had any. e.g. "Every bite is a chance to be here, now, fully." The collaborative "we" : one author, plural pronoun. e.g. "we will unpack each one in turn" Sycophancy : not a figure of speech but a training artefact, and the fastest way to spot raw chatbot output. e.g. "What a genuinely profound question." Part four: Formatting Title case headings : see the top of this page Bullet lists where prose would do : the document turns into a slide deck. e.g. this page, from here to the bottom Bold-first bullets : every item opens with a bolded keyword and a colon. e.g. yes, also this page, I know Emoji as punctuation : rocket for aspiration, key for insight, sparkles because the paragraph ended Em-dashes : mid-sentence, twice, sometimes three times, where a comma would have done the job The find and replace tell : double hyphens everywhere, because someone removed the character and kept the habit Unicode decoration : arrows and curly quotes nobody typed on a keyboard. e.g. Input → Processing → Output One thought per line : paragraphs abolished. e.g. "It happened. Alone. On a Tuesday." Part five: Composition Announce then answer : says what the text is about to do instead of doing it. e.g. "This guide will explore what those signs look like." Rapid-fire historical analogies : authority borrowed from a list, with no argument underneath. e.g. "Marconi. Sony. Apple. Print, radio, web, mobile." The metaphor that will not end : e.g. the garden that stays a garden for six sentences, then becomes a north star that moves the needle Self-echo : a word from earlier returning as if it were being paid off, when it is the same narrow vocabulary surfacing again One point diluted : the same idea in five coats, sounding like progress. e.g. "put differently", "to rephrase", "in other words" Fractal summaries : every section summarises itself, including the one you are inside. e.g. "In this section we explored composition." The tie-back : closes by looping the answer back to the original question, long after the point was made. e.g. "So, to answer your question..." Concede and dismiss : e.g. "despite its fluency, it faces challenges typical of automated systems. Despite those challenges, it endures." Signposted conclusion : competent writing does not need to announce that it is ending. e.g. "in conclusion", "to sum up", "in summary" The conclusion that refuses to end : clause stacked on clause, quieter and more meaningful each time. e.g. "the real AI generated text was the paragraphs we scrolled past along the way" Engagement bait : e.g. "Agree?" plus a pointing emoji Tells on the list that did not fit in the episode The recording would have run to forty minutes. These are worth knowing anyway. Reasoning leak : the text narrating its own decisions instead of just making them. e.g. "I want to be exact about my own role here." Premise stacking : a paragraph of evidence in front of the point, so the point has been made twice before it arrives Compulsive counting : states the number of items before listing them. e.g. "Five things we wish to discuss" Excessive enumeration : a listicle disguised as prose. e.g. "The first wall is... The second wall is..." Belaboring the unnecessary : defending a minor point against an objection nobody was going to raise Synonym cycling : refusing to repeat a noun. e.g. the dashboard, then the interface, then the portal, then the analytics hub Wh-headings : the default shape a model reaches for when naming a section. e.g. "What this means", "Why it matters" Content duplication : the same paragraph appearing twice, because the model lost track of what it had written Why this is not a detector guide Liang, Yuksekgonul, Mao, Wu and Zou, Stanford, published in Patterns (Cell Press) on 10 July 2023. Seven commercial GPT detectors were run over 91 TOEFL essays written by non-native English speakers and 88 US eighth grade essays. Average false positive rate on the TOEFL essays: 61.3 percent. 89 of the 91 essays were flagged as AI generated by at least one detector. All seven agreed on 18 of them. The US eighth grade essays came back near perfect. Plainer word choice, lower perplexity, reads as machine to the software. Feeding the TOEFL essays through ChatGPT with the prompt "enhance the word choices to sound more like that of a native speaker" dropped the false positive rate to 11.6 percent. So the way to stop being accused of writing like a machine was to have a machine rewrite you. Do not take my word for it, the paper is open access: https://www.cell.com/patterns/fulltext/S2666-3899(23)00130-7 Preprint: https://arxiv.org/abs/2304.02819 The pointers, for real Write with things in it: names, dates, prices, the model number of the drive that died. Say something a machine has no way to know, because it happened to you. Be willing to be wrong out loud. Keep one weird sentence that your editor would cut. Links and references The list this episode leaned on: tropes.fyi , by ossama.is The detector study: Liang et al., "GPT detectors are biased against non-native English writers", Patterns, 2023 "Not an Addict", K's Choice, 1995. It's not a habit, it's cool, I feel alive. "Friends, Romans, countrymen" and "I come to bury Caesar, not to praise him": Shakespeare, Julius Caesar, act 3 scene 2 "Veni, vidi, vici", attributed to Julius Caesar by Suetonius and Plutarch Over to you There is a comment section under this episode. Tell me which tell I missed, and which one you are guilty of. Better yet, record it. Read your worst, most machine sounding paragraph out loud and post it to Hacker Public Radio. The queue is always hungry. Provide feedback on this episode.

    HPR4721: HPR Community News for August 2026

    Play Episode Listen Later Sep 7, 2026


    This show has been flagged as Explicit by the host. New hosts Welcome to our new hosts: Kristoff number9 Last Month's Shows Id Day Date Title Host 4696 Mon 2026-08-03 HPR Community News for July 2026 HPR Volunteers 4697 Tue 2026-08-04 Correcting the Dates of Files Vance 4698 Wed 2026-08-05 ID3 Tags and Vorbis Comments Whiskeyjack 4699 Thu 2026-08-06 Sunshine, Moonlight, Playnite !? operat0r 4700 Fri 2026-08-07 Robert A. Heinlein: The Juveniles Ahuka 4701 Mon 2026-08-10 Elsbeth muses with Lee on her experiences and opinions on AI Elsbeth 4702 Tue 2026-08-11 MakeACopy is an open-source document scanner app for Android Ken Fallon 4703 Wed 2026-08-12 Ebooks and Audiobooks Ahuka 4704 Thu 2026-08-13 HPR Beer Garden 17 - Double DDH IPAs Kevie 4705 Fri 2026-08-14 Free Software Is Wasted On You Teens Trollercoaster 4706 Mon 2026-08-17 Quirks and Customisations Lee 4707 Tue 2026-08-18 UNIX Curio #12 - expr Vance 4708 Wed 2026-08-19 Programmable Logic Controls - Episode 1 Whiskeyjack 4709 Thu 2026-08-20 Peertube: my two penneth Kevie 4710 Fri 2026-08-21 Civilization VI Ahuka 4711 Mon 2026-08-24 Second-Hand Phone TrumpetJohn 4712 Tue 2026-08-25 friedcamp interviews part 1: Wim van Gool Kristoff 4713 Wed 2026-08-26 July2026 Community News response, and Future Plans TheDUDE 4714 Thu 2026-08-27 HPR Beer Garden 18 - Amber Ale Kevie 4715 Fri 2026-08-28 friedcamp interviews part 2: Thomas Farstrike Kristoff 4716 Mon 2026-08-31 PocketMod TrumpetJohn Comments this month Past shows hpr3708 (2022-10-19) "Insomnia as a Hobby" by TrumpetJohn. Robert St.Preux said: "Insomnia as a hobby" (2026-08-30 00:56:59) hpr3766 (2023-01-09) "ACER Nitro 5 laptop review" by Bookewyrmm. wevaba6950 said: "A refreshing contrast between enterprise gear and low-power hardware" (2026-08-10 09:19:47) candycanearter07 said: "re: a refreshing contrast..." (2026-08-12 02:54:05) hpr4581 (2026-02-23) "Sharp Intake of Breath City (A.K.A.) How I learnt to stop worrying about the fork bomb" by not_toby. Windigo said: "Fantastic episode" (2026-08-08 16:51:00) hpr4655 (2026-06-05) "Tips for Glasses" by norrist. Archer72 said: "Glasses and age" (2026-08-06 11:41:39) hpr4676 (2026-07-06) "HPR Community News for June 2026" by HPR Volunteers. Archer72 said: "hpr4657 :: UNIX Curio #8" (2026-08-02 19:29:26) hpr4677 (2026-07-07) "UNIX Curio #10 - Checksums and Hashes" by Vance. Whiskeyjack said: "Checksums and HPR4677" (2026-07-31 00:37:40) hpr4678 (2026-07-08) "High Resolution Elapsed Time in Shell Scripts" by Whiskeyjack. Archer72 said: "Reply to Whiskeyjack and candycanearter07 " (2026-08-03 10:12:47) hpr4692 (2026-07-28) "Noise Music Tutorial 2: Using Audacity to Make Noise" by TheDUDE. Windigo said: "Audacity for noise music" (2026-08-06 16:09:59) candycanearter07 said: "re: Audacity for noise music" (2026-08-12 18:55:18) This month's shows hpr4696 (2026-08-03) "HPR Community News for July 2026" by HPR Volunteers. Archer72 said: "Amateur Radio Field Days" (2026-08-02 11:50:11) Archer72 said: "hpr4673 First contact" (2026-08-03 10:16:09) candycanearter07 said: "re: mic issues" (2026-08-03 22:21:42) Th3Dud3 said: "response to Kevin not being able to get cream ale" (2026-08-06 00:12:38) hpr4697 (2026-08-04) "Correcting the Dates of Files" by Vance. Jim DeVore said: "Useful episode!" (2026-08-04 10:53:12) Vance said: "Modifying metadata" (2026-08-07 01:44:51) Henrik Hemrin said: "Exif in digiKam" (2026-08-08 19:20:13) candycanearter07 said: "useful!" (2026-08-10 16:08:18) hpr4698 (2026-08-05) "ID3 Tags and Vorbis Comments" by Whiskeyjack. xmanmonk said: "Great episode!" (2026-08-05 15:19:01) candycanearter07 said: "quirks in hpr" (2026-08-05 15:52:18) Whiskeyjack said: "Reply to xmanmonk in HPR4698 - ID3 Tags" (2026-08-06 00:12:26) Whiskeyjack said: "Reply to candycanearter07 in HPR4698 ID3 tags" (2026-08-06 00:28:48) hpr4703 (2026-08-12) "Ebooks and Audiobooks" by Ahuka. candycanearter07 said: "useful!!" (2026-08-12 02:30:58) Archer72 said: "Audiobooks and Audible" (2026-08-12 09:06:40) Jack said: "Misleading" (2026-08-12 17:05:21) hpr4705 (2026-08-14) "Free Software Is Wasted On You Teens" by Trollercoaster. Archer72 said: "Brilliant! " (2026-08-03 14:08:08) Trollercoaster said: "One left in my six pack" (2026-08-14 07:53:38) old guy said: ":-)" (2026-08-14 09:24:15) Trollercoaster said: "old guys together" (2026-08-14 13:14:48) candycanearter07 said: "good satire again" (2026-08-14 21:42:55) Trollercoaster said: "Who's talking about satire?" (2026-08-15 07:54:33) Trollercoaster (our of character) said: "Woopsie" (2026-08-16 19:25:41) hpr4706 (2026-08-17) "Quirks and Customisations" by Lee. candycanearter07 said: "cool ep!" (2026-08-30 20:15:40) hpr4707 (2026-08-18) "UNIX Curio #12 - expr" by Vance. xmanmonk said: "Another great show" (2026-08-18 22:22:56) Whiskeyjack said: "HPR4707 Unix curio - dc" (2026-08-19 14:31:02) Vance said: "dc" (2026-08-20 04:47:32) Whiskeyjack said: "HPR4707 Unix curio - Stack Machines" (2026-08-21 16:00:48) Trollercoaster said: "Suggestion for Linux Curio" (2026-08-27 10:42:43) Whiskeyjack said: "Obscure X Window programs" (2026-08-27 16:16:15) candycanearter07 said: "re: Suggestion for Linux Curio" (2026-08-27 18:13:51) Archer72 said: "re: Suggestion for Linux Curio" (2026-08-28 10:07:31) Vance said: "Thanks for the ideas" (2026-08-28 16:39:28) Whiskeyjack said: "Reply to Vance on episode research" (2026-08-30 04:14:01) candycanearter07 said: "re: re: Suggestion for Linux Curio" (2026-08-30 12:06:31) hpr4708 (2026-08-19) "Programmable Logic Controls - Episode 1" by Whiskeyjack. Archer72 said: "Thanks you" (2026-08-08 10:49:34) Whiskeyjack said: "Reply to Archer72 on HPR4708 - PLCs Episode 1" (2026-08-08 17:11:10) Trey said: "Memories of Ladder Logic" (2026-08-19 13:01:41) Whiskeyjack said: "Reply to Trey on HPR4708 - PLCs Episode 1" (2026-08-20 02:02:44) Trey said: "Cyber in ICS" (2026-09-02 22:31:51) Whiskeyjack said: "Reply to Trey on Cyber in ICS" (2026-09-03 15:24:51) hpr4709 (2026-08-20) "Peertube: my two penneth" by Kevie. xmanmonk said: "Thanks for the episode" (2026-08-20 19:15:57) hpr4711 (2026-08-24) "Second-Hand Phone" by TrumpetJohn. candycanearter07 said: "interesting!" (2026-08-24 19:17:44) Whiskeyjack said: "HPR4711 - TCL Flip phone" (2026-08-24 22:22:11) hpr4712 (2026-08-25) "friedcamp interviews part 1: Wim van Gool" by Kristoff. Archer72 said: "Interview" (2026-08-26 23:11:49) Laindir said: "Fascinating interview!" (2026-08-26 23:18:33) hpr4716 (2026-08-31) "PocketMod" by TrumpetJohn. Kightlinger said: "I love PocketMods!" (2026-08-31 17:35:43) candycanearter07 said: "analog solutions" (2026-08-31 20:52:55) Mailing List discussions Policy decisions surrounding HPR are taken by the community as a whole. This discussion takes place on the Mailing List which is open to all HPR listeners and contributors. The discussions are open and available on the HPR server under Mailman. The threaded discussions this month can be found here: https://lists.hackerpublicradio.com/pipermail/hpr/2026-August/thread.html Events Calendar With the kind permission of LWN.net we are linking to The LWN.net Community Calendar. Quoting the site: This is the LWN.net community event calendar, where we track events of interest to people using and developing Linux and free software. Clicking on individual events will take you to the appropriate web page. Provide feedback on this episode.

    HPR4720: Robert A. Heinlein: Earlier Novels

    Play Episode Listen Later Sep 4, 2026


    This show has been flagged as Clean by the host. Heinlein published his first novel in 1948, and within a decade had published some major works. What distinguishes these early novels from his later ones is that he has not pushed the boundary of what he can write about to the degree he does in the 1960s and later. But there are fine novels in this period. Heinlein's Earlier Novels During the 1950s Heinlein was busy with his Juvenile series, but also found time to write some adult novels, and some of them are very good. A few of them were expansions of earlier, shorter works that he turned into full novels. Beyond This Horizon (1948) – This is Heinlein's first novel after the lackluster For Us The Living (which never was published during his lifetime; Heinlein knew it was sub-par). It is set in a future society that is practicing a form of eugenics, with a breeding program designed to produce the perfect human by selecting for health, longevity, and intelligence. The protagonist, Hamilton Felix, is not the one, but he is near to the end. And this society has also made it a point to keep a certain number of people who are not part of the breeding program, as a form control for the experiment. Hamilton Felix is in fact the penultimate step in this program, but has so far shown no interest in marriage or procreation. But in the course of the novel he is persuaded. His children are shown to be the end point of the program at the end of the novel. A sub-plot involves his friend Mordan Claude (in this book everyone puts their family name first) who falls for a woman he meets. When she sneezes, he begins to suspect she is one of the “control naturals”. They are protected, but clearly this is a class society, which is to be expected in any society that practices eugenics, and should be off-limits for Claude. But love conquers all, and then he discovers that she is not a control natural after all, which to my mind is a somewhat weaker outcome.Another aspect of this society is that most people are armed, and dueling is common. This is explained as “An armed society is a polite society,” since if you offended someone you could find yourself in a duel very quickly. A lot of gun enthusiasts have picked up on this and repeated it as if it was revealed truth, but even a cursory examination of societies with a lot of guns shows it to be false. Sixth Column (1949) – This novel was originally a serial written in 1941, when the Sino-Japanese war was in full swing, and this motivates some of the ideas in this book. The setting is a United States that has been conquered by the Pan-Asian Federation. This Federation had previously absorbed the Soviet Union and India, and is portrayed in very much Yellow Peril manner. John W. Campbell had a lot to do with this, and it makes the novel something that you can skip without losing much. The Pan-Asians regard the Americans as slaves. And their policy towards their slaves is “Three things only do slaves require: work, food, and their religion.” In an American military outpost hidden in the mountains of Colorado a miracle weapon is found that can kill, and it can somehow be tuned to only affect the Asians and not the Americans. Since the Pan-Asians have allowed religion (better to pacify the slaves), the Americans create a religion and use that to infiltrate the Pan-Asian facilities. Heinlein himself had a low opinion of this novel, and deservedly so. The Puppet Masters (1951) – This novel is a product of the paranoia of the times regarding Communists. But this novel is more of an allegory than a direct anti-Communist screed. It is fundamentally about “the enemy within”, in the form of alien parasites called slugs that can take over a human by controlling the nervous system, making the human a powerless slave to the alien. And they are attempting to conquer the world, though all of the action we see takes place in the United States. This is essentially The Body Snatchers plot, and has been done many times. But both this novel and the previous Sixth Column reflect the feeling of paranoia prevalent in society when people thought there were communists under every bed looking to corrupt the youth and subvert The American Way of Life. And it is notable that the organization that leads the fight against the slugs is a top secret outfit established without the knowledge of Congress and responsible only to the President. Double Star (1956) – This is when Heinlein as a novelist starts to really click, and it was shown by his winning his first Hugo for best novel. The plot is somewhat reminiscent of Prisoner of Zenda. In a future solar system, Earth, Venus, Mars, and the Jovian satellites are united under a parliamentary democracy, which is in turn under a constitutional monarchy. Think of it as similar to the UK, only in this case it is the House of Orange that are the monarchs. A politician named John Joseph Bonforte is the leader of the Expansionist coalition, and one of the most prominent politicians in the solar system. And he has been kidnapped sat a crucial time. His staff find an actor, stage name The Great Lorenzo, who is similar enough physically to impersonate Bonforte, while they try to get the real Bonforte back. They do succeed, but he has been very badly treated by the kidnappers, so the actor has to continue for the election campaign. And he wins the election, but the real Bonforte dies. The actor then continues to impersonate him to the point of really becoming him. The two things that make this novel so interesting are first, the focus on acting as seen through the eyes of Lorenzo; and second, the focus on the machinery of politics. And this draws upon Heinlein's own experience in electoral politics. Though he was not successful in getting elected, he clearly had absorbed a lot about the how-to of the process. And he did write a non-fiction book called Take Back Your Government (1992), which was published posthumously. It was subtitled A Practical Handbook for the Private Citizen Who Wants Democracy to Work, and was originally written in 1946. It was based on his experience with EPIC and in trying to get Upton Sinclair elected Governor of California in 1934. The Door Into Summer (1957) – This is another good novel, which features several themes that would reappear through Heinlein's work. The first is that Heinlein was a very confirmed cat lover. The title comes from a cat who went from door to door in the middle of winter, trying to find the door into summer. Second, the protagonist is an engineer, which is of course Heinlein's background. The third is the time travel element. People can travel into the future through a type of suspended animation called Cold Sleep. But for the purposes of the plot a scientist has invented a time travel device that sort of works. It sent a grad student named Leonard Vincent a few centuries back in to Italy where he became Leonardo da Vinci. But it sends our hero, Daniel Boone Davis, back exactly where he wanted to go. We see a few things in this novel that are of interest. First, the cat, Pete, has the full name of “Petronius the Arbiter”, who was the author of the Satyricon, so Heinlein's interest in sex is starting to make an oblique appearance. Second, when Dan goes back in time, he lands in the middle of a nudist camp, and that is also something Heinlein was very interested in.The plot can be summarized as Dan gets robbed of his inventions by his business partner and his secretary/fianceé, gets put into Cold Sleep, then goes back in time to just before he got robbed and fixes things to his satisfaction, then takes the Cold Sleep again to finish his plans. It is a pretty good yarn. Methusaleh's Children (1958) – This was originally a novella written in 1941, then expanded into a novel. It is part of the Future history. It introduces Lazarus Long, who would go on to be Heinlein's alter ego through many of his future books, and thus implicitly makes those books part of the Future History, though most scholars will dispute this. What cannot be disputed is that this novel is a cornerstone for where Heinlein would go in many of his future stories.The story begins with a successful businessman named Ira Howard who dies of old age at around the age of 49 in the 19th century. In his will he leaves his estate to trustees with the mandate to find a way to extend human life span. The best they can come up with is to encourage (financially) people who had long-lived grandparents to marry each other and have children. They carry this on and by the 22nd century the Howard Families, as they call themselves, have an average life span of 150 years. But they have to hide this form the rest of society, and arrange from time to time to “die” and then become someone else. This masquerade helped them survive the years of Nehemiah Scudder and his successors, but a few of them reveal themselves during the Covenant government. This has a bad result because people want the secret that they assume the Howard families are hiding, and they might be willing to kill to get the secret. So the Howard families steal a starship and make their escape. One of the people onboard is Andrew Jackson “Slipstick” Libby, who we first met in the short story Misfit, and he manages to come up with a Faster-Than-Light drive. They finally decide to go back to Earth, where they discover that scientists have found ways to prolong human life and they are no longer enemies, in fact they are welcomed for bringing the FTL drive.This is definitely a must-read novel for anyone who wants to get into the Heinlein universe. So many other works are based on it. Links https://en.wikipedia.org/wiki/Beyond_This_Horizon https://en.wikipedia.org/wiki/Sixth_Column https://en.wikipedia.org/wiki/The_Puppet_Masters https://en.wikipedia.org/wiki/Double_Star https://en.wikipedia.org/wiki/Take_Back_Your_Government https://en.wikipedia.org/wiki/The_Door_into_Summer https://en.wikipedia.org/wiki/Methuselah%27s_Children https://www.palain.com/science-fiction/the-golden-age/robert-a-heinlein/heinleins-earlier-novels/ Provide feedback on this episode.

    HPR4719: How to use a multimeter, introduction and basic usage

    Play Episode Listen Later Sep 3, 2026


    This show has been flagged as Clean by the host. Outline of this radio program: Short history of multimeters Differences between VTVM, VOM, DMM Why you may need a VTVM Analog vs Digital Current manufacturers Why you may want to use an analog meter Safety and CAT Probes Functions of the modern DMM and notes Wrap up Provide feedback on this episode.

    HPR4718: Programmable Logic Controls - Episode 2

    Play Episode Listen Later Sep 2, 2026


    This show has been flagged as Clean by the host. -------------------- 01 Introduction This is the second episode in an 8 part series. 02 In the previous episode we discussed the predecessors of PLCs, in particular relay logic. In this episode we will discuss how relay logic came to be expressed in software rather than in actual hardware components. 03 The topics to be covered include * Early computers in industry. * The first PLC. * PC versus PLC - what's in a name. * Who the major brands are. * What does a PLC actually look like. * Machine architecture. * PLC programs. * The scan. * PLC programming languages. * Relative popularity of PLC programming languages versus more conventional computer programming languages. -------------------- 04 Early Computers in Industry Computers came to be used in industry fairly early on. Minicomputers were used in some large industries to control things like electric power plants. For example, the DEC PDP8 was used to control the refuelling machines in CANDU nuclear power plants. These would load and unload fuel from the reactor, which happens continually on a daily basis while the reactor is running. 05 The first microprocessor based computer sold on the commercial market was the MICRAL from France, based on the Intel 8008. It was sold as a cost effective replacement for minicomputers used in industry. It preceded what are generally considered to be the first Personal Computers. So you can see that industry were not reluctant to adopt new technology. 06 However, mini computers were large complex systems that did not fit well into a factory floor. They had particular niches in very large complex integrated systems, but were not suited to controlling many individual machines in a factory that produced things like automobiles or appliances. 07 What was needed was something that would fit into a standard electrical enclosure, withstand the temperatures found in a factory, could stand up to vibration and noise, was tolerant of voltage fluctuations, interfaced directly to sensors and actuators, and could be readily programmed by engineers, technicians, and tradesmen who were familiar with the processes to be controlled, but had little or no experience with computers. 08 This required a complete integrated package covering hardware, software, and product distribution through industrial supply retailers. Something that could meet these criteria is what was needed to become the PLC. -------------------- 09 History Many histories point to a US developer that became Modicon. However, their first hardware was more a proof of concept than a viable commercial product. In fact multiple companies in the US, Europe, and Japan were working on the problem and released comparable products all at around the same time in the early 1970s. 10 The idea preceded the implementation by a number of years. For example, General Motors had asked industrial control equipment suppliers in the mid 1960s for some sort of programmable control device to replace relay logic. This showed potential suppliers that there was a market for this sort of thing, and gave them a clearer idea of what customers were looking for. 11 What made this possible was the development of the first 8 bit microprocessor in that time period, combined with readily available bit slice processors from the minicomputer industry and other components. 12 People knew what to do, the problem was waiting for the development of suitable component hardware. Minicomputers were already being used in industry, but were normally located in control rooms. PLCs were an effort to take that technology out of control rooms and put it on the shop floor. 13 PC Versus PLC - What's in a Name In the early days, these systems were known as either PLC, which means "Programmable Logic Controller", or PC, which means "Programmable Controller". Different vendors favoured different terminology, but both were common. I have a book which was at one time one of the standard reference handbooks for this industry which was published in 1989, and refers to them as Programmable Controllers, or PCs. 14 The term PC was also used to mean "Personal Computer", but that wasn't really a problem in the early days. However, a certain large company decided to call their entry into the personal computer market the "IBM PC", and suddenly "PC" became a generic term for desktop computers. 15 After a long struggle to keep referring to their products as "PCs", even the biggest vendors caved in and gave up the fight and switched to using the "PLC" term. I will therefore use the term "PLC" in this podcast series even when talking about products which were originally called "PCs" at the time they were introduced. 16 Who the Major Brands Are The companies that came to dominate the industry fairly early on were generally companies that already made industrial electrical hardware. These were Siemens Allen Bradley, later known as Rockwell Schneider Mitsubishi Omron 17 These are still the dominant companies in the business, although there are many small brands, particularly at the cheaper end of the market. All of them were suppliers of a wide range of industrial control hardware, such that you could build all or nearly all of the parts of your control system using only their products. 18 Each of these sells an integrated hardware and software package, including development software, that is completely proprietary. If you thought that the mainframe business had a lot of vendor lock-in, you haven't seen the industrial market. -------------------- 19 What Does One of These Things Actually Look Like? At this point you are probably still very confused as to what a PLC actually is. I will attempt to describe one in basic terms by giving an example of one. The smallest and simplest ones are what are termed "shoebox" PLCs. These are basically a rectangular box with a plastic case. 20 Here are the dimensions for a typical low end model, a Mitsubishi FX3U-32M. According to specs in the manual, it is 150mm wide, 90mm high, and 86mm deep. 21 It can be mounted to the panel in an electrical enclosure by snapping it onto what is termed a DIN rail. DIN rails are standard mounting systems which use a strip of metal which is U shaped with a lip at the top of each end of the U. You screw the DIN rail to the electrical panel in the enclosure, and most industrial components such as PLCs, terminal blocks, circuit breakers, and all sorts of other things will simply snap onto it and be ready to wire together. 22 Along the top and bottom of the PLC are terminals to which you can attach wires from the things you want to sense or control in the rest of the machine, such as push buttons, pilot lights, proximity sensors, and valves. 23 Inputs are along the top, and outputs are along the bottom. The FX3U-32M has 16 inputs and 16 outputs. These I/O can be 24 volts DC, or 100 to 120 volts AC, depending on the model. Alternatively it may have small relays for outputs. While AC I/O once predominated, 24VDC became the standard in most industries several decades ago as it interfaced with electronic devices more readily and also allowed for cheaper and more compact wiring. 24 More inputs and outputs can be added by connecting additional I/O modules to the main PLC next to it on the same DIN rail, up to a total of 256 I/O The connection is typically via short ribbon cables which plug into the adjacent module. These I/O modules look like the main PLC, but just add I/O. 25 Inside the PLC are a CPU, memory, and firmware. This model has 64K "steps" of memory, which can be thought of as how many instructions you can have. The program runs in RAM, but you can add a small flash memory device to save the program to. There is a run/stop switch that allows you to start or stop the user program. There is a port that you can use to connect the PLC to a laptop computer with a cable so you can download your program to it. 26 The biggest part of the market for PLCs is for these "shoebox" style. However, there are bigger ones as well which have more I/O, more memory, faster CPUs, etc. These are meant for tasks such as coordinating large assembly lines and things like that. These are what are termed rack systems, where the rack is an empty box which is open at the front and has a backplane bus running along the back. You plug the main CPU into the bus, normally in the leftmost position, and then plug I/O modules into the rack. The I/O modules are tall, thin, fully enclosed boxes with the I/O terminals along the front. 27 You should have a rough idea of their appearance at this stage, so I'll leave the physical description aside for now and go on to the concepts behind how they actually work and what makes them different from something like say a Raspberry Pi. -------------------- 28 Machine Architecture It is not really the hardware which defines the PLC. Rather, it is the software system architecture. Every PLC that I am aware of has a common set of features. 29 Data Table A data table is simply a block of memory which may or may not be subdivided into different parts. All logic, and all, or nearly all, I/O works by writing to and reading from addresses in the data table. 30 I/O Every input and output point maps to a fixed memory address in the PLC. To read the state of an input, you read its memory address. To change the state of an output, you write to its memory address. 31 These digital I/O appear as single bit boolean values. The PLC programming language has instructions which allow single bits to be read or written to directly without have to mask off other bits as you would have to do if you were using a conventional programming language. I have so far only mentioned digital I/O, which are single bit on/off values. 32 Other types of I/O Many PLCs also have other types of I/O such as Analogue I/O, which represent variable voltages rather than just on/off values. For example you may wish to read a temperature from a thermocouple where the voltage level varies with the temperature. Often these are mapped into the data table as byte or word values. 33 Internal Bit or Boolean Memory There will be a range of single bit or boolean memory which is used for internal logic state. Your program may need to come up with a series of intermediate logical values, and you store them in these internal bits or flags. 34 Timers and Counters Control of machinery often involves timing and counting. Timer and counters are mapped into the data table. Timer and counter presets and values can be read as words, and there will be bit addresses which indicate the status of the timer or counter, such as whether it has reached its preset and is "done". 35 Integer and Floating Point Values There will be word addresses where integer and floating point words can be stored. If you need to do some mathematical calculations and store the results, you would save them in an integer or floating point word. 36 Typed Memory Unlike when programming something like a PC where you simply have a range of undifferentiated bytes and it is up to your software to impose meaning on it, PLC data table memory has defined types and meanings and the system firmware enforces the correct memory access methods. 37 Size of Data Table Data tables vary greatly in size. A bigger data table allows for bigger and more complex program. Generally, new PLCs will have bigger data tables than older ones, and more expensive PLCs will have bigger data tables than cheaper ones of the same generation. 38 Example Having picked a current PLC as an example for physical dimensions, I will pick an old and obsolete one for an example of a data table. The Siemens S5-100 series was a small PLC that came in several sizes. The basic S5-100 had the following data table size. 39 Digital I/O had a maximum of 128 inputs and outputs taken together. Analogue inputs and outputs had a maximum of 8 taken together. Flag, or bit, memory was 1024 Timers - 16 Counters - 16 40 The S5-103 offered more of everything in the same basic package, but of course at a higher cost. Digital I/O had a maximum of 256 inputs and outputs taken together. Analogue inputs and outputs had a maximum of 32 taken together. Flag, or bit, memory was 2048 Timers - 128 Counters - 128 -------------------- 41 The PLC Program A PLC will come with what amounts to an operating system and virtual machine built into it. You as the programmer use the vendor's proprietary development software, what is generally called the "PLC programming software" to write an application for it. 42 You then connect your PC to the PLC using a cable of some sort, and download your program into it. The program gets stored in the PLC's RAM. There may be flash memory which serves to back up the RAM when the power is off so you don't lose the program. Before flash was available, a battery was typically required to hold the static RAM memory. 43 There is just one program in the PLC. There is no file system, just the program memory and the data table. When the PLC starts up, it runs the program that you wrote. It continues running the program until you turn off the power or you set the run/stop switch to the stop position. 44 I will come back to programming later, but we needed to cover these basic points before I could describe some further concepts we need to cover. -------------------- 45 The Scan A key thing to understand about PLCs is the "scan" concept. This works as follows. There is a repeated cycle called the scan. 46 First, the PLC reads all the physical inputs and updates the corresponding input addresses in the data table. Next it runs the user program once. Finally it reads the output addresses in the data table and writes them to the corresponding physical outputs. Then it repeats the scan from step 1. 47 A scan can take anywhere from a few milliseconds to hundreds of milliseconds, depending on the model of PLC. Older PLCs and cheaper PLCs tended to be slower. However, as integrated circuit technology advanced, programs got faster. 48 The PLC has a watchdog timer. This is a timer which runs in the background and resets at the start of a scan. 49 If a scan takes too long, the watchdog will trip and stop the program and set the outputs to some defined state, either turning them all off or holding them at the last value. This is known as "faulting" the processor. 50 A watchdog fault may be caused by a program that is too long, or uses a lot of very slow instructions, or in some cases it may be due to a bug in your program. However, this last cause is not as common or as easy to cause as you may think when it comes to faults. -------------------- 51 PLC Programming Languages The key to all of this is the unique way in which the programming languages used in PLCs work. I will first briefly describe the two main programming languages and then explain how they work in a PLC as part of a complete system. 52 Ladder Logic There are several programming languages, but the main one is called ladder logic. If you listened to the previous episode, the word "ladder" will ring a bell. When machines were controlled by electromechanical relays, the electrical drawings which specified and documented the types of relays and the connections between them were called "ladder diagrams". 53 PLCs simply take these ladder diagrams and reproduce them on your computer screen in the programming software using the same standard schematic symbols. 54 You do not need to draw the symbols like it was CAD. Instead you simply use your keyboard or mouse to say that you want this symbol to be entered in the current cursor location or you want this wire to be connected from here to there. When your rung is complete the software will check at some point if it is syntactically correct. You then go on to entering the next rungs one after another until you have your complete program. 55 Instruction List An alternative representation is something called "instruction list", although various vendors may use other terms. This is a text representation that looks like a sort of assembly language. However, it's actually really ladder, just shown in a different way as text and some types of programming software will allow you to toggle between ladder and instruction list mode, translating between them automatically. 56 This should give you a clue as to how a PLC can execute a schematic diagram. Behind the scenes the programming software will translate the diagram into instruction list, and then the PLC will either execute those instructions in an interpreter, or compile them to machine code and execute those. 57 Other Programming Languages There are other programming languages, but they are rarely seen. I won't go into detail in terms of describing them, just briefly mention them. 58 One is called Sequential Function Chart. This is a type of flow chart which is designed to show complex sequences, including ones with alternate or parallel paths. The original name for this is Grafcet, spelled G R A F C E T. This stands for "Graphe Fonctionnel de Commande Étape Transition". As well as being a programming language, it is also a very good design and analysis tool even if the PLC being used doesn't support it. 59 Another is Function Block Diagram. This is another graphical language which resembles flow diagrams used in process industries. This is supposedly used mainly in industries such as chemical manufacturing. However it appears to be very niche and most people who use PLCs will never have seen it, and many will not have even heard of it. 60 Yet another language is Structured Text. This is very obviously derived from Modula-2 and strongly resembles it. If you are not familiar with Modula-2, it was created by Nikolas Wirth and intended as the successor to Pascal, which it was derived from. Structured Text seems to be much loved by a small number of academics, but seems to have little actual use in the field. You lose pretty much all of the monitoring and debugging facilities built into a PLC if you use it, so it's kind of pointless except perhaps for a few niche applications. There are a few other languages as well, mainly proprietary ones, often using flow charts or the like. 61 PLC Languages are Non-Blocking The important thing about a PLC program is that it executes from top to bottom, left to right, without stopping or blocking. There is no waiting on input or output or for a system call to return. Each rung immediately yields a result which is written to a memory address or which enables a timer or counter. Every rung is executed every scan. 62 You can reproduce this in a traditional computer programming language. In ladder logic it is inherent to the syntax and it is either very difficult or impossible to do it any other way. I'll give an example in Python of what I mean. 63 a = (b or c) and not d 64 If b or c are true and d is false, then a is set to true. If b and c are false or d is true, then a is false. 65 Now imagine that we are not executing this statement once, but rather are executing it repeatedly. This statement will never block execution. It will always immediately yield a result. Now let's modify that a bit. 66 a = (b or a) and not d 67 Note that we have replaced c with a. Now the value of a depends the previous value of a as well as b and d. However, once a becomes true, the value of b no longer matters because b is in an or condition with a. Now if we execute it over and over again, only d becoming true will make a go false. 68 This is a standard push button circuit, also known as a "seal in circuit", because it "seals" around the start condition. 69 b is the start push button with a normally open contact. d is the stop push button with a normally closed contact. a is a relay with one of its contacts being used to hold it on. 70 If you wired this up with actual push buttons and relays or if you programmed it into a PLC with ladder logic it would work the same way. A PLC program will consists of rung after rung of logic like this and executes it repeatedly scan after scan, only pausing to update its I/O. 71 Async Programming Some of you may be thinking that this cyclical scan sounds like the async programming that is all the rage with web server applications these days. Essentially it is exactly the same principle. 72 With async programming, your program must never use blocking instructions and execution proceeds on a repeated cycle. PLCs solve this by not having any instructions which block, and many PLCs do not allow backwards jumps. Tradesmen in coveralls in factories were doing async programming decades before the cool kids heard about it. 73 Most PLC Programming Languages are Visual or Graphical Languages If ladder, Sequential Function Chart, or Grafcet and Function Block Diagram sound like visual programming languages, they are. In fact ladder is probably one of the earliest visual languages in commercial use. Wikipedia defines a visual programming language as: 74 In computing, a visual programming language (visual programming system, VPL, or, VPS), also known as diagrammatic programming, graphical programming or block coding, is a programming language that lets users create programs by manipulating program elements graphically rather than by specifying them textually. A VPL allows programming with visual expressions, spatial arrangements of text and graphic symbols, used either as elements of syntax or secondary notation. For example, many VPLs are based on the idea of "boxes and arrows", where boxes or other screen objects are treated as entities, connected by arrows, lines or arcs which represent relations. VPLs are generally the basis of low-code development platforms. Scratch is an example of a VPL 75 End of quote. As you can see, what is cool today was on the factory floor more than 40 years ago. -------------------- 76 Popularity of PLC Programming Languages PLCs are about as proprietary as you can get. Pretty much every vendor has his own proprietary take on each language. How you can program any particular PLC is determined by that vendor's programming software. If the vendor doesn't support it, you can't use it. An individual vendor may even have multiple incompatible product lines which have to be programmed in different ways with different software, although that is not as common these days as it once was. 77 Nearly all PLCs support programming in Ladder. Some support programming in instruction list as well as ladder. Anything else is much less common. 78 Ladder logic happens to be on the Tiobe Index by the way. For those who have not heard of it, the Tiobe Index, that is T I O B E, is a web site that lists the popularity of numerous programming languages based on various criteria. 79 Number one on their list happens to be Python, currently at 19.98%. Number two is C, at 11.55%. 80 At the time of writing this script, Ladder Logic was at number 46 with a 0.28% rating, which put it just below Erlang and just above Haskell. I'm not sure whether that means that Ladder Logic is not as obscure as you thought it was, or whether it means that Erlang and Haskell are in fact more obscure than you thought they were. -------------------- 81 Episode Summary In this episode we covered we covered The early history of computers in industrial control The early history of PLCs, including how they got their name Who the major brands are What they look like physically 82 A basic description of the abstract machine architecture A very brief look at what a PLC program is like The scan concept The main PLC programming languages The minor PLC programming languages The relative popularity of each of the programming languages 83 In the next episode we will take a look at one of the early PLCs from the era when they began seeing widespread use. This PLC was hugely successful and was for many companies the first PLC they used. This is the Allen Bradley PLC2. 84 This has been the second episode in an 8 part series. -------------------- Provide feedback on this episode.

    HPR4717: Visit with a blind Ham operator

    Play Episode Listen Later Sep 1, 2026


    This show has been flagged as Clean by the host. Hi, this is Archer72 for another episode of Hacker Public Radio. In this episode, it is my first experience troubleshooting with an experienced blind Ham operator who is located 20 miles away from my hometown. When traveling there, I could not miss his house, which was the only one off the main road with an estimated 50 foot antenna. That's 15 meters for the rest of the world. This antenna was intended for the HF high frequency band, for which the local Ham radio club had very recently extended to this height. The target radio bands are 20, 40 and 80 meters. I had missed a great opportunity to record the session so wanted record (and write this) while it was fresh on my mind. Several months later… This particualar operator (KG4QWH) (Kilo-Golf-Four-Quebec-Whiskey-Hotel) was a radio operator for the local emergency services for 22 years, after which the new company decided to cut back on staff. A local broadcast radio station was hiring soon after and was using some version of Linux which was not accessible for a blind user like himself. This conversation was started after I was asked about his computer that he was trying to force update on older hardware from Windows (7?) to Windows 11, in true hacker fashion. While talking about the Linux situation and also the Windows side, it brough to light the glaring (near) ommision of accessibility software in both camps. On the Windows side, which is more familiar to my friend, is Jaws. Great software, but year after year the barrier of cost is getting more, and on the Linux side accessibility is not looking any better. While cost is not a factor in using it, and this is only coming from me, the voices could be better. Piper is an option for natural sounding voices, but has yet to be integrated into a FOSS screen reader AFAIK. On the positive side of accessibility, the Kenwood radio (model TS-590S) has the option to add a module to give an audible description of the buttons being pressed, and at the time there was gnother operator who came through and talk him through some receiver settings. The reason I went there is the first place was that the Kenwood microphone was causing noise to come across the speaker when he keyed up the mic. Initially the proprosed solution was to switch two wires inside the Kenwood microphone. I was asked about this ahead of time so was prepared with an electrical box with miscellaneous low voltage wires and stripping tool, also a Pincil soldering iron equiped with a USB C 100 watt power supply. To fix the problem on the Kenwood MC-60 microphone, you need to swap the wires so that mic hi is on Pin 1 and mic low (shield) is on Pin 7. This is often necessary due to factory wiring errors. After finding out that the proposed solution was to open the mic, which required a heat gun the soften the locktight, I tried another route. My friend had a toroid choke handy, and I coiled the feed line to the back of the radio around the toroid. (8 - 10 times?) This had no effect. Next to try was to ground the mic from the outside, which there was a bare metal screw on. This connected to a dedicated ground on the back of the Kenwood TS-590S radio. This seem to suppress the hum when using PTT. The rest of the evening (the best time for HF), Matthew was able to make contacts on 40 meters. Great to meet you as well my friend and I appreciate you coming up. I was able to talk on 40 this evening with no problems. I reached several in Kentucky Indiana and I even reached Kansas. Come to think of it. I was even able to reach someone on the Jersey shore. References Blind Hams Network New CQ Blind Hams Podcast: CQBH 011 TS-590SG Tutorial by N3AIN New CQ Blind Hams Podcast: CQBH 012 TS-590SG tutorial by N3AIN KENWOOD TS-590S instruction manual KENWOOD VGS-1 instruction manual KENWOOD Communications Microphone MC-60A Instruction Manual Image of a 15 meter HF antenna on a two story house in Kentucky. Provide feedback on this episode.

    HPR4716: PocketMod

    Play Episode Listen Later Aug 31, 2026


    This show has been flagged as Clean by the host. Last week, I discussed the "Second-Hand phone" approach to digital minimalism. In that episode I mentioned a calendar-making site "Pocket-Mod" Here is a review. the site: https://www.pocketmod.com.Provide feedback on this episode.

    HPR4715: friedcamp interviews part 2: Thomas Farstrike

    Play Episode Listen Later Aug 28, 2026


    This show has been flagged as Clean by the host. MicroPythonOS https://MicroPythonOS.org/ https://github.com/MicroPythonOS/MicroPythonOS Thomas Farstrike https://github.com/ThomasFarstrike Provide feedback on this episode.

    HPR4714: HPR Beer Garden 18 - Amber Ale

    Play Episode Listen Later Aug 27, 2026


    This show has been flagged as Clean by the host. The HPR Beer Garden returns for it's eighteenth episode with a look at Amber ales. Dave tries out Hobgoblin Amber , whilst Kevie samples Banks's Amber . Connect with the guys on Untappd : Dave Kevie The intro sounds for the show are used from: https://freesound.org/people/mixtus/sounds/329806/ https://freesound.org/people/j1987/sounds/123003/ https://freesound.org/people/greatsoundstube/sounds/628437/ The next three beer styles to be reviewed are: lager mild bitter Provide feedback on this episode.

    HPR4713: July2026 Community News response, and Future Plans

    Play Episode Listen Later Aug 26, 2026


    This show has been flagged as Explicit by the host. The show I'm responding to https://hackerpublicradio.org/eps/hpr4696/index.html The Album I plan on reviewing in the future (not the best album to start with getting into noise, but it's one of the more famous ones) https://open.spotify.com/album/2T2a5nzJ0uHJVhLkgiMeYA Reading on why I will never review anything by Boyd Rice (also if you don't mind paying for a patreon, the podcast The Empire Never Ended did a patreon exclusive episode on Boyd Rice and his ties to Neo-Nazi and Neo-Fascist groups) https://spencersunshine.com/2024/05/21/boyd-rice-neo-nazi-collaborator-video/Provide feedback on this episode.

    HPR4712: friedcamp interviews part 1: Wim van Gool

    Play Episode Listen Later Aug 25, 2026


    This show has been flagged as Clean by the host. Fri3d Camp is a biennial family-friendly summer camp for hackers, creators and do-it-yourselfers. https://fri3d.be/wat/ campbadge at fri3dcamp 2026: https://fri3d.be/en/badge/ Hardware design: Wim van Gool: https://mastodon.social/@wimvangool Contact: badge@fri3d.be Software design: MicroPythonOS Thomas FarstrikeProvide feedback on this episode.

    HPR4711: Second-Hand Phone

    Play Episode Listen Later Aug 24, 2026


    This show has been flagged as Clean by the host. I have a second phone. I use it for my family, close friends, and my sanity to keep my smart phone at bay. It is inexpensive and can be extremely useful. In this podcast, I discuss "Why," "Benefits," "Drawbacks," and "Rules" that I have in place. If you are looking for a way to get away from the daily rigors of smartphone use, this may be your episode. Provide feedback on this episode.

    HPR4710: Civilization VI

    Play Episode Listen Later Aug 21, 2026


    This show has been flagged as Clean by the host. Civilization VI, released in 2016, was a further evolution of the franchise that added interesting new features. We introduce it in this episode. Civilization VI Released in 2016, Civ VI is probably still the most played version of the game. Although there has been a general gap of 5-6 years between versions, the effects of the Covid-19 pandemic slowed down many things. Since early 2025 we have had Civilization VII come out, but in my opinion it is still being tweaked and refined. In the meantime, Civilization VI is the game I play now when I play Civ. I've played all of them from the first, and put in many hours here. Since I now play Civ on Steam mostly, I have statistics! I played Civ V for a total of 769 hours, and so far I have played Civ VI for 689 hours, but since this is what I play for now I will probably exceed my Civ V hours pretty soon. BTW, I probably have well over 1000 hours on Civ II, which I think I have played the most, and certainly more than 3000 hours total over all all versions. I'm going to cover this without worrying too much about whether it is the base game or an expansion. Fact is, Firaxis have started moving to something more akin to a subscription model when they introduced the New Frontier Pass, which works very well when you are on Steam. The idea was that you bought this pass, and very few months got new content, and on Steam it would automatically be downloaded to your account. That is not to say that there weren't actual expansions, but since the last thing they released was this “pass”, i'm kind of wondering what they will do with Civ VII. In any case, let's take a look at this. Gameplay Again, you start with a tribe in 4000BC which founds your first city, and you immediately begin building units, exploring, researching, and developing your city. this is a time-tested mechanic that never changes. but there are some interesting changes that make this game fascinating. First, in the earlier versions of Civ you thought of yourself as playing a particular civ, which came with a particular leader. In different versions of Civ the name of the leader might change, like for France you might have Napoleon on some versions, or Joan of Arc in another, but in each case one civ gets one leader, so you tended to think of yourself as playing the nation. Rome might be Caesar in one version, Augustus in another, or Trajan in yet another. (Fun fact: Sid Meier says he always plays as Rome because it just feels right to him). In Civ VI this linkage is broken. One leader, Eleanor of Aquitaine, can be played as the Queen of England, or she can be played as the Queen of France. And each version has different abilities and strengths. If you want a fairly easy Culture victory, play her as Queen of France, and watch as other players' cities rebel and join your Empire because they admire you so much. Teddy Roosevelt also has two different manifestations, Rough Rider Teddy, and Big Stick Teddy, when you have all the expansions. China has two possible leaders, with different strengths: Qin Shi Huang, and Kublai Khan. And Kublai Khan can be either Chinese or Mongolian, with different strengths. So in Civ VI you don't think of what Civ you want to play, you think of which leader you want to play. Every leader comes with a Civilization Ability, a Unique Unit, and a Unique Infrastructure. These matter a lot. For example, take John Curtin, the leader of the Australian civilization. His Civilization Ability is called Land Down Under, and it gives him +3 Housing in coastalcities. Building a Pasture triggers a Culture Bomb, claiming surrounding tiles. Campus, Commercial Hub, Holy Site, and Theater Squaredistricts gain +1 to their yields in tiles with Charming Appeal, and +3 in tiles with Breathtaking Appeal. Then his Unique Unit is the Digger, a melee military unit that replaces the Infantry unit. And his Unique Infrastructure is tile improvement called the Outback Station. This gives you increased food, production, and housing, some of which varies according to what is on surrounding tiles. The point is that each leader gives you very specific advantages that you should play to. In Civ VI it is even more important to tailor your strategy to the particular leader. Leaders like Frederic Barbarossa or Simon Bolivar are very good for Domination, while Peter the Great and Saladin are very good for Religious victories. If you take a random leader be ready to adapt your play style and strategy to fit, or alternatively decide what kind of victory you want to achieve and pick a leader who is good at it. Or if you want a real challenge, pick a leader who is not suited to the victory condition you are aiming at. But keep in mind that the game may take you in places you didn't expect. One game I picked Wilfrid Laurier of Canada, who is ideal for Diplomatic and Cultural victories, and I thought I would be going for a Cultural victory. But Wilfrid's strengths come from his advantages on Tundra land tiles, and I somehow managed to spawn in the middle of the map with no Tundra tiles at all in my empire. I had work hard to manage a Science victory in that case. Districts This is a major change in Civ. In earlier versions you built buildings inside of cities, and you tended to build the same buildings in most or all cities. You were only limited by your ability to generate Production to get them done. Civ VI is different. You have to place Districts on specific tiles, and and you can then develop the district with added buildings. If you want to develop your industry, you can place an Industrial Zone, and then add a Workshop, then a Factory, then a Power plant, and so on, each one increasing your Production. For Science you place down a Campus District, then a Library, then a University, then a Research Lab. And the game mechanic means you cannot built everything in every city. You can place one district at the start, then one more when your city reaches a population of 4, then a third one when you reach 7, and so on with each added population of three allowing one more district. The point is to force you to make choices. Districts get adjacency bonuses which increase their output. The Campus (generates Science) and the Holy Site (generates Faith) both benefit from adjacent Mountains, and the effect is additive. So if you find a tile with three mountains around it, you will want to place one of these districts there. Districts also get adjacency bonuses from other districts, so the planning the layout of your cities is really important to maximize these bonuses. And they can get bonuses even with adjacent Districts that belong to a different city! Another key district is the Encampment, which let you build better, more veteran military units. Since building units requires Production, you should build build an Encampment in a city which has a lot of Production, and that probably means one with an Industrial Zone. A Harbor District would go in a city with coastal tiles, of course. All of this requires planning. Expert players will usually start out by exploring to see what the map looks like around them, what terrain features they have to work with, what resources are available, and so on. Then, around turn ten they will plan out their next cities, and figure out where they want to place districts and so on. There is a built-in “map pin” system for this, and it can be improved by installing the right mod. While you don't have to do this, it does help you to be successful. Maps and Terrain Terrain features matter a lot in this game. We already mentioned adjacency bonuses of Mountains for Holy Sites and Campuses, but there is much more. The map is divided into Continents, and it is quite normal for a contiguous land mass to contain two or more continents if it is large enough. Think of how Europe and Asia are really just one large land mass to see what I mean. This matters because certain units may defend differently depending on which continent they are on, or some civilizations may be affected from having cities on a different continent. Terrain features like Rivers are extremely important for the placement of cities because they provide fresh water. You can sometimes get around that by building an Aqueduct to bring water from a Lake or a Mountain, but that means using up one of your city tiles, and spending production to build it. If you can place your city on a river you can avoid that problem and get off to a fast start. But the downside is that rivers can flood, and that can wreck your improvements. A big idea for terrain is Appeal. Each tile has an Appeal level ranging from Disgusting to Breathtaking, and it is determined by a combination of the tile's features themselves and by adjacencies. The modifiers are added together to determine the Appeal level of the tile, and there is a lens you use to view your Appeal levels on all tiles, which are color coded. This matters particularly if you are trying for a Culture victory. Culture victories are own by generating Tourism, and while some that can come from things like Museums and Wonders, you will really want to maximize your Tourism to win this game, and two good ways to do that are building National Parks and Seaside Resorts. You can only do that if the appeal is at least Charming (or even better, Breathtaking). If you find you cannot build them in what seems like a good spot, chances are Appeal is the problem. So check that out. You can, for instance, remove marshes (which give negative appeal), and plant forests (which add appeal), and that might be all it takes to get these going. The underlying issue in managing your cities is that you only have so many tiles, and a tile that might be great for a farm might also be great for a District. You need food to grow, and you need to grow to put down Districts, so you are always making choices about this, and that is what makes this a great strategy game. Other Resources Civilization 6 Tutorial: In Game Settings Links https://www.pcgamesn.com/civilization-vii/narrative-lead-job-posting https://civilization.fandom.com/wiki/Qin_Shi_Huang_(Civ6) https://civilization.fandom.com/wiki/Kublai_Khan_(Chinese)_(Civ6) https://civilization.fandom.com/wiki/Housing_(Civ6) https://civilization.fandom.com/wiki/Coastal_(Civ6) https://civilization.fandom.com/wiki/Pasture_(Civ6) https://civilization.fandom.com/wiki/Tile_(Civ6) https://civilization.fandom.com/wiki/Campus_(Civ6) https://civilization.fandom.com/wiki/Commercial_Hub_(Civ6) https://civilization.fandom.com/wiki/Holy_Site_(Civ6) https://civilization.fandom.com/wiki/Theater_Square_(Civ6) https://civilization.fandom.com/wiki/District_(Civ6) https://civilization.fandom.com/wiki/Appeal_(Civ6) https://civilization.fandom.com/wiki/Continent_(Civ6) https://www.youtube.com/watch?v=lkas_uiq_fk https://www.palain.com/gaming/civilization-vi/ Provide feedback on this episode.

    HPR4705: Free Software Is Wasted On You Teens

    Play Episode Listen Later Aug 14, 2026


    This show has been flagged as Explicit by the host. Freedom 0–3 (verbatim reference) The four freedoms, GNU/FSF: https://www.gnu.org/philosophy/free-sw.html Richard Stallman: https://www.stallman.org/ Named FOSS figures (freedom 3 list) Linus Torvalds (Linux): https://en.wikipedia.org/wiki/Linus_Torvalds Dries Buytaert (Drupal): https://dri.es Guido van Rossum (Python): https://gvanrossum.github.io Ian Murdock (Debian): https://en.wikipedia.org/wiki/Ian_Murdock Brian Behlendorf (Apache): https://en.wikipedia.org/wiki/Brian_Behlendorf Miguel de Icaza (GNOME/Mono): https://en.wikipedia.org/wiki/Miguel_de_Icaza Infrastructure block (post beer 1) curl / Daniel Stenberg: https://curl.se and https://daniel.haxx.se xkcd 2347 (dependency comic): https://xkcd.com/2347/ xz backdoor, CVE-2024-3094: https://en.wikipedia.org/wiki/XZ_Utils_backdoor Andres Freund's original disclosure: https://www.openwall.com/lists/oss-security/2024/03/29/4 Licensing block (beer 2–3) GPL: https://www.gnu.org/licenses/gpl-3.0.html MIT License: https://opensource.org/license/mit FreeBSD: https://www.freebsd.org macOS/Darwin BSD lineage: https://en.wikipedia.org/wiki/Darwin_(operating_system) PlayStation using FreeBSD (Orbis OS): https://en.wikipedia.org/wiki/Orbis_OS Industry acquisitions (beer 4) Microsoft acquires GitHub, 2018, $7.5B: https://news.microsoft.com/2018/06/04/microsoft-to-acquire-github-for-7-5-billion/ FOSDEM field report (beer 4–5) FOSDEM: https://fosdem.org Ladybird browser / Andreas Kling: https://ladybird.org Godot Engine: https://godotengine.org Home Assistant: https://www.home-assistant.io Redis → Valkey fork: https://valkey.io Terraform → OpenTofu fork: https://opentofu.org Homework block (beer 5) Ollama: https://ollama.com Codeberg: https://codeberg.org LibreOffice: https://www.libreoffice.org Firefox: https://www.mozilla.org/firefox Provide feedback on this episode.

    HPR4704: HPR Beer Garden 17 - Double DDH IPAs

    Play Episode Listen Later Aug 13, 2026


    This show has been flagged as Clean by the host. In the seventeenth episode of the HPR Beer Garden, the guys look at a beer style (or label) that has recently appeared from across the pond: DDH IPA. Kevie tries out Smug DDH IPA by Northern Monk , Paul samples Hazy Jaipur by the Thornbrige Brewery and Dave enjoys Pinball by Brewdog . Connect with the guys on Untappd : Dave Paul Kevie The intro sounds for the show are used from: https://freesound.org/people/mixtus/sounds/329806/ https://freesound.org/people/j1987/sounds/123003/ https://freesound.org/people/greatsoundstube/sounds/628437/ The next 3 beer styles to be reviewed: Amber Ale Lager Mild Provide feedback on this episode.

    HPR4703: Ebooks and Audiobooks

    Play Episode Listen Later Aug 12, 2026


    This show has been flagged as Clean by the host. I tend to prefer Ebook and Audiobooks to physical books, and these are some of the apps I use, and some of the sources I go to to find Ebooks or Audiobooks. These can be inexpensive, or in the case of Public Domain, free. Ebooks and Audiobooks I no longer wish to devote space to accumulating and storing physical books. As a former college professor I had more of them than most people, and tended to fill the house with bookcases and shelves. That made a certain sense in the pre-Internet years since I would often want to go back to them to look up things. But now I have more information at my fingertips than I ever had in those days, and I find it more convenient to just look up anything I need to know. And with Ebooks I can take my library with me anywhere I go. This means if I am sitting in a waiting room for a Doctor's appointment (and at my age that happens often enough) I can just pull out my phone and open up a book. I always have at least one. Right now on my phone I have apps for Kindle , Google Play , Barnes & Noble Nook , Kobo Cantook (successor to Aldiko), Bookshop.org , and Calibre . As for devices other than my phone, I own a kindle, I once owned a Nook, and I will buy a Kobo reader when Trump is gone. Kobo is Canadian, and last time I looked Trump had put on a tariff that was twice what the device costs. And finally I have the Bookshop.org app and Calibre. I started collecting Ebooks some years back, and at first the only option seemed to be buying them from large corporations. That has changed now, but I still have collections On Kindle, Google Play, Nook, and Kobo. I have all four because it seemed prudent to not put all my eggs in one basket. But now there are other options. One I like to use when possible is Bookshop.org. It is group of independent bookstores and I would rather support them than some giant corporation. And they seem to have all of the popular titles. Another similar site is Books-a-Million , which lets you order online and pick up at a local store if you need a physical book. Cantook and Calibre are both good for holding any miscellaneous Ebooks you have, and you can give them your Ebooks from the other sellers, though I have found that the native apps tend to work better. These days I rarely purchase books on Kindle, etc. But sometimes they have a special deals. If you want to build your library, there are some good places to try. One is BookBub which will send you emails with deals on books. On any one e-mail you may not see anything you want, but I found that once or twice a month I did see books I wanted and at good prices. And Books-a-Million has 99 cent deals to check out. But if you want to get free books, you have several options. If you want a chance to read a popular Ebook but don't need to own it, see what your local Library offers. Mine offers Hoopla which is good for Ebooks, Audiobooks, and streaming music. What you can find depends on what your library has in its collection, but my wife uses it almost daily for audiobooks. Then there are the works that have become part of the Public Domain. This varies somewhat by your country, but you might be surprised to learn how much is available. For Ebooks one of the biggest sites is Project Gutenberg . They follow US Copyright law for their collection, and they are a non-profit that can always use some support, so if you use them, give them a few Dollars or Euros. They tend to be the source for many or most other sites for Public Domain Ebooks They have over 75,000 free Ebooks. A newer site is Faded Page which is much smaller but focused on Canadian works. Standard Ebooks is a site that pulls from Project Gutenberg but does some additional formatting and is very easy to read online in your browser. For Audiobooks a good source is Open Culture , which advertises it has 1,000 free Audiobooks. We should also mention LibriVox , which also pulls from Project Gutenberg for its texts, but then turns them into Public Domain Audiobooks. They are always looking for volunteers who have a microphone and a computer to record Public Domain audiobooks. And last but not least the Internet Archive has tons of Ebooks and Audiobooks that are free. Links https://www.amazon.com/kindle/ https://play.google.com/store/books?hl=en_US&pli=1 https://www.barnesandnoble.com/b/ebooks-nook/_/N-8qa https://www.kobo.com/us/en?srsltid=AfmBOoquJmiNH_aVTUx22AIRlBH8CF4iir4H8qpTKjQ4dZ-fSMCDAaD7 https://market.cantook.com/ https://bookshop.org/ebooks https://calibre-ebook.com/ https://www.booksamillion.com/ https://www.bookbub.com/ https://www.hoopladigital.com/ https://www.gutenberg.org/ https://www.fadedpage.com/ https://standardebooks.org/ https://www.openculture.com/freeaudiobooks https://librivox.org/ https://archive.org/ https://www.palain.com/ebooks-and-audiobooks/ Provide feedback on this episode.

    HPR4702: MakeACopy is an open-source document scanner app for Android

    Play Episode Listen Later Aug 11, 2026


    This show has been flagged as Clean by the host. MakeACopy MakeACopy is an open-source document scanner app for Android that allows you to digitize paper documents with OCR functionality. The app is designed to be privacy-friendly, working completely offline without any cloud connection or tracking. Features Camera Scanning : Capture documents using the device camera Edge Detection : Automatic document edge detection using OpenCV, enhanced with an ONNX model (DocAligner) Perspective Correction : Adjust and crop documents with manual or automatic perspective correction Image Enhancement : Apply filters (grayscale, contrast, sharpening) OCR : Offline text recognition with Tesseract OCR Review : Interactive review and correction of OCR results with word-level editing, dictionary-based suggestions, confidence highlighting, and re-OCR for individual words PDF Export : Save as searchable PDF with recognized text JPEG Export : Export scans as high-quality JPEG images (configurable quality, color/BW) Multi-page Scanning : Combine multiple pages into one document; reorder and manage pages before export Last Scans : Quickly access and reuse your most recent scans Share & Save : Export locally or share with other apps Dark Mode : Material 3 theme with day/night support Privacy-Focused : 100% offline functionality, no internet connection required Provide feedback on this episode.

    HPR4701: Elsbeth muses with Lee on her experiences and opinions on AI

    Play Episode Listen Later Aug 10, 2026


    This show has been flagged as Explicit by the host. Overview: Elroy sits down with Elsbeth to unpack her perspective on AI ethics — where the technology helps, where it risks harm, and what responsible use actually looks like in practice. Topics covered (In no particular order, as the rabid squirrels of Elsbeth's AuDHD brain don't do "order"): Elsbeth's path into AI evaluation and content moderation, and how that shaped her thinking on ethics in practice What "ethical use" of AI means day-to-day, not just in the abstract Respecting intellectual property — the case for protecting artists and creators as AI tools become more capable and widespread Finding the balance: supporting AI's genuine benefits without letting them come at creators' expense AI as an accessibility tool — its particular promise for neurodivergent people, and where it can lower barriers others don't face Where the conversation is heading next, and what listeners should watch for Closing thoughts: Elsbeth's take is one of cautious optimism — a call to hold both truths at once: AI can do real good, and that good has to be built on respect for the people whose work made it possible. Further Reading & Resources On AI, Ethics, and Intellectual Property AI and Intellectual Property in 2026: why transparency and court rulings will define the next phase of governance — The AI Journal https://aijourn.com/ai-and-intellectual-property-in-2026-why-transparency-and-court-rulings-will-define-the-next-phase-of-governance/ Global laws governing intellectual property rights for AI-generated works — Discover Artificial Intelligence, Springer Nature Link https://link.springer.com/article/10.1007/s44163-026-01165-8 AI and IP laws 2026: Understanding Authorship and Ownership legalities — AnalystIP https://analystip.com/ai-and-ip-laws-2026-authorship-ownership-explained/ AI Art in 2026: The Ethics, Law, and What Artists Should Know — UrduPure https://www.urdupure.com/blog/ai-art-in-2026-the-ethics-law-and-what-artists-should-know On AI and Neurodivergent Accessibility Navigating Neurodivergence with AI Chatbots: Benefits, Tensions, and Implications for HCI — CHI 2026 Conference Proceedings https://dl.acm.org/doi/10.1145/3772318.3791334 Is AI making work more accessible for neurodiverse people? — Everway https://www.everway.com/en-gb/blog/is-ai-making-work-more-accessible-for-neurodiverse-people/ Autoethnographic Insights from Neurodivergent GAI "Power Users" — NCBI/PMC https://www.ncbi.nlm.nih.gov/pmc/articles/PMC12645485/ A scoping review of inclusive and adaptive human–AI interaction design for neurodivergent users — Disability and Rehabilitation: Assistive Technology https://www.tandfonline.com/doi/full/10.1080/17483107.2025.2579822 Show rated *explicit* for possible course language and strong opinions. Provide feedback on this episode.

    HPR4700: Robert A. Heinlein: The Juveniles

    Play Episode Listen Later Aug 7, 2026


    This show has been flagged as Clean by the host. Heinlein wrote a series of books under contract to Scribners that were aumed at younger readers, pre-teen and teen. Today we would call them Young Adult, but back then they were called Juveniles. But even an adult reader can enjoy many of these books. Because they were aimed at younger readers, he could not always be as explicit as he might have liked, but if you pay attention you just might noticed he slipped in something subversive. Heinlein: The Juveniles As a boy I read voraciously. I remember my mother organizing weekly trips to the town library, where I would load up on books, and I quickly became focused on Science Fiction, along with the usual stuff kids read, like the Hardy Boys, Tom Swift, and the Walter Farley horse books. But the idea of going into space grabbed me very early. And one of the first authors I read was Heinlein. He had taken a leave from publishing during World War II, when he was doing research at the Philadelphia Navy Yard. But when the war was over, he set out to move beyond the “pulps” and expand the market for his stories. And one big market for him was what were called “juveniles” at the time, and would today be called “Young Adult”. I was reading adult fiction by the time I was 11 or 12, but before that (and even after that, in fact) I read these Heinlein novels with great relish. Heinlein's target audience for these novels was teenage boys. He did a few stories aimed at girls, but mostly he wrote for boys. And these were mostly “coming of age” stories where the teenage protagonist has adventures, and as a result grows and develops. They are very loosely related via some internal references, but should really be thought of as stand-alone stories. They also in some cases have references to his other stories, including the Future history stories. He wrote 13 of these novels, one per year, from 1947 to 1959. The series was published by Scribners until the last one was rejected by them. Heinlein then published it with a different publisher, and stopped writing these novels altogether in favor of more adult fiction. The novels roughly form a progression telling the story of space exploration. It starts with a trip to the Moon, then Venus, Mars, Jupiter's moon, and so on until we reach the Lesser Magellanic Cloud. Rocket Ship Galileo (1947) – While readable, this initial effort was not up to Heinlein's later standards. The plot concerns three teenagers who assist an uncle to build a rocket ship and go to the Moon. When they get there they discover Nazis have already arrived. The Nazis try to kill the group, but they succeed in turning the tables, stealing the Nazi ship, and returning to Earth as heroes. This novel became the basis (loosely) for the movie Destination Moon (1950), and I personally would consider the movie to be superior to the novel. It is also worth noting that the theory brought up in Blowups Happen reappears in this novel. They find evidence of an ancient Lunar civilization that was destroyed, and theorize that the craters on the moon were caused by the explosion of nuclear reactors that caused the extinction of the civilization. Space Cadet (1948) – This was in part the inspiration for the Tom Corbett franchise, which licensed the name Space Cadet from Heinlein. It is about a young man who is accepted to the Academy for the Space Patrol. It follows him through his education in the Academy, and then into his first mission after graduating. This holds up better than the previous novel. And it is tied back to the story The Long Watch from the Future History. Part of the story takes place on an inhabited Venus that is cloudy and swampy. Red Planet (1949) – This is set on Mars, as it is also portrayed in Stranger In A Strange Land (1961). Mars is inhabited by native Martians, but also by human colonists. It has the canals, and with seasonal changes the colonists migrate from north to south and back. A pair of teenage boys get caught up in a revolution when the evil corporation that controls the colony pushes the colonists too far. In the end you wish there really were canals and Martians. Farmer In The Sky (1950) – This is one of the best, as seen by the Retro Hugo this novel won in 2000. Jupiter's moon Ganymede is being terraformed because Earth is overcrowded and food is rationed. A teenage boy and his family emigrate to Ganymede and try to make a life there, which they eventually succeed in doing. The Green Hills of Earth is mentioned here, tying this into the future History. There are frequent references to the Boy Scouts, due to the fact that the story ran as a serial in Boy's Life magazine. Between Planets (1951) – A teenage boy is caught up in interplanetary intrigue. Venus and Mars have colonies, but Earth is trying to control them too much. So revolution is on the menu. This is clearly patterned in the colonial wars of the 18th and 19th centuries, such as the American Revolution against England. By this point the so-called “Juveniles” are really having more adult content, and reviewers re starting to rate them in comparison with adult science fiction. This novel was also first serialized in Boy's Life magazine. The Rolling Stones (1952) – Here we have teenage twin boys, Castor and Pollux, as the protagonists. They and their family live on the Moon, but decide to travel, so this novel is a kind of travelogue as they go to Mars, then to the Asteroid belt. The grandmother, Hazel Stone, appears in Heinlein's later works as well. One interesting episode in this story involves “martian flat cats”, which are furry, lovable, and reproduce like mad with the right conditions. If this sound like Star Trek's Tribbles, that is also what the Star Trek producers thought, so they got permission from Heinlein to use the idea. Starman Jones (1953) – We are now further into the future, and the human race is exploring the stars. Unfortunately, very restrictive guilds closely control who can participate in this. A teenage boy named Max, who happens to have an eidetic memory, has memorized the Astrogation tables from his uncle's books, and wants to join the Guild, but is turned down. He lies his way onboard a ship, and through a series of events becomes the only one who can guide the ship home. The Star Beast (1954) – A teenage boy has an alien “pet” his great-grandfather had brought back that has grown very large, and is considered a nuisance. A court decides the beast must be killed, but that proves easier to say than to do. It appears that the beast isn't even aware that people are trying to kill it. Meanwhile, a powerful and hitherto unknown alien species demand the return of one of their own, or they will destroy the Earth. Of course, it is this beast, who is actually royalty to the alien species. One interesting point is that government officials in this story are portrayed sympathetically as intelligent and dedicated. Tunnel In The Sky (1955) – In the future humanity is colonizing other planets, and a group of teenagers are taking their final survival test. They are sent to a planet and told that they have to survive for 10 days, But more than 10 days go by with no pickup, and they know something went wrong. So they have to establish their own little society to keep surviving. An interesting note is that the protagonist, Rod Walker, is black. It was never explicitly stated in the text, but Heinlein was firm in stating this. The clue is when the others expect Rod to end up with Caroline, who is explicitly stated to be black. This was Heinlein being subtly subversive. To have a black protagonist for a boy's story in 1955 in America would be impossible. but Heinlein was completely anti-racist, among other things. Time For The Stars (1956) – This is a novel that takes Relativity seriously, which was not common in the 1950s. Researchers have discovered that some twins and triplets can communicate telepathically (and instantaneously), and so when a group of ships is sent out to explore other star systems, one twin is on the ship and the other remains on Earth to provide communication. The twin on Earth ages must faster than the one in space, of course, and eventually the Earth twin dies, But they discover that the connection sometimes passes down through the family, so the protagonist, Tom Bartlett, becomes connected first to his niece, then his grandniece, and finally his great-grandniece. Citizen of the Galaxy (1957) – This book is about a future slave trade, which Heinlein strongly hated. The protagonist is a boy who is bought at a slave auction by an old beggar, but the beggar is more than he seems. He is actually spying and gathering data regarding the slave trade. When discovered, he commits suicide, but he had prepared the young boy, Thorby, who then contacts the Free Traders who spirit him away. He has to adapt to this new society, but then is delivered to the Hegemonic Guard. It turns out his “father” (i.e. the man who bought him) was an officer in this organization. And when they run the background checks, they discover that he is the heir to a large conglomerate, and that conglomerate may be implicated in the slave trade. Have Space Suit—Will Travel (1958) – Clifford “Kip” Russell dreams of going to the Moon, and enters a contest with that as the top prize. Unfortunately, he wins the somewhat lesser prize of a used spacesuit. The first few chapters focus on him doing repairs and maintenance to make it functional again, and this displays Heinlein's engineering background. It is more engaging than you might think. Then while wearing the spacesuit he receives a radio message, and he is kidnapped along with an alien called “The Mother Thing” and a young girl who is a genius. The kidnappers are a group of aliens who consider anyone not of their race to be animals. The trio first try to escape on the Moon, but are recaptured, then taken to Pluto, where they succeed in killing the alien kidnappers. Then they are taken to the Lesser Magellanic Cloud to be put on trial to determine if the human race should be allowed to live. Starship Troopers (1959) – This is the novel that Scribners rejected, and which brought the Juvenile series to an end. And it bears absolutely no resemblance at all to the movie, to the point that for Heinlein fans the word Verhoeven is considered an obscenity. A young man, Juan “Johnny” Rico joins the military, where he has to grow up and then take part in a war against an insectoid race, but that is all background really. The book is primarily a glorification of military service, which is not surprising given Heinlein's background. And it focuses on a series of discussions under the heading of “History and Moral Philosophy”, which lets Heinlein expound on his values and beliefs. The novel won a Hugo, but it is an add one given that the plot is secondary to the philosophizing. One of the most controversial ideas is that in this society the right to vote is limited to people who have been in Federal Service. Heinlein said this didn't have to be military, but the only ones we see are in fact military veterans. So, these are the Heinlein Juveniles. In my opinion, many of them are quite good reading for adults. The thing that separates them from adult novels in Heinlein's body of work is the lack of any sex element. That would become prominent in Heinlein's later adult novels, but it was not something you could put in a book aimed at teenagers, certainly not in the 1950s, and arguably the case today as well. Links https://en.wikipedia.org/wiki/Rocket_Ship_Galileo https://en.wikipedia.org/wiki/Destination_Moon_(film) https://en.wikipedia.org/wiki/Space_Cadet https://en.wikipedia.org/wiki/Tom_Corbett,_Space_Cadet_(TV_series) https://en.wikipedia.org/wiki/Red_Planet_(novel) https://en.wikipedia.org/wiki/Stranger_in_a_Strange_Land https://en.wikipedia.org/wiki/Farmer_in_the_Sky https://en.wikipedia.org/wiki/Scout_Life https://en.wikipedia.org/wiki/Between_Planets https://en.wikipedia.org/wiki/The_Rolling_Stones_(novel) https://en.wikipedia.org/wiki/Starman_Jones https://en.wikipedia.org/wiki/The_Star_Beast_(novel) https://en.wikipedia.org/wiki/Tunnel_in_the_Sky https://en.wikipedia.org/wiki/Time_for_the_Stars https://en.wikipedia.org/wiki/Citizen_of_the_Galaxy https://en.wikipedia.org/wiki/Have_Space_Suit%E2%80%94Will_Travel https://en.wikipedia.org/wiki/Starship_Troopers https://www.palain.com/science-fiction/the-golden-age/robert-a-heinlein/heinlein-the-juveniles/ Provide feedback on this episode.

    HPR4699: Sunshine, Moonlight, Playnite !?

    Play Episode Listen Later Aug 6, 2026


    This show has been flagged as Clean by the host. sunshine / xbox contlers / plex / steam / UWPHook / Bluetoothctl restart / HDMI dongle https://www.youtube.com/watch?v=FM4FbA4-W_c UGREEN USB C Hub 5 in 1 Multiport Adapter Revodok 105 4K HDMI, 100W Power Delivery, 3 USB-A Data Ports, USB C Dongle for MacBook Pro/Air, iPad Pro, iMac, iPhone 16 Pro/Pro Max, XPS, Thinkpad https://www.amazon.com/dp/B0BR3M8XHK Detached Command: @ECHO OFF cd "C:backupgamestream_launchpad" c:windowsSystem32HdrSwitcher.exe disable start /MIN gamestream_launchpad.exe 1920 1080 gamestream_playnite.ini .bindkeys rc cat .xbindkeysrc /bin/bash /home/plex/.local/bin/Plex.sh /bin/bash /home/plex/.local/bin/Steam.sh /home/plex/.local/bin/kasa --host 192.168.1.239 --port 9999 --type dimmer on; /home/plex/.local/bin/kasa --host 192.168.1.239 --port 9999 --type dimmer brightness 100;xgamma -gamma 1.3 /home/plex/.local/bin/kasa --host 192.168.1.239 --port 9999 --type dimmer on; /home/plex/.local/bin/kasa --host 192.168.1.239 --port 9999 --type dimmer brightness 40;xgamma -gamma 1.3 /home/plex/.local/bin/kasa --host 192.168.1.239 --port 9999 --type dimmer on; /home/plex/.local/bin/kasa --host 192.168.1.239 --port 9999 --type dimmer brightness 12;xgamma -gamma 1.3 /home/plex/.local/bin/kasa --host 192.168.1.239 --port 9999 --type dimmer off;xgamma -gamma 1.3" cat /home/plex/.local/bin/Steam.sh # requires wmctrl -l and xbindkeys # # xdotool windowactivate ```xdotool search --name 'window name'``` # 0 StartSteamLink(){ echo "restarting bluetooth" sudo systemctl restart bluetooth echo "Waking Game PC" sudo /usr/sbin/etherwake -i enp1s0 -D "d8:bb:c1:a2:2c:0b" echo "Starting steamlink" killall -9 steamlink killall moonlight sleep 20 # /snap/bin/moonlight /home/plex/.local/bin/Moonlight-6.1.0-x86_64.AppImage } StartSteamLink SUMMARY: Speaker discusses technical challenges with Sun Shine, Moonlight, and Play Night setups. IDEAS: Sun Shine and Moonlight enable remote game streaming. Play Night acts as a multimodal launcher for Steam. Resolution changes cause display issues during gameplay. Proper exit sequence is critical to revert settings. Ultra-wide resolutions are unusable in some configurations. Multiple launchers require separate logins for different games. Environment variables can adjust client dimensions. Background commands improve system stability. Cat named Mojo is mentioned during the discussion. 5G networks support slower-paced gaming. Technical glitches include frame drops and latency. Steam accounts are tied to specific game libraries. Detached commands run in the background without user interaction. GameStream Launchpad manages resolution and launcher paths. Magical system behavior simplifies remote gaming. Star Wars and Baldur’s Gate are cited as example games. 22nd Millie thing refers to network latency. Multiple Steam accounts complicate game access. Task killing reverts system settings automatically. Cross-platform streaming solutions are highlighted. RECOMMENDATIONS: Use environment variables for client resolution adjustments. Exit applications properly to revert settings. Set up detached background commands for stability. Monitor ultra-wide resolution compatibility. Utilize Play Night for Steam account management. Avoid multiple logins for different game libraries. Opt for cross-platform streaming solutions. Check network latency for smooth gameplay. Use bat files for automated task execution. Configure GameStream Launchpad for resolution changes. Prioritize proper task termination to prevent glitches. Test 5G networks for slower-paced gaming. Leverage environment variables for client settings. Ensure all applications exit before shutting down. Use detached commands for background processes. Verify resolution compatibility with ultra-wide displays. Combine Sun Shine and Moonlight for reliable streaming. Log in once for multiple Steam accounts. Address frame drops in low-latency networks. Stream games universally across platforms. Provide feedback on this episode.

    HPR4698: ID3 Tags and Vorbis Comments

    Play Episode Listen Later Aug 5, 2026


    This show has been flagged as Clean by the host. -------------------- 01 Introduction In a response to a post on a previous episode, I said that I would take a look at ID3 tags. ID3 tags are text information that is added to an MP3 audio file, such as the author, date, name, and other information. 02 While I am at it I will also look at Vorbis comments, which perform a similar function for vorbis, the container format for "ogg" audio files. As example audio files, I will use a recent HPR episode, hpr4678 in both mp3 and vorbis formats plus also one from another podcast as well. 03 There is Free Software which you can use to view, edit, or remove both types of tags or comments, and I will describe how to use it in this episode. 04 I will cover how to view tags and extract the text information, as well as how to strip the tags from a file and why you may wish to do so under certain very specific circumstances. I won't cover how to add to or edit tags in an MP3 or OGG file, as that is a more involved subject that I don't have much experience with. 05 I will mainly talk about ID3 MP3 tags rather than vorbis comments for the simple reason that the situation with MP3 files is an utter mess while vorbis comments are very straightforward and so there isn't as much to say about them. 06 As often happens when researching a subject to write a podcast script, I have learned quite a bit that I didn't know previously, and discovered that things that I thought I did know were wrong. I hope that you may learn a few things from this episode that you didn't know previously either. -------------------- 07 Background I won't go over the detailed history of ID3 tags, as I don't have a reliable source for this. Briefly however, so far as I can determine, there is no official independent standard for ID3 tags or vorbis comments. Both seem to be more in the nature of a convention that was created by an unofficial group of contributors rather than something issued by a standards body. 08 However, I don't see the lack of a conventional standards body as necessarily a problem with respect to the use of ID3 tags or vorbis comments. I just am not familiar enough with the industry to know who to regard as being an authoritative source when it comes to the history and development of them Since I am unsure as who to credit with what developments, I will avoid that sort of detail. 09 ID3 Tags There is a web site with the URL of ID3.org that seems to have the best reference material on the topic of ID3 tags. According to this site, the term "ID3" means "IDentify an MP3". 10 Vorbis Comments For vorbis, the reference site seems to be xiph.org. Although the implementation details may differ from ID3, from our perspective as podcast listeners, they can be seen as more or less equivalent in terms of what I am going to address here. -------------------- 11 ID3 Details Versions One of the problems with ID3 is that there are multiple incompatible versions, particularly from the very early days. ID3v1 tags are located at the end of the audio file in the last 128 bytes. This was done for compatibility reasons to allow early MP3 players to simply ignore the tags if they didn't know how to deal with them. The tags would simply appear as a short burst of static from the perspective of these early players. 12 ID3v2 moved the tags to the start of the MP3 file to allow players to scan the tags for information such as titles without having to read to the end of the file to find them. There are far fewer limits on the amount of information that can be placed in ID3v2 tags. 13 ID3v1 is obsolete and only very old players will require it. However, it is still used by some publishers for backward compatibility reasons. ID3v1 included numerical musical "genre" category codes which apparently turned out to be a very bad idea in practice. 14 Furthermore, all genre categories above 70 were defined by an audio software company called Nullsoft who created software such as Winamp. These codes were never actually part of the ID3 standard, although there was never really a standard to begin with. 15 The current ID3 version is 2.3. There is a version 2.4, but apparently it is not actually generally accepted and may be a developmental dead end. 16 The id3.org web site contains a copy of the ID3v2.3 standard, but I am not going to address the technical details here. This would only be of interest to someone who was creating software to read and write ID3 tags. 17 ID3v2 Frames The ID3v2 information is encoded into what are called "frames". The text information is contained in text information frames. 18 Text information frames start with a set of four character identifiers, all starting with the capital letter 'T'. Examples "TALB" is the "Album/Movie/Show title" frame. "TIT2" is the "Title/Songname/Content description" frame. "TYER" is the "Year" frame. There are many more, but I won't go into more detail here. 19 HPR ID3 Tags HPR makes an interesting case study because they use both ID3v1 and ID3v2 in the same file. This can cause some interesting problems with software that tries to read those tags. This is because most software appears to expect one or the other, but not both. However, so long as this does not cause problems with anything that actually plays the files, this is not a problem so far as people who just want to listen to podcasts are concerned. It does mean though that we have more to talk about than we would otherwise would have had. -------------------- 20 Vorbis Comment Fields The situation with Vorbis comments is much simpler, as there seems to be just one standard that was adhered to from the start rather than a succession of hacks. Information is stored in "fields", which xiph describes as being like Unix environment variables. These consist of a field name followed by an equal sign and then the information intended for that field. Field names are case insensitive. 21 The field names are not firmly defined at this stage, but there is a list of recommended names. Examples are "TITLE" is the Track or Work name. "ARTIST" is the person responsible for the work. "LICENSE" is the license information. 22 You can see the complete list for yourself on the comment field and header specification page at xiph.org -------------------- 23 Software for Listing, Adding, and Modifying Tags and Fields There are three software packages that I will now describe which allow you to list, add, modify, and remove tags and fields. There are other packages which can do the same, including some which offer a GUI interface. However, I will limit myself to describing these three. The principles should be the same for others. 24 ffprobe ffprobe is part of the ffmpeg package. If you have listened to my previous episodes on audio, you will have heard me talk about ffmpeg. ffprobe is used to display information about media files rather than for modifying them. ffprobe is licensed under the GPLv2 or later. ffprobe can be used to display information about both MP3 and OGG Vorbis files. 25 ID3v2 The next is the rather aptly named id3v2 and works with MP3 files. On Linux systems, this should be provided by the id3v2 package. On Debian derivatives this can be installed as follows sudo apt install id3v2 26 This also installs a man page which provides a brief list of the options. According to the README file in the source tarball, this is published under the LGPL ID3v2 is particularly useful for displaying ID3v1 tags. 27 vorbiscomment The third is "vorbiscomment" and works with OGG files. On Linux systems this should be provided by the "vorbis-tools" package. On Debian derivatives this can be installed as follows sudo apt install vorbis-tools 28 The vorbiscomment program is used to list or edit comments in Ogg Vorbis files. This also installs a man page which provides a brief list of the options. According to the license.lgpl file in the source tarball, this is published under the LGPL version2. 29 The display format for vorbiscomment follows the data definition format in the vorbis standard, whereas ffprobe re-formats it to match its own preferred appearance. -------------------- 30 Examples from HPR With the background out of the way, I will now give several examples of how to list the tags or fields. 31 Listing ID3v1 Tags As previously mentioned HPR uses both ID3v1 and ID3v2 tags in the same file. However, so far as I can tell, most software seems to look for ID3v2 tags first, and don't display the ID3v1 tags if both are present. 32 The ID3v2 program however seems to do the opposite, at least with HPR podcasts. However, the number of samples that I have which have both are rather limited, so I can't be sure if this is always the case or if this is a side effect of something else. I did mention that ID3 tags were a mess, didn't I? 33 Let's go on to our example however. If we want to see the ID3v1 tags, then using hpr4678 as an example, if we type id3v2 -l hpr4678.mp3 = we get the following result. 34 id3v1 tag info for hpr4678.mp3: Title : High Resolution Elapsed Time i Artist: Whiskeyjack Album : Hacker Public Radio Year: 2026, Genre: Unknown (186) Comment: https://hackerpublicradio.or Track: 0 hpr4678.mp3: No ID3v2 tag 35 The first line tells us that this information is ID3v1 tags. The last line tells us that there are no ID3v2 tags. This last line is incorrect, but we will come back to that later. 36 In between are three lines of text. The first line contains the title and the artist. The title is the name of the HPR episode, or at least part of it. The artist is the HPR contributor who made that episode. 37 The second line contains the album name, the year, and the genre. The album name is this case is simply Hacker Public Radio, as the concept of an album doesn't really fit a podcast. The year is the year that the episode was recorded, or at least the year in which the MP3 file was assembled with the HPR intro and the tags added. 38 The genre is listed as "unknown 186". Recall that with ID3v1 tags there is a one byte numeric genre code, but that no genres above 70 were ever officially assigned. It seems to be a general convention though to use a code 186 for podcasts. 39 The third line contain a comment and track number. The comment in this case is the HPR web site URL. The track is zero. "Track" would appear to serve no useful purpose in this instance. However, it may be there for reasons of compatibility that I am unaware of, so I would be very reluctant to remove that without very good reason. 40 If we look at the above information in detail we can see that two of the tags appear to have cut their text information off short. The title is cut off in mid word after the 30th character. The final "g" in "hackerpublicradio.org" is cut off in the comment. 41 Alternative Method for ID3v1 We can confirm whether the text being cut short is due to a problem with the id3v2 program, or whether it really represents the data in the file by using a rather simple check. 42 Recall that ID3v1 tags are simply the last 128 bytes of the MP3 file. All we need to do is to extract the last 128 bytes of the file. We can do this using the standard tail command. tail -c128 hpr4678.mp3 | tr '' ' ' | tr -c '[:print:]' 'x' 43 The -c128 option used with tail tells it to extract the last 128 bytes of the file. We then pass the result through the "tr" command and tell it to replace null bytes with new line characters. Then we replace any remaining non-printable characters with an 'x'. When we do that we get the following 44 TAGHigh Resolution Elapsed Time iWhiskeyjack Hacker Public Radio 2026https://hackerpublicradio.or x 45 The first three characters are capital TAG. This is a flag which indicates that what follows are ID3 tags. 46 Next, we have 30 characters which specify the title. The next 30 characters specify the artist. The next 30 characters are the album, or in this case just "Hacker Public Radio". The next 4 characters are the year. The next 30 characters are a comment, or in this case the HPR URL, except for the final "g". The last character is the genre code, which we have replaced with an "x" because it is otherwise non-printable. 47 Taken together, these add up to 128 bytes. We can see that the field lengths are of fixed length with pre-defined meanings based on position. -------------------- 48 ID3v2 Using ffprobe Now lets move on to ID3v2 tags, which is probably more useful for most people. For this, we will switch to using ffprobe. The command for this is ffprobe -hide_banner hpr4678.mp3 The -hide_banner option suppresses extra data about the codecs which doesn't interest us much and leaves mainly the tag information plus a few other things. 49 The output gives us the full data that is associated with the podcast episode from the HPR web site. This includes the episode number, year, full title, author, license, and full summary text. You can see a full copy of this in the show notes. Input #0, mp3, from 'hpr4678.mp3': Metadata: track : 4678 year : 2026 title : High Resolution Elapsed Time in Shell Scripts author : Whiskeyjack copyright : CC-BY-SA artist : Whiskeyjack album : Hacker Public Radio comment : https://hackerpublicradio.org Clean; Surprises encountered when measuring elapsed time in shell scripts The license is CC-BY-SA genre : Podcast encoder : Lavf61.7.103 date : 2026 Duration: 00:30:10.18, start: 0.023021, bitrate: 64 kb/s Stream #0:0: Audio: mp3, 48000 Hz, mono, fltp, 64 kb/s 50 The ID3v2 tag version contains all of the information which was provided by the author, including the full title and description without the 30 character limit of ID3V1. If you want any of this information for some reason you should be able to extract it from the MP3 file using a combination of ffprobe, grep, and cut rather than trying to scrape the HPR web site and matching it to the MP3 later. -------------------- 51 ID3v1 Using ffprobe I previously mentioned that HPR MP3 files have both ID3v1 and ID3v2 tags in the same file, and that ffprobe will default to using ID3v2 tags if present. However, what happens if we remove the ID3v2 tags and leave the ID3v1 tags? I will describe how to strip tags later on in this episode, but let's just assume for now that I have done this. If we then use ffprobe to read the ID3 tags using the same command as before, we get the following output. 52 We get a series of lines in the same format as with ID3v2, but with each data element limited to at most 30 bytes. These include title, artist, album, date, comment, and genre. You can see the full output in the show notes. Input #0, mp3, from 'test.mp3': Metadata: title : High Resolution Elapsed Time i artist : Whiskeyjack album : Hacker Public Radio date : 2026 comment : https://hackerpublicradio.or genre : Podcast Duration: 00:30:10.18, start: 0.023021, bitrate: 64 kb/s Stream #0:0: Audio: mp3, 48000 Hz, mono, fltp, 64 kb/s 53 The information is the same as when read by the id3v2 program, but formatted for display in the manner that ffprobe uses. This shows that ffprobe can indeed read ID3v1 tags if they are the only ones present. -------------------- 54 Reading Vorbis Comments Now let us turn our attention to vorbis comments, which are the equivalent to tags for ogg files. We will look at this using two methods. 55 Using vorbiscomment The first method we will look at is using the vorbiscomment package. The command is vorbiscomment -l hpr4678.ogg 56 The output of this is a series of lines with key value pairs separated by equal signs. The output is also exactly the same as the MP3 file, except that there is an additional "language" field, "track" becomes "TRACKNUMBER", and there is no "date" field. You can see the full output in the show notes. encoder=Lavc61.19.101 libvorbis TRACKNUMBER=4678 year=2026 language=English title=High Resolution Elapsed Time in Shell Scripts author=Whiskeyjack copyright=CC-BY-SA artist=Whiskeyjack album=Hacker Public Radio DESCRIPTION=https://hackerpublicradio.org Clean; Surprises encountered when measuring elapsed time in shell scripts The license is CC-BY-SA genre=Podcast 57 Using ffprobe Now lets do the same again using ffprobe. The command for this is ffprobe -hide_banner hpr4678.ogg 58 The output content is the same of course, but the field names have all been forced to lower case, and instead of an equal sign as a separator between the key and value, this has been replaced by a colon and white space has been added to make the output look a bit nicer. You can see the full output in the show notes. Input #0, ogg, from 'hpr4678.ogg': Duration: 00:30:10.14, start: 0.000000, bitrate: 86 kb/s Stream #0:0(English): Audio: vorbis, 192000 Hz, mono, fltp, 4294967 kb/s Metadata: encoder : Lavc61.19.101 libvorbis track : 4678 year : 2026 title : High Resolution Elapsed Time in Shell Scripts author : Whiskeyjack copyright : CC-BY-SA artist : Whiskeyjack album : Hacker Public Radio comment : https://hackerpublicradio.org Clean; Surprises encountered when measuring elapsed time in shell scripts The license is CC-BY-SA genre : Podcast -------------------- 59 Another Example from Another Podcast The above is interesting, but it's a sample of one podcast. Let's look at another different one altogether. For this test I used two episodes of the Linux Matters podcast, episodes 68 and 82. As to why I am using two different episodes I will explain in a moment. 60 Episode 68 We will start with examining episode 68 Using id3v2 The command using id3v2 is id3v2 -l LMP68.mp3 61 This provides output as a series of lines containing the official 4 character identifiers from the standard, a description of the identifiers, and the text provided by the authors. The identifiers include TIT2 indicating title, TALB indicating show title, TRCK indicating track number, and a number of others. You can see the full output in the show notes. id3v2 tag info for LMP68.mp3: TIT2 (Title/songname/content description): 68: Frameworks, Filesystems and Fixes TPE1 (Lead performer(s)/Soloist(s)): Linux Matters TALB (Album/Movie/Show title): Linux Matters TYER (Year): 2025 TRCK (Track number/Position in set): 68 COMM (Comments): ()[]: https://linuxmatters.sh/ APIC (Attached picture): (LMP-3000-moon.jpg)[, 3]: image/jpeg, 554576 bytes LMP68.mp3: No ID3v1 tag 62 From this we can see what the id3v2 program would normally do with ID3v2 tags. Note that it outputs the actual 4 character identifiers, plus a description of what they mean, and then the actual data. This helps when trying to understand the actual encoding of the data. 63 Using ffprobe Now let's try that with ffprobe. The command is ffprobe -hide_banner LMP68.mp3 64 This provides the same publisher provided data as before. However it does not display the 4 character identifiers but instead uses its own format for display. Also note in both cases that there is a picture embedded in the MP3 file which is used to generate an icon for display in your file manager. With ffprobe this results in there being two keys called "title" and two keys called "comment". This makes grepping for the metadata more complicated, but it should still be possible. You can see the full output in the show notes. Input #0, mp3, from 'LMP68.mp3': Metadata: title : 68: Frameworks, Filesystems and Fixes artist : Linux Matters album : Linux Matters comment : https://linuxmatters.sh/ track : 68 date : 2025 Duration: 00:28:12.45, start: 0.025056, bitrate: 114 kb/s Stream #0:0: Audio: mp3, 44100 Hz, mono, fltp, 112 kb/s Metadata: encoder : LAME3.100 Stream #0:1: Video: mjpeg (Progressive), yuvj444p(pc, bt470bg/unknown/unknown), 4166x4166 [SAR 72:72 DAR 1:1], 90k tbr, 90k tbn (attached pic) Metadata: title : LMP-3000-moon.jpg comment : Cover (front) 65 Episode 82 Now lets try that again with a different episode, 82. Using id3v2 The command for id3v2 is id3v2 -l LMP82.mp3 This results in id3v2 saying LMP82.mp3: No ID3 tag What happened here? 66 Using ffprobe Let's try that again with ffprobe. The command ffprobe -hide_banner LMP82.mp3 provides the expected output. Input #0, mp3, from 'LMP82.mp3': Metadata: date : 2026-05 title : 82: Ditching Grammarly for Open Sauce album : Linux Matters track : 82 artist : Linux Matters comment : https://linuxmatters.sh Duration: 00:33:37.83, start: 0.025056, bitrate: 113 kb/s Stream #0:0: Audio: mp3, 44100 Hz, mono, fltp, 112 kb/s Stream #0:1: Video: png, rgb24(pc, gbr/unknown/unknown), 3000x3000, 90k tbr, 90k tbn (attached pic) Metadata: title : Linux Matters Logo comment : Cover (front) 67 This results in a few minor changes from episode 68, but otherwise it looks the same. So there are ID3 tags, but for some reason id3v2 couldn't recognize them. A bit more research and experimentation shows that this change appears to have happened right after episode 68, when they changed hosting and processing arrangements. I suspect that something changed with respect to the ID3v2 tag formatting somewhere along the way in the change over, and this in turn has affected the ability of the id3v2 program to recognize the tags. I will come back to the implications of this later in my conclusions. -------------------- 68 Stripping ID3 Tags Now let's turn to a differen topic. Stripping ID3 tags refers to removing the ID3 tags from the audio file. I will start off by emphasizing that normally, you don't want to do this. You should only be doing it if you suspect the ID3 tags are causing a problem with the playback or ordering of the files. 69 In my case I do it when I have problems with my MP3 player when playing certain podcasts. This MP3 player orders files according to ID3 tags rather than by file name. This can result in the podcasts being played in an unpredictable order which I find undesirable. This is particularly a problem with podcasts from certain publishers where the title data does not follow any consistent pattern, but is whatever someone felt like doing that day. 70 I also often have to normalize the files from the same publishers to get a consistent audio loudness. See my series on Simple Podcasting for information on how to use ffmpeg to normalize the audio loudness. The solution to the inconsistent tag formats in these cases is to simply strip the ID3 tags altogether. The player then falls back on using the file names, and I can readily rename the files to a consistent format. I have never had these sorts of problems with HPR podcasts. If you are not having any problems of this nature, then as I said, don't bother stripping the tags. 71 To strip the ID3 tags from an MP3 file use the following. id3v2 -D hpr4678.mp3 id3v2 will strip the tags and overwrite the existing file. If you wish to keep a copy with the tags, be sure to keep a backup before you try things. 72 When it comes to stripping tags, the options are "-s" deletes ID3v1 tags. "-d" deletes ID3v2 tags. "-D" deletes both v1 and v2 tags. -------------------- 73 Conclusions In this episode we took a very brief look at ID3 tags and vorbis comments and ways of reading them. 74 ID3 tags and Vorbis comments provide a means of allowing information about an MP3 or OGG Vorbis file to be embedded in the file itself. Podcast publishers very often use this to label the file with information such as title, publisher, and author. We can read this information using Fee Software tools such as ffprobe, ID3v2, and vorbiscomment. 75 ID3 tags seem to be a mess with more than one incompatible versions, and difficulties in reading them even within the same version. They are difficult to test for because there is so much hardware out there of varying ages, much of which you will never have heard of let alone had access to. If you are recording episodes for HPR you do not have to worry about this, as HPR will do this behind the scenes for you. However, if you are responsible for producing a podcast or other similar audio and you have a setup that works, it is probably best not to change anything without good reason. 76 Vorbis comments seem to be much less of a problem. However, there are far fewer devices which can play OGG files compared to MP3, so simply switching to OGG may not be a realistic solution to the ID3 tag problem. 77 If you wish to have one tool that can read ID3 tags of all sorts and vorbis comments, then ffprobe is your obvious choice. 78 The ID3v2 program will provide more information about the ID3 tags, including the actual identifiers used. However, it does not work in all cases. 79 The vorbiscomment program will read Vorbis comments from OGG files in a manner which is closer to the actual vorbis format than ffprobe does, which uses its own display format. 80 HPR includes both ID3v1 and ID3v2 tags in its MP3 files. ffprobe can be used to read the ID3v2 tags, and the id3v2 program can be used to read the ID3v1 tags. You can also read the ID3v1 tags using the tail command. 81 I have barely scratched the surface of this subject and have not talked at all about creating tags or comments. If anyone else would like to take up the challenge of providing more detail, or of correcting any mistakes that have made, please send in a podcast episode on the subject. If you have any comments you would like to make, leave them in the comment section below this episode on the HPR web site. 82 I hope to see you all again in future in another episode of HPR. -------------------- References https://id3.org/Introduction https://www.xiph.org/ https://wiki.xiph.org/VorbisComment -------------------- Provide feedback on this episode.

    HPR4697: Correcting the Dates of Files

    Play Episode Listen Later Aug 4, 2026


    This show has been flagged as Clean by the host. I recently had an experience where UNIX tools proved very useful. A relative had an old mobile phone running Android that stopped connecting to the carrier's network and bought a new one to replace it. I took on the job of trying to copy their files (consisting of just photos and videos) off of the old phone. Google's software was desperate to convince me to upload everything to the cloud, but I wasn't interested. It offered the option of copying the files over to an SD card, but failed on repeated attempts to do that. The option I tried next was to transfer them to another device via Bluetooth—that one did actually work, although it was slow and would only handle sending about 100 files at a time. They came over to my laptop OK, but the problem with that method was that all of the file times were set to the time when they were transferred. I'm not super familiar with how mobile apps manage metadata, but would presume that they look to file times for organizing photos by date. Fortunately, the names of each of the files included the date and time they were created. I recognized that I could write a bit of shell script to parse the filenames and set the file times accordingly. While there were over 800 files, the good news is that there were only three different categories of filenames, so the logic to extract the information needed was relatively simple. Each file had eight numerical digits representing the date and six digits representing the time. It would definitely be an option to come up with a more sophisticated parser that could handle a wide variety of filenames, but I went the lazy way and just handled those three cases. Another nice aspect was that none of the filenames contained spaces, which allowed me to be a bit less careful when using them in command lines. I didn't need to worry about time zones because my laptop was set to the same time zone as the phone—also, if a time was off a by a few hours it wouldn't make a practical difference. Examples of the three different types of filenames I had to deal with, labeled with the relevant values: YYYY=year, MM=month, DD=day, hh=hour, mm=minute, and SS=second. 00001IMG_00001_BURST20250525140124.jpg YYYYMMDDhhmmSS IMG_20220223_124023.jpg VID_20221017_095024.mp4 YYYYMMDD hhmmSS 20191224_195939.jpg 20161021_122620-1.jpg 20191130_134317_Burst01.jpg 20200129_223612_010.jpg YYYYMMDD hhmmSS I considered awk as an option (see Whiskeyjack's comment on HPR episode 4657 ), but realized it has no built-in way to change file times, so I set it aside. Don't worry, I will come back to that later. My approach was to use an if-then shell construct to choose how to treat the three categories of filenames. For the if condition, I fed the filename into the grep -q command with an appropriate regular expression to test whether it matches. The -q option to grep causes it not to output anything—it returns a zero exit status if there's a match and a status greater than zero if there isn't. Then, there is an elif statement with another grep -q test for the second category of filenames. Finally, an else statement is followed by the command to run for all other filenames. The whole thing is wrapped in a for loop that runs over all the files in the current directory. The touch command , when used with the -t option, can be given a string consisting of the year, month, day, hour, minute, and second. These are all numerals that are run together, except that a period sits between the minute and second. So we need a way to extract these numbers and to insert the period. That's where the cut utility comes in. It can be given a set of characters to select, and I specified a different set representing the appropriate ones depending on which category a filename fit into. To insert the period, I used sed to replace the last two characters with a period followed by those characters. The first script was to test out that I was getting the correct results. for fn in * do if echo "$fn" | grep -q BURST then printf "$fn " echo $fn | cut -c '21-34' | sed 's/..$/.&/' elif echo "$fn" | grep -q -E '^(IMG_|VID_)' then printf "$fn " echo $fn | cut -c '5-12,14-19' | sed 's/..$/.&/' else printf "$fn " echo $fn | cut -c '1-8,10-15' | sed 's/..$/.&/' fi done This one actually sets the file times. The -c option to touch prevents it from creating a file if one with that name doesn't already exist. for fn in * do if echo "$fn" | grep -q BURST then touch -c -t "$(echo $fn | cut -c '21-34' | sed 's/..$/.&/')" "$fn" elif echo "$fn" | grep -q -E '^(IMG_|VID_)' then touch -c -t "$(echo $fn | cut -c '5-12,14-19' | sed 's/..$/.&/')" "$fn" else touch -c -t "$(echo $fn | cut -c '1-8,10-15' | sed 's/..$/.&/')" "$fn" fi done The script ran over all the files in less than 15 seconds and correctly set the file time on each. Job done, right? Well, after I did this, it struck me that there was room for improvement. The script would probably run more quickly if I used a case construct instead of an if construct that called grep multiple times. While the pattern-matching notation used with case is not as flexible and can handle fewer situations than the regular expression syntax available with grep , in this case (see what I did there?) it is sufficient. Testing it out, using case reduced the running time by 45%. Replacing if with case —the commands to be executed for each category of filename can remain exactly the same. for fn in * do case "$fn" in *BURST*) printf "$fn " echo $fn | cut -c '21-34' | sed 's/..$/.&/' ;; IMG_*|VID_*) printf "$fn " echo $fn | cut -c '5-12,14-19' | sed 's/..$/.&/' ;; *) printf "$fn " echo $fn | cut -c '1-8,10-15' | sed 's/..$/.&/' esac done for fn in * do case "$fn" in *BURST*) touch -c -t "$(echo $fn | cut -c '21-34' | sed 's/..$/.&/')" "$fn" ;; IMG_*|VID_*) touch -c -t "$(echo $fn | cut -c '5-12,14-19' | sed 's/..$/.&/')" "$fn" ;; *) touch -c -t "$(echo $fn | cut -c '1-8,10-15' | sed 's/..$/.&/')" "$fn" esac done I couldn't completely put awk out of my mind, though, and I eventually came up with an awk script for the same purpose. This is far faster, probably because everything can be done within awk except actually modifying the file times, which is possible using the system() function to call touch . I was able to knock 90% off the running time, which for 800 files isn't a big deal but might make a difference if you have hundreds of thousands of files. The awk counterparts to both scripts above. Unlike those, ls is used to feed it with the list of filenames. We have the full power of extended regular expressions available to use for matching against the filenames. The next statement causes awk to skip any remaining pattern-action pairs and go to the next line of input. ls | awk '/BURST/ { print $0, substr($0, 21, 12) "." substr($0, 33, 2) next } /^(IMG_|VID_)/ { print $0, substr($0, 5, 8) substr($0, 14, 4) "." substr($0, 18, 2) next } { print $0, substr($0, 1, 8) substr($0, 10, 4) "." substr($0, 14, 2) }' ls | awk '/BURST/ { system("touch -c -t " substr($0, 21, 12) "." substr($0, 33, 2) " " $0) next } /^(IMG_|VID_)/ { system("touch -c -t " substr($0, 5, 8) substr($0, 14, 4) "." substr($0, 18, 2) " " $0) next } { system("touch -c -t " substr($0, 1, 8) substr($0, 10, 4) "." substr($0, 14, 2) " " $0) }' A further optimization that came to me later was to not call system() from within awk , but to instead just have awk print out a set of command lines. These can then be piped to sh to actually be executed. This cut the running time down by 95% compared to my original script. The fastest version I was able to come up with. If you run it without the | sh on the end, you can check that it's outputting the right information before actually modifying anything. The backslash on the end of a couple lines causes the subsequent line to be treated as a continuation of the existing line. Normally I would just keep everything on one line even if it runs longer than 80 columns, but for display purposes this looks nicer. ls | awk '/BURST/ { print "touch -c -t " substr($0, 21, 12) "." substr($0, 33, 2) " " $0 next } /^(IMG_|VID_)/ { print "touch -c -t " substr($0, 5, 8) substr($0, 14, 4) "." substr($0, 18, 2) " " $0 next } { print "touch -c -t " substr($0, 1, 8) substr($0, 10, 4) "." substr($0, 14, 2) " " $0 }' | sh It is probably true that this could have been carried out just as easily on Windows using Microsoft's PowerShell. I'm not very familiar with it, but would imagine (or hope) that it includes commands for managing these basic things like text manipulation and modifying file times. If you are stuck in an environment where you don't have a UNIX-like system available, investigate how to accomplish a task with the tools you do have. While I had the necessary information in the filenames to use, that might not be the case in all situations. You could look for other sources of dates—most digital cameras will add EXIF tags to a JPEG file giving the date and time it was created. (Hopefully, the clock in the camera will be set accurately.) While there is no standard UNIX utility to read those tags, free and open source software tools are widely available for that purpose. I found one called exiftags that included the utility exiftime , which specifically outputs EXIF data relating to time. The output format was a little trickier to handle, but awk was able to manage it with a little coaxing. Example of output produced by exiftime . Note that the first line with the filename is only printed if more than one filename is given as an argument. Also, for amusing-sign.jpg , apparently I edited that photo after taking it and the editing software updated the "created" tag but left the others intact. Not all images will necessarily have created, generated, and digitized tags; we will just take whichever ones exist. I redirected standard error to /dev/null to get rid of error messages for files that don't have EXIF tags; we'll handle those below. $ exiftime *.jpg 2>/dev/null 20260508_154743.jpg: Image Created: 2026:05:08 15:47:43 Image Generated: 2026:05:08 15:47:43 Image Digitized: 2026:05:08 15:47:43 20260508_155044.jpg: Image Created: 2026:05:08 15:50:44 Image Generated: 2026:05:08 15:50:44 Image Digitized: 2026:05:08 15:50:44 3704a78e771c2a25a894ef2f0b5a2a629f1eba80.jpg: amusing-sign.jpg: Image Created: 2017:01:24 23:14:04 Image Generated: 2017:01:24 21:18:07 Image Digitized: 2017:01:24 21:18:07 dscf3011.jpg: Image Created: 2015:01:01 00:02:19 Image Generated: 2015:01:01 00:02:19 Image Digitized: 2015:01:01 00:02:19 window-view.jpg: $ We can take advantage of the fact that different records are separated by a blank line. In awk , when RS is set to a null string and FS is set to a newline character, each set of non-blank lines is treated as a record and each line within those sets is treated as a field. One or more blank lines separate each record. For the output of exiftime , this means that $1 will contain the filename and $2 will contain the first line after the filename. For those files without an EXIF date tag, $2 will be a null string, which is treated by awk as FALSE, so the pattern will not match, the action will not be taken, and nothing will be printed. If a file has multiple tags, I will just use the first one reported by exiftime (contained in $2 ). The sub() function call removes the colon that exiftime prints after the filename, and the gsub() function call removes all non-numeric characters from the date and time in the tag. (After a comma within a print statement, a backslash is not necessary to continue a line.) Also, this time I bothered to print quotation marks around the filename in case it contains spaces. $ exiftime *.jpg 2>/dev/null | awk 'BEGIN { FS = "n" ; RS = "" } $2 { sub(":$", "", $1) gsub("[^0-9]", "", $2) print "touch -c -t", substr($2, 1, 12) "." substr($2, 13, 2), """ $1 """ }' touch -c -t 202605081547.43 "20260508_154743.jpg" touch -c -t 202605081550.44 "20260508_155044.jpg" touch -c -t 201701242314.04 "amusing-sign.jpg" touch -c -t 201501010002.19 "dscf3011.jpg" $ I would imagine that there's some photo management program out there that I could have used to accomplish this. But then I would have had to locate it, verify that it wasn't some malware-loaded garbage, download, and install it. And chances are it would want to take over all the photos on my laptop. Instead, with standard UNIX tools and shell capabilities like if , case , process substitution, and pipelines, I was able to complete the task without having to install anything. The techniques I described can be used in different circumstances and with the output of different utilities. My intention was not just to explain how to solve this specific problem, but to hopefully teach you some things that you can apply in many situations. Perhaps if you use them to tackle a challenge of your own, you'll record an episode for HPR to share what you know. Provide feedback on this episode.

    HPR4696: HPR Community News for July 2026

    Play Episode Listen Later Aug 3, 2026


    This show has been flagged as Explicit by the host. New hosts There were no new hosts this month. Last Month's Shows Id Day Date Title Host 4673 Wed 2026-07-01 First contact conversation Archer72 4674 Thu 2026-07-02 Audiobooks Ahuka 4675 Fri 2026-07-03 Yard Inflatables operat0r 4676 Mon 2026-07-06 HPR Community News for June 2026 HPR Volunteers 4677 Tue 2026-07-07 UNIX Curio #10 - Checksums and Hashes Vance 4678 Wed 2026-07-08 High Resolution Elapsed Time in Shell Scripts Whiskeyjack 4679 Thu 2026-07-09 HPR Beer Garden 15 - Double IPA Kevie 4680 Fri 2026-07-10 Robert A. Heinlein: The Future History, Part 2 Ahuka 4681 Mon 2026-07-13 My Disabilities Antoine 4682 Tue 2026-07-14 Behind the Keyboard: A Cybersecurity Operator's Real-World Workflow operat0r 4683 Wed 2026-07-15 Recording the hallway track Ken Fallon 4684 Thu 2026-07-16 Sim Racing on the cheap! operat0r 4685 Fri 2026-07-17 Listening to SSB stations in the early 1980s Lennart Benschop 4686 Mon 2026-07-20 Debugging Security Cameras: Firmware Updates, Python Scripts and Windows Workarounds operat0r 4687 Tue 2026-07-21 UNIX Curio #11 - Merging Files Vance 4688 Wed 2026-07-22 Downloading Podcasts with a Shell Script Whiskeyjack 4689 Thu 2026-07-23 Cheap Yellow Display Project Part 8: Writing the code Trey 4690 Fri 2026-07-24 Playing Civilization V, Part 14 Ahuka 4691 Mon 2026-07-27 Viva la Coda Lee 4692 Tue 2026-07-28 Noise Music Tutorial 2: Using Audacity to Make Noise TheDUDE 4693 Wed 2026-07-29 Amateur Radio Field Days Archer72 4694 Thu 2026-07-30 HPR Beer Garden 16 - Belgian Blonde Kevie 4695 Fri 2026-07-31 Try not to buy a phone operat0r Comments this month Past shows hpr4644 (2026-05-21) "Response to comments on HPR4424: Newsboat..." by Archer72. Archer72 said: "Ken on Community Show HPR4676" (2026-07-06 13:48:39) Ken Fallon said: "hpr3962 :: It's your data" (2026-07-06 15:07:47) hpr4669 (2026-06-25) "HPR Beer Garden 14 - Super Strong Lager" by Kevie. The_Dud3 said: "Favorite Malt Liquores/Super Strong Lagers" (2026-07-22 02:07:59) hpr4672 (2026-06-30) "Hey Mum, I'm on Spotify ! " by Ken Fallon. Archer72 said: "Another great show!" (2026-07-08 09:46:44) This month's shows hpr4674 (2026-07-02) "Audiobooks" by Ahuka. The Librarian said: "Ook ?" (2026-07-02 10:50:38) hpr4677 (2026-07-07) "UNIX Curio #10 - Checksums and Hashes" by Vance. xmanmonk said: "Another great show" (2026-07-07 21:17:41) candycanearter07 said: "cool show :D" (2026-07-08 11:32:04) Vance said: "Thanks, and systemd as a future topic" (2026-07-09 01:50:23) Vance said: "Sorry, xmanmonk" (2026-07-12 03:20:02) hpr4678 (2026-07-08) "High Resolution Elapsed Time in Shell Scripts" by Whiskeyjack. candycanearter07 said: "cool ep" (2026-07-09 14:38:32) Whiskeyjack said: "Reply to candycanearter07 on HPR4678" (2026-07-09 22:48:47) hpr4681 (2026-07-13) "My Disabilities" by Antoine. Archer72 said: "Reading" (2026-07-22 13:43:46) hpr4684 (2026-07-16) "Sim Racing on the cheap!" by operat0r. Jim DeVore said: "Great episode!" (2026-07-28 03:43:23) hpr4685 (2026-07-17) "Listening to SSB stations in the early 1980s" by Lennart Benschop. Lucinda said: "Thank you" (2026-07-21 10:53:42) hpr4688 (2026-07-22) "Downloading Podcasts with a Shell Script" by Whiskeyjack. candycanearter07 said: "cool solution" (2026-07-22 23:14:22) Whiskeyjack said: "Response to candycanearter07 in HPR4688" (2026-07-23 19:14:55) Mailing List discussions Policy decisions surrounding HPR are taken by the community as a whole. This discussion takes place on the Mailing List which is open to all HPR listeners and contributors. The discussions are open and available on the HPR server under Mailman. The threaded discussions this month can be found here: https://lists.hackerpublicradio.com/pipermail/hpr/2026-July/thread.html Events Calendar With the kind permission of LWN.net we are linking to The LWN.net Community Calendar. Quoting the site: This is the LWN.net community event calendar, where we track events of interest to people using and developing Linux and free software. Clicking on individual events will take you to the appropriate web page. Provide feedback on this episode.

    HPR4695: Try not to buy a phone

    Play Episode Listen Later Jul 31, 2026


    This show has been flagged as Clean by the host. IDEAS: Using a cheap phone plan with SMS for authentication. Mighty Text as a free SMS solution. Google VoIP number for shared accounts. Issues with SMS verification blocking VoIP numbers. Avoiding carrier-specific number blocks. Multiple SIM cards for cost-effective SMS. Rooting a phone to manage apps. Security concerns with third-party apps. Limited data usage for minimal phone plans. Challenges with app compatibility on rooted devices. Short-term phone solutions for SMS needs. Shared Google accounts for streamlined access. Avoiding premium SMS services like $15/month plans. Using Wi-Fi for data instead of cellular plans. Importance of SMS for MFA (multi-factor authentication). Transitioning from old phones to new setups. Balancing convenience and cost in phone plans. Reliance on SMS for banking and insurance access. Difficulty finding non-blocked SMS verification options. Preference for minimal, low-cost phone solutions. RECOMMENDATIONS: Use a shared Google account for SMS access. Opt for a cheap phone plan with unlimited texting. Try Mighty Text as a free SMS alternative. Avoid premium SMS services with high fees. Use Wi-Fi instead of cellular data for minimal plans. Choose carrier numbers over VoIP for critical services. Root a device to manage app settings. Test SMS compatibility with banks and providers. Consider multiple SIM cards for redundancy. Prioritize SMS for MFA over other verification methods. Monitor app updates for compatibility with rooted devices. Select phones with flexible data plans. Use downloaded content instead of streaming. Check for SMS blockages with new services. Explore low-cost phone options for minimal use. Maintain backup SMS methods for emergencies. Simplify phone setups to reduce costs. Verify SMS support before switching providers. Combine Wi-Fi and SMS for reliable connectivity. Share accounts to streamline digital access. Provide feedback on this episode.

    HPR4694: HPR Beer Garden 16 - Belgian Blonde

    Play Episode Listen Later Jul 30, 2026


    This show has been flagged as Clean by the host. Dave and Kevie are back with another HPR Beer Garden and this time they turn their attention to Belgian Blonde Ales. Kevie samples Leffe Blonde , whilst Dave opts for La Chouffe . Connect with the guys on Untappd: Dave Kevie The intro sounds for the show are used from: https://freesound.org/people/mixtus/sounds/329806/ https://freesound.org/people/j1987/sounds/123003/ https://freesound.org/people/greatsoundstube/sounds/628437/ The next 3 beer styles to be reviewed: DDH IPA Amber Ale Lager Provide feedback on this episode.

    HPR4693: Amateur Radio Field Days

    Play Episode Listen Later Jul 29, 2026


    This show has been flagged as Clean by the host. Hi, this is Archer72 for another episode of Hacker Public Radio. In this episode, the ARRL Field Days was in the past month, so I thought this would be a good time to highlight events in the US as well as around the world. Field Day (amateur radio : edited on 4 June 2026, at 13:51) Experience the power of ham radio at 2025 ARRL Field Day Harrison County Amateur Radio Club Jun 12, 2025 Updated Jun 17, 2025 Amateur Radio Club to host annual field day By Keith Clifford Harrison County Amateur Radio Club Jun 15, 2026 Harrison County Amateur Radio Club Field Day Jun 22, 2026 Preceding collage used with permission by Keith Clifford of the Harrison County Amateur Radio Club (K4HSN) Provide feedback on this episode.

    HPR4692: Noise Music Tutorial 2: Using Audacity to Make Noise

    Play Episode Listen Later Jul 28, 2026


    This show has been flagged as Explicit by the host. Links to a more in depth way to do the musique concrete method and harsh noise wall (they don't use audacity, but it all can be done on audacity, just gives you an idea what I'm talking about) visual of generating noise on audacity (for harsh noise, you want to have a larger amplitude or any thing that makes the noise louder) https://youtu.be/CkZS1C7JUmM?si=qGe7g94lrBE-fAh6 Musique Concrete https://youtu.be/hvI0URwiCJc?si=l_7N3DASLu4Cw7qQ Harsh Noise Wall https://youtu.be/_zwgleyfBgQ?si=IgtK3ydM0queuHBX Provide feedback on this episode.

    HPR4691: Viva la Coda

    Play Episode Listen Later Jul 27, 2026


    This show has been flagged as Clean by the host. C++ is a high-level, general-purpose programming language created by Danish computer scientist Bjarne Stroustrup. First released in 1985 as an extension of the C programming language, adding object-oriented (OOP) features, it has since expanded significantly over time adding more OOP and other features - from https://en.wikipedia.org/wiki/Main_Page Serenity OS - https://serenityos.org The C Programming Language, Kernighan and Ritchie - https://colorcomputerarchive.com/repo/Documents/Books/The%20C%20Programming%20Language%20%28Kernighan%20Ritchie%29.pdf C++ - https://en.wikipedia.org/wiki/C%2B%2B The Ghost of Unix SVR4 - https://github.com/macsplit/unix_docProvide feedback on this episode.

    HPR4690: Playing Civilization V, Part 14

    Play Episode Listen Later Jul 24, 2026


    This show has been flagged as Clean by the host. In our sample game we look at playing as Austria and aiming for a Diplomatic Victory. And our focus is on puppeting City-States, but I misunderstood and instead of making a Diplomatic Victory easier, it makes it harder. I still managed to get my Diplomatic Victory, but a Science or Domination Victory would definitely have been easier in this scenario. Playing Civilization V, Part 14 Now I am at turn 340, I just puppeted another City-State, and I have one more on the way. I have sent a large number of military units, both land and sea, to the City-States that are on Japan's border. If he tries anything now he will likely regret it. Now I am starting to build things I had not bothered with before, like Granaries and Amphitheaters. I got a couple of Great Engineers, and used them to rush build Wonders. I am nearly finished puppeting all of the City-States, and my Happiness and Income are both quite healthy. I am in such good shape I started to build the World's Fair, which I initally proposed then ignored. At this point I only have one more City-State to puppet, then I will have puppeted every City-State in the game. So it is time to put my large income to use in other ways by giving gifts to the other players. I may want to get a few more votes on my side to get over the top in the World Leader vote when it happens. On turn 357 I completed the puppeting of all of the City-States in the game. Meanwhile, I am building up my Science and building Wonders as they become available. I didn't build any in the early game because I had other priorities, but now I have a strong military, high income, and no other pressing needs. My score on the Leader Board is now double that of my nearest competitor which is still Japan. And their denunciation me of just expired with them taking no action. I used a Great Engineer to rush build the Porcelain Tower, earning me another Great Scientist, which I then used to build another Academy. At this point it is mostly a slog to the finish. Since I was so dominant and so wealthy I could afford to pursue a couple of other options just in case. One was a Science victory, which looked like a possibility, though it would be close. I had to be very focused in my Science Research. The other option was a Culture victory, and I had dominated two other empires culturally without half trying, and I was generating Great Artists, Great Musicians, and Great Writers pretty rapidly. So I built Museums, then Archeologists, and grabbed every artifact I find to stuff into the Museums. But the final Victory came when I researched Globalization. This tech allows you to get an extra vote in a World Council for every Spy you send to another empire's capital and designate as an Ambassador. I immediately sent my spies out (they had previously been in my cities doing counter-espionage since I had a tech lead). And a few turns later a vote for World Leader came up and I won. This was my first time using Maria Theresa of Austria as my leader, and it was fun, but in the end puppeting all of the City-Staters actually made it harder to win a Diplomatic victory. In other games I have played, every City-State that was an ally was an extra vote in the World Council, and I assumed that making them puppets would mean I would get that many votes. But that didn't happen. Of course, if I had read more carefully in the Civilization Wiki I would have realized this, because it says there very clearly that Austria is one of the worst Empires to pick if you are going for a Diplomatic victory. So the fact that I managed it anyway is nice. I think I actually could have done a Science victory as I had my Spaceship half-built when I won the Diplomatic Victory. But I hope this analysis of how I actually played this game will be helpful to someone else. Links https://www.palain.com/gaming/civilization-v/playing-civilization-v-part-14/ Provide feedback on this episode.

    HPR4689: Cheap Yellow Display Project Part 8: Writing the code

    Play Episode Listen Later Jul 23, 2026


    This show has been flagged as Clean by the host. Hello, again. This is Trey. Welcome to part 8 in my Cheap Yellow Display (CYD) Project series. If you wish to catch up on earlier episodes, you can find them on my HPR profile page https://www.hackerpublicradio.org/correspondents/0394.html It is hard to believe that I started this project and the HPR series to document it more than a year ago. Time flies. Life happens. I spent the last 8 months so focused on work related activities that I had to set the project aside. And once I set it aside, it was difficult to get back to again. The one time I tried, I found that my son's old Windows laptop, which I had commandeered to use for the project, was once and truly dead. We live in a different world now than we did when I began this project. Today, everything is about AI – how it is changing our world, increasing efficiencies, and even displacing certain types of jobs. "Vibe coding" is transforming the way we make software, and now everyone is a developer. Within my organization, we are all being strongly encouraged to learn more about AI and apply it in our daily work. We are blessed to have access to a wide range of training and to powerful tools which support the process. Several colleagues within my organization and outside my organization have recommended Claude Code -- for development, for organization, for brainstorming, and for much more. My role is not that of a developer, and I have had no need for Claude Code at work. There are plenty of other tools for me to use. But at home, I thought... I could install Claude Code at home to experiment with and to learn. And then it hit me. I wonder if I could use Claude Code to help me with my stalled CYD project. "Hello, my name is Trey, and I am a fraud." OK. I don't think I am a fraud, but having never used such a powerful tool to help me code, I feel a little bit like a fraud, with Claude doing the work for me. Let's talk through what we did. As I mentioned, I was unable to use the laptop on which I created the original GUI code. But no worries, because It was all on GitHub, right? So, I began by trying to install Claude Code on one of my Ubuntu machines. That failed miserably, and all the instructions I found online recommended running it on Windows. So I transitioned to installing Claude Code on a freshly built Windows 10 system using some old hardware which will not support Windows 11. Surprisingly, It seems that Claude wants to run within Ubuntu on Windows Subsystem for Linux (WSL). Once I went through all the hoops for installing and setting up my basic subscription, I got to work. I created a new directory to use for all my project files, and another one for Claude to write all its output files to. Everything I have read and heard about using Claude Code for a project like this recommended beginning by using Claude to create the project plan. So my first prompt was as follows: "I am building a project using an ESP32 cheap yellow display. The final goal is to have a device with a graphical user interface which will allow me store several text messages, each assigned to their own specific button. Then, when one of the buttons is pressed, the message will be converted into morse code, and the message will be sent by blinking an onboard LED. I already have the initial design for the GUI coded in my github repository. Please construct a detailed step by step plan for building this application" I wanted to keep it simple at the beginning, so even though I plan to use an opto-isolated relay for the output, I am starting out using the built in LED. Claude asked me for the URL for my Github repository, and I provided it. After thinking for a bit, it produced a project plan. CYD Morse Sender — Step-by-Step Build Plan What You Already Have - 3 fully designed LVGL screens (Send, Config, Keyboard) - 7 send buttons with green styling on the Send Screen - Speed slider (5–30 WPM) and program slot dropdown on Config Screen - Text area + LVGL keyboard widget on Keyboard Screen - Display driver and touchscreen hardware initialized (but touch read was stubbed out) --- Phase 1: Fix Touchscreen Input Initialize the XPT2046 on VSPI, replace the hardcoded touched = false with real touch data, calibrate raw ADC coordinates to screen pixels, and verify all three nav buttons transition screens correctly. Phase 2: Persistent Message Storage Use Preferences.h / NVS to store 7 messages ("msg0" – "msg6") that survive power cycles. Load on boot and populate send button labels. Phase 3: Config Screen — Slot Selection & Speed Wire the Program dropdown to g_selectedSlot, wire the Speed slider to g_wpm with a live WPM label, and wire the Set button to clear the text area and navigate to the Keyboard Screen. Phase 4: Keyboard Screen — Capture and Save Text On keyboard OK (LV_EVENT_READY): read the text area, save to NVS, update the send button label, navigate back. On Cancel: navigate back without saving. Phase 5: Morse Code Engine Build morse.h with the full A–Z / 0–9 lookup table, a textToMorse() converter, and Paris-standard timing (unit_ms = 1200 / wpm). Phase 6: Non-Blocking LED Transmission State machine (IDLE / LED_ON / LED_OFF) driven by millis() in a morseUpdate() function called every loop — no delay(). LED on GPIO 17 (blue). Phase 7: Wire the Send Buttons Each button calls startMorse(getMessage(slot)) if not already transmitting. Disable all send buttons during TX; re-enable when the state machine reaches the end. Phase 8: Integration & Polish Stop button, WPM persistence, empty-slot guard, serial debug output, final touch calibration, end-to-end test checklist. --- Recommended order: Phase 1 → 2 → 7 (partial) → 5 → 6 → 7 (full) → 3 → 4 → 8 This was wild! Claude determined exactly how far along I was in the project, and also alerted me to the fact that the "touch read was stubbed out". Ugh. This means that the files I had uploaded to GitHub were my original GUI files (Episode 05 – HPR4532 - https://hackerpublicradio.org/eps/hpr4532/index.html ) and not the ones that I finally got working properly (Episode 07 – HPR4624 - https://hackerpublicradio.org/eps/hpr4624/index.html ). That was my own fault. Did I mention that I don't get Git? I REALLY need to learn to properly use Git! But, we have a plan, broken down by eight numbered phases. And they seem to address all the functionality I wanted with a few additional things I had not thought about. Interestingly, even though these phases are sequentially numbered, Claud recommended that we approach them in a bizarre order: Phase 1 → 2 → 7 (partial) → 5 → 6 → 7 (full) → 3 → 4 → 8 . Alright. Let's see what we can do. The first phase is to fix the touchscreen input. Claude took me through it step-by-step, asking as it needed to read specific project files. Finally, it wrote a new ui.ino code file to my speficied output directory for me to test. I copied it into the correct file location, said a quick prayer, compiled in Arduino IDE, and downloaded to the CYD. Well, that is... interesting. The display looked nothing like it was supposed to. There were vertical green bars with smaller dashed green vertical stripes in them. I will include a picture in the show notes so that you can see what it looked like and why it was so difficult to describe. I spent the next hour or so trying to explain what I was seeing to a chat bot. Claude recommended potential fixes which either did nothing or made the situation worse. I began questioning whether this was a good idea, how people actually gained efficiencies talking to a bot, and even several life choices. Then I had a thought. I prompted Claude: If I were to take a picture of the screen on the cheap yellow display and copy it into the output folder, would you be able to analyze it to better determine what is wrong and how to fix it? Shockingly, Claude answered in the affirmative, and told me to copy the picture to the output folder and let it know when to proceed. It analyzed the picture and more of the supporting files it had copied from my GitHub, asking each time if it could access that file. It determined that my original code was written for a flavor of LVGL version 8 and I was now using LVGL 9.5. It recommended changes, and then asked permission to make those changes, file by file. .h files & .c files, Finally, I just gave it permission to edit the files in the project folder without asking for permission for each file each time. Claude was still explaining each change, showing me exactly what would be changed, and asking for permission, so that I could review all of the changes. But now it was not asking additional permission to write to each of the impacted files. Next, Code compiled and downloaded. Different screen, but not right. Again, I took a picture and gave it to Claude to analyze. So, Claude paused and altered the code to generate a specific test pattern overtop of the GUI. The test pattern was supposed to cover the entire rectangular screen. But parts of the pattern were in a square on the screen and parts were not. Another photograph and analysis, told Claude that there were some rotation/screensize issues. We repeated this several times. Some resulted in improvement, and others did not. This is the point where I noticed something interesting. Not about Claude, specifically, or about the app. But I noticed something interesting about myself and about the process. Previously, when I was working through some of these challenges without Claud, I found myself becoming more and more stressed, frustrated, and angry, until I found a solution. Then another problem would repeat the cycle. Success in the end was great, but the emotional extremes during the process were not always pleasant. Now, I was effectively managing the project, and relaying information to the resource responsible for fixing the problems -- a very different experience. But I also ran into another issue. Claude became absolutely certain that the problem revolved around the device not accurately knowing where the 4 corners of the screen were. But in reality, the output of the test pattern was rotated 90 degrees from the actual screen. It took several iterations of me insisting that the problem had to do with screen orientation and not corner coordinates. It was interesting to experience the tool doubling down on an obvious mistake, but we finally resolved that. Again, while it was frustrating, it was much less stressful. We proceeded to Phase 2: Persistent Message Storage where we ensured that the button labels on the send screen were stored in the devices persistent storage, so that, when they are edited to contain the message they should send, that information would survive a reboot. Next, we combined elements of Phase 5: Morse Code Engine , Phase 6: Non-Blocking LED Transmission , and Phase 7: Wire the Send Buttons together. Building the morse code engine was an area I had been thinking about for a while. I already had working parts of something similar in the Arduino practice oscillator I have referenced a few times in this series. The code for the practice oscillator may be found on my GitHub, but it was all based on original code from jmharvey1, with my only contribution being making pin assignments variables so that the code could easily be ported to different devices. So, I was happy that we were building the morse code engine directly. The code for it may be found in morse.h, which uses a constant character lookup table to define each character. Without any specific direction from me, Claude used the PARIS timing methods I have already described within Episode 6 of this series. It defines timing for DOT, DASH, LETTER_GAP, and WORD_GAP, and all are based on a simple calculation of 1200 ms / the number of words per minute (WPM) we wish to transmit. Along the way, we discovered that, if we tried to use the delay() function, it would crash the program due to a conflict with the LVGL timer used for touchscreen inputs. Claude altered all the delays accordingly. Then, Phase 3: Config Screen — Slot Selection & Speed allowed us to configure the WPM we wished to use in addition to selecting a specific Send button to reconfigure. This forced us to work on Phase 4: Keyboard Screen — Capture and Save Text which is used to type the entries for each Send button. At this point, I also decided that we would want to also use the Keyboard Screen to send ad hoc morse as we typed it. During this phase we discovered several bugs which seemed to cause random freezes. Careful troubleshooting with messages output to the Arduino IDE's serial console helped us narrow down the causes and remedy them. Finally all the tests worked and I am able to merrily pre-configure macro buttons with custom messages and use the CYD to send the morse code for those messages to the on-board LED at whichever rate I specify. I have noticed in my presentation of this narrative that I repeatedly slip into the first person plural terms "we" and "us" instead of the first person singular terms "I" and "me". I have unconsciously personified Claud and recognized it as an integral part of my (formerly one person) development team. I finally configured Claude to connect to my GitHub repo and upload all the files and documentation. We additionally created a CYD-Narrative.md file which describes in more detail all the work which was done on the project. I still do not 100% get git, but we are successfully using it. You can find all these files in my GitHub repo ( https://github.com/jttrey3/CYD_MorseSender ) where they are shared under a GPL 3.0 license. There are still several additional steps I plan to complete in the next few months. 1. I will be integrating an opto-isolated relay which will allow me to plug the device into the straight key input on any amateur radio. This will require a battery power source, charge controller, and more hardware. I... make that "We" (Claude & I) will be modifying the code to support an audio side tone through an attached speaker when sending code We will add an output selection switch to the config page to choose any combination of speaker, relay, or LED as output. We will develop a downloadable firmware which I hope to share with the Cheap Yellow Display community. If you can think of any additional features you would like to see integrated, please drop me an email using the address in my HPR profile. I may also work with a friend to attempt to 3d print a case for the entire contraption, and I will be sure to record additional episodes sharing the process. I have learned so much throughout this project, about the CYD, ESP32, GUIs, Claude Code, GitHub, and most of all, about myself. Does using AI to develop this code make me a fraud? It still feels like it in some ways. Does it make me more productive? ABSOLUTELY! I made consistent forward progress when I only had 30-60 minutes each day to work on it, and everything discussed in this episode was completed in less than a week. If I had been able to work on it for a few hours uninterrupted, it may have only taken me 3-5 hours. Does it empower and inspire me to do more projects like this? 100% I feel like I had support working with me the whole way. I was less stressed overall, and it had less of an impact on the amount of and quality of time I spent with my family. I will be wrapping up this series soon, without any more 6 month gaps, I hope. Until next time... Provide feedback on this episode.

    HPR4688: Downloading Podcasts with a Shell Script

    Play Episode Listen Later Jul 22, 2026


    This show has been flagged as Clean by the host. 01 Introduction In this episode I will describe techniques for downloading podcasts using basic shell commands such as wget. I will illustrate this using a bash script that can be used to download HPR podcasts. Even if you do not have any interest in downloading your podcasts using this method, you may find some of the methods useful or interesting. It is the principles that are discussed here that are important, rather than the implementation. 02 I realize that there are already a number of different podcast download programs available, including at least one written in bash. However, you may feel that none of these suit how you wish to do things and want to create your own system tailored to your specific needs. If so, then I hope the following is of some use to you. If not, then you may still find some of the things discussed here to still be of interest. Some of the subjects I cover include wget to a user defined file name. parsing xml with xmllint. using inotifywait to trigger an action when a file is created or modified. using notify-send to send a message to the notification area. and a way of allowing a cron job to send a message to the user interface. 03 Background There has been an ongoing discussion in comments to some HPR episodes about problems downloading HPR podcast episodes. Apparently some people have been experiencing problems with the way the episode URLs are structured. 04 I am afraid that I don't fully understand the nature of these problems, so I won't be addressing that problem directly. Instead, I will present a bash script that I have written which can be used to download HPR podcasts. This bash script can be run using cron to automatically fetch new HPR podcasts and save them to a designated directory. This is a simplified version of a script that I have used for years to download HPR and other podcasts. 05 I won't try to read the full bash script out in this podcast, as that would be a bit dull to listen to. I will instead describe what each section does and why I chose to do things that way. Perhaps other people can offer suggestions of better ways to do things. I will post the full bash script in the show notes. 06 Fetching Podcasts The standard way of distributing podcasts is to publish an RSS feed containing URL links to the audio files. RSS is a very long established and widely supported mechanism for this and other purposes. An RSS feed is basically an XML document which can be accessed over HTTP. These URLs contained in the RSS XML document can then be used to download the actual audio files, such as MP3 or OGG files. 07 Basically what we need to do is the following • Download the RSS XML document. • Extract the URL links to the audio files. • Compare the list of these links to a previously saved list to see which ones are new and which ones are ones that we previously downloaded. 08 • Make a list of the new URLs. • Go through this list of new URLs and download each of the new audio files. • Check to see that we actually received the new audio file. • Add the URLs of the files we successfully downloaded to our saved list of podcast URLs 09 In addition to this, we would like to have the above happen automatically in the background without our having to take any action on our own. We may wish to receive a notification of when a new podcast has arrived however. We would probably also wish to receive notification of any errors or failures. 10 Fetching Podcasts - The Preliminaries Our desire to be able to run the script automatically imposes some requirements on our solution. To schedule the script we will use cron. Cron is a Linux facility to run scripts on a schedule. 11 One of the side effects of using cron however is that we need to specify the full path to the locations where we intend to keep any data files, plus also the full path to where we intend to put the downloaded podcasts. 12 So the first thing we need to do in our script is to specify a number of different values for things like file location, the URL for the HPR RSS feed, and several other things as well. I will skip over the details of these, although I may make reference to them later. 13 Get the RSS Data The first thing of real substance to do is to fetch the current RSS feed data. I have put this in a bash function called getrssurldata The contents of this function are a one liner, but with a number of elements chained together through pipes. 14 Downloading the RSS XML Document • First we use wget, which is a standard command on most Linux distros. • We specify four things. • First we set a timeout. I have chosen 20 seconds. • Next we set the retry limit. I have chosen 3. 15 • Then we specify that the output of wget is sent to stdout rather than saved as a file. • This is done by using the -O option followed by a space and then a dash. • The O option is usually used to specify a file to save the output to, but when used with a dash causes output to go to stdout. • Then we specify the URL of the HPR RSS feed. 16 Contents of the XML Document This gives us the HPR RSS XML document. There are about 5,000 lines in this RSS document. Most of those lines are the show notes which are also included in the feed. 17 Extracting the Podcast Episode URLs There are only 10 lines of the document that contain information that we are interested in however. These lines are enclosed in "enclosure" XML tags. We just need to find those lines and separate out the URLs 18 Standard Command Line Tools There are two ways that we can do this. One is to use a combination of grep, sed, and cut. Grep can find the lines containing the enclosure tags. Sed and cut can extract the URL from the surrounding extraneous data. 19 However, this method does not discriminate between real enclosure tags in the data portion of the RSS feed and enclosure tags in the show notes which are included in the feed from episodes such as this one. This may be an acceptable problem in practical terms, but we can do better. 20 Using an XML Parser The other method is to actually parse the XML document. there are at least two command line XML parsers that I am aware of. These are "xmllint", and "xlmstarlet". I have used xmllint in this example. I have not used xmlstarlet, so I can't offer any comment on how easy or difficult to use it is. 21 I won't give a detailed explanation of all the things that xmllint can do. It has many features, most of which, as the name suggests, have to do with finding formatting problems with the XML itself. Describing everything it can do would be at least one episode in itself. I will instead just give the particular command used and explain each element of it. 22 In this example assume that we are piping the output of wget directly into xmllint. The complete command is xmllint --xpath "//channel/item/enclosure/@url" - | cut -d'"' -f2 23 In this example, xmllint is the name of the command. --xpath tells it to parse the document according to the string which follows. "//channel/item/enclosure/@url" tells it to find a series of tags in the hierarchy of channel, followed by item, followed by enclosure, and then extract the url attribute from the enclosure tag. The "-" which follows tells it to look for input from stdin rather than from a file. 24 The result is a string which has the url attribute name, an equal sign, and the URL that we want enclosed in quotes. To get just the URL itself, we pipe the output from xmllint into cut, using the doublequote characters as delimiters. We then save the result in a temporary file. 25 Finding the New Episodes Next we wish to find the new podcast episodes. Each HPR episode is identified by a unique URL. This means that if we save the URLs of episodes that we have already downloaded, we just have to look for the URLs that do not appear in this saved list. https://hub.hackerpublicradio.org/ccdn.php?filename=/eps/hpr4659/hpr4659.mp3 26 The easiest way to do this is to take our two lists of URLs, sort each into temporary files, and then compare the sorted URLs using the "comm" command. 27 This is simple, but has a drawback. Some podcasts occasionally change distributors. When they do this, the old podcasts are re-published with new URLs and you end up downloading a lot of old episodes over again. 28 With HPR we could get around this by extracting just the file name and looking for that instead of the full URL. I will however leave that problem as an exercise for the student and just accept that if the URL format changes we may end up downloading old episodes over again. Since the feed has a maximum of only 10 episodes in it however, that isn't really that big of a problem. It would be more of a problem with podcasts which have very large numbers of episodes in their feed, but the solutions to those will be feed specific. 29 Downloading the New Podcasts We should now have a list of URLs for the new podcasts we do not already have. Typically this should be only one file, but there could be several, or even as many as 10, if we have not turned on our computer in a while. Therefore, we need to iterate through the file of new podcast URLs and download each one. 30 Before we do that however, we should check to see if there is in fact anything new to download. To do this, simply use "wc -l" to count the number of lines in the list of new URLs and save the resulting number. 31 If this number is zero, there is nothing to download, we can skip the download step. As an additional check, we should see if the number of downloads exceeds some threshold value that we wish to set. This is not a major problem with HPR, but some podcasts have hundreds of files in their RSS feed rather than just the most recent ones. If we do exceed our download limit, then we need to log an error and skip downloading. 32 Assuming there are no problems so far however, the first thing we need to do is to extract the name of the audio file from the URL. We can do that using the "basename" command. We will use this to specify the name that we use when we save the audio file. 33 HPR has a very well formed file name. Some podcasts do not however, and for those you would need to construct some sort of suitable name either using information found in the URL or simply creating a name using a time stamp. 34 Next we download the audio file using wget. This is similar to how we downloaded the RSS feed, but with a few changes. One is that I have increased the timeout to 90 seconds. This may not have been necessary, but seemed like a good idea. 35 The next is that when specifying the output file name using -O, we use the file name we extracted from the URL. The third is that we specify a destination directory using the -P option. 36 After wget has finished, including any retries that it had to do, we next check that the expected new file is both present and not empty. We did this using an "if" statement with the "-s" option. If the file was found and not zero, then we add that URL to a temporary list of downloaded URLs. 37 If the file was not present, or was zero length, we output an error message to an error log. I will come back to this point later. 38 Next, if there is more that one podcast to download we sleep for 3 seconds. While not strictly necessary, it is considered to be "polite" to not hammer a server repeatedly, but rather to put a small delay between file downloads.. 39 After we have downloaded all the audio files in our list, we can add the list of URLs for the files downloaded to the permanent list. While we are at it, we should use "tail" to trim the permanent log to keep it from growing indefinitely. This limit should be several times bigger than the number of files in the RSS feed. In this case I selected 50. 40 Finally we write any errors to the permanent error log, and also write these same errors to another file used to signal errors for display to the user. We have now successfully downloaded at least one HPR podcast. 41 Notify the User of Events It would be convenient to be informed of new podcast downloads when they occur, and also be notified of any errors. One of the limitations of cron jobs is that they cannot access the user interface. This means that we cannot readily send a message directly to the notification system to inform the user of the presence of new podcasts or of errors. 42 inotifywait The solution to this is to use "inotifywait" to monitor particular files and directories for changes. The man page for inotifywait states the following - 43 inotifywait efficiently waits for changes to files using Linux's inotify(7) interface. It is suitable for waiting for changes to files from shell scripts. It can either exit once an event occurs, or continually execute and output events as they occur. End of quote. 44 In many Linux distros, inotifywait is provided by the "inotify-tools" package. I won't go over all the features of inotifywait. Instead, I will just describe how to use it for our purposes here. 45 inotifywait Modes I should point out first though that inotifywait operates in two different modes. In the normal default mode, it exits after being triggered by an event and must be re-established again in order to resume monitoring. In monitor mode, which is enabled by using the "-m" option, it runs indefinitely, responding to events. I will use the default mode here. 46 The man page for inotifywait provides a simple example that we could copy and modify for our purposes. A great many examples that you will find are based on this example. However, it doesn't quite do what we want, so we need to change a few things. 47 podfetchnotify The first shell script is one which monitors for the arrival of new podcasts and sends a notification to the user. I will call this "podfetchnotify". The complete scripts are in the show notes, I will just provide a brief description here. 48 Setting Up Event Watches Using inotifywait The script is enclosed in a while loop which run indefinitely. In the first line inside the while loop, we call inotifywait. inotifywait will then block until the event it is told to look for occurs. In short, execution of the script will wait there until an event occurs. 49 The names of the events are listed in the man file. In this case we are looking for "modify", "create", and "moved_to". Each of these does pretty much as you would expect, reacting to modifying an existing file, creating a new file, or moving a file to that directory. 50 Problems When Testing Using Text Editors I should point out that if you are testing a script which uses inotifywait, then modifying a file with a text editor may not produce the results that you may think it would. Instead it treats this as a new file with the same name, with the original file being erased. Since inotifywait attaches itself to the inode rather than the filename, it sees the file that the text editor changed as being a new file. If you wish to test this realistically, then use "echo" to overwrite the file by using I/O redirection. 51 Capturing Output In my example I capture the output from standard out into a variable, but I don't do anything with it. If you wish to for example display the name of the newly downloaded podcast file, then use the --format option along with an appropriate formatting code. There are details about this in the man page. On the next line we capture the exit code using "$?" 52 Responding to Exit Codes If the exit code was zero, then a monitored event was triggered and there should a new podcast in the directory. In this case we display a message indicating that a new podcast has arrived. I will describe how to send notifications shortly. If the exit code was not zero, then an error occurred. An example of such an error would be if the directory were not present when monitoring was started. In this case we display a message indicating that a fatal error has occurred and then exit. 53 Delay for More Podcasts Finally, we use "sleep" to wait for some arbitrary period of time to prevent notifications from being triggered multiple times if several podcasts were being downloaded in succession. In this case I chose to wait for 60 seconds. 54 We have now completed the process and can return to the top of the loop and resume waiting using inotifywait. 55 Sending Notifications to the User I mentioned above about sending notification messages to the user. In the Gnome desktop, notification messages appear from the centre of the top bar in a list. Other desktops or operating systems may have something similar. 56 To send a notification message to the notification area, you use the "notify-send" command. Simply follow notify-send with a quoted string and it will be displayed in the notification area. 57 podfetcherrornotify The second shell script is one which notifies the user of errors. I will call this "podfetcherrornotify". With this shell script we set up a watch on a file which contains any error messages from podfetch. This script is very similar to podfetchnotify. 58 The exceptions are With inotifywait we only monitor for "modify". There is no sleep command at the end of the loop. Instead we sleep for a few seconds just after getting the exit code from inotifywait. This helps prevent problems caused by race conditions. 59 Next we check the inotifywait exit code. If it was zero, then we read the error report file and send a notification message to the user containing that error message. 60 If it was not zero, then we check to make sure that the directory that should contain the error log exists. If it does not exist, then we send a notification message to that effect to the user and terminate the script. 61 If the directory exists, then we check to see if the error message file used for signalling exists. If the file does not exist, then we create it. 62 One of the reasons for an inotifywait error is that if the file that it is told to monitor does not exist, it cannot set up a watch condition. By creating the file we correct the cause of the error and allow inotifywait to operate normally. 63 Finally we increment an error counter and check to see if the limit is exceeded. If there are excessive errors, then send a notification message to the user and exit. The reason for this is to give the user an indication that the error notifications are not working for some reason and there may be a problem that needs looking into. 64 The error counter is reset every time the inotifywait exit status is ok, so occasional unexpected glitches should be something that is ignored. Of course podcast fetching errors are something that will probably happen only rarely if at all, so this final step may be seen as an unnecessary embellishment. 65 Installing the Scripts Next I will describe how to install and prepare the scripts to run. We need to perform the following steps. 66 • First, we need to create a directory to hold the scripts and their associated data files. • Next we need to create a directory to hold the downloaded podcasts. • Then we must copy the scripts to these directories and make them executable. • Then, we must edit the scripts to have the file path in the script match the locations of the new directories that we created. 67 • Then we need to install xmllint, or alternatively modify the download script to comment out the use of xmllint and enable the alternative method using grep and sed instead. • Then we need to run each script manually from the command line to check for errors. • If podfetch ran correctly, it should download the most recent 10 podcasts during this test. 68 Adding podfetch to the Crontab The above describes how to run the scripts manually. In order to fetch podcasts automatically, we need to add the podfetch script to the cron schedule. To do this, open a terminal. 69 Type "crontab -e", and then press return. A text editor should open up containing the crontab file. On Ubuntu, this editor is GNU nano. Enter the appropriate cron parameters. I will provide an example here for running it 12 minutes past the hour every three hours. 70 12 */3 * * * /home/username/pathtofiles/podfetch.sh 71 I won't explain cron in detail here. The example that I have just given should be good enough for most people. The "*/3" parameter will cause it to run every three hours. The "12" parameter will cause it to run 12 minutes past the hour when it does run. 72 Checking every three hours should be good enough for most people, but you can adjust that as you see fit. I would recommend however that you don't check more frequently than once per hour. Checking more frequently than necessary puts extra load on the distribution servers. It is very unlikely that you really do need each new episode the moment it is available. 73 I would also recommend changing the "12" parameter to some other random minute value. I would suggest avoiding on the hour or on the half hour, as a lot of other people are probably checking at those times, and it would be better to spread the load out more evenly over time. 74 The file path parameter should of course match the actual path to wherever you have located the script, including the correct user name. 75 Making the Notification Scripts Start Automatically The two notification scripts can be made to start automatically. The exact method to do this may vary according to distribution or desktop. 76 On Ubuntu this is done using the Startup Applications Preferences GUI program, which should come already installed. 77 I won't go into details on this here, it should be fairly self evident how to use it once you see it. What this program does is to create ".desktop" files in the ".config/autostart" directory in your home directory. 78 These ".desktop" files are all run automatically on start up. Once you have added the notification scripts, you will need to log out and then log back in to make them active. 79 Conclusion I this episode I explained how to write a set of simple shell scripts to automatically download each new episode of HPR as it comes out and to notify you of its arrival. 80 The download script described here is tailored specifically for use with HPR only. However, it was derived from a larger script that downloaded other podcasts as well, based on information read in from a text file. If you are feeling ambitious, you can add those features back into this to handle all of the podcasts that you listen to. 81 In a comment to another episode of HPR I had said that I would cover ID3 tags in MP3 files, but this episode is long enough now, so I will leave that subject for later. I look forward to seeing you again later on another episode of Hack Public Radio. # ====================================================================== podfetchdownloader #!/bin/bash # Fetch pending HPR podcasts listed in the HPR RSS feed. # 8-Jun-2026 # Licensed under GPLv3 or later. # ====================================================================== # Today's date and time as YYYYMMDDHHMMSS. podttimestamp=$( date +"%Y%m%d%H%M%S" ) # The absolute path to the script. This is necessary when running it # using a cron job. podpath="/home/me/Apps/hprfetch" # This is the absolute path to where to store the podcast files. podfilepath="/home/me/Music/Podcasts/HPR" # Create the full path names here for all the text files used. podcastsfetched="$podpath/podcastsfetched.txt" poderrorslog="$podpath/poderrorslog.txt" poderrorsreport="$podpath/poderrorsreport.txt" tmpoldurlssorted="$podpath/tmpoldurlssorted.txt" tmppodsnew="$podpath/tmppodsnew.txt" tmppodstodownload="$podpath/tmppodstodownload.txt" tmppodserrors="$podpath/tmppodserrors.txt" tmppodcastsfetched="$podpath/tmppodcastsfetched.txt" tmplog="$podpath/tmplog.txt" # The URL for the HPR RSS feed. PodURL="http://hackerpublicradio.org/hpr_rss.php" # Limit on number of podcasts to download. DownloadLimit=11 # Name of the podcast. PodName="Hacker Public Radio" # ====================================================================== # Check if the required paths exist. # If this path does not exist, cannot log the error. if [[ ! -d "$podpath/" ]]; then echo "$podttimestamp Error - Could not find $podfilepath." exit 1 fi # Where to store the podcast file fetched. if [[ ! -d "$podfilepath/" ]]; then echo "$podttimestamp Error - Could not find $podfilepath." >> $tmppodserrors # Copy the errors log from the temporary errors file to the permanent files. LogErrors exit 1 fi # ====================================================================== # Check if the podcast log exists. We read it before we write to it, # so it must exist or we will hang on it not being present. if [[ ! -e $podcastsfetched ]]; then touch $podcastsfetched fi # ====================================================================== # Delete the specified files if they exist. # This accepts multiple file names in a variable number of parameters. CleanupFiles () { # $@ accepts multiple parameters. for f in "$@"; do # Check if the file exists. if [ -e "$f" ]; then rm "$f" fi done } # ====================================================================== # Copy the errors log from the temporary errors file to the permanent files. LogErrors () { if [ -e $tmppodserrors ]; then # The permanent log. cat $tmppodserrors >> $poderrorslog # This file is monitored for display by other scripts. cat $tmppodserrors > $poderrorsreport fi } # ====================================================================== # Get the URL data from an RSS feed GetRSSURLData () { wget --timeout=20 --tries=3 -O - "$PodURL" | xmllint --xpath "//channel/item/enclosure/@url" - | cut -d'"' -f2 | sort > $tmppodsnew # This is an alternate method that does not use xmllint. # However, it is not as robust. If someone were to include the # first grep search pattern in their show notes, then it would # look for that as a valid tag and output the following text # as a URL. #wget --timeout=20 --tries=3 -O - "$PodURL" | grep " $poderrorsreport fi # Increment the error counter. count=$(( count + 1 )) if (( count > 3 )); then notify-send "Podfetch error: Excessive unknown errors, exiting." exit 1 fi fi done # ====================================================================== Provide feedback on this episode.

    HPR4687: UNIX Curio #11 - Merging Files

    Play Episode Listen Later Jul 21, 2026


    This show has been flagged as Clean by the host. ether This series is dedicated to exploring little-known—and occasionally useful—trinkets lurking in the dusty corners of UNIX-like operating systems. I frequently find myself reaching for the cut utility when writing scripts to extract one piece of data from a line, or to select specific fields from a log file. While I am familiar with its counterpart, paste , I don't employ it very often because I don't typically need its functionality. This perhaps has to do with the fact that I rarely work with text files containing lists. For shorter lists, I usually end up using a spreadsheet and for larger ones, a relational database. Both are valuable tools with their own strengths and weaknesses, but it is good to also know about standard utilities for working with lists. After uploading UNIX Curio #8 ( HPR episode 4657 ), I felt like maybe I had been too dismissive of the comm utility in that episode and should talk more about tools that are useful when managing lists. I don't frequently find myself using paste 1 , but can explain how it works. Briefly, it is a rough opposite of cut —when given multiple files as arguments, it assembles the first line from each one separated by tabs, then the second line, and so on. Instead of tabs, a different delimiter can be chosen with the -d option. Another option is -s , which swaps rows and columns so that the contents of each named file would appear on one line. While paste itself doesn't qualify as a UNIX Curio in my opinion, there is one feature that does: a hyphen can be given as an argument multiple times. In this special case, the output is taken line by line from standard input, but is spread across as many columns as there are hyphens. Example of using paste to turn the output of ls into columns. Because these columns are separated by tabs, they don't necessarily line up when a filename is eight or more characters long. The -1 is not required for the second ls command since that behavior is implied when output isn't going to a terminal. The -C option to ls usually gives nicer-looking output on a terminal—also, it lists in ascending order down by column. (Most implementations default to -C when output goes to a terminal.) If you want items ascending along rows like the paste example does, try ls -x instead. $ ls -1 /proc/net anycast6 arp bnep connector dev dev_mcast dev_snmp6 fib_trie fib_triestat hci icmp icmp6 if_inet6 igmp igmp6 ip6_flowlabel ip6_mr_cache ip6_mr_vif ip_mr_cache ip_mr_vif ip_tables_matches ip_tables_names [...35 more entries not shown...] $ ls /proc/net | paste - - - - anycast6 arp bnep connector dev dev_mcast dev_snmp6 fib_trie fib_triestat hci icmp icmp6 if_inet6 igmp igmp6 ip6_flowlabel ip6_mr_cache ip6_mr_vif ip_mr_cache ip_mr_vif ip_tables_matches ip_tables_names ip_tables_targets ipv6_route l2cap mcfilter mcfilter6 netfilter netlink netstat packet protocols psched ptype raw raw6 rfcomm route rt6_stats rt_acct rt_cache sco snmp snmp6 sockstat sockstat6 softnet_stat stat tcp tcp6 udp udp6 udplite udplite6 unix wireless xfrm_stat $ ls -C /proc/net anycast6 if_inet6 l2cap rfcomm tcp arp igmp mcfilter route tcp6 bnep igmp6 mcfilter6 rt6_stats udp connector ip6_flowlabel netfilter rt_acct udp6 dev ip6_mr_cache netlink rt_cache udplite dev_mcast ip6_mr_vif netstat sco udplite6 dev_snmp6 ip_mr_cache packet snmp unix fib_trie ip_mr_vif protocols snmp6 wireless fib_triestat ip_tables_matches psched sockstat xfrm_stat hci ip_tables_names ptype sockstat6 icmp ip_tables_targets raw softnet_stat icmp6 ipv6_route raw6 stat $ ls -x /proc/net anycast6 arp bnep connector dev dev_mcast dev_snmp6 fib_trie fib_triestat hci icmp icmp6 if_inet6 igmp igmp6 ip6_flowlabel ip6_mr_cache ip6_mr_vif ip_mr_cache ip_mr_vif ip_tables_matches ip_tables_names ip_tables_targets ipv6_route l2cap mcfilter mcfilter6 netfilter netlink netstat packet protocols psched ptype raw raw6 rfcomm route rt6_stats rt_acct rt_cache sco snmp snmp6 sockstat sockstat6 softnet_stat stat tcp tcp6 udp udp6 udplite udplite6 unix wireless xfrm_stat The paste command has limitations—the files you give it must all be already arranged in the same order, and if any file is missing a value, it must have a blank line so that subsequent lines will match up correctly. The files do not necessarily have to be sorted alphabetically, but whatever order they are in has to be the same. Check out HPR episodes 962 and 4201 for some more background on the paste utility. Example of using paste with files where some values are empty. Bob works from home so doesn't have an office assigned, and the laboratory Carol works in doesn't have a phone. This relies on the fact that the same line number in every file relates to the same person/entry. $ cat names Alice Bob Carol Dave $ cat offices 203 Lab6A 117 $ cat phones +1 212-555-1234 +1 919-555-2345 +1 212-555-1278 $ paste names offices phones Alice 203 +1 212-555-1234 Bob +1 919-555-2345 Carol Lab6A Dave 117 +1 212-555-1278 Our second UNIX Curio for today is a utility called join 2 , which has a bit more sophistication. It operates on two files, which can have multiple columns, and combines them using the join field. By default, the first column/field in each file is the join field, and only entries that exist in both files are printed. The -1 and -2 options can be used to join on a different field, and -o selects specific fields to be output. To make it so lines with missing entries also appear, you need to use the -a option, but an actual empty string with separator won't be printed unless -o is also present and includes the field. The default field separator character is one or more "blanks" in the current locale—for the POSIX locale, this means a space or a horizontal tab. The -t option selects a different character and also removes the treatment of multiple occurrences as a single separator, making it possible to have an empty field in one or both of the files. By default, a single space is used to separate fields in the output. If -t is given, the same character is used for separating fields in both input and output. You would need to pipe output through another tool like tr if you wanted to have a different separator in the output. The join utility might be an improvement over paste in some cases, since the join field makes it a little easier to identify which entries match up across files. It is limited to operating only on two files (one of which can be standard input), so combining more than that requires either creating temporary intermediate files or chaining together join commands in a pipeline. Another requirement is that all files must already be sorted in the current locale. Example showing how join can be used with two tab-separated lists. The LC_ALL assignment forces join to sort using the C (POSIX) locale instead of whatever might be set in your environment. The "@" on the header line has no special meaning; it is just there to make sure it sorts before any letters or numbers (in the C locale; it might not in other locales). Note that if -t were not specified, plist would be treated as having three fields because of the space separating the country code from the rest of the phone number. $ export tab="$(printf 't')" #To more easily use tab characters below $ cat olist @Name Office Alice 203 Carol Lab6A Dave 117 $ cat plist @Name Phone Alice +1 212-555-1234 Bob +1 919-555-2345 Dave +1 212-555-1278 $ LC_ALL=C join -t "$tab" olist plist @Name Office Phone Alice 203 +1 212-555-1234 Dave 117 +1 212-555-1278 $ LC_ALL=C join -t "$tab" -a 1 -a 2 olist plist @Name Office Phone Alice 203 +1 212-555-1234 Bob +1 919-555-2345 Carol Lab6A Dave 117 +1 212-555-1278 $ #By default, join acts as if empty fields don't exist; use -o to include $ LC_ALL=C join -t "$tab" -a 1 -a 2 -o 0,1.2,2.2 olist plist @Name Office Phone Alice 203 +1 212-555-1234 Bob +1 919-555-2345 Carol Lab6A Dave 117 +1 212-555-1278 $ #The -e option sets a placeholder to use for empty fields $ LC_ALL=C join -t "$tab" -e "(none)" -a 1 -a 2 -o 0,1.2,2.2 olist plist @Name Office Phone Alice 203 +1 212-555-1234 Bob (none) +1 919-555-2345 Carol Lab6A (none) Dave 117 +1 212-555-1278 The brief description for join is "relational database operator"—I won't dispute that, but in my view it offers far fewer capabilities than people would expect from today's relational databases. I would imagine that when most people think of those they have Structured Query Language (SQL) in mind, which offers a lot more flexibility and functions to operate on data. However, I can see how join could be suitable for simple operations. Our last UNIX Curio for today relates to the sort utility 3 . While, as you might expect, it is well-known for its ability to sort data, it has another feature that is more obscure. When used with the -m option, instead of sorting the files given as arguments, it merges them together. All of the files are expected to already be sorted—once combined, the list that is output will also be sorted. The order in which the files are named does not matter; it is not required for the contents of the first file to start before the second, just that both are sorted. $ cat women Alice Carol $ cat men Bob Dave $ sort -m men women Alice Bob Carol Dave Imagine that you organize an annual event and have a separate pre-sorted list of attendees' e-mail addresses for each of the past three years. You are planning this year's event and want to send out an announcement to all of these people, as they will probably be interested. The command sort -m -u 2023list 2024list 2025list would spit out a combined list that you can use for your e-mail blast. Because it is likely that some people would have attended in more than one year, I included the -u option—it removes any duplicate entries. It is probably no surprise that the sort utility appeared early on—it was in 1971's First Edition UNIX, though it didn't gain the merging functionality until Fifth Edition 4 in 1973. What did come as a shock to me is that both cut and paste didn't show up until 1980 with System III 5 , and were actually preceded by join , which was in Seventh Edition UNIX 6 from 1979. I assumed that at least cut would have been around far earlier, given its usefulness and how firmly established it is, but I suppose it just seems to have been with us forever. As mentioned, I don't typically manage data as text files containing lists, and I probably won't start using the join utility or these features of paste and sort very much. But it is still useful to know that they exist and how they work. Hopefully this episode has taught you a bit about them. References: Paste specification https://pubs.opengroup.org/onlinepubs/9699919799/utilities/paste.html Join specification https://pubs.opengroup.org/onlinepubs/9699919799/utilities/join.html Sort specification https://pubs.opengroup.org/onlinepubs/9699919799/utilities/sort.html A Research UNIX Reader: Fifth Edition sort manual page https://archive.org/details/a_research_unix_reader/page/n19/mode/1up System III paste manual page https://www.tuhs.org/cgi-bin/utree.pl?file=SysIII/usr/src/man/man1/paste.1 Seventh Edition UNIX join manual page https://man.cat-v.org/unix_7th/1/join Provide feedback on this episode.

    HPR4686: Debugging Security Cameras: Firmware Updates, Python Scripts and Windows Workarounds

    Play Episode Listen Later Jul 20, 2026


    This show has been flagged as Explicit by the host. Show Notes Episode Overview Operator kicks off the episode feeling under the weather but shares a quick tip for making perfect egg drop soup before diving into his main project: diagnosing why his front-door security camera stopped sending alerts and recording events. What follows is a live-debugging session covering network config, script logging, Windows permission hacks, NTP time drift, and firmware flashing. Key Topics & Breakdown Egg Drop Soup Hack: How to get that perfect ribbony texture by creating a boiling swirl before pouring in the eggs, plus broth-to-egg ratio tips. Camera Setup & Network Config: Using static DHCP via MAC address binding on a UniFi Dream Machine (UDM) for local domain resolution instead of hardcoding IPs. Python & Cron Automation: Running a custom Python script every 2 minutes to check for new recordings, parsing logs with grep -v , and navigating massive log files in vi . Windows Troubleshooting Tangent: Deleting the stubborn Windows.old folder using the TrustedInstaller service hack ( ExecTI.exe ) instead of taking ownership manually. Time Sync & Firmware Quirks: Discovering the camera's system clock was stuck in 2011/2026, causing missed events. Downloading firmware via a slow third-party link, renaming .bin to .zip , and extracting with 7-Zip. Pre-Flash Backup Routine: Exporting camera configuration before upgrading, storing it in Google Drive for searchable documentation, and clearing old log/trigger files to reset the event pipeline. ️ Tools & Techniques Mentioned crontab + Python scripts for automated monitoring grep -v , cat , tail , and vi (line navigation with :1000 ) Obsidian for note-taking & AI assistant integration Firefox/Playwright for headless browser testing Turbo Download Manager & Bolt Media Downloader for multi-threaded/sniffing downloads 7-Zip for archive extraction Google Drive for searchable config backups Resources & Links Python API Script: Uniview IPC3628SR Recording Checker Camera Model: IPC3628SR (Uniview Wyze ISP Warm Light Deterrent Network Camera) TrustedInstaller Run-as Tool: ExecTI TrustedInstaller Runner Quick Takeaways Always verify NTP/time sync on IoT cameras before troubleshooting missed events or alerts. Use grep -v "noise" to quickly filter out repetitive log entries when debugging automation scripts. Windows system folders can be stubborn; running commands as TrustedInstaller bypasses hidden file locks without manual ownership changes. Always export and back up device configs before flashing firmware, even if the upgrade seems straightforward. Third-party download links often use temporary tokens or .bin wrappers; renaming to .zip and verifying with 7-Zip can save headaches. Thanks for listening! Stay curious, keep your logs clean, and remember: defense in depth starts at home. Example trusted installer hack # Shhhh I can't IR ... Defender, ForcePoint, SMS Agent Host ...I just can't anymore ... sc config TrustedInstaller binPath= "Reg add "HKEY_LOCAL_MACHINESYSTEMCurrentControlSetServicesSense" /v Start /t reg_dword /d 4 /f" sc start "TrustedInstaller" sc config TrustedInstaller binPath= "Reg add "HKEY_LOCAL_MACHINESYSTEMCurrentControlSetServicesFppsvc" /v Start /t reg_dword /d 4 /f" sc start "TrustedInstaller" sc config TrustedInstaller binPath= "Reg add "HKEY_LOCAL_MACHINESYSTEMCurrentControlSetServicesCcmExec" /v Start /t reg_dword /d 4 /f" sc start "TrustedInstaller" sc config TrustedInstaller binPath= "Reg add "HKEY_LOCAL_MACHINESYSTEMCurrentControlSetServicesWinDefend" /v Start /t reg_dword /d 4 /f" sc config TrustedInstaller binPath= "C:WindowsservicingTrustedInstaller.exe" Provide feedback on this episode.

    HPR4685: Listening to SSB stations in the early 1980s

    Play Episode Listen Later Jul 17, 2026


    This show has been flagged as Clean by the host. Lennart tells about the shortwave radio he had in the early 1980s and what he could hear on it, for example he marine band, amateur radio, CB and of course broadcast stations. The radio did not have a BFO to demodulate SSB stations, but using a second radio close by and using its local oscillator he could still make those signals intelligible. Provide feedback on this episode.

    HPR4684: Sim Racing on the cheap!

    Play Episode Listen Later Jul 16, 2026


    This show has been flagged as Clean by the host. Thrustmaster TMX Force Feedback Pro Black Xbox One / Xbox Series X/S / PC https://www.ebay.com/itm/157554569422 Dayton Audio DAEX25 Audio Exciter Pair - Sound Exciter Pair Audio Transducer - 5 Watts RMS, 8 Ohms Impedance - 2 Pack - Turn Any Surface into a Speaker System https://www.amazon.com/dp/B001EYEM8C https://www.simhubdash.com/ https://www.accsetupcomparator.com/ https://www.iracing.com/ ( they have buy 2 years get discount during holiday but still can't afford it .. ) https://forza.net/horizon DiRT Rally 2.0 GOTY https://k4g.com/store?distribution[]=3&q=DiRT%20Rally%202.0%20GOTY&sort=price CrewChiefV4 https://thecrewchief.org/ https://app.tracktitan.io/sessions/3ebbf63b-93de-4309-9a42-9311a745209d/20241228052252 SUMMARY. User discusses sim racing challenges, costs, and setup tips. IDEAS. Sim racing requires time and investment. I Racing is expensive with annual costs. Set of Courses offers one-time payment. Proper setup enhances sim racing experience. Cable connections can complicate setup. Upgrading hardware improves performance. Arcade games like Forza offer casual play. Realistic sim racing demands dedication. License requirements vary between platforms. Remote gaming systems save space. Steering wheel upgrades improve smoothness. Dedicated spaces optimize sim racing. Balancing fun and realism is key. Multi-launchers manage gaming platforms. Hacked accounts may cause issues. Monitoring hardware wear is important. Shifting mechanisms enhance control. Curved monitors improve immersion. Time constraints affect sim racing participation. Exploring multiple games adds variety. RECOMMENDATIONS. Consider Set of Courses for a one-time payment. Invest in a proper setup for serious sim racing. Use a multi-launcher for managing games. Upgrade hardware for smoother performance. Buy specific tracks and cars to avoid costs. Opt for a dedicated space for sim racing. Check for license requirements before purchasing. Remote into gaming systems to save space. Replace plastic parts with bearings for smoother operation. Use a 7-speed shifter for better control. Avoid hacked accounts for reliability. Purchase multiple accounts for different players. Focus on arcade games for casual play. Prioritize a curved monitor for immersion. Use a standing desk for accessibility. Monitor cable connections to prevent setup issues. Upgrade steering wheel components for better experience. Balance fun and realism based on personal preference. Consider time investment for sim racing. Explore different racing games for variety. Provide feedback on this episode.

    HPR4683: Recording the hallway track

    Play Episode Listen Later Jul 15, 2026


    This show has been flagged as Clean by the host. Recording Kit General Lanyard - HPR - Your Name HPR Business Cards - Your email address HPR Stickers Pen A6 Notebook Android Mobile phone OpenCamera Zoom H2 Zoom H2 Handy Recorder Set format to best and date format to ISO8601 Replacement Batteries Micro USB Cable 2.5 mm headphones 3.5 mm Male to Male cable 3.5 mm earbuds Backup 1 Sansa Clip Rockbox Remove before flight key fob Set format to best and date format to ISO8601 Backup 2 Android Mobile phone AudioRecorder Set format to best and date format to ISO8601 Provide feedback on this episode.

    HPR4682: Behind the Keyboard: A Cybersecurity Operator's Real-World Workflow

    Play Episode Listen Later Jul 14, 2026


    This show has been flagged as Explicit by the host. SUMMARY The presenter outlines a practical cybersecurity workflow, covering ergonomic setups, browser isolation, virtual machine troubleshooting, AI-assisted scripting, and network tunneling methods utilized during active security assessments. ONE-SENTENCE TAKEAWAY Isolate browser environments, utilize automation scripts, and verify network paths before starting security tests to avoid workflow interruptions. TOOLS Talon Voice – Open-source voice recognition software enabling hands-free computer control and command execution. Obsidian – Local-first markdown note-taking application supporting secure, AI-friendly knowledge management. AutoHotkey – Windows scripting utility for creating custom macros and remapping keyboard inputs. Chrome Debug Commands – Browser developer tools allowing direct inspection of extensions, cookies, and storage. Whisper Diarization – Audio processing script that separates speaker tracks and converts recordings to searchable text. Hyper-V / WSL – Microsoft virtualization platforms enabling isolated guest environments and Linux subsystem integration. OpenConnect / OpenVPN – Command-line tunneling clients used for establishing secure, split-tunnel network connections. Jamboree Framework – Portable PowerShell environment that dynamically provisions development tools without altering system paths. MOBA Portable – Feature-rich terminal emulator supporting static/dynamic tunnels, auto-reconnect, and embedded X-server capabilities. Nmap – Network discovery and security auditing tool utilized for comprehensive port scanning and service detection. 00:00:00 Ergonomic Workspace Configuration Configures physical workstation elements to reduce strain during extended testing sessions. Proper alignment prevents repetitive stress injuries while maintaining focus on technical tasks. Monitor Positioning – Displays should align with eye level to maintain neutral neck posture; the speaker notes their curved 49-inch screen sits slightly high due to chair adjustments. Split Keyboard Layout – Utilizes a Freestyle 2 mechanical keyboard, allowing natural shoulder-width arm placement and reducing wrist deviation during prolonged typing. Postural Adaptation – Acknowledges that ergonomic equipment requires matching body alignment; elbow rests should sit between hip and shoulder height for optimal leverage. 01:45:00 Voice Control & Note Synchronization Utilizes auditory input methods and localized knowledge bases to streamline documentation workflows. Separating secure work notes from casual observations prevents data contamination. Talon Voice Integration – Runs continuously to handle navigation, text entry, and application switching without manual keyboard interaction. Obsidian Migration – Transitions from cloud-based keep apps to local markdown files, enabling direct querying by local AI models while maintaining offline accessibility. Note Categorization – Divides information into secure work records and insecure personal logs, ensuring clean data pipelines for future retrieval and analysis. 03:50:00 Browser Extension Management & Security Isolation Separates web browsing activities from primary work processes to minimize attack surfaces. Running dedicated user profiles prevents plugin conflicts and credential leakage. Jailed User Accounts – Creates restricted system profiles that only launch the browser, isolating extensions from core workstation operations. Shared Folder Synchronization – Establishes a single directory path bridging work and browsing users, allowing seamless file transfers without cross-contamination. Extension Audit Process – Leverages Chrome debug commands to enumerate installed plugins, verifying functionality before deployment on target networks. 06:15:00 Training Optimization & Audio Processing Accelerates mandatory compliance viewing through speed manipulation and automated transcription. Converting video content into searchable text enables rapid information retrieval. Global Speed Control – Increases playback rates up to sixteen times normal speed, drastically reducing time spent on repetitive corporate training modules. Whisper Diarization Pipeline – Downloads video tracks, separates speaker voices, and generates timestamped transcripts for quick reference during assessments. Download Management – Employs multi-threaded swarm downloaders and classic turbo managers to handle bulk media retrieval without interrupting active workflows. 10:40:00 Virtualization & Network Tunneling Protocols Establishes isolated testing environments using Windows virtual machines while managing connectivity constraints. Proper session handling prevents unexpected disconnections during remote engagements. Enhanced Session Mode – A Hyper-V feature providing higher resolution and shared clipboard functionality; disabling it is required before initiating certain VPN clients to avoid routing conflicts. Split Tunneling Mechanics – Routes specific traffic through the virtual network while keeping local resources accessible, preventing complete internet loss during connection tests. Certificate Verification – Identifies self-signed SSL mismatches early in the process, documenting them as preliminary findings before proceeding with authentication steps. 15:30:00 Macro Automation & Input Remapping Remaps frequently used keyboard shortcuts to reduce physical strain and accelerate command execution. Running scripts with elevated privileges ensures reliable input registration across virtual environments. Caps Lock Repurposing – Converts the caps lock key into a primary modifier, assigning copy/paste functions to adjacent letters for faster workflow navigation. Physical Typing Macros – Simulates keystrokes with deliberate delays, allowing seamless data entry into restricted VM consoles that block standard clipboard operations. Administrator Execution Requirement – Highlights that macro scripts must run with elevated privileges to successfully inject inputs across different desktop sessions. 20:15:00 Portable Development Environments & Python Management Deploys lightweight scripting frameworks that dynamically provision necessary tools without modifying host configurations. Verifying package contents prevents dependency conflicts during testing. Jamboree Framework – A PowerShell-driven utility that downloads and configures development stacks on demand, resetting environment variables to maintain system cleanliness. NuGet Package Filtering – Queries Microsoft's repository API to retrieve specific Python versions, ensuring compatibility with legacy tunneling scripts. Binary Verification Process – Checks extracted archives for bundled pip.exe or pip3.exe executables, eliminating manual module installation steps during rapid deployments. 28:40:00 AI-Assisted Scripting & Debugging Workflows Generates and refines PowerShell functions through iterative conversational prompts. Validating AI output against actual system behavior prevents silent configuration errors. Vibe Coding Approach – Relies on continuous feedback loops with language models to draft, minimize, and debug automation scripts in real-time. Parameter Standardization – Enforces strict formatting rules for PowerShell commands, avoiding hardcoded paths and ensuring cross-environment compatibility. Temporary Storage Management – Monitors extraction directories to prevent disk saturation, redirecting large package downloads away from constrained system partitions. 35:10:00 Terminal Emulation & Advanced Tunneling Strategies Facilitates complex network routing through dedicated terminal applications. Configuring dynamic and static tunnels enables reliable reverse connections for remote assessments. MOBA Portable Configuration – Utilizes an INI-based tunnel manager that automatically maintains connections across changing IP addresses or Wi-Fi networks. Reverse Shell Routing – Establishes outbound channels back to the tester, then proxies all subsequent traffic through those connections for consistent monitoring. Proxy Chain Integration – Forces non-proxy-aware applications to route through Burp Suite or custom interceptors using Windows utility wrappers like Priboxy. 42:30:00 Final Connectivity Testing & Engagement Wrap-Up Executes comprehensive port scans to verify target accessibility before documenting findings. Acknowledging workflow detours ensures realistic time management during active engagements. Nmap Verification – Runs full-port scans with verbose output to confirm host responsiveness and identify open services prior to credential testing. Connection Refusal Documentation – Captures screenshot evidence of failed routing attempts, providing clear proof of network restrictions for client reporting. Workflow Reflection – Recognizes that exploratory debugging adds value but requires time boundaries; balancing thoroughness with engagement scope maintains professional efficiency. Provide feedback on this episode.

    HPR4681: My Disabilities

    Play Episode Listen Later Jul 13, 2026


    This show has been flagged as Clean by the host. As a child, I was so fond of reading what I saw as beautiful. Even when above [lacking] the understanding. The perception of beauty came mainly from the cover and the fonts used ( same today ) or from the place the book occupied on my father's shelf. One of them was Tuareg. More than once I took this classic from the home library, only to glance at the first page with no interest. It was only decades later — some years ago — that I saw the title again, and read with pleasure and no difficulties. It's not a hard read, even to a 12 year-old, probably only the argument, the plot, didn't catch me by then. Anyway, I was attracted to the book, as if simply wanting to read it made me part of the classic, the intellectual. I have less of this today. [I mean,] Not the inability to read a lot of books, but the urge to be a consumer of certain cultural product. Maybe due to not greeding to build a personal image, content without exposition. Still, sometimes, wanting to consume a piece of media and being unable to.. I wanted a story of robots, the book I though was not available [(All Systems Red)], so I bought one of scientific fiction. Somehow it attracted me when I flipped the few pages of Planet of Exile at the bookstore, an item that could lead me to a travel outside of this place, an escape. At home, I immediately saw I couldn't grasp it. There were too many characters (too many = more than two in the first page, specially when another atmosphere is the location, a new physics to grasp). Too much information, can't retain the minimum necessary in the way to the second, third… fifth page, by when more is being presented. This was always a disability of mine, focused on a little tiny thing, intensely, for some time, all lost in some weeks or months. I know it happens to me , because people are able to remember the names of the cars of the movie Cars. Not an incredible feat for them (maybe they haven't paid attention, nor actively tried to remember, only did), and something strange to me. It was decided to register this because when I saw myself unable to read the [Ursula] Le Guin's book, I got nervous. I've already been forgetting more ultimately, take confused steps, and now I can't center on a book?! What's happening? But then I took a breath: much can be going way too wrong from current circumstances outside and inside, but your limited comprehension of the world (and its art) is very part of you. This trace, or frailty, of your character, is not your brain rotting, it's part of what you have been since always. Thank you. Provide feedback on this episode.

    HPR4680: Robert A. Heinlein: The Future History, Part 2

    Play Episode Listen Later Jul 10, 2026


    This show has been flagged as Clean by the host. In his early days as a writer, Heinlein wrote his stories in the context of a shared universe that he called the Future History. These were mostly short stories at first, with the occasional novella. But they include some great stories. The Future History, Part 2 There were a few key themes running through Heinlein's body of work. One we have already remarked upon, individual freedom, which had to be protected from any source of power, including both government and private corporations. This was essentially a libertarian perspective, but unlike many of today's libertarians he was equally averse to the corporate type of power as a threat. But he had a complex view of the world which has resisted some attempts to pigeonhole him. He started out as a socialist, and while he didn't remain one, he never became a knee-jerk reactionary either. In fact, he clearly despised them just as much. One way of looking at his body of work is that he explored the ramifications of different social policies through his stories, but in most cases the needs of a good story came first in the early years. In his later works he often surrendered to the temptation to pontificate, which reduced the enjoyment of them somewhat for anyone who was not already in agreement with his opinions The second major theme you see throughout all of his works is the idea of the competent individual. He admired anyone who could do a job well, and clearly did not care whether they were man or woman, nor black or white. Alexei Panshin writes, in Heinlein in Dimension: “There is one unique and vivid human Heinlein character, but he is a composite of Joe-Jim Gregory, Harriman, Waldo, Lazarus Long, Mr. Kiku, and many others, rather than any one individual. I call the composite the Heinlein Individual. . . . It is a single personality that appears in three different stages and is repeated in every Heinlein book in one form or another. “The earliest stage is that of the competent but naïve youngster. . . . The second stage is the competent man in full glory, the man who knows how things work. . . . The last stage is the wise old man who not only knows how things work, but why they work, too.” Harriman we have already encountered in The Man Who Sold The Moon, and the others appear later. The Heinlein Individual, as he is often referred to, appears in many of Heinlein's stories. A third major theme has to do with morality and religion. Heinlein grew up in what he considered the heart of the Bible Belt, in Missouri, and saw first-hand how the evangelical Christians operated, and despised what he saw. As someone who believed in individual freedom, he could never surrender to someone else's idea of how he should live his life. He saw them as a danger to his ideal libertarian society, and this shows up very early in his work. He personified the good, upright, church-going folk as “Mrs. Grundy”, and while you might want to draw the drapes to keep her from knowing what you were doing, you should never let her dictate how you would live your life. Revolt in 2100 begins the exploration of this in detail. There is a chart of the future history at Baen Books, and in it we see that the 1960s were what Heinlein called The Crazy Years. (Remember, he conceived this in the 1940s and 1950s.) But in 2012 the major thing occurred when Nehemiah Scudder, a backwoods preacher, managed to get elected as President. This would be the last election held under the U.S. Constitution as he established a religious dictatorship that lasted a couple of generations. IS this plausible? Heinlein wrote about this: “As for … the idea that we could lose our freedom by succumbing to a wave of religious hysteria, I am sorry to say that I consider it possible. I hope that it is not probable. But there is a latent deep strain of religious fanaticism in this, our culture; it is rooted in our history and it has broken out many times in the past. “It is with us now; there has been a sharp rise in strongly evangelical sects in this country in recent years, some of which hold beliefs theocratic in the extreme, anti-intellectual, anti-scientific, and anti-libertarian.“ His background in the Bible Belt is what informs a lot of his thinking. He goes on to describe how this might happen: “Throw in a Depression for good measure, promise a material heaven here on earth, add a dash of anti-Semitism, anti-Catholicism, anti-Negroism, and a good large dose of anti-“furriners” in general and anti-intellectuals here at home, and the result might be something quite frightening — particularly when one recalls that our voting system is such that a minority distributed as pluralities in enough states can constitute a working majority in Washington.” As the science fiction author David Brin points out, Heinlein accurately predicted much of what we are going through in the United States right now. There is an emerging dictatorship in the United States, promoted by right-wing religious groups. The “material heaven here on earth” is represented by the Prosperity Gospel, prominent in the Trump movement, and so on. Where the Prophet used a restored Ku Klux Klan as his muscle, we have The Proud Boys, and so on. It really does track very closely. Read David Brin's article for more on this. But nothing lasts forever. Empires rise and fall, governments change, and in this case a resistance movement arises. The revolt is depicted in the novella If This Goes On— (1940), and it is set in the year 2100, giving the title to the book. The main character is John Lyle, who is a young army officer assigned to the group protecting The Prophet in his capital of New Jerusalem. In the beginning he is thoroughly indoctrinated, but then begins to question his beliefs when he falls for one of The Prophet's virgins, Sister Judith. He has an older companion in the military who is not only unshocked when John confides in him about his doubts, but offers to help him. It turns out this companion, Zeb Jones, is a member of the underground group called The Cabal that is working to overthrow the theocracy. In the end they are successful, and in the course of this John Lyle does a lot of growing up. In this we see another common characteristic of Heinlein stories: a young, naive boy meets up with an older and wiser man who helps him to grow. In 2016 If This Goes On— won the Retro-Hugo Award for best novella of 1940. And in a personal note, I have T-shirt that says “Scudder for President 2012”. This baffles most people, but I enjoy the in-joke. What is interesting in this book is that Heinlein doesn't stop with a successful revolution. He then goes on in a second novella to describe the government that arose following the revolution, and this story is called Coventry (1940). The new government that arises after the revolution is called The Covenant, and it is an attempt to make sure that what happened with Scudder in 2012 could never happen again. It is a strongly libertarian government based on an agreement to be non-violent. In this society, scientists can cured criminal or violent tendencies, but any citizen convicted of such must agree to the treatment. The alternative to treatment is that they can be exiled to a place called Coventry. Coventry is outside of the Covenant society, and the Covenant society has nothing to do with them. Our protagonist, David McKinnon, is convicted of assault, and chooses to go to Coventry instead of getting treatment. He imagines it is a peaceful anarchy, but is disabused of this notion when he is robbed of all of this possessions upon entry and thrown in jail. A fellow inmate, Fader Magee, helps him escape, and we learn he is an agent of the Covenant government. They learn that two of the factions in Coventry have joined forces, and found a way to break through the barrier that surrounds Coventry. They plan to attack and overthrow the Covenant government. David and Fader separately work to escape and get back to warn the Covenant government, which they do successfully. And by doing this, David has demonstrated that he is no longer a danger to the Covenant society and no longer subject to treatment. This story won a Prometheus Hall of Fame Award, which is awarded by the Libertarian Futurist Society. And the Covenant society certainly has libertarian features. But this is not the Randian version of libertarianism, as exemplified by the fact that David is restored to the society because he demonstrated his concern for others. Heinlein always promoted individual freedom, but also the idea that people have a responsibility towards others. Finally, Revolt in 2100 contains the short story Misfit, w2hich we have looked at previously. The Past Through Tomorrow (1967) is a one volume collection of most of the Future history stories. I say most because just which stories belonged in this group could change from time to time. It also has the last version of the Chart of the Future History, and a few stories we have not yet mentioned (Methusaleh's Children, and The Menace From Earth). And many of his other works contain back references to these events that imply that they might be set in the same alternate universe. Heinlein gets the last word on this: “I have never been sure whether or not publishing that chart was a good idea or a bad mistake. Possibly it helped to sell some stories later—but certainly it caused me and still causes me to receive a lot nuisance mail from nitpickers. I have never felt bound by that chart; it was to serve me, not the other way around. If I found myself with a good story notion which fitted fairly well into the chart but not perfectly, I shed no tears—I went ahead and let the inconsistencies stand. I want each story to be internally consistent . . . but I won't let myself be painted into a corner through trying to fit that chart perfectly. I may start another “Future History” story tomorrow . . . and find that to make it a good yarn I must violate some item on that chart. I'll give the nitpickers something to pick, for I will not hurt a good yarn for the sake of “logic”—logic is not involved, as that chart is fiction, not Holy Writ.” Links: https://www.amazon.com/Heinlein-Dimension-Critical-Alexei-Panshin/dp/0911682015 https://web.archive.org/web/20151105170345/http://www.baenebooks.com/chapters/1439133417/1439133417___1.htm https://david-brin.medium.com/heinleins-future-history-coming-true-before-our-eyes-10356a95556a https://en.wikipedia.org/wiki/%22If_This_Goes_On%E2%80%94%22 https://en.wikipedia.org/wiki/Coventry_(short_story) https://en.wikipedia.org/wiki/Prometheus_Award#Hall_of_Fame_Award_inductees https://en.wikipedia.org/wiki/The_Past_Through_Tomorrow https://www.palain.com/science-fiction/the-golden-age/robert-a-heinlein/the-future-history-part-2/ Provide feedback on this episode.

    HPR4679: HPR Beer Garden 15 - Double IPA

    Play Episode Listen Later Jul 9, 2026


    This show has been flagged as Clean by the host. Kevie, Paul and Dave are back once again with the HPR Beer Garden, this time focusing on the relatively new style of beer called Double IPA. Kevie samples Man Overboard by Cromarty Brewing , Paul tastes Rumble by Beavertown and Dave opts for Ultra Phase by North Brewing Connect with the guys on Untappd: Dave Paul Kevie The intro sounds for the show are used from: https://freesound.org/people/mixtus/sounds/329806/ https://freesound.org/people/j1987/sounds/123003/ https://freesound.org/people/greatsoundstube/sounds/628437/ The next 3 beer styles to be reviewed: Belgian Blonde DDH IPA Amber Ale Provide feedback on this episode.

    HPR4678: High Resolution Elapsed Time in Shell Scripts

    Play Episode Listen Later Jul 8, 2026


    This show has been flagged as Clean by the host. 01 Introduction In this episode I will describe how to calculate elapsed time in bash or other shell scripts. While this may sound like a very simple and basic thing to do, there is a slightly more complex aspect to it if you wish to calculate elapsed time to a higher resolution than one second. 02 There are many reasons for calculating elapsed time in a shell script. For example you may wish to simply report how long an operation took to run. Another reason may be that you are trying to speed up a script and need to calculate benchmark data to see how different alternative methods perform. 03 What may seem like a simple task gets a bit more complicated if you want to do it for multiple different operating systems even if they are all unix related, as we shall see. -------------------- 04 Operating Systems Tested For the purposes of this episode, I ran tests on the current version of the following operating systems. Alma Alpine Debian FreeBSD OpenBSD RaspberryPi OpenSuse Ubuntu 2604 Alma is a close copy of Red Hat that we can take as representing Red Hat style distros. -------------------- 05 Simple Low Resolution Timing I will start with the simple and obvious method before describing the less obvious ones. This uses the date command to get the current time in seconds since the unix epoch. This is simply date '+%s' 06 Save this to a variable using whatever method you prefer. For example. starttime=$(date '+%s') 07 Next, do whatever operations it is you wish to time. Use the date command to get the current time again. endtime=$(date '+%s') 08 Now simply subtract the start time from the end time using shell arithmetic. This should be very obvious and basic. -------------------- 09 Higher Resolution Timing However, suppose we wish to measure time to greater than one second of precision. We need to do two things. The first is to obtain the current time at a higher degree of precision. The second is to conduct the calculations to a higher degree of precision. 10 Unfortunately, the standard time precision for POSIX shells seems to be 1 second. Some shells offer a higher precision, but others do not. Furthermore, standard shell arithmatic uses integer, which limits calculations to 1 second of precision. -------------------- 11 Bash High Resolution Shell Variable Fortunately, bash is one that does offer a high precision date. If you are using bash 5.0 or newer, there is a shell variable called EPOCHREALTIME which offers time since the the unix epoch (that is, since the first of January 1970, at 00:00:00 UTC) in seconds to 6 decimals of precision. 12 Example echo $EPOCHREALTIME 1779634800.184926 13 This is related to the similar bash variable known as EPOCHSECONDS which gives the number of seconds since the unix epoch. 14 Example echo $EPOCHSECONDS 1779634800 15 So if you are using bash, measuring time is very simple. -------------------- 16 But is it Really Bash? Is your script however actually using bash? Debian and derivatives actually have two shells. The first, the interactive shell is bash. The second, the non-interactive shell is dash, which stands for "debian almquist shell". 17 If you open a terminal, you get bash. If your script starts with a "bin/bash" shebang line, you get bash. However, if your script starts with a "bin/sh" shebang line, you get dash. Some people find themselves getting caught out by this one when they try something out in a terminal but find that it doesn't work in their script which started with "bin/sh". 18 Many other, but not all, Linux distros use bash for both the interactive and non-interactive shells, so "bin/sh" and "bin/bash" work the same with those ones. So if you intend to use bash, make sure your script calls for bash in the first line. -------------------- 19 The SHELL Variable So how can a script tell what shell it is running under? There is a shell variable called "SHELL" which will tell you the name of the shell. Well, sort of. 20 On Debian and derivatives "SHELL" will say "bash" regardless of whether the actual shell is bash or dash. On some other operating systems "SHELL" will simply say "sh" even if it is something else entirely. So we need to do some additional levels of checking to see what we have. 21 To start with though, here's what each of the test distros reports for SHELL. Alma : bash Alpine : sh Debian : bash FreeBSD : sh OpenBSD : ksh Raspberry-Pi : bash Suse : bash ubuntu2604 : bash -------------------- 22 Bash Versus Dash First, let's try to see which ones are bash and which ones are dash. The first thing we can check is for the shell variable BASH_VERSION. 23 Example echo $BASH_VERSION If the shell is bash, then it will report a version string. If the shell is not bash, then it will return an empty value. 24 Using this test, we can see that Alma and Opensuse are indeed using bash. We however need to check Debian, Raspberry Pi, and Ubuntu when running in an "sh" script. To check this we can use the "which" command to see what "sh" actually is. 25 Example echo $( ls -l $(which sh ) | rev | cut -d" " -f1 | cut -d/ -f1 | rev ) 26 "which sh" shows us the path to "sh" However, that is a link so we need to use "ls -l" to find the actual executable. "rev" reverses the string. 27 "cut" takes the first element separated by spaces. The second "cut" takes the first element separated by the "/" characters. The final "rev" takes that string and reverses it again to get it in the correct order. 28 In the case of Debian, Raspberry Pi, and Ubuntu it tells us that this is "dash". -------------------- 29 Openbsd Openbsd reports its shell as "ksh", which stands for Korn Shell. It is indeed Korn Shell, so we simply leave that one as is. -------------------- 30 Alpine and Freebsd Next we have Alpine Linux and Freebsd, which both report as "sh". In the case Freebsd there doesn't appear to be any further we can go that I am aware of. It's simple "sh". It is a basic POSIX shell which seems to be similar to the original unix shell, the Bourne Shell. Older versions of Freebsd used a different shell known as tsch (the C shell), but I haven't tested that so I will ignore that here. 31 With Alpine Linux however, we can get the actual shell using the same method that we used for Debian Linux. This reports as being "busybox". 32 Busybox is a limited shell intended for use in embedded systems. Alpine was originally an embedded distro, but some people started using it for containers. Alpine is Linux, but it is not GNU/Linux, and there are a number of areas which can trip you up if you are not aware of them. So, be extra careful if you are using it for anything, and test everything. -------------------- 33 Summary of Actual Shells Here is our revised list with the actual shell used when asking for "sh", so far as we can determine. Alma : bash Alpine : busybox Debian : dash FreeBSD : sh OpenBSD : ksh Raspberry-Pi : dash Suse : bash ubuntu2604 : dash 34 There are other shells, but none of them are the default shell for any of the distros on our list, so I haven't tested them. -------------------- 35 Solutions for Measuring Time Now we need to find solutions for bash, dash, ksh, sh, and busybox. -------------------- 36 Bash For bash, we can simply use EPOCHREALTIME, as mentioned above. -------------------- 37 Dash For dash, we can use the date command. This is a very conventional method, and is probably the first answer that anyone would give for this situation. However, while it will work in most cases, it will not work in all cases, so it is not a universal solution. 38 To use date we simply call it with the correct format string. This uses %s to get seconds since the epoch, and %N to get nanoseconds of the current second. If you put a decimal separator between the two it will appear in the output. You can use the correct decimal separator for your locale, but I won't go into that here. Instead I will just assume a period or dot. 39 Example date '+%s.%N' 1779634800.358916385 -------------------- 40 Problems with Date on Alpine and Openbsd Date will work for bash, dash, and sh on Freebsd. However it will not work for ksh on Openbsd, or for busybox on Alpine. 41 With busybox on Alpine, it simply ignores the %N format specifier and prints out the epoch in seconds only followed by the decimal separator. = Example date '+%s.%N' 1779634800. 42 With ksh on Openbsd it prints the epoch in seconds followed by the decimal separator and then the %N as a literal N. date '+%s.%N' 1779634800.N 43 Fortunately we have alternatives for these two cases. -------------------- 44 Openbsd Openbsd has the "ts" or timestamp utility installed by default. ts prints a time stamp in front of every line it receives from standard input. I won't go into details on all aspects of ts here, I'll leave that to someone else. Instead I will focus on how to use it for our specific purposes here. 45 We need to provide a format specifier to ts, which in this case is "%.s" We also need to provide something for standard input, or otherwise ts will simply sit there and wait for input. So what we need to do is to echo nothing through a pipe to ts while also giving ts the proper format specifier. 46 Example echo | ts "%.s" 47 This will output the epoch time in seconds to six decimals of precision. ts is installed in Openbsd and Freebsd by default and can be used in either. It can also be installed in many other distros. -------------------- 48 Busybox on Alpine None of the methods discussed so far will work for busybox on Alpine though. However there is a way, but it's a bit non obvious and somewhat hacky. 49 Busybox includes a command called "adjtimex". This is normally used to adjust the time hardware. However if it is run without arguments, it will report the current settings. 50 These include the current epoch time in seconds , and in another field the time in microseconds. These are reported as key value pairs. So what we need to do is to do the following 51 Run adjtimex Capture the output. Grep for "time.tv_sec" Grep for "time.tv_usec" Use cut to extract the time value in each case. Use tr to get rid of excess spaces in each case. Combine the two in a string with a decimal separator between them. 52 This takes a total of 4 lines of shell script. I will just describe them breifly here, see the show notes for details. 53 First we want to capture the output of adjtimex in a single operation. Run adjtimex and pipe the output through grep to capture lines containing "time.tv_" and save this to a variable. # Extract the current high resolution time from adjtimex. # We want two key value pairs, identified by time.tv_sec and time.tv_usec. tvals=$( adjtimex | grep "time.tv_" ) 54 Next echo the contents of this variable and pipe it through grep, cut, and tr to get first the seconds and then the microseconds while also removing excess spaces. Save these to two separate variables. "time.tv_sec" is the time in seconds since the epoch. "time.tv_usec" is the number of microseconds in the current second. # Get the time since the unix epoch in seconds and micro-seconds. timesec=$( echo "$tvals" | grep "time.tv_sec" | cut -d: -f2 | tr -d " " ) timeusec=$( echo "$tvals" | grep "time.tv_usec" | cut -d: -f2 | tr -d " " ) 55 Adjtimex does not zero pad the microsecond time value to provide leading zeros, so we need to take care of this using printf before we can append it to the seconds value. We didn't need to do this with date where the %N format character does this automatically. In this instance, the printf format string is '%06d' padusec=$( printf '%06d' $timeusec ) Now, combine these into a single number with a decimal separator by using simple string concatenation. # Combine them into a single number. timehires="$timesec"".""$padusec" -------------------- 56 Summary of Methods Let's summarize where we are so far in terms of methods we can use to get the current time as a high resolution number. Alma : use EPOCHREALTIME or date Debian (bash) : use EPOCHREALTIME or date Raspberry-Pi (bash) : use EPOCHREALTIME or date ubuntu2604 (bash) : use EPOCHREALTIME or date Suse : use EPOCHREALTIME or date Debian (dash) : use date Raspberry-Pi (dash) : use date ubuntu2604 (dash) : use date Alpine : use adjtimex and parse the output FreeBSD : use date or ts OpenBSD : use ts -------------------- 57 Other alternatives There are a few alternatives that we haven't discussed yet. 58 Bash with Dash In the case of Debian, Raspberry Pi, and Ubuntu running dash, since bash is available it is possible to write a separate bash script which simply echos EPOCHREALTIME and then call it from the dash script and capture the output. While this would work, there's probably not a lot of point to it. If you can rely on bash being there, then just change the first line of the script and make it a bash script. 59 Adding Packages to Alpine The ts or timestamp utility is a common unix utility that can be installed if it is not present by default. This does produce high resolution timestamps on Alpine. On Alpine Linux this comes as part of the "moreutils" package. To add the package, use the following sudo apk add moreutils echo | ts "%.s" 1779634800.959948 60 You can also add the GNU coreutils, which will provide a high resolution date command which works like in the other examples. To add the package use the following sudo apk add coreutils date '+%s.%N' 1779634800.212897332 61 If you can install more packages into your Alpine system, either of the above two is probably going to be preferable to parsing the output of adjtimex. 62 Custom Timestamp Programs You can also write a very short program in python, perl, tcl, or some other language and have it output the current epoch time. I won't discuss that here though. -------------------- 63 Calculating Time Differences Shell arithmetic is integer only. If we wish to use high resolution timing data, we need to do something so we don't lose the precision we have worked so hard to get. There are several possible solutions. 64 Change the Time Base One method is to change the time base from seconds to milli, micro, or nanoseconds. This can be done by simply multiplying the time values by the appropriate amount (e.g. 1000, 1,000,000, etc.) before subtracting them. This allows for integer arithmetic on high resolution values without losing precision. 65 Use the Shell bc Arbitrary Precision Calculator The bc command line calculator will perform calculations using real numbers and is easy to use in scripts. It is present by default in most distros. echo "scale=9; $endtime - $starttime" | bc where endtime and starttime are variables containing time values. 66 However, for some inexplicable reason, neither Debian nor Opensuse install it by default. It is present in Ubuntu and Raspberry Pi which are Debian derivatives, and it can be added to distros which lack it. 67 Use awk awk can also perform calculations using real numbers and it is present in nearly all distros including in all of the ones we tested here. echo "$endtime $starttime" | awk '{printf "%.6fn", $1 - $2}' -------------------- 68 Benchmarks And of course no comparative evaluation would be complete without benchmarks where we see how each method compares to another in terms of speed. In the benchmark test I ran each method in a loop through multiple iterations, measured the elapsed time, subtracted out the time for an empty loop, and then compared it to alternate methods. For anything other than EPOCHREALTIME, the empty loop time is negligible and has no real effect on the results. 69 Rather interestingly I came across a bug which caused date to run very slowly if called immediately after using EPOCHREALTIME in bash. The effect of the bug was to make the date benchmark test roughly 24 times slower. This has been fixed in newer releases, but if you are using an older distro release then beware of this bug. I was able to get around it either putting a sleep delay between benchmarking EPOCHREALTIME and benchmarking date, or by simply testing date before testing EPOCHREALTIME. 70 To be able to conduct additional tests I installed ts in Ubuntu and Alpine, and the GNU version of date in Alpine. 71 EPOCHREALTIME Versus date in Ubuntu 2604 bash The EPOCHREALTIME method is 3103 times faster than date. However, when the same test is run on Ubuntu 2404 when the date test is run before the EPOCHREALTIME test, EPOCHREALTIME is 1240 faster than date. Other Linux distros show performance to Ubuntu 2404. It appears that a side effect of fixing whatever the bug is has the effect of slowing down date. However, this is probably not a significant issue in normal circumstances. 72 date versus ts in Ubuntu 2604 bash The date method is 3.7 times faster than ts 73 date versus ts in Ubuntu 2604 dash The date method is 4.9 times faster than ts 74 date versus ts in Freebsd sh The date method is 2.5 times faster than ts 75 date versus adjtimex in Alpine Busybox The date method is 6.0 times faster than adjtimex 76 date versus ts in Alpine Busybox The date method is 20.0 times faster than ts 77 bc versus awk in Ubuntu 2604 I compared calculating the difference between two numbers when using bc versus awk. The difference is negligible, with bc being only 7% faster than awk. 78 Conclusion for Benchmarks Based on these results, if you need to measure elapsed time to high resolution and care about runing the command with as little overhead as possible, then the order of preference should be the following. 79 If you are using a newer version of bash, then use EPOCHREALTIME. If that is not available, then use date, provided it allows for high resolution times. If the above two cannot be used, then use ts. If you are using Busybox and cannot install either GNU date or ts, then use adjtimex. Date is the closest in terms of being the universal portable solution, but it does not work in all cases. 80 I have not compared different platforms to each other in terms of performance, as that would be a much more involved problem that is outside the scope of this episode. However, different operating systems implement different commands in different ways. 81 For example, on Openbsd and Freebsd, ts appears to be an ELF binary. That is, it is executable machine code, possibly written in C. On Ubuntu however, ts appears to be a perl script. As a result of this, the advantage that date has over ts is much less in Freebsd than it is with Ubuntu (and likely other Linux distros) as on Freebsd it doesn't need to load a perl interpreter to run ts. -------------------- 82 Overall Conclusion You no doubt thought that measuring elapsed time was going to be so simple, and how could someone get an entire podcast out of such a simple subject? And yet here we are half an hour later with just a basic overview of the subject. 83 I hope you found this interesting and informative. Please let us know in the comments if you think that I have done anything incorrectly, or if you have another way of doing things. I hope to see you all again in another future episode of HPR. -------------------- Provide feedback on this episode.

    Claim Hacker Public Radio

    In order to claim this podcast we'll send an email to with a verification link. Simply click the link and you will be able to edit tags, request a refresh, and other features to take control of your podcast page!

    Claim Cancel